Implement conversion from base64 into bytes.

This commit is contained in:
2022-03-26 19:14:38 -04:00
parent b490b67d55
commit 1e84f2cb58
3 changed files with 57 additions and 33 deletions

View File

@@ -12,30 +12,47 @@ impl std::fmt::Display for BytesBase64 {
impl BytesBase64 {
pub fn from_bytes(Bytes(bytes): Bytes) -> BytesBase64 {
fn chunk_to_base64(c: &[u8]) -> Vec<u8> {
let (value, iterations) = match c.len() {
0 => return vec![],
1 => ((c[0] as u32) << 16, 2),
2 => ((c[0] as u32) << 16 | (c[1] as u32) << 8, 3),
3 => ((c[0] as u32) << 16 | (c[1] as u32) << 8 | (c[2] as u32), 4),
_ => panic!("Unexpected number of chunks {}.", c.len()),
};
(0..iterations)
.map(|i| (value.rotate_right((3 - i) * 6) & 0b111111) as u8)
.collect()
fn to_base64(c: &[u8]) -> Vec<u8> {
let mut v = c.to_vec();
// pad with bytes for conversion
while v.len() < 3 {
v.push(0);
}
let mut result = vec![
(v[0] & 0b11111100) >> 2,
(v[0] & 0b00000011) << 4 | (v[1] & 0b11110000) >> 4,
(v[1] & 0b00001111) << 2 | (v[2] & 0b11000000) >> 6,
(v[2] & 0b00111111) << 0,
];
// removed padded bytes
for _ in c.len()..3 {
result.pop();
}
result
}
BytesBase64(
bytes
.chunks(3)
.map(|c| chunk_to_base64(c))
.flatten()
.collect(),
)
BytesBase64(bytes.chunks(3).map(|c| to_base64(c)).flatten().collect())
}
pub fn to_bytes(&self) -> Bytes {
Bytes(vec![])
let BytesBase64(v) = self;
fn chunk_to_bytes(c: &[u8]) -> Vec<u8> {
let mut v = c.to_vec();
// pad with bytes for conversion
while v.len() < 4 {
v.push(0);
}
let mut result: Vec<u8> = vec![
((v[0] & 0b00111111) << 2) | ((v[1] & 0b00110000) >> 4),
((v[1] & 0b00001111) << 4) | ((v[2] & 0b00111100) >> 2),
((v[2] & 0b00000011) << 6) | ((v[3] & 0b00111111) >> 0),
];
// removed padded bytes
for _ in c.len()..4 {
result.pop();
}
result
}
Bytes(v.chunks(4).map(|c| chunk_to_bytes(c)).flatten().collect())
}
pub fn from_base64(s: &str) -> BytesBase64 {
@@ -75,7 +92,7 @@ impl BytesBase64 {
r.push(pad);
}
3 => r.push(pad),
_ => (),
_ => panic!("Unexpected lenght for padding '{}'", r.len()),
}
str::from_utf8(r.as_slice()).unwrap().to_string()
}