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);
}
BytesBase64(
bytes
.chunks(3)
.map(|c| chunk_to_base64(c))
.flatten()
.collect(),
)
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| 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()
}

View File

@@ -3,10 +3,10 @@ mod bytes_base64;
mod set1;
fn main() {
// set1::challenge1();
// set1::challenge2();
// set1::challenge3();
// set1::challenge4();
// set1::challenge5();
set1::challenge1();
set1::challenge2();
set1::challenge3();
set1::challenge4();
set1::challenge5();
set1::challenge6();
}

View File

@@ -72,12 +72,12 @@ pub fn challenge5() {
}
pub fn challenge6() {
fn read(path: &str) -> BytesBase64 {
fn read(path: &str) -> Bytes {
let s = std::fs::read_to_string(path).unwrap();
BytesBase64::from_base64(&s)
BytesBase64::from_base64(&s).to_bytes()
}
fn write(path: &str, bytes_base64: &BytesBase64) {
fn _write(path: &str, bytes_base64: &BytesBase64) {
let width = 60;
let bytes = bytes_base64.to_string();
let mut output_vec = vec![];
@@ -88,12 +88,19 @@ pub fn challenge6() {
}
output_vec.push(*e.0);
}
output_vec.push('\n' as u8);
let mut f = std::fs::File::create(path).unwrap();
f.write(&output_vec).unwrap();
}
let bytes_base64 = read("data/6.txt");
write("data/6_out.txt", &bytes_base64);
println!("[open] Challenge 6");
fn _test_roundtrip() {
// Test that conversion from to bytes and back works
let bytes = read("data/6.txt");
let bytes_base64 = BytesBase64::from_bytes(bytes);
_write("data/6.txt", &bytes_base64);
}
_test_roundtrip();
let _bytes = read("data/6.txt");
println!("[open] Challenge 6: {}", 0);
}