Cleanup poll_event's try_decode hack.
This commit is contained in:
parent
bebe593c30
commit
c92273625e
2 changed files with 58 additions and 28 deletions
36
src/ebml.rs
36
src/ebml.rs
|
@ -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),
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in a new issue