#[cfg(not(feature = "std"))]
use collections::Vec;
use errors::*;
use varint;
pub const DEFAULT_MAX_LENGTH: usize = 1024;
pub const DEFAULT_MAX_DEPTH: usize = 8;
pub struct Parser<'m, H: Handler> {
max_length: usize,
max_depth: usize,
remaining: Vec<&'m [u8]>,
handler: H,
}
impl<'m, H: Handler> Parser<'m, H> {
pub fn new(handler: H) -> Parser<'m, H> {
Parser {
max_length: DEFAULT_MAX_LENGTH,
max_depth: DEFAULT_MAX_DEPTH,
remaining: Vec::new(),
handler: handler,
}
}
pub fn parse(&mut self, message: &'m [u8]) -> Result<()> {
if message.len() > self.max_length {
return Err(ErrorKind::OversizedMessage(message.len(), self.max_length).into());
}
if self.remaining.len() >= self.max_depth {
return Err(ErrorKind::MaxDepthExceeded(self.max_depth).into());
}
self.remaining.push(message);
while !self.remaining.last().expect("remaining").is_empty() {
let (id, wiretype) = self.parse_field_prefix()?;
match wiretype {
0 => self.parse_u64(id)?,
2 => self.parse_message(id)?,
3 => self.parse_binary(id)?,
_ => return Err(ErrorKind::UnknownWiretype(wiretype).into()),
}
}
self.remaining.pop().expect("empty remaining stack");
Ok(())
}
pub fn finish(self) -> Result<H::T> {
if self.remaining.is_empty() {
Ok(self.handler.finish())
} else {
Err(ErrorKind::UnconsumedMessages(self.remaining.len()).into())
}
}
pub fn parse_varint(&mut self) -> Result<(u64, &'m [u8])> {
let slice = self.remaining.pop().expect("remaining slice");
let mut slice_ref = &slice[..];
let value = varint::decode(&mut slice_ref)?;
Ok((value, slice_ref))
}
pub fn parse_field_prefix(&mut self) -> Result<(u64, u64)> {
let (value, remaining) = self.parse_varint()?;
self.remaining.push(remaining);
let field_id = value >> 3;
let wiretype = value & 0x7;
Ok((field_id, wiretype))
}
pub fn parse_u64(&mut self, id: u64) -> Result<()> {
let (value, remaining) = self.parse_varint()?;
self.remaining.push(remaining);
self.handler.uint64(id, value);
Ok(())
}
pub fn parse_length_prefixed_data(&mut self) -> Result<&'m [u8]> {
let (length_u64, remaining) = self.parse_varint()?;
let length = length_u64 as usize;
if remaining.len() < length {
let message = format!("want {} bytes, have {}", length, remaining.len());
return Err(ErrorKind::TruncatedMessage(message).into());
}
let result = &remaining[..length];
self.remaining.push(&remaining[length..]);
Ok(result)
}
pub fn parse_message(&mut self, id: u64) -> Result<()> {
self.handler.begin_nested();
let nested_message = self.parse_length_prefixed_data()?;
self.parse(nested_message)?;
self.handler.end_nested(id);
Ok(())
}
pub fn parse_binary(&mut self, id: u64) -> Result<()> {
let data = self.parse_length_prefixed_data()?;
self.handler.binary(id, data);
Ok(())
}
}
pub trait Handler {
type T;
fn uint64(&mut self, id: u64, value: u64);
fn binary(&mut self, id: u64, data: &[u8]);
fn begin_nested(&mut self);
fn end_nested(&mut self, id: u64);
fn finish(self) -> Self::T;
}