#![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 && {;
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) => {
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)
}
}