CS3700-project3/hptp/src/seg.rs

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
}
}