diff --git a/src/ebml.rs b/src/ebml.rs index 5a9293b..f0797e7 100644 --- a/src/ebml.rs +++ b/src/ebml.rs @@ -219,9 +219,45 @@ pub struct Ebml { } pub trait FromEbml<'a>: Sized { + /// Indicates if this tag's contents should be treated as a blob, + /// or if the tag header should be reported as an event and with further + /// parsing descending into its content. + /// + /// Unknown-size tags can *only* be parsed if unwrapped, and will error otherwise. fn should_unwrap(element_id: u64) -> bool; + + /// Given an element's ID and its binary payload, if any, construct a suitable + /// instance of this type to represent the event. The instance may contain + /// references into the given buffer. fn decode(element_id: u64, bytes: &'a[u8]) -> Result; + /// Check if enough space exists in the given buffer for decode_element() to + /// be successful; parsing errors will be returned eagerly. + fn check_space(bytes: &[u8]) -> Result, Error> { + match decode_tag(bytes) { + Ok(None) => Ok(None), + Err(err) => Err(err), + Ok(Some((element_id, payload_size_tag, tag_size))) => { + let should_unwrap = Self::should_unwrap(element_id); + + let payload_size = match (should_unwrap, payload_size_tag) { + (true, _) => 0, + (false, Varint::Unknown) => return Err(Error::UnknownElementLength), + (false, Varint::Value(size)) => size as usize + }; + + let element_size = tag_size + payload_size; + if element_size > bytes.len() { + // need to read more still + Ok(None) + } else { + Ok(Some(element_size)) + } + } + } + } + + /// Attempt to construct an instance of this type from the given byte slice fn decode_element(bytes: &'a[u8]) -> Result, Error> { match decode_tag(bytes) { Ok(None) => Ok(None), diff --git a/src/webm_stream.rs b/src/webm_stream.rs index d2a77b9..55d8e6e 100644 --- a/src/webm_stream.rs +++ b/src/webm_stream.rs @@ -26,40 +26,34 @@ impl, S: Stream> WebmBuffer { } } - pub fn try_decode(&mut self) -> Result>, ParsingError> { - match WebmElement::decode_element(&self.buffer) { - Err(err) => { - //println!("EBML error: {:?}", err); - return Err(ParsingError::EbmlError(err)) - }, - Ok(None) => { - //println!("Need refill"); - // need to refill buffer - return Ok(Async::NotReady); - }, - Ok(Some((element, element_size))) => { - //println!("Parsed element: {:?}", element); - self.last_read = element_size; - return Ok(Async::Ready(Some(element))) - } - }; - } - - pub fn can_decode(&mut self) -> bool { - match self.try_decode() { - Ok(Async::NotReady) => false, - _ => true - } - } - pub fn poll_event<'a>(&'a mut self) -> Result>>, ParsingError> { // release buffer from previous event self.buffer.advance(self.last_read); self.last_read = 0; loop { - if self.can_decode() { - return self.try_decode() + match WebmElement::check_space(&self.buffer) { + Err(err) => { + return Err(ParsingError::EbmlError(err)) + }, + Ok(None) => { + // need to refill buffer, below + }, + Ok(Some(_)) => { + return match WebmElement::decode_element(&self.buffer) { + Err(err) => { + Err(ParsingError::EbmlError(err)) + }, + Ok(None) => { + // buffer should have the data already + panic!("Buffer was supposed to have enough data to parse element, somehow did not.") + }, + Ok(Some((element, element_size))) => { + self.last_read = element_size; + return Ok(Async::Ready(Some(element))) + } + } + } } match self.stream.poll() {