93 lines
2.6 KiB
Rust
93 lines
2.6 KiB
Rust
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<SegIdx>,
|
|
}
|
|
*/
|
|
|
|
#[derive(Clone)]
|
|
pub struct SegData {
|
|
pub(crate) bytes: Vec<u8>,
|
|
pub is_last_segment: bool,
|
|
pub is_meow_encoded: bool,
|
|
}
|
|
|
|
impl SegData {
|
|
pub fn len(&self) -> usize {
|
|
self.bytes.len()
|
|
}
|
|
|
|
pub async fn read<IN>(inp: &mut IN) -> Result<SegData, tokio::io::Error>
|
|
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<OUT>(&self, out: &mut OUT) -> Result<(), tokio::io::Error>
|
|
where
|
|
OUT: AsyncWrite + Unpin,
|
|
{
|
|
use tokio::io::AsyncWriteExt;
|
|
out.write_all(&self.bytes).await
|
|
}
|
|
}
|