nom 4.0.0-alpha2

A byte-oriented, zero-copy, parser combinators library
Documentation
/*
#[macro_use]
extern crate nom;
extern crate bytes;

use nom::{Compare,CompareResult,InputLength,InputIter,Slice,HexDisplay};

use std::str;
use std::str::FromStr;
use bytes::{Buf,MutBuf};
use bytes::buf::{BlockBuf,BlockBufCursor};
use std::ops::{Range,RangeTo,RangeFrom,RangeFull};
use std::iter::{Enumerate,Iterator};
use std::fmt;
use std::cmp::{min,PartialEq};

#[derive(Clone,Copy)]
#[repr(C)]
pub struct BlockSlice<'a> {
  buf: &'a BlockBuf,
  start: usize,
  end:   usize,
}

impl<'a> BlockSlice<'a> {
  fn cursor(&self) -> WrapCursor<'a> {
    let mut cur = self.buf.buf();
    cur.advance(self.start);
    WrapCursor {
      cursor: cur,
      length: self.end - self.start,
    }
  }
}

impl<'a> fmt::Debug for BlockSlice<'a> {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "BlockSlice {{ start: {}, end: {}, data:\n{}\n}}", self.start, self.end, self.buf.bytes().unwrap_or(&b""[..]).to_hex(16))
  }
}

impl<'a> PartialEq for BlockSlice<'a> {
  fn eq(&self, other: &BlockSlice<'a>) -> bool {
    let bufs = (self.buf as *const BlockBuf) == (other.buf as *const BlockBuf);
    self.start == other.start && self.end == other.end && bufs
  }
}

impl<'a> Slice<Range<usize>> for BlockSlice<'a> {
  fn slice(&self, range:Range<usize>) -> Self {
    BlockSlice {
      buf:   self.buf,
      start: self.start + range.start,
      //FIXME: check for valid end here
      end:   self.start + range.end,
    }
  }
}

impl<'a> Slice<RangeTo<usize>> for BlockSlice<'a> {
  fn slice(&self, range:RangeTo<usize>) -> Self {
    self.slice(0..range.end)
  }
}

impl<'a> Slice<RangeFrom<usize>> for BlockSlice<'a> {
  fn slice(&self, range:RangeFrom<usize>) -> Self {
    self.slice(range.start..self.end - self.start)
  }
}

impl<'a> Slice<RangeFull> for BlockSlice<'a> {
  fn slice(&self, _:RangeFull) -> Self {
    BlockSlice {
      buf:   self.buf,
      start: self.start,
      end:   self.end,
    }
  }
}


impl<'a> InputIter for BlockSlice<'a> {
    type Item     = u8;
    type RawItem  = u8;
    type Iter     = Enumerate<WrapCursor<'a>>;
    type IterElem = WrapCursor<'a>;

    fn iter_indices(&self)  -> Self::Iter {
      self.cursor().enumerate()
    }
    fn iter_elements(&self) -> Self::IterElem {
      self.cursor()
    }
    fn position<P>(&self, predicate: P) -> Option<usize> where P: Fn(Self::RawItem) -> bool {
      self.cursor().position(|b| predicate(b))
    }
    fn slice_index(&self, count:usize) -> Option<usize> {
      if self.end - self.start >= count {
        Some(count)
      } else {
        None
      }
    }
}


impl<'a> InputLength for BlockSlice<'a> {
  fn input_len(&self) -> usize {
    self.end - self.start
  }
}

impl<'a,'b> Compare<&'b[u8]> for BlockSlice<'a> {
  fn compare(&self, t: &'b[u8]) -> CompareResult {
    let len     = self.end - self.start;
    let blen    = t.len();
    let m       = if len < blen { len } else { blen };
    let reduced = self.slice(..m);
    let b       = &t[..m];

    for (a,b) in reduced.cursor().zip(b.iter()) {
      if a != *b {
        return CompareResult::Error;
      }
    }
    if m < blen {
      CompareResult::Incomplete
    } else {
      CompareResult::Ok
    }
  }


  #[inline(always)]
  fn compare_no_case(&self, t: &'b[u8]) -> CompareResult {
    let len     = self.end - self.start;
    let blen    = t.len();
    let m       = if len < blen { len } else { blen };
    let reduced = self.slice(..m);
    let other   = &t[..m];

    if !reduced.cursor().zip(other).all(|(a, b)| {
      match (a,*b) {
        (0...64, 0...64) | (91...96, 91...96) | (123...255, 123...255) => a == *b,
        (65...90, 65...90) | (97...122, 97...122) | (65...90, 97...122 ) |(97...122, 65...90) => {
          a & 0b01000000 == *b & 0b01000000
        }
        _ => false
      }
    }) {
      CompareResult::Error
    } else if m < blen {
      CompareResult::Incomplete
    } else {
      CompareResult::Ok
    }
  }
}

impl<'a,'b> Compare<&'b str> for BlockSlice<'a> {
  fn compare(&self, t: &'b str) -> CompareResult {
    self.compare(str::as_bytes(t))
  }
  fn compare_no_case(&self, t: &'b str) -> CompareResult {
    self.compare_no_case(str::as_bytes(t))
  }
}

//Wrapper to implement Iterator on BlockBufCursor
pub struct WrapCursor<'a> {
  pub cursor: BlockBufCursor<'a>,
  pub length: usize,
}

impl<'a> Iterator for WrapCursor<'a> {
  type Item = u8;
  fn next(&mut self) -> Option<u8> {
    //println!("NEXT: length={}, remaining={}", self.length, self.cursor.remaining());
    if min(self.length, self.cursor.remaining()) > 0 {
      self.length -=1;
      Some(self.cursor.read_u8())
    } else {
      None
    }
  }
}

//Reimplement eat_separator instead of fixing iterators
#[macro_export]
macro_rules! block_eat_separator (
  ($i:expr, $arr:expr) => (
    {
      use nom::{InputLength,InputIter,Slice};
      if ($i).input_len() == 0 {
        Ok(($i, ($i).slice(0..0)))
      } else {
        match ($i).iter_indices().position(|(_, item)| {
          for (_,c) in ($arr).iter_indices() {
            if *c == item { return false; }
          }
          true
        }) {
          Some(index) => {
            Ok((($i).slice(index..), ($i).slice(..index)))
          },
          None => {
            Ok((($i).slice(($i).input_len()..), $i))
          }
        }
      }
    }
  )
);

#[macro_export]
macro_rules! block_named (
  ($name:ident, $submac:ident!( $($args:tt)* )) => (
    fn $name<'a>( i: BlockSlice<'a> ) -> nom::IResult<BlockSlice<'a>, BlockSlice<'a>, u32> {
      $submac!(i, $($args)*)
    }
  );
  ($name:ident<$o:ty>, $submac:ident!( $($args:tt)* )) => (
    fn $name<'a>( i: BlockSlice<'a> ) -> nom::IResult<BlockSlice<'a>, $o, u32> {
      $submac!(i, $($args)*)
    }
  );
);

block_named!(sp, block_eat_separator!(&b" \t\r\n"[..]));

macro_rules! block_ws (
  ($i:expr, $($args:tt)*) => (
    {
      sep!($i, sp, $($args)*)
    }
  )
);

block_named!(digit, is_a!("0123456789"));

block_named!(parens<i64>, block_ws!(delimited!( tag!("("), expr, tag!(")") )) );


block_named!(factor<i64>, alt!(
      map_res!(
        block_ws!(digit),
        to_i64
    )
  | parens
  )
);

block_named!(term <i64>, do_parse!(
    init: factor >>
    res:  fold_many0!(
        pair!(alt!(tag!("*") | tag!("/")), factor),
        init,
        |acc, (op, val): (BlockSlice, i64)| {
            if (op.cursor().next().unwrap() as char) == '*' { acc * val } else { acc / val }
        }
    ) >>
    (res)
  )
);

block_named!(expr <i64>, do_parse!(
    init: term >>
    res:  fold_many0!(
        pair!(alt!(tag!("+") | tag!("-")), term),
        init,
        |acc, (op, val): (BlockSlice, i64)| {
            if (op.cursor().next().unwrap() as char) == '+' { acc + val } else { acc - val }
        }
    ) >>
    (res)
  )
);


fn blockbuf_from(input: &[u8]) -> BlockBuf {
  let mut b = BlockBuf::new(2, 100);
  b.copy_from(input);
  b
}


fn sl<'a>(input: &'a BlockBuf) -> BlockSlice<'a> {
  BlockSlice {
    buf: input,
    start: 0,
    end:   input.len(),
  }
}

fn to_i64<'a>(input: BlockSlice<'a>) -> Result<i64, ()> {
  let v: Vec<u8> = input.cursor().collect();

  match str::from_utf8(&v) {
    Err(_) => Err(()),
    Ok(s) => match FromStr::from_str(s) {
      Err(_) => Err(()),
      Ok(i)  => Ok(i)
    }
  }
}

#[test]
fn factor_test() {
  let a = blockbuf_from(&b"3"[..]);
  println!("calculated: {:?}", factor(sl(&a)));
}

#[test]
fn parens_test() {
  let input1 = blockbuf_from(&b" 2* (  3 + 4 ) "[..]);
  println!("calculated 1: {:?}", expr(sl(&input1)));
  let input2 = blockbuf_from(&b"  2*2 / ( 5 - 1) + 3"[..]);
  println!("calculated 2: {:?}", expr(sl(&input2)));
}
*/