Skip to content

Instantly share code, notes, and snippets.

@utkarshkukreti
Created June 1, 2017 21:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save utkarshkukreti/54b07a5cdd46c58d40c537194f18efea to your computer and use it in GitHub Desktop.
Save utkarshkukreti/54b07a5cdd46c58d40c537194f18efea to your computer and use it in GitHub Desktop.
#[macro_use]
extern crate munch;
use munch::{P, Parser};
use munch::byte::*;
#[derive(Debug, PartialEq)]
pub enum Term<'a> {
SmallInteger(u8),
Integer(i32),
List(Vec<Term<'a>>),
ImproperList(Vec<Term<'a>>),
Binary(&'a [u8]),
}
pub type Result<T> = munch::Result<T, munch::byte::Error<'static>>;
pub fn parse(bytes: &[u8]) -> Result<Term> {
(P(131) >> term).parse(bytes, 0)
}
pub fn term(bytes: &[u8], from: usize) -> Result<Term> {
use self::Term::*;
muncher! (
tag <- Any,
t <- @match (tag) {
97 => Any.map(SmallInteger),
98 => BigEndian::i32.map(Integer),
106 => |_, from| Ok((from, List(Vec::new()))),
107 => BigEndian::u16.bind(|u16| Any.map(SmallInteger).repeat(u16 as usize).map(List)),
108 => muncher! {
len <- BigEndian::u32,
elements <- term.repeat(len as usize),
tail <- term,
({
Ok(if tail == List(Vec::new()) {
List(elements)
} else {
let mut elements = elements;
elements.push(tail);
ImproperList(elements)
})
})
},
109 => BigEndian::u32.bind(|u32| Take(u32 as usize).map(Binary)),
tag => |_, _| panic!("unimplemented: {:?}", tag),
},
(Ok(t))
)
.parse(bytes, from)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment