-
-
Save RandyMcMillan/f72ede9bff8bb79ec70d004ee34dd3ad to your computer and use it in GitHub Desktop.
perfect_ip.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #[derive(Debug, Clone)] | |
| struct Header { | |
| seq_num: u32, | |
| total_packets: u32, | |
| } | |
| #[derive(Debug, Clone)] | |
| struct ProtocolSlice { | |
| id: String, | |
| header: Header, | |
| data: Vec<u8>, | |
| is_parity: bool, | |
| } | |
| const MTU_PAYLOAD: usize = 1460; | |
| fn calculate_parity(left: &[u8], right: &[u8]) -> Vec<u8> { | |
| let max_len = left.len().max(right.len()); | |
| let mut parity = vec![0; max_len]; | |
| for i in 0..max_len { | |
| let l = if i < left.len() { left[i] } else { 0 }; | |
| let r = if i < right.len() { right[i] } else { 0 }; | |
| parity[i] = l ^ r; | |
| } | |
| parity | |
| } | |
| fn process_slice(id: String, data: Vec<u8>, seq: &mut u32) -> Vec<ProtocolSlice> { | |
| if data.len() <= MTU_PAYLOAD { | |
| let slice = ProtocolSlice { | |
| id: id.clone(), | |
| header: Header { seq_num: *seq, total_packets: 0 }, | |
| data, | |
| is_parity: false, | |
| }; | |
| *seq += 1; | |
| return vec![slice]; | |
| } | |
| let half = data.len() / 2; | |
| let left_data = data[..half].to_vec(); | |
| let right_data = data[half..].to_vec(); | |
| let mut slices = process_slice(format!("{}.0", id), left_data.clone(), seq); | |
| slices.append(&mut process_slice(format!("{}.1", id), right_data.clone(), seq)); | |
| let parity = calculate_parity(&left_data, &right_data); | |
| slices.push(ProtocolSlice { | |
| id: format!("{}.P", id), | |
| header: Header { seq_num: *seq, total_packets: 0 }, | |
| data: parity, | |
| is_parity: true, | |
| }); | |
| *seq += 1; | |
| slices | |
| } | |
| fn main() { | |
| let raw_data = vec![0xAB; 300000]; | |
| let mut seq = 0; | |
| let mut packets = process_slice("ROOT".to_string(), raw_data, &mut seq); | |
| let total = packets.len() as u32; | |
| for p in packets.iter_mut() { | |
| p.header.total_packets = total; | |
| } | |
| println!("--- Protocol Initialized: {} Packets ---", total); | |
| for p in &packets { | |
| println!("ID: {:<8} | Seq: {:>2}/{} | Type: {:<6} | Size: {}B", | |
| p.id, p.header.seq_num, p.header.total_packets, | |
| if p.is_parity { "PARITY" } else { "DATA" }, p.data.len()); | |
| } | |
| } | |
| #[cfg(test)] | |
| mod tests { | |
| use super::*; | |
| #[test] | |
| fn test_recovery_and_throughput() { | |
| let raw_data = vec![0xDE; 2000]; | |
| let mut seq = 0; | |
| let packets = process_slice("ROOT".to_string(), raw_data, &mut seq); | |
| let p_missing = packets.iter().find(|p| p.id == "ROOT.0").expect("ROOT.0 missing"); | |
| let p_sibling = packets.iter().find(|p| p.id == "ROOT.1").expect("ROOT.1 missing"); | |
| let p_parity = packets.iter().find(|p| p.id == "ROOT.P").expect("ROOT.P missing"); | |
| println!("\n[TEST] Simulating loss of slice: {}", p_missing.id); | |
| println!("[TEST] Using sibling: {} and parity: {}", p_sibling.id, p_parity.id); | |
| let recovered = calculate_parity(&p_sibling.data, &p_parity.data); | |
| println!("[TEST] Recovery Data (First 10 bytes): {:02X?}", &recovered[..10]); | |
| assert_eq!(p_missing.data, recovered, "Recovery failed!"); | |
| println!("[TEST] Recovery successful and verified."); | |
| } | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=54a6357a37122955cfc031ff2d67e012