Add b64 enocoding and test

This commit is contained in:
Nathan Fisher 2024-05-02 12:15:22 -04:00
parent 683aa50d2a
commit e12cc66fba
3 changed files with 59 additions and 17 deletions

View File

@ -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<R: Read, W: Write> {
mod tests {
use super::*;
}

View File

@ -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<R: Read, W: Write> {
impl<R: Read, W: Write> Encoder<R, W> {
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(())
}
}

View File

@ -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<usize> {
for (idx, x) in self.items.iter().enumerate() {
if *x == c {
return Some(idx)
return Some(idx);
}
}
};
None
}