Separate segments function in ogg_pager

Signed-off-by: Serial <69764315+Serial-ATA@users.noreply.github.com>
This commit is contained in:
Serial 2021-06-26 21:14:03 -04:00
parent 181b4cfef0
commit 822a312b0d
3 changed files with 126 additions and 122 deletions

View file

@ -67,11 +67,11 @@ const CRC_LOOKUP_ARRAY : &[u32] = &[
]; ];
pub fn crc32(page: &[u8]) -> u32 { pub fn crc32(page: &[u8]) -> u32 {
let mut crc: u32 = 0; let mut crc: u32 = 0;
for p in page { for p in page {
crc = (crc << 8) ^ CRC_LOOKUP_ARRAY[(u32::from(*p) ^ (crc >> 24)) as usize]; crc = (crc << 8) ^ CRC_LOOKUP_ARRAY[(u32::from(*p) ^ (crc >> 24)) as usize];
} }
crc crc
} }

View file

@ -5,36 +5,36 @@ pub type Result<T> = std::result::Result<T, PageError>;
#[derive(Debug)] #[derive(Debug)]
pub enum PageError { pub enum PageError {
InvalidVersion, InvalidVersion,
BadSegmentCount, BadSegmentCount,
MissingMagic, MissingMagic,
Io(std::io::Error), Io(std::io::Error),
} }
impl fmt::Display for PageError { impl fmt::Display for PageError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
PageError::InvalidVersion => { PageError::InvalidVersion => {
write!(f, "Invalid stream structure version (Should always be 0)") write!(f, "Invalid stream structure version (Should always be 0)")
} },
PageError::BadSegmentCount => write!(f, "Page has a segment count < 1"), PageError::BadSegmentCount => write!(f, "Page has a segment count < 1"),
PageError::MissingMagic => write!(f, "Page is missing a magic signature"), PageError::MissingMagic => write!(f, "Page is missing a magic signature"),
PageError::Io(..) => write!(f, "Encountered an std::io::Error"), PageError::Io(..) => write!(f, "Encountered an std::io::Error"),
} }
} }
} }
impl Error for PageError { impl Error for PageError {
fn source(&self) -> Option<&(dyn Error + 'static)> { fn source(&self) -> Option<&(dyn Error + 'static)> {
match *self { match *self {
PageError::Io(ref e) => Some(e), PageError::Io(ref e) => Some(e),
_ => None, _ => None,
} }
} }
} }
impl From<std::io::Error> for PageError { impl From<std::io::Error> for PageError {
fn from(err: std::io::Error) -> PageError { fn from(err: std::io::Error) -> PageError {
PageError::Io(err) PageError::Io(err)
} }
} }

View file

@ -1,5 +1,5 @@
mod error;
mod crc; mod crc;
mod error;
use std::io::{Read, Seek, SeekFrom}; use std::io::{Read, Seek, SeekFrom};
@ -9,116 +9,120 @@ pub use error::{PageError, Result};
#[derive(Clone)] #[derive(Clone)]
pub struct Page { pub struct Page {
pub content: Vec<u8>, pub content: Vec<u8>,
pub header_type: u8, pub header_type: u8,
pub abgp: u64, pub abgp: u64,
pub serial: u32, pub serial: u32,
pub seq_num: u32, pub seq_num: u32,
pub checksum: u32, pub checksum: u32,
pub start: usize, pub start: usize,
pub end: usize, pub end: usize,
} }
impl Page { impl Page {
pub fn as_bytes(&self) -> Vec<u8> { pub fn as_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new(); let mut bytes = Vec::new();
let segments = self.segments(); let segments = self.segments();
let segment_count = [segments.len() as u8]; let segment_count = [segments.len() as u8];
bytes.extend(b"OggS".iter()); bytes.extend(b"OggS".iter());
bytes.extend([0_u8].iter()); bytes.extend([0_u8].iter());
bytes.extend(self.header_type.to_le_bytes().iter()); bytes.extend(self.header_type.to_le_bytes().iter());
bytes.extend(self.abgp.to_le_bytes().iter()); bytes.extend(self.abgp.to_le_bytes().iter());
bytes.extend(self.serial.to_le_bytes().iter()); bytes.extend(self.serial.to_le_bytes().iter());
bytes.extend(self.seq_num.to_le_bytes().iter()); bytes.extend(self.seq_num.to_le_bytes().iter());
bytes.extend(self.checksum.to_le_bytes().iter()); bytes.extend(self.checksum.to_le_bytes().iter());
bytes.extend(segment_count.iter()); bytes.extend(segment_count.iter());
bytes.extend(segments.iter()); bytes.extend(segments.iter());
bytes.extend(self.content.iter()); bytes.extend(self.content.iter());
bytes bytes
} }
pub fn segments(&self) -> Vec<u8> { pub fn segments(&self) -> Vec<u8> {
let len = self.content.len(); segments(&*self.content)
}
let mut last_len = (len % 255) as u8; pub fn read<V>(mut data: V) -> Result<Self>
if last_len == 0 { where
last_len = 255 V: Read + Seek,
} {
let start = data.seek(SeekFrom::Current(0))? as usize;
let mut needed = len / 255; let mut sig = [0; 4];
if needed != 255 { data.read_exact(&mut sig)?;
needed += 1
}
let mut segments = Vec::new(); if &sig != b"OggS" {
return Err(PageError::MissingMagic);
}
for i in 0..needed { // Version, always 0
if i + 1 < needed { let version = data.read_u8()?;
segments.push(255)
} else {
segments.push(last_len)
}
}
segments if version != 0 {
} return Err(PageError::InvalidVersion);
}
pub fn read<V>(mut data: V) -> Result<Self> let header_type = data.read_u8()?;
where
V: Read + Seek,
{
let start = data.seek(SeekFrom::Current(0))? as usize;
let mut sig = [0; 4]; let abgp = data.read_u64::<LittleEndian>()?;
data.read_exact(&mut sig)?; let serial = data.read_u32::<LittleEndian>()?;
let seq_num = data.read_u32::<LittleEndian>()?;
let checksum = data.read_u32::<LittleEndian>()?;
if &sig != b"OggS" { let segments = data.read_u8()?;
return Err(PageError::MissingMagic);
}
// Version, always 0 if segments < 1 {
let version = data.read_u8()?; return Err(PageError::BadSegmentCount);
}
if version != 0 { let mut segment_table = vec![0; segments as usize];
return Err(PageError::InvalidVersion); data.read_exact(&mut segment_table)?;
}
let header_type = data.read_u8()?; let mut content = vec![0; segment_table.iter().map(|&b| b as usize).sum()];
data.read_exact(&mut content)?;
let abgp = data.read_u64::<LittleEndian>()?; let end = data.seek(SeekFrom::Current(0))? as usize;
let serial = data.read_u32::<LittleEndian>()?;
let seq_num = data.read_u32::<LittleEndian>()?;
let checksum = data.read_u32::<LittleEndian>()?;
let segments = data.read_u8()?; Ok(Page {
content,
header_type,
abgp,
serial,
seq_num,
checksum,
start,
end,
})
}
if segments < 1 { pub fn gen_crc(&mut self) {
return Err(PageError::BadSegmentCount); self.checksum = crc::crc32(&*self.as_bytes());
} }
let mut segment_table = vec![0; segments as usize];
data.read_exact(&mut segment_table)?;
let mut content = vec![0; segment_table.iter().map(|&b| b as usize).sum()];
data.read_exact(&mut content)?;
let end = data.seek(SeekFrom::Current(0))? as usize;
Ok(Page {
content,
header_type,
abgp,
serial,
seq_num,
checksum,
start,
end,
})
}
pub fn gen_crc(&mut self) {
self.checksum = crc::crc32(&*self.as_bytes());
}
} }
pub fn segments(cont: &[u8]) -> Vec<u8> {
let len = cont.len();
let mut last_len = (len % 255) as u8;
if last_len == 0 {
last_len = 255
}
let mut needed = len / 255;
if needed != 255 {
needed += 1
}
let mut segments = Vec::new();
for i in 0..needed {
if i + 1 < needed {
segments.push(255)
} else {
segments.push(last_len)
}
}
segments
}