Cleanup poll_event's try_decode hack.

This commit is contained in:
Tangent 128 2018-04-03 21:19:46 -04:00
parent bebe593c30
commit c92273625e
2 changed files with 58 additions and 28 deletions

View File

@ -219,9 +219,45 @@ pub struct Ebml<Source> {
}
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<Self, Error>;
/// 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<Option<usize>, 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<Option<(Self, usize)>, Error> {
match decode_tag(bytes) {
Ok(None) => Ok(None),

View File

@ -26,40 +26,34 @@ impl<I: AsRef<[u8]>, S: Stream<Item = I>> WebmBuffer<S> {
}
}
pub fn try_decode(&mut self) -> Result<Async<Option<WebmElement>>, ParsingError<S::Error>> {
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<Async<Option<WebmElement<'a>>>, ParsingError<S::Error>> {
// 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() {