prettify code

This commit is contained in:
Wuelle
2021-12-30 21:59:29 +01:00
parent 5e563cddf8
commit 9a010ca0c4
17 changed files with 1312 additions and 1060 deletions

View File

@@ -1,15 +1,14 @@
use std::collections::HashMap;
use std::io;
use std::io::SeekFrom::{Current, Start};
use std::io::{Seek, Read};
use std::collections::HashMap;
use std::io::{Read, Seek};
use byteorder::LittleEndian;
use byteorder::ReadBytesExt;
use super::errors::Error;
use super::fourcc::{FourCC, ReadFourCC};
use super::fourcc::{RIFF_SIG, RF64_SIG, BW64_SIG, WAVE_SIG, DS64_SIG, DATA_SIG};
use super::fourcc::{BW64_SIG, DATA_SIG, DS64_SIG, RF64_SIG, RIFF_SIG, WAVE_SIG};
// just for your reference...
// RF64 documentation https://www.itu.int/dms_pubrec/itu-r/rec/bs/R-REC-BS.2088-1-201910-I!!PDF-E.pdf
@@ -21,12 +20,26 @@ const RF64_SIZE_MARKER: u32 = 0xFF_FF_FF_FF;
#[derive(Debug)]
pub enum Event {
StartParse,
ReadHeader { signature: FourCC, length_field: u32 },
ReadRF64Header { signature: FourCC },
ReadDS64 {file_size: u64, long_sizes: HashMap<FourCC,u64> },
BeginChunk { signature: FourCC, content_start: u64, content_length: u64 },
Failed { error: Error },
FinishParse
ReadHeader {
signature: FourCC,
length_field: u32,
},
ReadRF64Header {
signature: FourCC,
},
ReadDS64 {
file_size: u64,
long_sizes: HashMap<FourCC, u64>,
},
BeginChunk {
signature: FourCC,
content_start: u64,
content_length: u64,
},
Failed {
error: Error,
},
FinishParse,
}
#[derive(Debug)]
@@ -36,67 +49,80 @@ enum State {
ReadyForDS64,
ReadyForChunk { at: u64, remaining: u64 },
Error,
Complete
Complete,
}
pub struct Parser<R: Read + Seek> {
stream: R,
state: State,
ds64state: HashMap<FourCC,u64>
ds64state: HashMap<FourCC, u64>,
}
#[derive(Debug, PartialEq, Eq)]
pub struct ChunkIteratorItem {
pub signature: FourCC,
pub start: u64,
pub length: u64
pub length: u64,
}
impl<R: Read + Seek> Parser<R> {
// wraps a stream
pub fn make(stream: R) -> Result<Self, Error> {
let newmap: HashMap<FourCC, u64> = HashMap::new();
let mut the_stream = stream;
the_stream.seek(Start(0))?;
return Ok(Parser {
stream: the_stream,
stream: the_stream,
state: State::New,
ds64state: newmap,
})
});
}
// pub fn into_inner(self) -> R {
// self.stream
// }
pub fn into_chunk_iterator(self) -> impl Iterator<Item = Result<ChunkIteratorItem, Error>>{
self.filter_map({|event|
if let Event::BeginChunk {signature , content_start, content_length } = event {
Some(Ok(ChunkIteratorItem {signature, start: content_start, length: content_length }))
} else if let Event::Failed { error } = event {
Some(Err(error))
} else {
None
pub fn into_chunk_iterator(self) -> impl Iterator<Item = Result<ChunkIteratorItem, Error>> {
self.filter_map({
|event| {
if let Event::BeginChunk {
signature,
content_start,
content_length,
} = event
{
Some(Ok(ChunkIteratorItem {
signature,
start: content_start,
length: content_length,
}))
} else if let Event::Failed { error } = event {
Some(Err(error))
} else {
None
}
}
})
}
pub fn into_chunk_list(self) -> Result<Vec<ChunkIteratorItem>,Error> {
pub fn into_chunk_list(self) -> Result<Vec<ChunkIteratorItem>, Error> {
let mut error = Ok(());
let chunks = self.into_chunk_iterator()
let chunks = self
.into_chunk_iterator()
.scan(&mut error, |err, res| match res {
Ok(ok) => Some(ok),
Err(e) => { **err = Err(e); None }
Err(e) => {
**err = Err(e);
None
}
})
.collect();
error?;
Ok( chunks )
Ok(chunks)
}
}
impl<R: Read + Seek> Iterator for Parser<R> {
@@ -110,55 +136,53 @@ impl<R: Read + Seek> Iterator for Parser<R> {
}
impl<R: Read + Seek> Parser<R> {
fn parse_header(&mut self) -> Result<(Event,State),io::Error> {
fn parse_header(&mut self) -> Result<(Event, State), io::Error> {
let file_sig = self.stream.read_fourcc()?;
let length = self.stream.read_u32::<LittleEndian>()?;
let list_sig = self.stream.read_fourcc()?;
let event : Event;
let event: Event;
let next_state: State;
match (file_sig, length, list_sig) {
(RIFF_SIG, size, WAVE_SIG) => {
event = Event::ReadHeader {
signature: file_sig,
length_field: size
length_field: size,
};
next_state = State::ReadyForChunk {
at: 12,
remaining: (length - 4) as u64,
};
},
}
(RF64_SIG, RF64_SIZE_MARKER, WAVE_SIG) | (BW64_SIG, RF64_SIZE_MARKER, WAVE_SIG) => {
event = Event::ReadRF64Header {
signature: file_sig
signature: file_sig,
};
next_state = State::ReadyForDS64;
},
}
_ => {
event = Event::Failed {
error: Error::HeaderNotRecognized
error: Error::HeaderNotRecognized,
};
next_state = State::Error;
}
}
return Ok( (event, next_state) );
return Ok((event, next_state));
}
fn parse_ds64(&mut self) -> Result<(Event, State), Error> {
let at :u64 = 12;
let at: u64 = 12;
let ds64_sig = self.stream.read_fourcc()?;
let ds64_size = self.stream.read_u32::<LittleEndian>()? as u64;
let mut read :u64 = 0;
let mut read: u64 = 0;
if ds64_sig != DS64_SIG {
return Err(Error::MissingRequiredDS64);
} else {
let long_file_size = self.stream.read_u64::<LittleEndian>()?;
let long_data_size = self.stream.read_u64::<LittleEndian>()?;
@@ -176,10 +200,10 @@ impl<R: Read + Seek> Parser<R> {
}
self.ds64state.insert(DATA_SIG, long_data_size);
if read < ds64_size {
/* for some reason the ds64 chunk returned by Pro Tools is longer than
it should be but it's all zeroes so... skip.
it should be but it's all zeroes so... skip.
For the record libsndfile seems to do the same thing...
https://github.com/libsndfile/libsndfile/blob/08d802a3d18fa19c74f38ed910d9e33f80248187/src/rf64.c#L230
@@ -189,7 +213,7 @@ impl<R: Read + Seek> Parser<R> {
let event = Event::ReadDS64 {
file_size: long_file_size,
long_sizes : self.ds64state.clone(),
long_sizes: self.ds64state.clone(),
};
let state = State::ReadyForChunk {
@@ -197,19 +221,17 @@ impl<R: Read + Seek> Parser<R> {
remaining: long_file_size - (4 + 8 + ds64_size),
};
return Ok( (event, state) );
return Ok((event, state));
}
}
fn enter_chunk(&mut self, at :u64, remaining: u64) -> Result<(Event, State), io::Error> {
fn enter_chunk(&mut self, at: u64, remaining: u64) -> Result<(Event, State), io::Error> {
let event;
let state;
if remaining == 0 {
event = Event::FinishParse;
state = State::Complete;
} else {
let this_fourcc = self.stream.read_fourcc()?;
let this_size: u64;
@@ -221,59 +243,67 @@ impl<R: Read + Seek> Parser<R> {
this_size = self.stream.read_u32::<LittleEndian>()? as u64;
}
let this_displacement :u64 = if this_size % 2 == 1 { this_size + 1 } else { this_size };
let this_displacement: u64 = if this_size % 2 == 1 {
this_size + 1
} else {
this_size
};
self.stream.seek(Current(this_displacement as i64))?;
event = Event::BeginChunk {
signature: this_fourcc,
content_start: at + 8,
content_length: this_size
content_length: this_size,
};
state = State::ReadyForChunk {
at: at + 8 + this_displacement,
remaining: remaining - 8 - this_displacement
remaining: remaining - 8 - this_displacement,
}
}
return Ok( (event, state) );
return Ok((event, state));
}
fn handle_state(&mut self) -> Result<(Option<Event>, State), Error> {
match self.state {
State::New => {
return Ok( ( Some(Event::StartParse) , State::ReadyForHeader) );
},
return Ok((Some(Event::StartParse), State::ReadyForHeader));
}
State::ReadyForHeader => {
let (event, state) = self.parse_header()?;
return Ok( ( Some(event), state ) );
},
return Ok((Some(event), state));
}
State::ReadyForDS64 => {
let (event, state) = self.parse_ds64()?;
return Ok( ( Some(event), state ) );
},
return Ok((Some(event), state));
}
State::ReadyForChunk { at, remaining } => {
let (event, state) = self.enter_chunk(at, remaining)?;
return Ok( ( Some(event), state ) );
},
return Ok((Some(event), state));
}
State::Error => {
return Ok( ( Some(Event::FinishParse) , State::Complete ) );
},
return Ok((Some(Event::FinishParse), State::Complete));
}
State::Complete => {
return Ok( ( None, State::Complete ) );
return Ok((None, State::Complete));
}
}
}
fn advance(&mut self) -> (Option<Event>, State) {
match self.handle_state() {
Ok(( event , state) ) => {
Ok((event, state)) => {
return (event, state);
},
}
Err(error) => {
return (Some(Event::Failed { error: error.into() } ), State::Error );
return (
Some(Event::Failed {
error: error.into(),
}),
State::Error,
);
}
}
}
}