<commit_before>//! Data producers
//!
//! The goal of data producers is to parse data as soon as it is generated.
//!
//! # Example
//!
//! ```
//! # #[macro_use] extern crate nom;
//! # use std::fmt::Debug;
//! # use nom::IResult;
//! # use nom::IResult::*;
//! # use nom::{Producer,ProducerState,FileProducer};
//! # fn main() {
//!  use std::str;
//!  fn local_print<'a, T: Debug>(input: T) -> IResult<'a, T, ()> {
//!    println!("{:?}", input);
//!    Done(input, ())
//!  }
//!
//!  // create a data producer from a file
//!  FileProducer::new("links.txt", 20).map(|producer: FileProducer| {
//!    let mut p = producer;
//!
//!    // adapt the parsing function to the producer
//!    pusher!(push, local_print);
//!    // get started
//!    push(&mut p);
//!  });
//! # }
//! ```

use self::ProducerState::*;

use std::fs::File;
use std::path::Path;
use std::io;
use std::io::{Read,Seek,SeekFrom};
use std::iter::repeat;

/// Holds the data producer's current state
///
/// * Eof indicates all data has been parsed, and contains the parser's result
///
/// * Continue indicates that more data is needed and should be available,
/// but not right now. Parsing should resume at some point.
///
/// * Data contains already parsed data
///
/// * ProducerError indicates something went wrong
#[derive(Debug,PartialEq,Eq)]
pub enum ProducerState<O> {
  Eof(O),
  Continue,
  Data(O),
  ProducerError(u32),
}

/// A producer implements the produce method, currently working with u8 arrays
pub trait Producer {
  fn produce(&mut self)                   -> ProducerState<&[u8]>;
  fn seek(&mut self,   position:SeekFrom) -> Option<u64>;
}

/// Can produce data from a file
///
/// the size field is the size of v, the internal buffer
pub struct FileProducer {
  size: usize,
  file: File,
  v:    Vec<u8>
}

impl FileProducer {
  pub fn new(filename: &str, buffer_size: usize) -> io::Result<FileProducer> {
    File::open(&Path::new(filename)).map(|f| {
      FileProducer {size: buffer_size, file: f, v: Vec::with_capacity(buffer_size)}
    })
  }
}

impl Producer for FileProducer {
  fn produce(&mut self) -> ProducerState<&[u8]> {
    let len = self.v.len();
    //let mut v = Vec::with_capacity(self.size);
    //self.v.clear();
    self.v.extend(repeat(0).take(self.size - len));
    match self.file.read(&mut self.v) {
      Err(e) => {
        //println!("producer error: {:?}", e);
        match e.kind() {
          //ErrorKind::NoProgress => Continue,
          //ErrorKind::EndOfFile  => Eof(&self.v[..]),
          _          => ProducerError(0)
        }
      },
      Ok(n)  => {
        //println!("read: {} bytes\ndata:\n{}", n, (&self.v).to_hex(8));
        self.v.truncate(n);
        if n == 0 {
          Eof(&self.v[..])
        } else {
          Data(&self.v[..])
        }
      }
    }
  }

  fn seek(&mut self, position: SeekFrom) -> Option<u64> {
    self.file.seek(position).ok()
  }
}

/// Can parse data from an already in memory byte array
///
/// * buffer holds the reference to the data that must be parsed
///
/// * length is the length of that buffer
///
/// * index is the position in the buffer
///
/// * chunk_size is the quantity of data sent at once
pub struct MemProducer<'x> {
  buffer: &'x [u8],
  chunk_size: usize,
  length: usize,
  index: usize
}

impl<'x> MemProducer<'x> {
  pub fn new(buffer: &'x[u8], chunk_size: usize) -> MemProducer {
    MemProducer {
      buffer:     buffer,
      chunk_size: chunk_size,
      length:     buffer.len(),
      index:      0
    }
  }
}

impl<'x> Producer for MemProducer<'x> {
  fn produce(&mut self) -> ProducerState<&[u8]> {
    if self.index + self.chunk_size < self.length {
      //println!("self.index({}) + {} < self.length({})", self.index, self.chunk_size, self.length);
      let new_index = self.index+self.chunk_size;
      let res = Data(&self.buffer[self.index..new_index]);
      self.index = new_index;
      res
    } else if self.index < self.length {
      //println!("self.index < self.length - 1");
      let res = Eof(&self.buffer[self.index..self.length]);
      self.index = self.length;
      res
    } else {
      Eof(&b""[..])
    }
  }

  fn seek(&mut self, position: SeekFrom) -> Option<u64> {
    match position {
      SeekFrom::Start(pos) => {
        if pos as usize > self.length {
          self.index = self.length
        } else {
          self.index = pos as usize
        }
        Some(self.index as u64)
      },
      SeekFrom::Current(offset) => {
        let next = if offset >= 0 {
          (self.index as u64).checked_add(offset as u64)
        } else {
          (self.index as u64).checked_sub(-offset as u64)
        };

        match next {
          None    => None,
          Some(u) => {
            if u as usize > self.length {
              self.index = self.length
            } else {
              self.index = u as usize
            }
            Some(self.index as u64)
          }
        }
      },
      SeekFrom::End(_) => {
        //FIXME: to implement
        panic!("SeekFrom::End not implemented");
      }
    }
  }

}

/// Prepares a parser function for a push pipeline
///
/// It creates a function that accepts a producer and immediately starts parsing the data sent
///
/// # Example
///
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::Needed;
/// # use std::fmt::Debug;
/// # use nom::IResult;
/// # use nom::IResult::*;
/// # use nom::{ProducerState,Producer,MemProducer};
/// # fn main() {
/// fn local_print<'a, T: Debug>(input: T) -> IResult<'a, T, ()> {
///   println!("{:?}", input);
///   Done(input, ())
/// }
/// let mut p = MemProducer::new(b"abcdefgh", 8);
///
/// pusher!(ps, local_print);
/// ps(&mut p);
/// # }
/// ```
#[macro_export]
macro_rules! pusher (
  ($name:ident, $f:expr) => (
    #[allow(unused_variables)]
    fn $name(producer: &mut $crate::Producer) {
      let mut acc: Vec<u8> = Vec::new();
      loop {
        let state = producer.produce();
        match state {
          $crate::ProducerState::Data(v) => {
            //println!("got data");
            acc.extend(v.iter().cloned())
          },
          $crate::ProducerState::Eof(v) => {
            if v.is_empty() {
              //println!("eof empty, acc contains {} bytes: {:?}", acc.len(), acc);
              break;
            } else {
              //println!("eof with {} bytes", v.len());
              acc.extend(v.iter().cloned())
            }
          }
          _ => {break;}
        }
        let mut v2: Vec<u8>  = Vec::new();
        v2.extend(acc[..].iter().cloned());
        //let p = IResult::Done(b"", v2.as_slice());
        match $f(&v2[..]) {
          $crate::IResult::Error(e)      => {
            //println!("error, stopping: {}", e);
            break;
          },
          $crate::IResult::Incomplete(_) => {
            //println!("incomplete");
          },
          $crate::IResult::Done(i, _)    => {
            //println!("data, done");
            acc.clear();
            acc.extend(i.iter().cloned());
          }
        }
      }
    }
  );
);

#[cfg(test)]
mod tests {
  use super::*;
  use internal::{Needed,IResult};
  use std::fmt::Debug;

  fn local_print<'a,T: Debug>(input: T) -> IResult<'a,T, ()> {
    println!("{:?}", input);
    IResult::Done(input, ())
  }

  #[test]
  fn mem_producer() {
    let mut p = MemProducer::new(&b"abcdefgh"[..], 4);
    assert_eq!(p.produce(), ProducerState::Data(&b"abcd"[..]));
  }

  #[test]
  fn mem_producer_2() {
    let mut p = MemProducer::new(&b"abcdefgh"[..], 8);
    fn pr<'a,'b>(data: &'a [u8]) -> IResult<&'a [u8],()> {
      local_print(data)
    }
    pusher!(ps, pr);
    ps(&mut p);
    //let mut iterations: uint = 0;
    //let mut p = MemProducer::new(b"abcdefghi", 4);
    //p.push(|par| {iterations = iterations + 1; par.flat_map(print)});
    //assert_eq!(iterations, 3);
  }

  #[test]
  #[allow(unused_must_use)]
  fn file() {
    FileProducer::new("links.txt", 20).map(|producer: FileProducer| {
      let mut p = producer;
      //p.push(|par| {println!("parsed file: {}", par); par});
      //p.push(|par| par.flat_map(print));

      pusher!(ps, local_print);
      ps(&mut p);
      //assert!(false);
    });
  }

  #[test]
  fn accu() {
    fn f(input:&[u8]) -> IResult<&[u8],&[u8]> {
      if input.len() <= 4 {
        IResult::Incomplete(Needed::Size(4))
      } else {
        IResult::Done(b"", input)
      }
    }

    let mut p = MemProducer::new(b"abcdefgh", 4);
    fn pr<'a,'b>(data: &'b [u8]) -> IResult<&'b [u8],&'b [u8]> {
      let r = f(data);
      println!("f: {:?}", r);
      r
    }
    pusher!(ps, pr );
    ps(&mut p);
    //assert!(false);
  }

  #[test]
  fn accu_2() {
    fn f(input:&[u8]) -> IResult<&[u8],&[u8]> {
      if input.len() <= 4 || &input[0..5] != b"abcde" {
        IResult::Incomplete(Needed::Size(4))
      } else {
        IResult::Done(&input[5..], &input[0..5])
      }
    }

    let mut p = MemProducer::new(b"abcdefgh", 4);
    fn pr<'a,'b,'c>(data: &'b [u8]) -> IResult<&'b [u8],&'b [u8]> {
      let r = f(data);
      println!("f: {:?}", r);
      r
    }
    pusher!(ps, pr );
    ps(&mut p);
    //assert!(false);
  }
}
<commit_msg>Add the Stepper, able to apply a parser once on a producer<commit_after>//! Data producers
//!
//! The goal of data producers is to parse data as soon as it is generated.
//!
//! # Example
//!
//! ```
//! # #[macro_use] extern crate nom;
//! # use std::fmt::Debug;
//! # use nom::IResult;
//! # use nom::IResult::*;
//! # use nom::{Producer,ProducerState,FileProducer};
//! # fn main() {
//!  use std::str;
//!  fn local_print<'a, T: Debug>(input: T) -> IResult<'a, T, ()> {
//!    println!("{:?}", input);
//!    Done(input, ())
//!  }
//!
//!  // create a data producer from a file
//!  FileProducer::new("links.txt", 20).map(|producer: FileProducer| {
//!    let mut p = producer;
//!
//!    // adapt the parsing function to the producer
//!    pusher!(push, local_print);
//!    // get started
//!    push(&mut p);
//!  });
//! # }
//! ```

use self::ProducerState::*;

use std::fs::File;
use std::path::Path;
use std::io;
use std::io::{Read,Seek,SeekFrom};
use std::iter::repeat;

/// Holds the data producer's current state
///
/// * Eof indicates all data has been parsed, and contains the parser's result
///
/// * Continue indicates that more data is needed and should be available,
/// but not right now. Parsing should resume at some point.
///
/// * Data contains already parsed data
///
/// * ProducerError indicates something went wrong
#[derive(Debug,PartialEq,Eq)]
pub enum ProducerState<O> {
  Eof(O),
  Continue,
  Data(O),
  ProducerError(u32),
}

/// A producer implements the produce method, currently working with u8 arrays
pub trait Producer {
  fn produce(&mut self)                   -> ProducerState<&[u8]>;
  fn seek(&mut self,   position:SeekFrom) -> Option<u64>;
}

/// Can produce data from a file
///
/// the size field is the size of v, the internal buffer
pub struct FileProducer {
  size: usize,
  file: File,
  v:    Vec<u8>
}

impl FileProducer {
  pub fn new(filename: &str, buffer_size: usize) -> io::Result<FileProducer> {
    File::open(&Path::new(filename)).map(|f| {
      FileProducer {size: buffer_size, file: f, v: Vec::with_capacity(buffer_size)}
    })
  }
}

impl Producer for FileProducer {
  fn produce(&mut self) -> ProducerState<&[u8]> {
    let len = self.v.len();
    //let mut v = Vec::with_capacity(self.size);
    //self.v.clear();
    self.v.extend(repeat(0).take(self.size - len));
    match self.file.read(&mut self.v) {
      Err(e) => {
        //println!("producer error: {:?}", e);
        match e.kind() {
          //ErrorKind::NoProgress => Continue,
          //ErrorKind::EndOfFile  => Eof(&self.v[..]),
          _          => ProducerError(0)
        }
      },
      Ok(n)  => {
        //println!("read: {} bytes\ndata:\n{}", n, (&self.v).to_hex(8));
        self.v.truncate(n);
        if n == 0 {
          Eof(&self.v[..])
        } else {
          Data(&self.v[..])
        }
      }
    }
  }

  fn seek(&mut self, position: SeekFrom) -> Option<u64> {
    self.file.seek(position).ok()
  }
}

/// Can parse data from an already in memory byte array
///
/// * buffer holds the reference to the data that must be parsed
///
/// * length is the length of that buffer
///
/// * index is the position in the buffer
///
/// * chunk_size is the quantity of data sent at once
pub struct MemProducer<'x> {
  buffer: &'x [u8],
  chunk_size: usize,
  length: usize,
  index: usize
}

impl<'x> MemProducer<'x> {
  pub fn new(buffer: &'x[u8], chunk_size: usize) -> MemProducer {
    MemProducer {
      buffer:     buffer,
      chunk_size: chunk_size,
      length:     buffer.len(),
      index:      0
    }
  }
}

impl<'x> Producer for MemProducer<'x> {
  fn produce(&mut self) -> ProducerState<&[u8]> {
    if self.index + self.chunk_size < self.length {
      //println!("self.index({}) + {} < self.length({})", self.index, self.chunk_size, self.length);
      let new_index = self.index+self.chunk_size;
      let res = Data(&self.buffer[self.index..new_index]);
      self.index = new_index;
      res
    } else if self.index < self.length {
      //println!("self.index < self.length - 1");
      let res = Eof(&self.buffer[self.index..self.length]);
      self.index = self.length;
      res
    } else {
      Eof(&b""[..])
    }
  }

  fn seek(&mut self, position: SeekFrom) -> Option<u64> {
    match position {
      SeekFrom::Start(pos) => {
        if pos as usize > self.length {
          self.index = self.length
        } else {
          self.index = pos as usize
        }
        Some(self.index as u64)
      },
      SeekFrom::Current(offset) => {
        let next = if offset >= 0 {
          (self.index as u64).checked_add(offset as u64)
        } else {
          (self.index as u64).checked_sub(-offset as u64)
        };

        match next {
          None    => None,
          Some(u) => {
            if u as usize > self.length {
              self.index = self.length
            } else {
              self.index = u as usize
            }
            Some(self.index as u64)
          }
        }
      },
      SeekFrom::End(_) => {
        //FIXME: to implement
        panic!("SeekFrom::End not implemented");
      }
    }
  }

}

/// Prepares a parser function for a push pipeline
///
/// It creates a function that accepts a producer and immediately starts parsing the data sent
///
/// # Example
///
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::Needed;
/// # use std::fmt::Debug;
/// # use nom::IResult;
/// # use nom::IResult::*;
/// # use nom::{ProducerState,Producer,MemProducer};
/// # fn main() {
/// fn local_print<'a, T: Debug>(input: T) -> IResult<'a, T, ()> {
///   println!("{:?}", input);
///   Done(input, ())
/// }
/// let mut p = MemProducer::new(b"abcdefgh", 8);
///
/// pusher!(ps, local_print);
/// ps(&mut p);
/// # }
/// ```
#[macro_export]
macro_rules! pusher (
  ($name:ident, $f:expr) => (
    #[allow(unused_variables)]
    fn $name(producer: &mut $crate::Producer) {
      let mut acc: Vec<u8> = Vec::new();
      loop {
        let state = producer.produce();
        match state {
          $crate::ProducerState::Data(v) => {
            //println!("got data");
            acc.extend(v.iter().cloned())
          },
          $crate::ProducerState::Eof(v) => {
            if v.is_empty() {
              //println!("eof empty, acc contains {} bytes: {:?}", acc.len(), acc);
              break;
            } else {
              //println!("eof with {} bytes", v.len());
              acc.extend(v.iter().cloned())
            }
          }
          _ => {break;}
        }
        let mut v2: Vec<u8>  = Vec::new();
        v2.extend(acc[..].iter().cloned());
        //let p = IResult::Done(b"", v2.as_slice());
        match $f(&v2[..]) {
          $crate::IResult::Error(e)      => {
            //println!("error, stopping: {}", e);
            break;
          },
          $crate::IResult::Incomplete(_) => {
            //println!("incomplete");
          },
          $crate::IResult::Done(i, _)    => {
            //println!("data, done");
            acc.clear();
            acc.extend(i.iter().cloned());
          }
        }
      }
    }
  );
);

#[derive(Debug,PartialEq,Eq)]
pub enum StepperState<'a,O> {
  Eof,
  Value(O),
  ProducerError(u32),
  Continue,
  ParserError(super::Err<'a>),
}

pub struct Stepper<T: Producer> {
  acc:       Vec<u8>,
  remaining: Vec<u8>,
  producer: T,
}

impl<T: Producer> Stepper<T> {
  pub fn new(producer: T) -> Stepper<T> {
    Stepper { acc: Vec::new(), remaining: Vec::new(), producer: producer }
  }

  pub fn step<'a, F, O>(&'a mut self, parser: F) -> StepperState<'a, O>
                      where F: Fn(&'a [u8]) -> super::IResult<&'a [u8],O> {
    self.acc.clear();
    self.acc.extend(self.remaining.iter().cloned());
    let state = self.producer.produce();
    match state {
      ProducerState::Data(v) => {
        self.acc.extend(v.iter().cloned())
      },
      ProducerState::Eof(v) => {
        self.acc.extend(v.iter().cloned())
      },
      ProducerState::Continue => {
        return StepperState::Continue;
      },
      ProducerState::ProducerError(u) => {
        return StepperState::ProducerError(u);
      }
    }

    if self.acc.is_empty() {
      return StepperState::Eof;
    }

    match parser(&(self.acc)[..]) {
      super::IResult::Error(e)      => {
        self.remaining.clear();
        self.remaining.extend(self.acc.iter().cloned());
        return StepperState::ParserError(e);
      },
      super::IResult::Incomplete(_) => {
        self.remaining.clear();
        self.remaining.extend(self.acc.iter().cloned());
        return StepperState::Continue;
      },
      super::IResult::Done(i, o)    => {
        self.remaining.clear();
        self.remaining.extend(i.iter().cloned());
        return StepperState::Value(o);
      }
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use internal::{Needed,IResult};
  use std::fmt::Debug;

  fn local_print<'a,T: Debug>(input: T) -> IResult<'a,T, ()> {
    println!("{:?}", input);
    IResult::Done(input, ())
  }

  #[test]
  fn mem_producer() {
    let mut p = MemProducer::new(&b"abcdefgh"[..], 4);
    assert_eq!(p.produce(), ProducerState::Data(&b"abcd"[..]));
  }

  #[test]
  fn mem_producer_2() {
    let mut p = MemProducer::new(&b"abcdefgh"[..], 8);
    fn pr<'a,'b>(data: &'a [u8]) -> IResult<&'a [u8],()> {
      local_print(data)
    }
    pusher!(ps, pr);
    ps(&mut p);
    //let mut iterations: uint = 0;
    //let mut p = MemProducer::new(b"abcdefghi", 4);
    //p.push(|par| {iterations = iterations + 1; par.flat_map(print)});
    //assert_eq!(iterations, 3);
  }

  #[test]
  #[allow(unused_must_use)]
  fn file() {
    FileProducer::new("links.txt", 20).map(|producer: FileProducer| {
      let mut p = producer;
      //p.push(|par| {println!("parsed file: {}", par); par});
      //p.push(|par| par.flat_map(print));

      pusher!(ps, local_print);
      ps(&mut p);
      //assert!(false);
    });
  }

  #[test]
  fn accu() {
    fn f(input:&[u8]) -> IResult<&[u8],&[u8]> {
      if input.len() <= 4 {
        IResult::Incomplete(Needed::Size(4))
      } else {
        IResult::Done(b"", input)
      }
    }

    let mut p = MemProducer::new(b"abcdefgh", 4);
    fn pr<'a,'b>(data: &'b [u8]) -> IResult<&'b [u8],&'b [u8]> {
      let r = f(data);
      println!("f: {:?}", r);
      r
    }
    pusher!(ps, pr );
    ps(&mut p);
    //assert!(false);
  }

  #[test]
  fn accu_2() {
    fn f(input:&[u8]) -> IResult<&[u8],&[u8]> {
      if input.len() <= 4 || &input[0..5] != b"abcde" {
        IResult::Incomplete(Needed::Size(4))
      } else {
        IResult::Done(&input[5..], &input[0..5])
      }
    }

    let mut p = MemProducer::new(b"abcdefgh", 4);
    fn pr<'a,'b,'c>(data: &'b [u8]) -> IResult<&'b [u8],&'b [u8]> {
      let r = f(data);
      println!("f: {:?}", r);
      r
    }
    pusher!(ps, pr );
    ps(&mut p);
    //assert!(false);
  }

  #[test]
  fn stepper() {
    let p = MemProducer::new(&b"abcdabcd"[..], 3);
    fn pr<'a>(input: &'a [u8]) -> IResult<&'a [u8],&[u8]> {
      if input.len() >= 4 {
        IResult::Done(&input[4..], &input[0..4])
      } else {
        IResult::Incomplete(Needed::Size(4 - input.len()))
      }
    }

    let mut s = Stepper::new(p);
    for i in 0..3 {
      let res = s.step(|x| pr(x));
      match i {
        0     => assert_eq!(res, StepperState::Continue),
        1 | 2 => assert_eq!(res, StepperState::Value(&b"abcd"[..])),
        _     => assert!(false)
      }
    }
    let res2 = s.step(|x| pr(x));
    assert_eq!(res2, StepperState::Eof);
  }
}
<|endoftext|>


<commit_before>#![feature(core, old_io, std_misc)]
#![deny(unused_mut)]
extern crate zookeeper;

use zookeeper::{Acl, CreateMode, Watcher, WatchedEvent, ZooKeeper};
use zookeeper::perms;

use std::old_io::{BufferedReader, Command, Process};
use std::slice::SliceExt;
use std::time::Duration;

struct LoggingWatcher;
impl Watcher for LoggingWatcher {
    fn handle(&self, e: &WatchedEvent) {
        println!("{:?}", e)
    }
}

fn start_zk() -> Process {
    match Command::new("java")
            .arg("-jar")
            .arg("zk-test-cluster/target/main.jar")
            .spawn() {
        Ok(p) => p,
        Err(e) => panic!("failed to execute process: {}", e),
    }
}

fn get_connect_string(server: &mut Process) -> String {
    let reader = server.stdout.take().unwrap();
    let mut reader = BufferedReader::new(reader);

    let mut connect_string = reader.read_line().unwrap();
    connect_string.pop(); // remove '\n'
    connect_string
}

#[test]
fn simple_integration_test() {

    // Create a test cluster and obtain its connection string
    let mut server = start_zk();
    let connect_string = get_connect_string(&mut server);

    // Connect to the test cluster
    let client = ZooKeeper::connect(connect_string.as_slice(), Duration::seconds(5), LoggingWatcher).unwrap();

    // Do the tests
    let acl1 = vec![Acl{perms: perms::ALL, scheme: "world".to_string(), id: "anyone".to_string()}];
    let create = client.create("/test", vec![8,8], acl1, CreateMode::Ephemeral);

    assert_eq!(create.ok(), Some("/test".to_string()));

    let exists = client.exists("/test", true);

    assert!(exists.is_ok());

    let children = client.get_children("/", true);

    assert!(children.is_ok());

    let mut sorted_children = children.unwrap();
    sorted_children.sort();

    assert_eq!(sorted_children, vec!["test".to_string(), "zookeeper".to_string()]);

    // After closing the client all operations return Err
    client.close();

    let exists = client.exists("/test", true);

    assert!(exists.is_err());

    // Close the server
    server.signal_exit().unwrap();
}
<commit_msg>nightly fix<commit_after>#![feature(core, old_io, std_misc)]
#![deny(unused_mut)]
extern crate zookeeper;

use zookeeper::{Acl, CreateMode, Watcher, WatchedEvent, ZooKeeper};
use zookeeper::perms;

use std::old_io::{BufferedReader, Command, Process};
use std::time::Duration;

struct LoggingWatcher;
impl Watcher for LoggingWatcher {
    fn handle(&self, e: &WatchedEvent) {
        println!("{:?}", e)
    }
}

fn start_zk() -> Process {
    match Command::new("java")
            .arg("-jar")
            .arg("zk-test-cluster/target/main.jar")
            .spawn() {
        Ok(p) => p,
        Err(e) => panic!("failed to execute process: {}", e),
    }
}

fn get_connect_string(server: &mut Process) -> String {
    let reader = server.stdout.take().unwrap();
    let mut reader = BufferedReader::new(reader);

    let mut connect_string = reader.read_line().unwrap();
    connect_string.pop(); // remove '\n'
    connect_string
}

#[test]
fn simple_integration_test() {

    // Create a test cluster and obtain its connection string
    let mut server = start_zk();
    let connect_string = get_connect_string(&mut server);

    // Connect to the test cluster
    let client = ZooKeeper::connect(connect_string.as_slice(), Duration::seconds(5), LoggingWatcher).unwrap();

    // Do the tests
    let acl1 = vec![Acl{perms: perms::ALL, scheme: "world".to_string(), id: "anyone".to_string()}];
    let create = client.create("/test", vec![8,8], acl1, CreateMode::Ephemeral);

    assert_eq!(create.ok(), Some("/test".to_string()));

    let exists = client.exists("/test", true);

    assert!(exists.is_ok());

    let children = client.get_children("/", true);

    assert!(children.is_ok());

    let mut sorted_children = children.unwrap();
    sorted_children.sort();

    assert_eq!(sorted_children, vec!["test".to_string(), "zookeeper".to_string()]);

    // After closing the client all operations return Err
    client.close();

    let exists = client.exists("/test", true);

    assert!(exists.is_err());

    // Close the server
    server.signal_exit().unwrap();
}
<|endoftext|>


<commit_before>//! A small server that writes as many nul bytes on all connections it receives.
//!
//! There is no concurrency in this server, only one connection is written to at
//! a time.

#[macro_use]
extern crate futures;
extern crate futures_io;
extern crate futures_mio;

use std::env;
use std::net::SocketAddr;

use futures::Future;
use futures::stream::Stream;
use futures_io::IoFuture;

fn main() {
    let addr = env::args().nth(1).unwrap_or("127.0.0.1:8080".to_string());
    let addr = addr.parse::<SocketAddr>().unwrap();

    let mut l = futures_mio::Loop::new().unwrap();
    let server = l.handle().tcp_listen(&addr).and_then(|socket| {
        socket.incoming().and_then(|(socket, addr)| {
            println!("got a socket: {}", addr);
            write(socket).or_else(|_| Ok(()))
        }).for_each(|()| {
            println!("lost the socket");
            Ok(())
        })
    });
    println!("Listenering on: {}", addr);
    l.run(server).unwrap();
}

// TODO: this blows the stack...
fn write(socket: futures_mio::TcpStream) -> IoFuture<()> {
    static BUF: &'static [u8] = &[0; 1 * 1024 * 1024];
    futures_io::write_all(socket, BUF).and_then(|(socket, _)| {
        write(socket)
    }).boxed()
}
<commit_msg>Rewrite recursion with a loop in sink.rs<commit_after>//! A small server that writes as many nul bytes on all connections it receives.
//!
//! There is no concurrency in this server, only one connection is written to at
//! a time.

#[macro_use]
extern crate futures;
extern crate futures_io;
extern crate futures_mio;

use std::env;
use std::iter;
use std::net::SocketAddr;

use futures::Future;
use futures::stream::{self, Stream};
use futures_io::IoFuture;

fn main() {
    let addr = env::args().nth(1).unwrap_or("127.0.0.1:8080".to_string());
    let addr = addr.parse::<SocketAddr>().unwrap();

    let mut l = futures_mio::Loop::new().unwrap();
    let server = l.handle().tcp_listen(&addr).and_then(|socket| {
        socket.incoming().and_then(|(socket, addr)| {
            println!("got a socket: {}", addr);
            write(socket).or_else(|_| Ok(()))
        }).for_each(|()| {
            println!("lost the socket");
            Ok(())
        })
    });
    println!("Listenering on: {}", addr);
    l.run(server).unwrap();
}

fn write(socket: futures_mio::TcpStream) -> IoFuture<()> {
    static BUF: &'static [u8] = &[0; 64 * 1024];
    let iter = iter::repeat(()).map(|()| Ok(()));
    stream::iter(iter).fold(socket, |socket, ()| {
        futures_io::write_all(socket, BUF).map(|(socket, _)| socket)
    }).map(|_| ()).boxed()
}
<|endoftext|>


<commit_before>use std::mem;
use std::ptr;
use std::marker::PhantomData;
use std::borrow::BorrowMut;
use gl;
use gl::types::*;
use context::ContextOf;
use framebuffer::FramebufferBinding;
use types::{DrawingMode, GLError};
use index_data::{IndexData, IndexDatum, IndexDatumType};

pub struct Buffer {
    gl_id: GLuint
}

impl Buffer {
    pub fn gl_id(&self) -> GLuint {
        self.gl_id
    }
}

impl Drop for Buffer {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteBuffers(1, &self.gl_id as *const GLuint);
        }
    }
}

impl<AB, EAB, P, FB, RB, TU> ContextOf<AB, EAB, P, FB, RB, TU> {
    pub fn gen_buffer(&self) -> Buffer {
        unsafe {
            let mut id : GLuint = 0;

            gl::GenBuffers(1, &mut id as *mut GLuint);
            dbg_gl_sanity_check! {
                GLError::InvalidValue => "`n` is negative",
                _ => "Unknown error"
            }

            Buffer { gl_id: id }
        }
    }

    pub fn bind_array_buffer<'a>(self, buffer: &'a mut Buffer)
        -> (
            ArrayBufferBinding<'a>,
            ContextOf<(), EAB, P, FB, RB, TU>
        )
        where AB: BorrowMut<ArrayBufferBinder>
    {
        let (mut array_buffer, gl) = self.split_array_buffer();
        (array_buffer.borrow_mut().bind(buffer), gl)
    }

    pub fn bind_element_array_buffer<'a>(self, buffer: &'a mut Buffer)
        -> (
            ElementArrayBufferBinding<'a>,
            ContextOf<AB, (), P, FB, RB, TU>
        )
        where EAB: BorrowMut<ElementArrayBufferBinder>
    {
        let (mut element_array_buffer, gl) = self.split_element_array_buffer();
        (element_array_buffer.borrow_mut().bind(buffer), gl)
    }
}

gl_enum! {
    pub gl_enum BufferDataUsage {
        StreamDraw as STREAM_DRAW = gl::STREAM_DRAW,
        StaticDraw as STATIC_DRAW = gl::STATIC_DRAW,
        DynamicDraw as DYNAMIC_DRAW = gl::DYNAMIC_DRAW
    }
}

gl_enum! {
    pub gl_enum BufferBindingTarget {
        ArrayBuffer as ARRAY_BUFFER = gl::ARRAY_BUFFER,
        ElementArrayBuffer as ELEMENT_ARRAY_BUFFER = gl::ELEMENT_ARRAY_BUFFER
    }
}

pub trait BufferBinding {
    fn target(&self) -> BufferBindingTarget;

    fn buffer_bytes(&mut self, bytes: &[u8], usage: BufferDataUsage) {
        let ptr = bytes.as_ptr();
        let size = bytes.len() * mem::size_of::<u8>();
        unsafe {
            gl::BufferData(self.target().gl_enum(),
                           size as GLsizeiptr,
                           ptr as *const GLvoid,
                           usage.gl_enum());
            dbg_gl_error! {
                GLError::InvalidEnum => "Invalid `target` or `usage`",
                GLError::InvalidValue => "`size` is negative",
                GLError::InvalidOperation => "Object 0 is bound to buffer target",
                GLError::OutOfMemory => "Unable to create a large enough buffer",
                _ => "Unknown error"
            }
        }
    }
}

pub struct ArrayBufferBinding<'a> {
    phantom: PhantomData<&'a mut Buffer>
}

impl<'a> BufferBinding for ArrayBufferBinding<'a> {
    fn target(&self) -> BufferBindingTarget {
        ARRAY_BUFFER
    }
}

unsafe fn _draw_elements(mode: DrawingMode,
                         count: usize,
                         index_type: IndexDatumType,
                         indices: *const GLvoid)
{
    let gl_index_type: GLenum = match index_type {
        IndexDatumType::UnsignedByte => gl::UNSIGNED_BYTE,
        IndexDatumType::UnsignedShort => gl::UNSIGNED_SHORT
    };
    gl::DrawElements(mode.gl_enum(),
                     count as GLsizei,
                     gl_index_type,
                     indices);
    dbg_gl_error! {
        GLError::InvalidEnum => "`mode` or `type` is not an accepted value",
        GLError::InvalidValue => "`count` is negative",
        GLError::InvalidFramebufferOperation => "The current framebuffer is not framebuffer-complete",
        _ => "Unknown error"
    }
}

impl<'a> ArrayBufferBinding<'a> {
    pub unsafe fn vertex_attrib_pointer(&self,
                                        attrib: super::ProgramAttrib,
                                        components: i8,
                                        gl_type: super::DataType,
                                        normalized: bool,
                                        stride: usize,
                                        offset: usize)
    {
        debug_assert!(1 <= components && components <= 4);

        let gl_normalized = if normalized { gl::TRUE } else { gl::FALSE };
        gl::VertexAttribPointer(attrib.gl_index,
                                components as GLint,
                                gl_type.gl_enum(),
                                gl_normalized,
                                stride as GLsizei,
                                offset as *const GLvoid);
        dbg_gl_error! {
            GLError::InvalidEnum => "Illegal vertex attribute type",
            GLError::InvalidValue => "`stride` is negative, `size` is not in range, or `index` is >= GL_MAX_VERTEX_ATTRIBS",
            GLError::InvalidFramebufferOperation => "Currently bound framebuffer is not framebuffer complete",
            _ => "Unknown error"
        }
    }
}

impl<'a> FramebufferBinding<'a> {
    pub unsafe fn draw_arrays_range(&mut self,
                                    _ab: &ArrayBufferBinding,
                                    mode: DrawingMode,
                                    first: u32,
                                    count: usize)
    {
        gl::DrawArrays(mode.gl_enum(), first as GLint, count as GLsizei);
        dbg_gl_sanity_check! {
            GLError::InvalidEnum => "`mode` is not an accepted value",
            GLError::InvalidValue => "`count` is negative",
            _ => "Unknown error"
        }
    }

    pub unsafe fn draw_n_elements_buffered(&mut self,
                                           _ab: &ArrayBufferBinding,
                                           _eab: &ElementArrayBufferBinding,
                                           mode: DrawingMode,
                                           count: usize,
                                           index_type: IndexDatumType)
    {
        _draw_elements(mode, count, index_type, ptr::null());
    }

    pub unsafe fn draw_n_elements<I>(&mut self,
                                     _ab: &ArrayBufferBinding,
                                     mode: DrawingMode,
                                     count: usize,
                                     indices: &[I])
        where I: IndexDatum, [I]: IndexData
    {
        debug_assert!(count <= indices.len());

        let ptr = indices.index_bytes().as_ptr();
        let index_type = I::index_datum_type();
        _draw_elements(mode, count, index_type, mem::transmute(ptr));
    }

    pub unsafe fn draw_elements<I>(&mut self,
                                   _ab: &ArrayBufferBinding,
                                   mode: DrawingMode,
                                   indices: &[I])
        where I: IndexDatum, [I]: IndexData
    {
        self.draw_n_elements(_ab, mode, indices.len(), indices);
    }
}

pub struct ElementArrayBufferBinding<'a> {
    phantom: PhantomData<&'a mut Buffer>
}

impl<'a> BufferBinding for ElementArrayBufferBinding<'a> {
    fn target(&self) -> BufferBindingTarget {
        ELEMENT_ARRAY_BUFFER
    }
}

fn _bind_buffer(target: BufferBindingTarget, buffer: &mut Buffer) {
    unsafe {
        gl::BindBuffer(target as GLuint, buffer.gl_id());
        dbg_gl_sanity_check! {
            GLError::InvalidEnum => "`target` is not an allowed value",
            _ => "Unknown error"
        }
    }
}

pub struct BufferBinderOf<A, E> {
    array: A,
    element_array: E
}

pub type BufferBinder = BufferBinderOf<ArrayBufferBinder,
                                       ElementArrayBufferBinder>;

pub type BufferBinderRef<'a> = BufferBinderOf<&'a ArrayBufferBinder,
                                              &'a ElementArrayBufferBinder>;

pub type BufferBinderMut<'a> = BufferBinderOf<&'a mut ArrayBufferBinder,
                                              &'a mut ElementArrayBufferBinder>;

pub struct ArrayBufferBinder;
impl ArrayBufferBinder {
    pub fn bind<'a>(&mut self, buffer: &'a mut Buffer) -> ArrayBufferBinding<'a>
    {
        let binding = ArrayBufferBinding { phantom: PhantomData };
        _bind_buffer(binding.target(), buffer);
        binding
    }
}

pub struct ElementArrayBufferBinder;
impl ElementArrayBufferBinder {
    pub fn bind<'a>(&mut self, buffer: &'a mut Buffer)
        -> ElementArrayBufferBinding<'a>
    {
        let binding = ElementArrayBufferBinding { phantom: PhantomData };
        _bind_buffer(binding.target(), buffer);
        binding
    }
}
<commit_msg>Add `BufferBinder.current()`<commit_after>use std::mem;
use std::ptr;
use std::marker::PhantomData;
use std::borrow::BorrowMut;
use gl;
use gl::types::*;
use context::ContextOf;
use framebuffer::FramebufferBinding;
use types::{DrawingMode, GLError};
use index_data::{IndexData, IndexDatum, IndexDatumType};

pub struct Buffer {
    gl_id: GLuint
}

impl Buffer {
    pub fn gl_id(&self) -> GLuint {
        self.gl_id
    }
}

impl Drop for Buffer {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteBuffers(1, &self.gl_id as *const GLuint);
        }
    }
}

impl<AB, EAB, P, FB, RB, TU> ContextOf<AB, EAB, P, FB, RB, TU> {
    pub fn gen_buffer(&self) -> Buffer {
        unsafe {
            let mut id : GLuint = 0;

            gl::GenBuffers(1, &mut id as *mut GLuint);
            dbg_gl_sanity_check! {
                GLError::InvalidValue => "`n` is negative",
                _ => "Unknown error"
            }

            Buffer { gl_id: id }
        }
    }

    pub fn bind_array_buffer<'a>(self, buffer: &'a mut Buffer)
        -> (
            ArrayBufferBinding<'a>,
            ContextOf<(), EAB, P, FB, RB, TU>
        )
        where AB: BorrowMut<ArrayBufferBinder>
    {
        let (mut array_buffer, gl) = self.split_array_buffer();
        (array_buffer.borrow_mut().bind(buffer), gl)
    }

    pub fn bind_element_array_buffer<'a>(self, buffer: &'a mut Buffer)
        -> (
            ElementArrayBufferBinding<'a>,
            ContextOf<AB, (), P, FB, RB, TU>
        )
        where EAB: BorrowMut<ElementArrayBufferBinder>
    {
        let (mut element_array_buffer, gl) = self.split_element_array_buffer();
        (element_array_buffer.borrow_mut().bind(buffer), gl)
    }
}

gl_enum! {
    pub gl_enum BufferDataUsage {
        StreamDraw as STREAM_DRAW = gl::STREAM_DRAW,
        StaticDraw as STATIC_DRAW = gl::STATIC_DRAW,
        DynamicDraw as DYNAMIC_DRAW = gl::DYNAMIC_DRAW
    }
}

gl_enum! {
    pub gl_enum BufferBindingTarget {
        ArrayBuffer as ARRAY_BUFFER = gl::ARRAY_BUFFER,
        ElementArrayBuffer as ELEMENT_ARRAY_BUFFER = gl::ELEMENT_ARRAY_BUFFER
    }
}

pub trait BufferBinding {
    fn target(&self) -> BufferBindingTarget;

    fn buffer_bytes(&mut self, bytes: &[u8], usage: BufferDataUsage) {
        let ptr = bytes.as_ptr();
        let size = bytes.len() * mem::size_of::<u8>();
        unsafe {
            gl::BufferData(self.target().gl_enum(),
                           size as GLsizeiptr,
                           ptr as *const GLvoid,
                           usage.gl_enum());
            dbg_gl_error! {
                GLError::InvalidEnum => "Invalid `target` or `usage`",
                GLError::InvalidValue => "`size` is negative",
                GLError::InvalidOperation => "Object 0 is bound to buffer target",
                GLError::OutOfMemory => "Unable to create a large enough buffer",
                _ => "Unknown error"
            }
        }
    }
}

pub struct ArrayBufferBinding<'a> {
    phantom: PhantomData<&'a mut Buffer>
}

impl<'a> BufferBinding for ArrayBufferBinding<'a> {
    fn target(&self) -> BufferBindingTarget {
        ARRAY_BUFFER
    }
}

unsafe fn _draw_elements(mode: DrawingMode,
                         count: usize,
                         index_type: IndexDatumType,
                         indices: *const GLvoid)
{
    let gl_index_type: GLenum = match index_type {
        IndexDatumType::UnsignedByte => gl::UNSIGNED_BYTE,
        IndexDatumType::UnsignedShort => gl::UNSIGNED_SHORT
    };
    gl::DrawElements(mode.gl_enum(),
                     count as GLsizei,
                     gl_index_type,
                     indices);
    dbg_gl_error! {
        GLError::InvalidEnum => "`mode` or `type` is not an accepted value",
        GLError::InvalidValue => "`count` is negative",
        GLError::InvalidFramebufferOperation => "The current framebuffer is not framebuffer-complete",
        _ => "Unknown error"
    }
}

impl<'a> ArrayBufferBinding<'a> {
    pub unsafe fn vertex_attrib_pointer(&self,
                                        attrib: super::ProgramAttrib,
                                        components: i8,
                                        gl_type: super::DataType,
                                        normalized: bool,
                                        stride: usize,
                                        offset: usize)
    {
        debug_assert!(1 <= components && components <= 4);

        let gl_normalized = if normalized { gl::TRUE } else { gl::FALSE };
        gl::VertexAttribPointer(attrib.gl_index,
                                components as GLint,
                                gl_type.gl_enum(),
                                gl_normalized,
                                stride as GLsizei,
                                offset as *const GLvoid);
        dbg_gl_error! {
            GLError::InvalidEnum => "Illegal vertex attribute type",
            GLError::InvalidValue => "`stride` is negative, `size` is not in range, or `index` is >= GL_MAX_VERTEX_ATTRIBS",
            GLError::InvalidFramebufferOperation => "Currently bound framebuffer is not framebuffer complete",
            _ => "Unknown error"
        }
    }
}

impl<'a> FramebufferBinding<'a> {
    pub unsafe fn draw_arrays_range(&mut self,
                                    _ab: &ArrayBufferBinding,
                                    mode: DrawingMode,
                                    first: u32,
                                    count: usize)
    {
        gl::DrawArrays(mode.gl_enum(), first as GLint, count as GLsizei);
        dbg_gl_sanity_check! {
            GLError::InvalidEnum => "`mode` is not an accepted value",
            GLError::InvalidValue => "`count` is negative",
            _ => "Unknown error"
        }
    }

    pub unsafe fn draw_n_elements_buffered(&mut self,
                                           _ab: &ArrayBufferBinding,
                                           _eab: &ElementArrayBufferBinding,
                                           mode: DrawingMode,
                                           count: usize,
                                           index_type: IndexDatumType)
    {
        _draw_elements(mode, count, index_type, ptr::null());
    }

    pub unsafe fn draw_n_elements<I>(&mut self,
                                     _ab: &ArrayBufferBinding,
                                     mode: DrawingMode,
                                     count: usize,
                                     indices: &[I])
        where I: IndexDatum, [I]: IndexData
    {
        debug_assert!(count <= indices.len());

        let ptr = indices.index_bytes().as_ptr();
        let index_type = I::index_datum_type();
        _draw_elements(mode, count, index_type, mem::transmute(ptr));
    }

    pub unsafe fn draw_elements<I>(&mut self,
                                   _ab: &ArrayBufferBinding,
                                   mode: DrawingMode,
                                   indices: &[I])
        where I: IndexDatum, [I]: IndexData
    {
        self.draw_n_elements(_ab, mode, indices.len(), indices);
    }
}

pub struct ElementArrayBufferBinding<'a> {
    phantom: PhantomData<&'a mut Buffer>
}

impl<'a> BufferBinding for ElementArrayBufferBinding<'a> {
    fn target(&self) -> BufferBindingTarget {
        ELEMENT_ARRAY_BUFFER
    }
}

fn _bind_buffer(target: BufferBindingTarget, buffer: &mut Buffer) {
    unsafe {
        gl::BindBuffer(target as GLuint, buffer.gl_id());
        dbg_gl_sanity_check! {
            GLError::InvalidEnum => "`target` is not an allowed value",
            _ => "Unknown error"
        }
    }
}

pub struct BufferBinderOf<A, E> {
    array: A,
    element_array: E
}

pub type BufferBinder = BufferBinderOf<ArrayBufferBinder,
                                       ElementArrayBufferBinder>;

pub type BufferBinderRef<'a> = BufferBinderOf<&'a ArrayBufferBinder,
                                              &'a ElementArrayBufferBinder>;

pub type BufferBinderMut<'a> = BufferBinderOf<&'a mut ArrayBufferBinder,
                                              &'a mut ElementArrayBufferBinder>;

impl<A, E> BufferBinderOf<A, E> {
    pub unsafe fn current() -> BufferBinder {
        BufferBinderOf {
            array: ArrayBufferBinder,
            element_array: ElementArrayBufferBinder
        }
    }
}

pub struct ArrayBufferBinder;
impl ArrayBufferBinder {
    pub fn bind<'a>(&mut self, buffer: &'a mut Buffer) -> ArrayBufferBinding<'a>
    {
        let binding = ArrayBufferBinding { phantom: PhantomData };
        _bind_buffer(binding.target(), buffer);
        binding
    }
}

pub struct ElementArrayBufferBinder;
impl ElementArrayBufferBinder {
    pub fn bind<'a>(&mut self, buffer: &'a mut Buffer)
        -> ElementArrayBufferBinding<'a>
    {
        let binding = ElementArrayBufferBinding { phantom: PhantomData };
        _bind_buffer(binding.target(), buffer);
        binding
    }
}
<|endoftext|>


<commit_before>use std::mem;
use std::ptr;
use std::marker::PhantomData;
use std::borrow::{Borrow, BorrowMut};
use gl;
use gl::types::*;
use context::ContextOf;
use framebuffer::FramebufferBinding;
use types::{DrawingMode, GLError};
use index_data::{IndexData, IndexDatum, IndexDatumType};

pub struct Buffer {
    gl_id: GLuint
}

impl Buffer {
    pub fn gl_id(&self) -> GLuint {
        self.gl_id
    }
}

impl Drop for Buffer {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteBuffers(1, &self.gl_id as *const GLuint);
        }
    }
}

impl<B, F, P, R, T> ContextOf<B, F, P, R, T> {
    pub fn gen_buffer(&self) -> Buffer {
        unsafe {
            let mut id : GLuint = 0;

            gl::GenBuffers(1, &mut id as *mut GLuint);
            dbg_gl_sanity_check! {
                GLError::InvalidValue => "`n` is negative",
                _ => "Unknown error"
            }

            Buffer { gl_id: id }
        }
    }
}

impl<BA, BE, F, P, R, T> ContextOf<BufferBinderOf<BA, BE>, F, P, R, T> {
    pub fn split_array_buffer(self)
        -> (BA, ContextOf<BufferBinderOf<(), BE>, F, P, R, T>)
    {
        let (buffers, gl) = self.split_buffers();
        let (ba_binder, rest_buffers) = buffers.split_array();

        (ba_binder, gl.join_buffers(rest_buffers))
    }

    pub fn split_element_array_buffer(self)
        -> (BE, ContextOf<BufferBinderOf<BA, ()>, F, P, R, T>)
    {
        let (buffers, gl) = self.split_buffers();
        let (be_binder, rest_buffers) = buffers.split_element_array();
        (be_binder, gl.join_buffers(rest_buffers))
    }

    pub fn bind_array_buffer<'a>(self, buffer: &'a mut Buffer)
        -> (
            ArrayBufferBinding<'a>,
            ContextOf<BufferBinderOf<(), BE>, F, P, R, T>
        )
        where BA: BorrowMut<ArrayBufferBinder>
    {
        let (mut ba_binder, gl) = self.split_array_buffer();
        (ba_binder.borrow_mut().bind(buffer), gl)
    }

    pub fn bind_element_array_buffer<'a>(self, buffer: &'a mut Buffer)
        -> (
            ElementArrayBufferBinding<'a>,
            ContextOf<BufferBinderOf<BA, ()>, F, P, R, T>
        )
        where BE: BorrowMut<ElementArrayBufferBinder>
    {
        let (mut be_binder, gl) = self.split_element_array_buffer();
        (be_binder.borrow_mut().bind(buffer), gl)
    }
}

gl_enum! {
    pub gl_enum BufferDataUsage {
        StreamDraw as STREAM_DRAW = gl::STREAM_DRAW,
        StaticDraw as STATIC_DRAW = gl::STATIC_DRAW,
        DynamicDraw as DYNAMIC_DRAW = gl::DYNAMIC_DRAW
    }
}

gl_enum! {
    pub gl_enum BufferBindingTarget {
        ArrayBuffer as ARRAY_BUFFER = gl::ARRAY_BUFFER,
        ElementArrayBuffer as ELEMENT_ARRAY_BUFFER = gl::ELEMENT_ARRAY_BUFFER
    }
}

pub trait BufferBinding {
    fn target(&self) -> BufferBindingTarget;

    fn buffer_bytes(&mut self, bytes: &[u8], usage: BufferDataUsage) {
        let ptr = bytes.as_ptr();
        let size = bytes.len() * mem::size_of::<u8>();
        unsafe {
            gl::BufferData(self.target().gl_enum(),
                           size as GLsizeiptr,
                           ptr as *const GLvoid,
                           usage.gl_enum());
            dbg_gl_error! {
                GLError::InvalidEnum => "Invalid `target` or `usage`",
                GLError::InvalidValue => "`size` is negative",
                GLError::InvalidOperation => "Object 0 is bound to buffer target",
                GLError::OutOfMemory => "Unable to create a large enough buffer",
                _ => "Unknown error"
            }
        }
    }
}

pub struct ArrayBufferBinding<'a> {
    phantom: PhantomData<&'a mut Buffer>
}

impl<'a> BufferBinding for ArrayBufferBinding<'a> {
    fn target(&self) -> BufferBindingTarget {
        ARRAY_BUFFER
    }
}

unsafe fn _draw_elements(mode: DrawingMode,
                         count: usize,
                         index_type: IndexDatumType,
                         indices: *const GLvoid)
{
    let gl_index_type: GLenum = match index_type {
        IndexDatumType::UnsignedByte => gl::UNSIGNED_BYTE,
        IndexDatumType::UnsignedShort => gl::UNSIGNED_SHORT
    };
    gl::DrawElements(mode.gl_enum(),
                     count as GLsizei,
                     gl_index_type,
                     indices);
    dbg_gl_error! {
        GLError::InvalidEnum => "`mode` or `type` is not an accepted value",
        GLError::InvalidValue => "`count` is negative",
        GLError::InvalidFramebufferOperation => "The current framebuffer is not framebuffer-complete",
        _ => "Unknown error"
    }
}

impl<'a> ArrayBufferBinding<'a> {
    pub unsafe fn vertex_attrib_pointer(&self,
                                        attrib: super::ProgramAttrib,
                                        components: i8,
                                        gl_type: super::DataType,
                                        normalized: bool,
                                        stride: usize,
                                        offset: usize)
    {
        debug_assert!(1 <= components && components <= 4);

        let gl_normalized = if normalized { gl::TRUE } else { gl::FALSE };
        gl::VertexAttribPointer(attrib.gl_index,
                                components as GLint,
                                gl_type.gl_enum(),
                                gl_normalized,
                                stride as GLsizei,
                                offset as *const GLvoid);
        dbg_gl_error! {
            GLError::InvalidEnum => "Illegal vertex attribute type",
            GLError::InvalidValue => "`stride` is negative, `size` is not in range, or `index` is >= GL_MAX_VERTEX_ATTRIBS",
            GLError::InvalidFramebufferOperation => "Currently bound framebuffer is not framebuffer complete",
            _ => "Unknown error"
        }
    }
}

impl<'a> FramebufferBinding<'a> {
    pub unsafe fn draw_arrays_range(&mut self,
                                    _ab: &ArrayBufferBinding,
                                    mode: DrawingMode,
                                    first: u32,
                                    count: usize)
    {
        gl::DrawArrays(mode.gl_enum(), first as GLint, count as GLsizei);
        dbg_gl_sanity_check! {
            GLError::InvalidEnum => "`mode` is not an accepted value",
            GLError::InvalidValue => "`count` is negative",
            _ => "Unknown error"
        }
    }

    pub unsafe fn draw_n_elements_buffered(&mut self,
                                           _ab: &ArrayBufferBinding,
                                           _eab: &ElementArrayBufferBinding,
                                           mode: DrawingMode,
                                           count: usize,
                                           index_type: IndexDatumType)
    {
        _draw_elements(mode, count, index_type, ptr::null());
    }

    pub unsafe fn draw_n_elements<I>(&mut self,
                                     _ab: &ArrayBufferBinding,
                                     mode: DrawingMode,
                                     count: usize,
                                     indices: &[I])
        where I: IndexDatum, [I]: IndexData
    {
        debug_assert!(count <= indices.len());

        let ptr = indices.index_bytes().as_ptr();
        let index_type = I::index_datum_type();
        _draw_elements(mode, count, index_type, mem::transmute(ptr));
    }

    pub unsafe fn draw_elements<I>(&mut self,
                                   _ab: &ArrayBufferBinding,
                                   mode: DrawingMode,
                                   indices: &[I])
        where I: IndexDatum, [I]: IndexData
    {
        self.draw_n_elements(_ab, mode, indices.len(), indices);
    }
}

pub struct ElementArrayBufferBinding<'a> {
    phantom: PhantomData<&'a mut Buffer>
}

impl<'a> BufferBinding for ElementArrayBufferBinding<'a> {
    fn target(&self) -> BufferBindingTarget {
        ELEMENT_ARRAY_BUFFER
    }
}

fn _bind_buffer(target: BufferBindingTarget, buffer: &mut Buffer) {
    unsafe {
        gl::BindBuffer(target as GLuint, buffer.gl_id());
        dbg_gl_sanity_check! {
            GLError::InvalidEnum => "`target` is not an allowed value",
            _ => "Unknown error"
        }
    }
}

pub struct BufferBinderOf<A, E> {
    array: A,
    element_array: E
}

pub type BufferBinder = BufferBinderOf<ArrayBufferBinder,
                                       ElementArrayBufferBinder>;

pub type BufferBinderRef<'a> = BufferBinderOf<&'a ArrayBufferBinder,
                                              &'a ElementArrayBufferBinder>;

pub type BufferBinderMut<'a> = BufferBinderOf<&'a mut ArrayBufferBinder,
                                              &'a mut ElementArrayBufferBinder>;

impl<A, E> BufferBinderOf<A, E> {
    pub unsafe fn current() -> BufferBinder {
        BufferBinderOf {
            array: ArrayBufferBinder,
            element_array: ElementArrayBufferBinder
        }
    }

    pub fn borrowed<'a, BA = A, BE = E>(&'a self)
        -> BufferBinderOf<&'a BA, &'a BE>
        where A: Borrow<BA>,
              E: Borrow<BE>
    {
        BufferBinderOf {
            array: self.array.borrow(),
            element_array: self.element_array.borrow()
        }
    }

    pub fn borrowed_mut<'a, BA = A, BE = E>(&'a mut self)
        -> BufferBinderOf<&'a mut BA, &'a mut BE>
        where A: BorrowMut<BA>,
              E: BorrowMut<BE>
    {
        BufferBinderOf {
            array: self.array.borrow_mut(),
            element_array: self.element_array.borrow_mut()
        }
    }

    pub fn split_array(self) -> (A, BufferBinderOf<(), E>) {
        (
            self.array,
            BufferBinderOf {
                array: (),
                element_array: self.element_array
            }
        )
    }

    pub fn split_element_array(self) -> (E, BufferBinderOf<A, ()>) {
        (
            self.element_array,
            BufferBinderOf {
                array: self.array,
                element_array: ()
            }
        )
    }
}

pub struct ArrayBufferBinder;
impl ArrayBufferBinder {
    pub fn bind<'a>(&mut self, buffer: &'a mut Buffer) -> ArrayBufferBinding<'a>
    {
        let binding = ArrayBufferBinding { phantom: PhantomData };
        _bind_buffer(binding.target(), buffer);
        binding
    }
}

pub struct ElementArrayBufferBinder;
impl ElementArrayBufferBinder {
    pub fn bind<'a>(&mut self, buffer: &'a mut Buffer)
        -> ElementArrayBufferBinding<'a>
    {
        let binding = ElementArrayBufferBinding { phantom: PhantomData };
        _bind_buffer(binding.target(), buffer);
        binding
    }
}
<commit_msg>Add `RefInto` and `MutInto` impls for `BufferBinderOf`<commit_after>use std::mem;
use std::ptr;
use std::marker::PhantomData;
use std::borrow::{Borrow, BorrowMut};
use gl;
use gl::types::*;
use ref_into::{RefInto, MutInto};
use context::ContextOf;
use framebuffer::FramebufferBinding;
use types::{DrawingMode, GLError};
use index_data::{IndexData, IndexDatum, IndexDatumType};

pub struct Buffer {
    gl_id: GLuint
}

impl Buffer {
    pub fn gl_id(&self) -> GLuint {
        self.gl_id
    }
}

impl Drop for Buffer {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteBuffers(1, &self.gl_id as *const GLuint);
        }
    }
}

impl<B, F, P, R, T> ContextOf<B, F, P, R, T> {
    pub fn gen_buffer(&self) -> Buffer {
        unsafe {
            let mut id : GLuint = 0;

            gl::GenBuffers(1, &mut id as *mut GLuint);
            dbg_gl_sanity_check! {
                GLError::InvalidValue => "`n` is negative",
                _ => "Unknown error"
            }

            Buffer { gl_id: id }
        }
    }
}

impl<BA, BE, F, P, R, T> ContextOf<BufferBinderOf<BA, BE>, F, P, R, T> {
    pub fn split_array_buffer(self)
        -> (BA, ContextOf<BufferBinderOf<(), BE>, F, P, R, T>)
    {
        let (buffers, gl) = self.split_buffers();
        let (ba_binder, rest_buffers) = buffers.split_array();

        (ba_binder, gl.join_buffers(rest_buffers))
    }

    pub fn split_element_array_buffer(self)
        -> (BE, ContextOf<BufferBinderOf<BA, ()>, F, P, R, T>)
    {
        let (buffers, gl) = self.split_buffers();
        let (be_binder, rest_buffers) = buffers.split_element_array();
        (be_binder, gl.join_buffers(rest_buffers))
    }

    pub fn bind_array_buffer<'a>(self, buffer: &'a mut Buffer)
        -> (
            ArrayBufferBinding<'a>,
            ContextOf<BufferBinderOf<(), BE>, F, P, R, T>
        )
        where BA: BorrowMut<ArrayBufferBinder>
    {
        let (mut ba_binder, gl) = self.split_array_buffer();
        (ba_binder.borrow_mut().bind(buffer), gl)
    }

    pub fn bind_element_array_buffer<'a>(self, buffer: &'a mut Buffer)
        -> (
            ElementArrayBufferBinding<'a>,
            ContextOf<BufferBinderOf<BA, ()>, F, P, R, T>
        )
        where BE: BorrowMut<ElementArrayBufferBinder>
    {
        let (mut be_binder, gl) = self.split_element_array_buffer();
        (be_binder.borrow_mut().bind(buffer), gl)
    }
}

gl_enum! {
    pub gl_enum BufferDataUsage {
        StreamDraw as STREAM_DRAW = gl::STREAM_DRAW,
        StaticDraw as STATIC_DRAW = gl::STATIC_DRAW,
        DynamicDraw as DYNAMIC_DRAW = gl::DYNAMIC_DRAW
    }
}

gl_enum! {
    pub gl_enum BufferBindingTarget {
        ArrayBuffer as ARRAY_BUFFER = gl::ARRAY_BUFFER,
        ElementArrayBuffer as ELEMENT_ARRAY_BUFFER = gl::ELEMENT_ARRAY_BUFFER
    }
}

pub trait BufferBinding {
    fn target(&self) -> BufferBindingTarget;

    fn buffer_bytes(&mut self, bytes: &[u8], usage: BufferDataUsage) {
        let ptr = bytes.as_ptr();
        let size = bytes.len() * mem::size_of::<u8>();
        unsafe {
            gl::BufferData(self.target().gl_enum(),
                           size as GLsizeiptr,
                           ptr as *const GLvoid,
                           usage.gl_enum());
            dbg_gl_error! {
                GLError::InvalidEnum => "Invalid `target` or `usage`",
                GLError::InvalidValue => "`size` is negative",
                GLError::InvalidOperation => "Object 0 is bound to buffer target",
                GLError::OutOfMemory => "Unable to create a large enough buffer",
                _ => "Unknown error"
            }
        }
    }
}

pub struct ArrayBufferBinding<'a> {
    phantom: PhantomData<&'a mut Buffer>
}

impl<'a> BufferBinding for ArrayBufferBinding<'a> {
    fn target(&self) -> BufferBindingTarget {
        ARRAY_BUFFER
    }
}

unsafe fn _draw_elements(mode: DrawingMode,
                         count: usize,
                         index_type: IndexDatumType,
                         indices: *const GLvoid)
{
    let gl_index_type: GLenum = match index_type {
        IndexDatumType::UnsignedByte => gl::UNSIGNED_BYTE,
        IndexDatumType::UnsignedShort => gl::UNSIGNED_SHORT
    };
    gl::DrawElements(mode.gl_enum(),
                     count as GLsizei,
                     gl_index_type,
                     indices);
    dbg_gl_error! {
        GLError::InvalidEnum => "`mode` or `type` is not an accepted value",
        GLError::InvalidValue => "`count` is negative",
        GLError::InvalidFramebufferOperation => "The current framebuffer is not framebuffer-complete",
        _ => "Unknown error"
    }
}

impl<'a> ArrayBufferBinding<'a> {
    pub unsafe fn vertex_attrib_pointer(&self,
                                        attrib: super::ProgramAttrib,
                                        components: i8,
                                        gl_type: super::DataType,
                                        normalized: bool,
                                        stride: usize,
                                        offset: usize)
    {
        debug_assert!(1 <= components && components <= 4);

        let gl_normalized = if normalized { gl::TRUE } else { gl::FALSE };
        gl::VertexAttribPointer(attrib.gl_index,
                                components as GLint,
                                gl_type.gl_enum(),
                                gl_normalized,
                                stride as GLsizei,
                                offset as *const GLvoid);
        dbg_gl_error! {
            GLError::InvalidEnum => "Illegal vertex attribute type",
            GLError::InvalidValue => "`stride` is negative, `size` is not in range, or `index` is >= GL_MAX_VERTEX_ATTRIBS",
            GLError::InvalidFramebufferOperation => "Currently bound framebuffer is not framebuffer complete",
            _ => "Unknown error"
        }
    }
}

impl<'a> FramebufferBinding<'a> {
    pub unsafe fn draw_arrays_range(&mut self,
                                    _ab: &ArrayBufferBinding,
                                    mode: DrawingMode,
                                    first: u32,
                                    count: usize)
    {
        gl::DrawArrays(mode.gl_enum(), first as GLint, count as GLsizei);
        dbg_gl_sanity_check! {
            GLError::InvalidEnum => "`mode` is not an accepted value",
            GLError::InvalidValue => "`count` is negative",
            _ => "Unknown error"
        }
    }

    pub unsafe fn draw_n_elements_buffered(&mut self,
                                           _ab: &ArrayBufferBinding,
                                           _eab: &ElementArrayBufferBinding,
                                           mode: DrawingMode,
                                           count: usize,
                                           index_type: IndexDatumType)
    {
        _draw_elements(mode, count, index_type, ptr::null());
    }

    pub unsafe fn draw_n_elements<I>(&mut self,
                                     _ab: &ArrayBufferBinding,
                                     mode: DrawingMode,
                                     count: usize,
                                     indices: &[I])
        where I: IndexDatum, [I]: IndexData
    {
        debug_assert!(count <= indices.len());

        let ptr = indices.index_bytes().as_ptr();
        let index_type = I::index_datum_type();
        _draw_elements(mode, count, index_type, mem::transmute(ptr));
    }

    pub unsafe fn draw_elements<I>(&mut self,
                                   _ab: &ArrayBufferBinding,
                                   mode: DrawingMode,
                                   indices: &[I])
        where I: IndexDatum, [I]: IndexData
    {
        self.draw_n_elements(_ab, mode, indices.len(), indices);
    }
}

pub struct ElementArrayBufferBinding<'a> {
    phantom: PhantomData<&'a mut Buffer>
}

impl<'a> BufferBinding for ElementArrayBufferBinding<'a> {
    fn target(&self) -> BufferBindingTarget {
        ELEMENT_ARRAY_BUFFER
    }
}

fn _bind_buffer(target: BufferBindingTarget, buffer: &mut Buffer) {
    unsafe {
        gl::BindBuffer(target as GLuint, buffer.gl_id());
        dbg_gl_sanity_check! {
            GLError::InvalidEnum => "`target` is not an allowed value",
            _ => "Unknown error"
        }
    }
}

pub struct BufferBinderOf<A, E> {
    array: A,
    element_array: E
}

pub type BufferBinder = BufferBinderOf<ArrayBufferBinder,
                                       ElementArrayBufferBinder>;

pub type BufferBinderRef<'a> = BufferBinderOf<&'a ArrayBufferBinder,
                                              &'a ElementArrayBufferBinder>;

pub type BufferBinderMut<'a> = BufferBinderOf<&'a mut ArrayBufferBinder,
                                              &'a mut ElementArrayBufferBinder>;

impl<A, E> BufferBinderOf<A, E> {
    pub unsafe fn current() -> BufferBinder {
        BufferBinderOf {
            array: ArrayBufferBinder,
            element_array: ElementArrayBufferBinder
        }
    }

    pub fn borrowed<'a, BA = A, BE = E>(&'a self)
        -> BufferBinderOf<&'a BA, &'a BE>
        where A: Borrow<BA>,
              E: Borrow<BE>
    {
        BufferBinderOf {
            array: self.array.borrow(),
            element_array: self.element_array.borrow()
        }
    }

    pub fn borrowed_mut<'a, BA = A, BE = E>(&'a mut self)
        -> BufferBinderOf<&'a mut BA, &'a mut BE>
        where A: BorrowMut<BA>,
              E: BorrowMut<BE>
    {
        BufferBinderOf {
            array: self.array.borrow_mut(),
            element_array: self.element_array.borrow_mut()
        }
    }

    pub fn split_array(self) -> (A, BufferBinderOf<(), E>) {
        (
            self.array,
            BufferBinderOf {
                array: (),
                element_array: self.element_array
            }
        )
    }

    pub fn split_element_array(self) -> (E, BufferBinderOf<A, ()>) {
        (
            self.element_array,
            BufferBinderOf {
                array: self.array,
                element_array: ()
            }
        )
    }
}

impl<'a, A, E, AI, EI> RefInto<'a, BufferBinderOf<AI, EI>>
    for BufferBinderOf<A, E>
    where A: RefInto<'a, AI>,
          E: RefInto<'a, EI>,
          AI: 'a, EI: 'a
{
    fn ref_into(&'a self) -> BufferBinderOf<AI, EI> {
        BufferBinderOf {
            array: self.array.ref_into(),
            element_array: self.element_array.ref_into()
        }
    }
}

impl<'a, A, E, AI, EI> RefInto<'a, BufferBinderOf<AI, EI>>
    for &'a BufferBinderOf<A, E>
    where A: RefInto<'a, AI>,
          E: RefInto<'a, EI>,
          AI: 'a, EI: 'a
{
    fn ref_into(&'a self) -> BufferBinderOf<AI, EI> {
        BufferBinderOf {
            array: self.array.ref_into(),
            element_array: self.element_array.ref_into()
        }
    }
}

impl<'a, A, E, AI, EI> MutInto<'a, BufferBinderOf<AI, EI>>
    for BufferBinderOf<A, E>
    where A: MutInto<'a, AI>,
          E: MutInto<'a, EI>,
          AI: 'a, EI: 'a
{
    fn mut_into(&'a mut self) -> BufferBinderOf<AI, EI> {
        BufferBinderOf {
            array: self.array.mut_into(),
            element_array: self.element_array.mut_into()
        }
    }
}

impl<'a, A, E, AI, EI> MutInto<'a, BufferBinderOf<AI, EI>>
    for &'a BufferBinderOf<A, E>
    where A: RefInto<'a, AI>,
          E: RefInto<'a, EI>,
          AI: 'a, EI: 'a
{
    fn mut_into(&'a mut self) -> BufferBinderOf<AI, EI> {
        BufferBinderOf {
            array: self.array.ref_into(),
            element_array: self.element_array.ref_into()
        }
    }
}

impl<'a, A, E, AI, EI> MutInto<'a, BufferBinderOf<AI, EI>>
    for &'a mut BufferBinderOf<A, E>
    where A: MutInto<'a, AI>,
          E: MutInto<'a, EI>,
          AI: 'a, EI: 'a
{
    fn mut_into(&'a mut self) -> BufferBinderOf<AI, EI> {
        BufferBinderOf {
            array: self.array.mut_into(),
            element_array: self.element_array.mut_into()
        }
    }
}

pub struct ArrayBufferBinder;
impl ArrayBufferBinder {
    pub fn bind<'a>(&mut self, buffer: &'a mut Buffer) -> ArrayBufferBinding<'a>
    {
        let binding = ArrayBufferBinding { phantom: PhantomData };
        _bind_buffer(binding.target(), buffer);
        binding
    }
}

pub struct ElementArrayBufferBinder;
impl ElementArrayBufferBinder {
    pub fn bind<'a>(&mut self, buffer: &'a mut Buffer)
        -> ElementArrayBufferBinding<'a>
    {
        let binding = ElementArrayBufferBinding { phantom: PhantomData };
        _bind_buffer(binding.target(), buffer);
        binding
    }
}
<|endoftext|>


<commit_before>use crate::runtime::{yield_now, Arc, Mutex};
use crate::BatchFn;
use std::collections::{HashMap, HashSet};
use std::fmt::Debug;
use std::hash::{BuildHasher, Hash};

pub trait Cache {
    type Key;
    type Val;
    fn get(&self, key: &Self::Key) -> Option<&Self::Val>;
    fn insert(&mut self, key: Self::Key, val: Self::Val);
    fn remove(&mut self, key: &Self::Key) -> Option<Self::Val>;
    fn clear(&mut self);
}

impl<K, V, S: BuildHasher> Cache for HashMap<K, V, S>
where
    K: Eq + Hash,
{
    type Key = K;
    type Val = V;

    #[inline]
    fn get(&self, key: &K) -> Option<&V> {
        HashMap::get(self, key)
    }

    #[inline]
    fn insert(&mut self, key: K, val: V) {
        HashMap::insert(self, key, val);
    }

    #[inline]
    fn remove(&mut self, key: &K) -> Option<V> {
        HashMap::remove(self, key)
    }

    #[inline]
    fn clear(&mut self) {
        HashMap::clear(self)
    }
}

struct State<K, V, C = HashMap<K, V>>
where
    C: Cache<Key = K, Val = V>,
{
    completed: C,
    pending: HashSet<K>,
}

impl<K: Eq + Hash, V, C> State<K, V, C>
where
    C: Cache<Key = K, Val = V>,
{
    fn with_cache(cache: C) -> Self {
        State {
            completed: cache,
            pending: HashSet::new(),
        }
    }
}

pub struct Loader<K, V, F, C = HashMap<K, V>>
where
    K: Eq + Hash + Clone,
    V: Clone,
    F: BatchFn<K, V>,
    C: Cache<Key = K, Val = V>,
{
    state: Arc<Mutex<State<K, V, C>>>,
    load_fn: Arc<Mutex<F>>,
    yield_count: usize,
    max_batch_size: usize,
}

impl<K, V, F, C> Clone for Loader<K, V, F, C>
where
    K: Eq + Hash + Clone,
    V: Clone,
    F: BatchFn<K, V>,
    C: Cache<Key = K, Val = V>,
{
    fn clone(&self) -> Self {
        Loader {
            state: self.state.clone(),
            max_batch_size: self.max_batch_size,
            load_fn: self.load_fn.clone(),
            yield_count: self.yield_count,
        }
    }
}

#[allow(clippy::implicit_hasher)]
impl<K, V, F> Loader<K, V, F, HashMap<K, V>>
where
    K: Eq + Hash + Clone + Debug,
    V: Clone,
    F: BatchFn<K, V>,
{
    pub fn new(load_fn: F) -> Loader<K, V, F, HashMap<K, V>> {
        Loader::with_cache(load_fn, HashMap::new())
    }
}

impl<K, V, F, C> Loader<K, V, F, C>
where
    K: Eq + Hash + Clone + Debug,
    V: Clone,
    F: BatchFn<K, V>,
    C: Cache<Key = K, Val = V>,
{
    pub fn with_cache(load_fn: F, cache: C) -> Loader<K, V, F, C> {
        Loader {
            state: Arc::new(Mutex::new(State::with_cache(cache))),
            load_fn: Arc::new(Mutex::new(load_fn)),
            max_batch_size: 200,
            yield_count: 10,
        }
    }

    pub fn with_max_batch_size(mut self, max_batch_size: usize) -> Self {
        self.max_batch_size = max_batch_size;
        self
    }

    pub fn with_yield_count(mut self, yield_count: usize) -> Self {
        self.yield_count = yield_count;
        self
    }

    pub fn max_batch_size(&self) -> usize {
        self.max_batch_size
    }

    pub async fn load(&self, key: K) -> V {
        let mut state = self.state.lock().await;
        if let Some(v) = state.completed.get(&key) {
            return (*v).clone();
        }

        if state.pending.get(&key).is_none() {
            state.pending.insert(key.clone());
            if state.pending.len() >= self.max_batch_size {
                let keys = state.pending.drain().collect::<Vec<K>>();
                let mut load_fn = self.load_fn.lock().await;
                let load_ret = load_fn.load(keys.as_ref()).await;
                drop(load_fn);
                for (k, v) in load_ret.into_iter() {
                    state.completed.insert(k, v);
                }
                return state
                    .completed
                    .get(&key)
                    .cloned()
                    .unwrap_or_else(|| panic!("found key {:?} in load result", key));
            }
        }
        drop(state);

        // yield for other load to append request
        let mut i = 0;
        while i < self.yield_count {
            yield_now().await;
            i += 1;
        }

        let mut state = self.state.lock().await;
        if let Some(v) = state.completed.get(&key) {
            return (*v).clone();
        }

        if !state.pending.is_empty() {
            let keys = state.pending.drain().collect::<Vec<K>>();
            let mut load_fn = self.load_fn.lock().await;
            let load_ret = load_fn.load(keys.as_ref()).await;
            drop(load_fn);
            for (k, v) in load_ret.into_iter() {
                state.completed.insert(k, v);
            }
        }

        state
            .completed
            .get(&key)
            .cloned()
            .unwrap_or_else(|| panic!("found key {:?} in load result", key))
    }

    pub async fn load_many(&self, keys: Vec<K>) -> HashMap<K, V> {
        let mut state = self.state.lock().await;
        let mut ret = HashMap::new();
        let mut rest = Vec::new();
        for key in keys.into_iter() {
            if let Some(v) = state.completed.get(&key).cloned() {
                ret.insert(key, v);
                continue;
            }
            if state.pending.get(&key).is_none() {
                state.pending.insert(key.clone());
                if state.pending.len() >= self.max_batch_size {
                    let keys = state.pending.drain().collect::<Vec<K>>();
                    let mut load_fn = self.load_fn.lock().await;
                    let load_ret = load_fn.load(keys.as_ref()).await;
                    drop(load_fn);
                    for (k, v) in load_ret.into_iter() {
                        state.completed.insert(k, v);
                    }
                }
            }
            rest.push(key);
        }
        drop(state);

        // yield for other load to append request
        let mut i = 0;
        while i < self.yield_count {
            yield_now().await;
            i += 1;
        }

        if !rest.is_empty() {
            let mut state = self.state.lock().await;
            if !state.pending.is_empty() {
                let keys = state.pending.drain().collect::<Vec<K>>();
                let mut load_fn = self.load_fn.lock().await;
                let load_ret = load_fn.load(keys.as_ref()).await;
                drop(load_fn);
                for (k, v) in load_ret.into_iter() {
                    state.completed.insert(k, v);
                }
            }

            for key in rest.into_iter() {
                let v = state
                    .completed
                    .get(&key)
                    .cloned()
                    .unwrap_or_else(|| panic!("found key {:?} in load result", key));
                ret.insert(key, v);
            }
        }

        ret
    }

    pub async fn prime(&self, key: K, val: V) {
        let mut state = self.state.lock().await;
        state.completed.insert(key, val);
    }

    pub async fn clear(&self, key: K) {
        let mut state = self.state.lock().await;
        state.completed.remove(&key);
    }

    pub async fn clear_all(&self) {
        let mut state = self.state.lock().await;
        state.completed.clear()
    }
}
<commit_msg>add prime_many<commit_after>use crate::runtime::{yield_now, Arc, Mutex};
use crate::BatchFn;
use std::collections::{HashMap, HashSet};
use std::fmt::Debug;
use std::hash::{BuildHasher, Hash};
use std::iter::IntoIterator;

pub trait Cache {
    type Key;
    type Val;
    fn get(&self, key: &Self::Key) -> Option<&Self::Val>;
    fn insert(&mut self, key: Self::Key, val: Self::Val);
    fn remove(&mut self, key: &Self::Key) -> Option<Self::Val>;
    fn clear(&mut self);
}

impl<K, V, S: BuildHasher> Cache for HashMap<K, V, S>
where
    K: Eq + Hash,
{
    type Key = K;
    type Val = V;

    #[inline]
    fn get(&self, key: &K) -> Option<&V> {
        HashMap::get(self, key)
    }

    #[inline]
    fn insert(&mut self, key: K, val: V) {
        HashMap::insert(self, key, val);
    }

    #[inline]
    fn remove(&mut self, key: &K) -> Option<V> {
        HashMap::remove(self, key)
    }

    #[inline]
    fn clear(&mut self) {
        HashMap::clear(self)
    }
}

struct State<K, V, C = HashMap<K, V>>
where
    C: Cache<Key = K, Val = V>,
{
    completed: C,
    pending: HashSet<K>,
}

impl<K: Eq + Hash, V, C> State<K, V, C>
where
    C: Cache<Key = K, Val = V>,
{
    fn with_cache(cache: C) -> Self {
        State {
            completed: cache,
            pending: HashSet::new(),
        }
    }
}

pub struct Loader<K, V, F, C = HashMap<K, V>>
where
    K: Eq + Hash + Clone,
    V: Clone,
    F: BatchFn<K, V>,
    C: Cache<Key = K, Val = V>,
{
    state: Arc<Mutex<State<K, V, C>>>,
    load_fn: Arc<Mutex<F>>,
    yield_count: usize,
    max_batch_size: usize,
}

impl<K, V, F, C> Clone for Loader<K, V, F, C>
where
    K: Eq + Hash + Clone,
    V: Clone,
    F: BatchFn<K, V>,
    C: Cache<Key = K, Val = V>,
{
    fn clone(&self) -> Self {
        Loader {
            state: self.state.clone(),
            max_batch_size: self.max_batch_size,
            load_fn: self.load_fn.clone(),
            yield_count: self.yield_count,
        }
    }
}

#[allow(clippy::implicit_hasher)]
impl<K, V, F> Loader<K, V, F, HashMap<K, V>>
where
    K: Eq + Hash + Clone + Debug,
    V: Clone,
    F: BatchFn<K, V>,
{
    pub fn new(load_fn: F) -> Loader<K, V, F, HashMap<K, V>> {
        Loader::with_cache(load_fn, HashMap::new())
    }
}

impl<K, V, F, C> Loader<K, V, F, C>
where
    K: Eq + Hash + Clone + Debug,
    V: Clone,
    F: BatchFn<K, V>,
    C: Cache<Key = K, Val = V>,
{
    pub fn with_cache(load_fn: F, cache: C) -> Loader<K, V, F, C> {
        Loader {
            state: Arc::new(Mutex::new(State::with_cache(cache))),
            load_fn: Arc::new(Mutex::new(load_fn)),
            max_batch_size: 200,
            yield_count: 10,
        }
    }

    pub fn with_max_batch_size(mut self, max_batch_size: usize) -> Self {
        self.max_batch_size = max_batch_size;
        self
    }

    pub fn with_yield_count(mut self, yield_count: usize) -> Self {
        self.yield_count = yield_count;
        self
    }

    pub fn max_batch_size(&self) -> usize {
        self.max_batch_size
    }

    pub async fn load(&self, key: K) -> V {
        let mut state = self.state.lock().await;
        if let Some(v) = state.completed.get(&key) {
            return (*v).clone();
        }

        if state.pending.get(&key).is_none() {
            state.pending.insert(key.clone());
            if state.pending.len() >= self.max_batch_size {
                let keys = state.pending.drain().collect::<Vec<K>>();
                let mut load_fn = self.load_fn.lock().await;
                let load_ret = load_fn.load(keys.as_ref()).await;
                drop(load_fn);
                for (k, v) in load_ret.into_iter() {
                    state.completed.insert(k, v);
                }
                return state
                    .completed
                    .get(&key)
                    .cloned()
                    .unwrap_or_else(|| panic!("found key {:?} in load result", key));
            }
        }
        drop(state);

        // yield for other load to append request
        let mut i = 0;
        while i < self.yield_count {
            yield_now().await;
            i += 1;
        }

        let mut state = self.state.lock().await;
        if let Some(v) = state.completed.get(&key) {
            return (*v).clone();
        }

        if !state.pending.is_empty() {
            let keys = state.pending.drain().collect::<Vec<K>>();
            let mut load_fn = self.load_fn.lock().await;
            let load_ret = load_fn.load(keys.as_ref()).await;
            drop(load_fn);
            for (k, v) in load_ret.into_iter() {
                state.completed.insert(k, v);
            }
        }

        state
            .completed
            .get(&key)
            .cloned()
            .unwrap_or_else(|| panic!("found key {:?} in load result", key))
    }

    pub async fn load_many(&self, keys: Vec<K>) -> HashMap<K, V> {
        let mut state = self.state.lock().await;
        let mut ret = HashMap::new();
        let mut rest = Vec::new();
        for key in keys.into_iter() {
            if let Some(v) = state.completed.get(&key).cloned() {
                ret.insert(key, v);
                continue;
            }
            if state.pending.get(&key).is_none() {
                state.pending.insert(key.clone());
                if state.pending.len() >= self.max_batch_size {
                    let keys = state.pending.drain().collect::<Vec<K>>();
                    let mut load_fn = self.load_fn.lock().await;
                    let load_ret = load_fn.load(keys.as_ref()).await;
                    drop(load_fn);
                    for (k, v) in load_ret.into_iter() {
                        state.completed.insert(k, v);
                    }
                }
            }
            rest.push(key);
        }
        drop(state);

        // yield for other load to append request
        let mut i = 0;
        while i < self.yield_count {
            yield_now().await;
            i += 1;
        }

        if !rest.is_empty() {
            let mut state = self.state.lock().await;
            if !state.pending.is_empty() {
                let keys = state.pending.drain().collect::<Vec<K>>();
                let mut load_fn = self.load_fn.lock().await;
                let load_ret = load_fn.load(keys.as_ref()).await;
                drop(load_fn);
                for (k, v) in load_ret.into_iter() {
                    state.completed.insert(k, v);
                }
            }

            for key in rest.into_iter() {
                let v = state
                    .completed
                    .get(&key)
                    .cloned()
                    .unwrap_or_else(|| panic!("found key {:?} in load result", key));
                ret.insert(key, v);
            }
        }

        ret
    }

    pub async fn prime(&self, key: K, val: V) {
        let mut state = self.state.lock().await;
        state.completed.insert(key, val);
    }

    pub async fn prime_many(&self, values: impl IntoIterator<Item = (K, V)>) {
        let mut state = self.state.lock().await;
        for (k, v) in values.into_iter() {
            state.completed.insert(k, v);
        }
    }

    pub async fn clear(&self, key: K) {
        let mut state = self.state.lock().await;
        state.completed.remove(&key);
    }

    pub async fn clear_all(&self) {
        let mut state = self.state.lock().await;
        state.completed.clear()
    }
}
<|endoftext|>


<commit_before>/// An iterator whose items are random accessible efficiently
///
/// # Safety
///
/// The iterator's .len() and size_hint() must be exact.
/// `.len()` must be cheap to call.
///
/// .get_unchecked() must return distinct mutable references for distinct
/// indices (if applicable), and must return a valid reference if index is in
/// 0..self.len().
#[doc(hidden)]
pub unsafe trait TrustedRandomAccess : ExactSizeIterator {
    unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item;
    /// Returns `true` if getting an iterator element may have
    /// side effects. Remember to take inner iterators into account.
    fn may_have_side_effect() -> bool;
}
<commit_msg>Remove iter_private.rs<commit_after><|endoftext|>


<commit_before>use std::fs;
use std::io;
use std::path::Path;
use std::sync::Arc;

use memmap::{Mmap, Protection};

/// A read only view into a memory map.
///
/// Reading a memory map is unsafe because we cannot guarantee that its
/// underlying memory is not mutated by external processes. This read only
/// memory map guarantees that consumers can at least never modify the
/// underlying data.
///
/// It is principally useful for controlling which region of a file an `Fst`
/// reads. Taking a slice from it is still considered unsafe.
pub struct MmapReadOnly {
    map: Arc<Mmap>,
    offset: usize,
    len: usize,
}

impl MmapReadOnly {
    /// Create a new memory map from an existing file handle.
    pub fn open(file: &fs::File) -> io::Result<MmapReadOnly> {
        Ok(try!(Mmap::open(file, Protection::Read)).into())
    }

    /// Open a new memory map from the path given.
    pub fn open_path<P: AsRef<Path>>(path: P) -> io::Result<MmapReadOnly> {
        MmapReadOnly::open(&try!(fs::File::open(path)))
    }

    /// Returns the size in byte of the memory map.
    ///
    /// If it is a range, the size is the size of the range.
    pub fn len(&self,) -> usize {
        self.len
    }

    /// Slice this memory map to a new `offset` and `len`.
    ///
    /// If the new range is outside the bounds of `self`, then this method
    /// panics.
    pub fn range(&self, offset: usize, len: usize) -> MmapReadOnly {
        assert!(offset + len <= self.len);
        MmapReadOnly {
            map: self.map.clone(),
            offset: self.offset + offset,
            len: len,
        }
    }

    /// Read the memory map as a `&[u8]`.
    pub unsafe fn as_slice(&self) -> &[u8] {
        self.map.as_slice()
    }
}

impl Clone for MmapReadOnly {
    fn clone(&self) -> MmapReadOnly {
        MmapReadOnly{
            map: self.map.clone(),
            offset: self.offset,
            len: self.len,
        }
    }
}

impl From<Mmap> for MmapReadOnly {
    fn from(mmap: Mmap) -> MmapReadOnly {
        let len = mmap.len();
        MmapReadOnly {
            map: Arc::new(mmap),
            offset: 0,
            len: len,
        }
    }
}
<commit_msg>Closes #14 as_slice returns the &[u8] slice implied by offset and len.<commit_after>use std::fs;
use std::io;
use std::path::Path;
use std::sync::Arc;

use memmap::{Mmap, Protection};

/// A read only view into a memory map.
///
/// Reading a memory map is unsafe because we cannot guarantee that its
/// underlying memory is not mutated by external processes. This read only
/// memory map guarantees that consumers can at least never modify the
/// underlying data.
///
/// It is principally useful for controlling which region of a file an `Fst`
/// reads. Taking a slice from it is still considered unsafe.
pub struct MmapReadOnly {
    map: Arc<Mmap>,
    offset: usize,
    len: usize,
}

impl MmapReadOnly {
    /// Create a new memory map from an existing file handle.
    pub fn open(file: &fs::File) -> io::Result<MmapReadOnly> {
        Ok(try!(Mmap::open(file, Protection::Read)).into())
    }

    /// Open a new memory map from the path given.
    pub fn open_path<P: AsRef<Path>>(path: P) -> io::Result<MmapReadOnly> {
        MmapReadOnly::open(&try!(fs::File::open(path)))
    }

    /// Returns the size in byte of the memory map.
    ///
    /// If it is a range, the size is the size of the range.
    pub fn len(&self,) -> usize {
        self.len
    }

    /// Slice this memory map to a new `offset` and `len`.
    ///
    /// If the new range is outside the bounds of `self`, then this method
    /// panics.
    pub fn range(&self, offset: usize, len: usize) -> MmapReadOnly {
        assert!(offset + len <= self.len);
        MmapReadOnly {
            map: self.map.clone(),
            offset: self.offset + offset,
            len: len,
        }
    }

    /// Read the memory map as a `&[u8]`.
    pub unsafe fn as_slice(&self) -> &[u8] {
        &self.map.as_slice()[self.offset..self.offset + self.len]
    }
}

impl Clone for MmapReadOnly {
    fn clone(&self) -> MmapReadOnly {
        MmapReadOnly{
            map: self.map.clone(),
            offset: self.offset,
            len: self.len,
        }
    }
}

impl From<Mmap> for MmapReadOnly {
    fn from(mmap: Mmap) -> MmapReadOnly {
        let len = mmap.len();
        MmapReadOnly {
            map: Arc::new(mmap),
            offset: 0,
            len: len,
        }
    }
}
<|endoftext|>


<commit_before>/// Run as an application, this is the starting point for our app

extern crate rustc_serialize;

use rustc_serialize::json::Json;
use std::slice::SliceConcatExt;

use std::process::Command;
use std::path::Path;
use std::vec::Vec;
use std::{env, fs};

pub enum ClippyState {
    Success,
    WithWarnings,
    WithErrors,
}

pub struct ClippyResult {
    pub ended: ClippyState,
    pub warnings: u8,
    pub errors: u8,
}

pub fn run<F>(path: &Path, logger: F) -> Result<ClippyResult, String>
    where F: Fn(&str)
{

    let libs_path = env::current_exe().unwrap();
    let libs_path = fs::canonicalize(libs_path).unwrap();
    let libs_path = libs_path.parent().unwrap();
    let libs_path = libs_path.join("deps");

    match Command::new("firejail")
              .args(&["--profile=/etc/firejail/cargo.profile",
                      format!("--whitelist={}",
                      &path.to_string_lossy().into_owned()).as_str(),
                      "cargo",
                      "rustc",
                      "--",
                      "-L",
                      &libs_path.to_string_lossy().into_owned(),
                      "-Zunstable-options",
                      "-Zextra-plugins=clippy",
                      "-Zno-trans",
                      "-lclippy",
                      "--error-format=json"])
              .current_dir(path)
              .output() {
        Ok(output) => {
            let mut warnings = 0;
            let mut errors = 0;
            let messages: Vec<String> = String::from_utf8(output.stderr)
                                            .unwrap()
                                            .split('\n')
                                            .filter_map(|line| Json::from_str(&line).ok())
                                            .filter_map(|json| {
                                                let obj = json.as_object().unwrap();
                                                match obj.get("level") {
                                                    Some(&Json::String(ref level)) => {
                                                        if level == "warning" {
                                                            warnings += 1;
                                                        } else if level == "error" {
                                                            errors += 1;
                                                        }
                                                        Some(format!("{level}: {msg}",
                                                                     level = level,
                                                                     msg = obj.get("message")
                                                                              .unwrap()))
                                                    }
                                                    _ => None,
                                                }
                                            })
                                            .collect();

            logger(&format!("Messages:\n {}", messages.join("\n")));

            if output.status.success() {
                match (errors, warnings) {
                    (0, 0) => {
                        Ok(ClippyResult {
                            ended: ClippyState::Success,
                            warnings: 0,
                            errors: 0,
                        })
                    }
                    (0, x) => {
                        Ok(ClippyResult {
                            ended: ClippyState::WithWarnings,
                            warnings: x,
                            errors: 0,
                        })
                    }
                    _ => {
                        Ok(ClippyResult {
                            ended: ClippyState::WithErrors,
                            warnings: warnings,
                            errors: errors,
                        })
                    }
                }
            } else {
                Err(format!("Clippy failed with Error code: {}",
                            output.status.code().unwrap_or(-999)))
            }
        }
        Err(error) => Err(format!("Running Clippy failed: {}", error)),
    }
}
<commit_msg>improved output for easier debugging<commit_after>/// Run as an application, this is the starting point for our app

extern crate rustc_serialize;

use rustc_serialize::json::Json;
use std::slice::SliceConcatExt;

use std::process::Command;
use std::path::Path;
use std::vec::Vec;
use std::{env, fs};

pub enum ClippyState {
    Success,
    WithWarnings,
    WithErrors,
}

pub struct ClippyResult {
    pub ended: ClippyState,
    pub warnings: u8,
    pub errors: u8,
}

pub fn run<F>(path: &Path, logger: F) -> Result<ClippyResult, String>
    where F: Fn(&str)
{

    let libs_path = env::current_exe().unwrap();
    let libs_path = fs::canonicalize(libs_path).unwrap();
    let libs_path = libs_path.parent().unwrap();
    let libs_path = libs_path.join("deps");

    match Command::new("firejail")
              .args(&["--profile=/etc/firejail/cargo.profile",
                      format!("--whitelist={}",
                      &path.to_string_lossy().into_owned()).as_str(),
                      "cargo",
                      "rustc",
                      "--",
                      "-L",
                      &libs_path.to_string_lossy().into_owned(),
                      "-Zunstable-options",
                      "-Zextra-plugins=clippy",
                      "-Zno-trans",
                      "-lclippy",
                      "--error-format=json"])
              .current_dir(path)
              .output() {
        Ok(output) => {
            let stdout = String::from_utf8(output.stdout).unwrap();
            let stderr = String::from_utf8(output.stderr).unwrap();
            logger(&format!("----- stdout:\n{}", &stdout));
            logger(&format!("----- stderr:\n{}", &stderr));
            let mut warnings = 0;
            let mut errors = 0;
            let messages: Vec<String> = stderr.split('\n')
                                            .filter_map(|line| Json::from_str(&line).ok())
                                            .filter_map(|json| {
                                                let obj = json.as_object().unwrap();
                                                match obj.get("level") {
                                                    Some(&Json::String(ref level)) => {
                                                        if level == "warning" {
                                                            warnings += 1;
                                                        } else if level == "error" {
                                                            errors += 1;
                                                        }
                                                        Some(format!("{level}: {msg}",
                                                                     level = level,
                                                                     msg = obj.get("message")
                                                                              .unwrap()))
                                                    }
                                                    _ => None,
                                                }
                                            })
                                            .collect();

            logger(&format!("-----\nMessages identified:\n {}", messages.join("\n")));

            if output.status.success() {
                match (errors, warnings) {
                    (0, 0) => {
                        Ok(ClippyResult {
                            ended: ClippyState::Success,
                            warnings: 0,
                            errors: 0,
                        })
                    }
                    (0, x) => {
                        Ok(ClippyResult {
                            ended: ClippyState::WithWarnings,
                            warnings: x,
                            errors: 0,
                        })
                    }
                    _ => {
                        Ok(ClippyResult {
                            ended: ClippyState::WithErrors,
                            warnings: warnings,
                            errors: errors,
                        })
                    }
                }
            } else {
                Err(format!("Clippy failed with Error code: {}",
                            output.status.code().unwrap_or(-999)))
            }
        }
        Err(error) => Err(format!("Running Clippy failed: {}", error)),
    }
}
<|endoftext|>