[go: up one dir, main page]

nom 0.3.9

A byte oriented, zero copy, parser combinators library
Documentation
#![crate_type = "lib"]
#![crate_id = "conveyor"]
#![desc = "A conveyor belt for bytes"]
#![license = "MIT"]
#![feature(macro_rules)]

use std::str;

type Err   = uint;
type Index = uint;

#[deriving(Clone)]
pub enum State<X> {
  Done(Box<Vec<X>>),
  MoreData(Index, uint),
  Error(Err)
}

pub enum Stream<X> {
  EOF,
  Chunk(Box<Vec<X>>),
  StreamError(Err)
}

pub trait Producer<T> {
  fn take(&mut self, idx: Index, nb: uint) -> Stream<T>;
}

pub trait Consumer<T, U> {
  fn start<V:Producer<T>>(&self, pr: &mut V) -> Option<U>;
}

pub struct Worker<'a, T, U> {
  state:    Box<State<U>>,
  producer: &'a mut Producer<T>,
  work:     fn(idx: Index, nb: uint, chunks: &[T]) -> Box<State<U>>
}

pub fn W<'a, T, U>(pr: &'a mut Producer<T>, w: fn(idx: Index, nb: uint, chunks: &[T]) -> Box<State<U>>) -> Box<Worker<'a, T, U>> {
  box Worker {
    state: box MoreData(0, 4),
    producer: pr,
    work: w
  }
}

impl<'a, T, U:Clone> Producer<U> for Worker<'a, T, U> {
  fn take(&mut self, idx: Index, nb: uint) -> Stream<U> {
    loop {
      let state = self.state.clone();
      match state {
        box Done(ref elements) => {
          println!("Done({})", elements.len());
          let length = elements.len()
          if elements.len() >= nb && {;
            // FIXME: if current index is idx
            let res = Chunk(box elements.slice(idx, idx + nb).to_vec());
            self.state = box Done(box elements.slice(idx + nb, elements.len()).to_vec());
            return res;
          } else {
            let v:&[T] = [];
            let work = self.work;
            self.state = work(nb, v);
          }
        }
        box MoreData(producerIndex, producerNb) => {
          println!("MoreData({}, {})", producerIndex, producerNb);
          match self.producer.take(producerIndex, producerNb) {
            EOF              => return EOF,
            StreamError(err) => return StreamError(err),
            Chunk(box elements)  => {
              let work = self.work;
              self.state = work(nb, elements.as_slice());
            }
          }
        }
        box Error(err) => {
          //FIXME: might want to handle Error
          println!("Error({})", err);
          return StreamError(err)
        }
      }
    }
  }
}

pub struct StringProducer {
  pub data: String,
  pub cursor: uint
}

impl Producer<u8> for StringProducer {
  fn take(&mut self, idx: Index, nb: uint) -> Stream<u8> {
    self.cursor = idx + nb;
    Chunk(box self.data.as_slice().slice(idx, idx + nb).as_bytes().to_vec())
  }
}


pub fn u8Worker(nb: uint, chunks: &[u8]) -> Box<State<u8>> {
  let data = box vec!(1u8, 2, 5, 4, 10);
  box Done(box data.as_slice().to_vec())
}

pub struct PrintConsumer {
  pub bytesWritten: uint
}

impl Consumer<u8, uint> for PrintConsumer {
  fn start<T:Producer<u8>>(&self, pr: &mut T) -> Option<uint> {
    match pr.take(0, 4) {
      Chunk(elems) => println!("slice: {}", elems),
      _           => println!("invalid data")
    }
    return Some(0)
  }
}