use byteorder::{ByteOrder, LittleEndian};
use crate::iter::SegmentIterator;
pub(crate) const SEGMENT_HEADER_LEN: usize = 17;
#[derive(Debug)]
pub struct Segment {
id: u32,
segment_type: u8,
length: u32,
chunk_id: u32,
offset: u32,
data: Vec<u8>,
}
#[derive(Debug)] #[repr(u8)]
enum SegmentType {
Chunk = 1,
Keyframe = 2,
}
impl Segment {
pub fn id(&self) -> u32 { self.id }
pub fn len(&self) -> usize { self.length as usize }
pub fn offset(&self) -> usize { self.offset as usize }
pub fn is_loaded(&self) -> bool { !self.data.is_empty() }
pub fn data(&self) -> &Vec<u8> { &self.data }
pub fn data_mut(&mut self) -> &mut Vec<u8> { &mut self.data }
#[warn(deprecated)]
pub fn from_raw_section(data: &[u8]) -> Segment {
Segment {
id: LittleEndian::read_u32(&data[0..]),
segment_type: data[4],
length: LittleEndian::read_u32(&data[5..]),
chunk_id: LittleEndian::read_u32(&data[9..]),
offset: LittleEndian::read_u32(&data[13..]),
data: Vec::new(),
}
}
pub fn from_slice(data: &[u8]) -> Result<Segment, crate::error::Errors> {
if data.len()<SEGMENT_HEADER_LEN {
Err(crate::error::Errors::BufferTooSmall)
} else {
Ok(Segment::from_raw_section(data))
}
}
pub fn set_data(&mut self, data: Vec<u8>) {
self.data = data;
}
pub fn is_chunk(&self) -> bool {
self.segment_type == SegmentType::Chunk as u8
}
pub fn is_keyframe(&self) -> bool {
self.segment_type == SegmentType::Keyframe as u8
}
pub fn section_iter<'a>(&'a self) -> Result<SegmentIterator<'a>, crate::Errors> {
if self.data.len() == 0 {
Err(crate::Errors::NoData)
} else {
Ok(SegmentIterator::new(&self.data[..]))
}
}
}
impl std::fmt::Display for Segment {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f,
"{} {} (len: {}, next: {}, offset: {}, loaded: {})",
if self.is_chunk() {"Chunk"} else { if self.is_keyframe() {"Keyframe"} else {"Segment"} },
self.id, self.length, self.chunk_id, self.offset, self.data.len() > 0,
)
}
}