mirror of
https://github.com/Serial-ATA/lofty-rs
synced 2024-11-10 06:34:18 +00:00
Separate segments function in ogg_pager
Signed-off-by: Serial <69764315+Serial-ATA@users.noreply.github.com>
This commit is contained in:
parent
181b4cfef0
commit
822a312b0d
3 changed files with 126 additions and 122 deletions
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
Loading…
Reference in a new issue