use tokio::io::{AsyncRead, AsyncWrite}; /// Per the assignment spec, `1472` is the maximum size packet we're allowed to send. pub const MAX_TOTAL_PACKET_SIZE: usize = 1472; // TODO: change these based off the decoders pub const UP_HEADER_SIZE: usize = 4; pub const DOWN_HEADER_SIZE: usize = 1; /// This is the maximum amount of segment data we can fit into a packet. pub const MAX_SEG_SIZE: usize = MAX_TOTAL_PACKET_SIZE - UP_HEADER_SIZE; // Note: we can only keep so much file data in RAM, so let's see what would be the // maximum amount of file data we keep in flux. // // 1456 B (MAX_SEG_SIZE) * 2.03% (compression factor for PSHex) = 2.96 KB/seg // 2.96 KB/seg * 11,648 seg (max possible SEGS_PER_CHUNK) = 34.5 MB // // 34 MB is actually much larger than the maximum test case size. /// This is calculated based on the max size we would need for a bit-field specifying /// which segments are present in a chunk. pub const SEG_PER_CHUNK: usize = (MAX_TOTAL_PACKET_SIZE - DOWN_HEADER_SIZE) * 8; /// Is `u32` big enough to handle all file sizes? /// /// 1.46 KB/seg * 2^32 seg = 6.3 TB /// /// If we used `u16` instead we would be just barely OK: /// /// 1.46 KB/seg * 2^16 seg = 95.4 MB /// pub type SegIdx = u32; /* #[derive(Copy, Clone, Eq, PartialEq, Debug)] pub enum SegmentEncoding { /// Un-encoded byte sequence. Raw, /// "PostScript style" Hex w/ linebreaks: ([0-9a-f]{60}\n)*. PSHex, } #[derive(Clone, Debug)] pub struct SegmentSet { pub latest_seg_idx: SegIdx, pub other_segs: std::collections::HashSet, } */ #[derive(Clone)] pub struct SegData { pub(crate) bytes: Vec, pub is_last_segment: bool, pub is_meow_encoded: bool, } impl SegData { pub fn len(&self) -> usize { self.bytes.len() } pub async fn read(inp: &mut IN) -> Result where IN: AsyncRead + Unpin, { use tokio::io::AsyncReadExt; let mut buf = [0u8; MAX_SEG_SIZE]; let len = inp.read(&mut buf).await.unwrap_or(0); if len > 0 { Ok(SegData { bytes: Vec::from(&buf[..len]), is_last_segment: false, is_meow_encoded: false, }) } else { Ok(SegData { bytes: vec![], is_last_segment: true, is_meow_encoded: false, }) } } pub async fn write(&self, out: &mut OUT) -> Result<(), tokio::io::Error> where OUT: AsyncWrite + Unpin, { use tokio::io::AsyncWriteExt; out.write_all(&self.bytes).await } }