diff --git a/src/decode.rs b/src/decode.rs index 0988833..8c6c82a 100644 --- a/src/decode.rs +++ b/src/decode.rs @@ -1,8 +1,6 @@ pub use { super::B64Alphabet, - std::{ - io::{self, Read, Write, ErrorKind}, - }, + std::io::{self, ErrorKind, Read, Write}, }; #[derive(Debug)] @@ -33,4 +31,3 @@ pub struct Decoder { mod tests { use super::*; } - diff --git a/src/encode.rs b/src/encode.rs index fa02faf..dd08d12 100644 --- a/src/encode.rs +++ b/src/encode.rs @@ -2,7 +2,7 @@ pub use { super::B64Alphabet, std::{ fmt::{self, Write}, - io::{self, Read, ErrorKind}, + io::{self, ErrorKind, Read}, }, }; @@ -50,11 +50,57 @@ pub struct Encoder { impl Encoder { pub fn new(reader: R, writer: W, alphabet: B64Alphabet) -> Self { - Self { reader, writer, alphabet } + Self { + reader, + writer, + alphabet, + } } pub fn encode(&mut self) -> Result<(), Error> { - todo!() + loop { + let mut ibuf = [0; 3]; + let mut obuf = [self.alphabet.pad(); 4]; + let mut n_bytes = 0; + let mut num: u64 = 0; + loop { + n_bytes += match self.reader.read(&mut ibuf) { + Ok(n) => n, + Err(e) if e.kind() == ErrorKind::Interrupted => continue, + Err(e) => return Err(e.into()), + }; + break; + } + if n_bytes == 0 { + break; + } + for (idx, n) in ibuf.iter().enumerate() { + num <<= 8; + if idx < n_bytes { + num |= *n as u64; + } + } + let pad = n_bytes * 8 % 6; + for idx in (0..4).rev() { + if pad == 0 || idx < 4 - pad { + let b = num & 0b111111; + obuf[idx] = self.alphabet.items[b as usize]; + } + num >>= 6; + } + write!( + self.writer, + "{}{}{}{}", + char::try_from(obuf[0]).unwrap(), + char::try_from(obuf[1]).unwrap(), + char::try_from(obuf[2]).unwrap(), + char::try_from(obuf[3]).unwrap() + )?; + if pad > 0 { + break; + } + } + Ok(()) } } diff --git a/src/lib.rs b/src/lib.rs index 6e3dc9e..d349fca 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,9 +1,9 @@ -mod encode; mod decode; +mod encode; pub use { - encode::{Error as B64EncoderError, Encoder as B64Encoder}, - decode::{Error as B64DecoderError, Decoder as B64Decoder}, + decode::{Decoder as B64Decoder, Error as B64DecoderError}, + encode::{Encoder as B64Encoder, Error as B64EncoderError}, }; #[derive(Clone, Copy)] @@ -14,11 +14,10 @@ pub struct B64Alphabet { pub static B64_RFC4648_ALPHABET: B64Alphabet = B64Alphabet { items: [ - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', - 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', - 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', - 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', '+', '/', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', + 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', + 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', + '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', ], pad: '=', }; @@ -33,9 +32,9 @@ impl B64Alphabet { pub fn idx(&self, c: char) -> Option { for (idx, x) in self.items.iter().enumerate() { if *x == c { - return Some(idx) + return Some(idx); } - }; + } None }