From 1e84f2cb58ac06f3851b3c95adf55c32f9e6c163 Mon Sep 17 00:00:00 2001 From: Felix Martin Date: Sat, 26 Mar 2022 19:14:38 -0400 Subject: [PATCH] Implement conversion from base64 into bytes. --- src/bytes_base64.rs | 59 +++++++++++++++++++++++++++++---------------- src/main.rs | 10 ++++---- src/set1.rs | 21 ++++++++++------ 3 files changed, 57 insertions(+), 33 deletions(-) diff --git a/src/bytes_base64.rs b/src/bytes_base64.rs index c535294..e3b93ac 100644 --- a/src/bytes_base64.rs +++ b/src/bytes_base64.rs @@ -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 { - 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 { + 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 { + let mut v = c.to_vec(); + // pad with bytes for conversion + while v.len() < 4 { + v.push(0); + } + let mut result: Vec = 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() } diff --git a/src/main.rs b/src/main.rs index 8b7aef6..1539d9e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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(); } diff --git a/src/set1.rs b/src/set1.rs index 23cf0f5..20c0cac 100644 --- a/src/set1.rs +++ b/src/set1.rs @@ -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); }