extern crate ascii;
use std::marker::PhantomData;
use self::ascii::AsciiChar;
use combinator::{satisfy, skip_many, token, tokens, Expected, Satisfy, SkipMany, Token, With};
use primitives::{ConsumedResult, Info, Parser, Stream, StreamError, Tracked};
#[inline(always)]
pub fn byte<I>(c: u8) -> Token<I>
where
I: Stream<Item = u8>,
{
token(c)
}
impl_token_parser! { Digit(), u8, Expected<Satisfy<I, fn (u8) -> bool>> }
macro_rules! byte_parser {
($name: ident, $ty : ident, $f : ident) => ({
let f = static_fn!((c, u8) -> bool {
AsciiChar::from(c).map(|c| c.$f()).unwrap_or(false)
});
$ty(satisfy(f).expected(stringify!($name)), PhantomData)
})
}
#[inline(always)]
pub fn digit<I>() -> Digit<I>
where
I: Stream<Item = u8>,
{
byte_parser!(digit, Digit, is_digit)
}
impl_token_parser! { Space(), u8, Expected<Satisfy<I, fn (u8) -> bool>> }
#[inline(always)]
pub fn space<I>() -> Space<I>
where
I: Stream<Item = u8>,
{
byte_parser!(space, Space, is_whitespace)
}
impl_token_parser! { Spaces(), u8, Expected<SkipMany<Space<I>>> }
#[inline(always)]
pub fn spaces<I>() -> Spaces<I>
where
I: Stream<Item = u8>,
{
Spaces(skip_many(space()).expected("whitespaces"), PhantomData)
}
impl_token_parser! { Newline(), u8, Expected<Satisfy<I, fn (u8) -> bool>> }
#[inline(always)]
pub fn newline<I>() -> Newline<I>
where
I: Stream<Item = u8>,
{
Newline(
satisfy(static_fn!((ch, u8) -> bool { ch == b'\n' })).expected("lf newline"),
PhantomData,
)
}
impl_token_parser! { CrLf(), u8, Expected<With<Satisfy<I, fn (u8) -> bool>, Newline<I>>> }
#[inline(always)]
pub fn crlf<I>() -> CrLf<I>
where
I: Stream<Item = u8>,
{
CrLf(
satisfy(static_fn!((ch, u8) -> bool { ch == b'\r' }))
.with(newline())
.expected("crlf newline"),
PhantomData,
)
}
impl_token_parser! { Tab(), u8, Expected<Satisfy<I, fn (u8) -> bool>> }
#[inline(always)]
pub fn tab<I>() -> Tab<I>
where
I: Stream<Item = u8>,
{
Tab(
satisfy(static_fn!((ch, u8) -> bool { ch == b'\t' })).expected("tab"),
PhantomData,
)
}
impl_token_parser! { Upper(), u8, Expected<Satisfy<I, fn (u8) -> bool>> }
#[inline(always)]
pub fn upper<I>() -> Upper<I>
where
I: Stream<Item = u8>,
{
byte_parser!(upper, Upper, is_uppercase)
}
impl_token_parser! { Lower(), u8, Expected<Satisfy<I, fn (u8) -> bool>> }
#[inline(always)]
pub fn lower<I>() -> Lower<I>
where
I: Stream<Item = u8>,
{
byte_parser!(lower, Lower, is_lowercase)
}
impl_token_parser! { AlphaNum(), u8, Expected<Satisfy<I, fn (u8) -> bool>> }
#[inline(always)]
pub fn alpha_num<I>() -> AlphaNum<I>
where
I: Stream<Item = u8>,
{
byte_parser!(alpha_num, AlphaNum, is_alphanumeric)
}
impl_token_parser! { Letter(), u8, Expected<Satisfy<I, fn (u8) -> bool>> }
#[inline(always)]
pub fn letter<I>() -> Letter<I>
where
I: Stream<Item = u8>,
{
byte_parser!(letter, Letter, is_alphabetic)
}
impl_token_parser! { OctDigit(), u8, Expected<Satisfy<I, fn (u8) -> bool>> }
#[inline(always)]
pub fn oct_digit<I>() -> OctDigit<I>
where
I: Stream<Item = u8>,
{
OctDigit(
satisfy(static_fn!((ch, u8) -> bool { ch >= b'0' && ch <= b'7' })).expected("octal digit"),
PhantomData,
)
}
impl_token_parser! { HexDigit(), u8, Expected<Satisfy<I, fn (u8) -> bool>> }
#[inline(always)]
pub fn hex_digit<I>() -> HexDigit<I>
where
I: Stream<Item = u8>,
{
byte_parser!(hex_digit, HexDigit, is_hex)
}
#[derive(Clone)]
pub struct Bytes<I>(&'static [u8], PhantomData<I>)
where
I: Stream<Item = u8>;
impl<'a, I> Parser for Bytes<I>
where
I: Stream<Item = u8, Range = &'a [u8]>,
{
type Input = I;
type Output = &'static [u8];
#[inline]
fn parse_lazy(&mut self, input: Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
tokens(|&l, r| l == r, Info::Range(self.0), self.0.iter())
.parse_lazy(input)
.map(|bytes| bytes.as_slice())
}
fn add_error(&mut self, errors: &mut Tracked<StreamError<Self::Input>>) {
tokens::<_, _, I>(|&l, r| l == r, Info::Range(self.0), self.0.iter()).add_error(errors)
}
}
#[inline(always)]
pub fn bytes<'a, I>(s: &'static [u8]) -> Bytes<I>
where
I: Stream<Item = u8, Range = &'a [u8]>,
{
Bytes(s, PhantomData)
}
#[derive(Clone)]
pub struct BytesCmp<C, I>(&'static [u8], C, PhantomData<I>)
where
I: Stream<Item = u8>;
impl<'a, C, I> Parser for BytesCmp<C, I>
where
C: FnMut(u8, u8) -> bool,
I: Stream<Item = u8, Range = &'a [u8]>,
{
type Input = I;
type Output = &'static [u8];
#[inline]
fn parse_lazy(&mut self, input: Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
let cmp = &mut self.1;
tokens(|&l, r| cmp(l, r), Info::Range(self.0), self.0).parse_lazy(input)
}
fn add_error(&mut self, errors: &mut Tracked<StreamError<Self::Input>>) {
let cmp = &mut self.1;
tokens::<_, _, I>(|&l, r| cmp(l, r), Info::Range(self.0), self.0.iter()).add_error(errors)
}
}
#[inline(always)]
pub fn bytes_cmp<'a, C, I>(s: &'static [u8], cmp: C) -> BytesCmp<C, I>
where
C: FnMut(u8, u8) -> bool,
I: Stream<Item = u8, Range = &'a [u8]>,
{
BytesCmp(s, cmp, PhantomData)
}
pub mod num {
use super::*;
use primitives::RangeStream;
use range::take;
use byteorder::{ByteOrder, BE, LE};
macro_rules! integer_parser {
(
$(#[$attr:meta])*
pub $type_name: ident,
$func_name: ident, $be_name: ident, $le_name: ident, $read_name: ident
) => {
#[derive(Clone)]
pub struct $type_name<B, I>(PhantomData<(B, I)>);
impl<'a, B, I> Parser for $type_name<B, I>
where
I: RangeStream<Range = &'a [u8]>,
B: ByteOrder,
{
type Input = I;
type Output = $func_name;
#[inline]
fn parse_lazy(&mut self, input: Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
take(::std::mem::size_of::<Self::Output>()).map(B::$read_name).parse_lazy(input)
}
fn add_error(&mut self, errors: &mut Tracked<StreamError<Self::Input>>) {
take::<I>(::std::mem::size_of::<Self::Output>()).add_error(errors)
}
}
$(#[$attr])*
#[inline(always)]
pub fn $func_name<'a, B, I>() -> $type_name<B, I>
where
I: RangeStream<Range = &'a[u8]>,
B: ByteOrder,
{
$type_name(PhantomData)
}
$(#[$attr])*
#[inline(always)]
pub fn $be_name<'a, I>() -> $type_name<BE, I>
where
I: RangeStream<Range = &'a[u8]>,
{
$func_name()
}
$(#[$attr])*
#[inline(always)]
pub fn $le_name<'a, I>() -> $type_name<LE, I>
where
I: RangeStream<Range = &'a[u8]>,
{
$func_name()
}
}
}
integer_parser!(
pub U16, u16, be_u16, le_u16, read_u16
);
integer_parser!(
pub U32, u32, be_u32, le_u32, read_u32
);
integer_parser!(
pub U64, u64, be_u64, le_u64, read_u64
);
integer_parser!(
pub I16, i16, be_i16, le_i16, read_i16
);
integer_parser!(
pub I32, i32, be_i32, le_i32, read_i32
);
integer_parser!(
pub I64, i64, be_i64, le_i64, read_i64
);
integer_parser!(
pub F32, f32, be_f32, le_f32, read_f32
);
integer_parser!(
pub F64, f64, be_f64, le_f64, read_f64
);
}