<commit_before>#![allow(deprecated)]
extern crate cupi;

use cupi::*;
use std::time::Duration;

static CGRAM_ADDRESS: u8 = 0x40;
static RS_COMMAND: bool = false;
static RS_DATA: bool = true;

pub struct HD44780 {
    //rs: PinOutput,
    //e: PinOutput,
    //data: Vec<PinOutput>,
    disp_rs: u32,
    disp_e: u32,
    datalines: [u32; 4],
    raspi: CuPi,
    cols: u32,
    rows: u32,
    lines: Vec<u8>,
}

impl HD44780 {
    pub fn new(disp_rs: u32,
               disp_e: u32,
               datalines: [u32; 4],
               disp_cols: u32,
               disp_rows: u32)
               -> HD44780 {
        let raspi = CuPi::new().unwrap();
        //let mut rs = raspi.pin(disp_rs as usize).unwrap().output();
        //let mut e = raspi.pin(disp_e as usize).unwrap().output();
        //let mut data: Vec<PinOutput> = Vec::new();
        let lines: Vec<u8>;

        //for x in 0..4 {
        //    data[x] = raspi.pin(datalines[x] as usize).unwrap().output();
        //}

        match disp_rows {
            1 => lines = vec![0x80],
            2 => lines = vec![0x80, 0xC0],
            3 => lines = vec![0x80, 0xC0, 0x94],
            4 => lines = vec![0x80, 0xC0, 0x94, 0xD4],
            _ => lines = vec![0x80],
        };

        let result = HD44780 {
            disp_rs: disp_rs,
            disp_e: disp_e,
            datalines: datalines,
            raspi: raspi,
            cols: disp_cols,
            rows: disp_rows,
            lines: lines,
        };

        result
    }

    pub fn init(&self) {
        HD44780::command(self, 0x33);
        HD44780::command(self, 0x32);
        HD44780::command(self, 0x28);
        HD44780::command(self, 0x0C);
        HD44780::command(self, 0x06);
        HD44780::clean(self);
    }
    pub fn clean(&self) {
        // clean display
        HD44780::command(self, 0x01);
    }

    pub fn command(&self, bits: u8) {
        // send command
        HD44780::send_byte(self, bits, RS_COMMAND);
    }

    pub fn send_string(&self, text: String, row: u32) {
        // prepare String to write it to the LCD
        let mut message: Vec<u8> = Vec::new();
        let col = self.cols;
        let row = row % self.rows;

        // TODO: implement check for custom characters

        for i in text.chars() {
            message.push(i as u8);
        }

        message.truncate(col as usize);

        self.select_row(row);
        self.write(message);
    }

    pub fn create_char(&self, address: u8, bitmap: [u8; 8]) {
        // TODO: Check for address in range 0..8
        // send new custom character to cgram address

        self.command(CGRAM_ADDRESS | address << 3);
        for row in 0..bitmap.len() {
            HD44780::send_byte(self, bitmap[row as usize], RS_DATA);
        }
    }

    fn e_wait() {
        std::thread::sleep(Duration::new(0, 50));
    }

    fn select_row(&self, row: u32) {
        // select the row where the String should be printed at
        HD44780::send_byte(self, self.lines[row as usize], RS_COMMAND);
    }

    fn write(&self, charlist: Vec<u8>) {
        // send every single char to send_byte
        for x in charlist {
            HD44780::send_byte(self, x, RS_DATA);
        }
    }

    fn send_byte(&self, bits: u8, mode: bool) {
        let mut rs = self.raspi.pin(self.disp_rs as usize).unwrap().output();
        let mut e = self.raspi.pin(self.disp_e as usize).unwrap().output();
        let mut data: Vec<PinOutput> = Vec::new();
        for x in 0..4 {
            data.push(self.raspi.pin(self.datalines[x] as usize).unwrap().output());
        }

        if mode {
            rs.high().unwrap();
        } else {
            rs.low().unwrap();
        }
        data[0].low().unwrap();
        data[1].low().unwrap();
        data[2].low().unwrap();
        data[3].low().unwrap();
        if bits & 0x10 == 0x10 {
            data[0].high().unwrap();
        }
        if bits & 0x20 == 0x20 {
            data[1].high().unwrap();
        }
        if bits & 0x40 == 0x40 {
            data[2].high().unwrap();
        }
        if bits & 0x80 == 0x80 {
            data[3].high().unwrap();
        }
        HD44780::e_wait();
        e.high().unwrap();
        HD44780::e_wait();
        e.low().unwrap();
        data[0].low().unwrap();
        data[1].low().unwrap();
        data[2].low().unwrap();
        data[3].low().unwrap();
        if bits & 0x01 == 0x01 {
            data[0].high().unwrap();
        }
        if bits & 0x02 == 0x02 {
            data[1].high().unwrap();
        }
        if bits & 0x04 == 0x04 {
            data[2].high().unwrap();
        }
        if bits & 0x08 == 0x08 {
            data[3].high().unwrap();
        }
        HD44780::e_wait();
        e.high().unwrap();
        HD44780::e_wait();
        e.low().unwrap();
    }
}
<commit_msg>use self. istread of HD44780::<commit_after>#![allow(deprecated)]
extern crate cupi;

use cupi::*;
use std::time::Duration;

static CGRAM_ADDRESS: u8 = 0x40;
static RS_COMMAND: bool = false;
static RS_DATA: bool = true;

pub struct HD44780 {
    disp_rs: u32,
    disp_e: u32,
    datalines: [u32; 4],
    raspi: CuPi,
    cols: u32,
    rows: u32,
    lines: Vec<u8>,
}

impl HD44780 {
    pub fn new(disp_rs: u32,
               disp_e: u32,
               datalines: [u32; 4],
               disp_cols: u32,
               disp_rows: u32)
               -> HD44780 {
        let raspi = CuPi::new().unwrap();

        let lines: Vec<u8>;

        match disp_rows {
            1 => lines = vec![0x80],
            2 => lines = vec![0x80, 0xC0],
            3 => lines = vec![0x80, 0xC0, 0x94],
            4 => lines = vec![0x80, 0xC0, 0x94, 0xD4],
            _ => lines = vec![0x80],
        };

        let result = HD44780 {
            disp_rs: disp_rs,
            disp_e: disp_e,
            datalines: datalines,
            raspi: raspi,
            cols: disp_cols,
            rows: disp_rows,
            lines: lines,
        };

        result
    }

    pub fn init(&self) {
        self.command(0x33);
        self.command(0x32);
        self.command(0x28);
        self.command(0x0C);
        self.command(0x06);
        self.clean();
    }
    pub fn clean(&self) {
        // clean display
        self.command(0x01);
    }

    pub fn command(&self, bits: u8) {
        // send command
        self.send_byte(bits, RS_COMMAND);
    }

    pub fn send_string(&self, text: String, row: u32) {
        // prepare String to write it to the LCD
        let mut message: Vec<u8> = Vec::new();
        let col = self.cols;
        let row = row % self.rows;

        // TODO: implement check for custom characters

        for i in text.chars() {
            message.push(i as u8);
        }

        message.truncate(col as usize);

        self.select_row(row);
        self.write(message);
    }

    pub fn create_char(&self, address: u8, bitmap: [u8; 8]) {
        // TODO: Check for address in range 0..8
        // send new custom character to cgram address

        self.command(CGRAM_ADDRESS | address << 3);
        for row in 0..bitmap.len() {
            self.send_byte(bitmap[row as usize], RS_DATA);
        }
    }

    fn e_wait() {
        std::thread::sleep(Duration::new(0, 50));
    }

    fn select_row(&self, row: u32) {
        // select the row where the String should be printed at
        self.send_byte(self.lines[row as usize], RS_COMMAND);
    }

    fn write(&self, charlist: Vec<u8>) {
        // send every single char to send_byte
        for x in charlist {
            self.send_byte(x, RS_DATA);
        }
    }

    fn send_byte(&self, bits: u8, mode: bool) {
        let mut rs = self.raspi.pin(self.disp_rs as usize).unwrap().output();
        let mut e = self.raspi.pin(self.disp_e as usize).unwrap().output();
        let mut data: Vec<PinOutput> = Vec::new();
        for x in 0..4 {
            data.push(self.raspi.pin(self.datalines[x] as usize).unwrap().output());
        }

        if mode {
            rs.high().unwrap();
        } else {
            rs.low().unwrap();
        }
        data[0].low().unwrap();
        data[1].low().unwrap();
        data[2].low().unwrap();
        data[3].low().unwrap();
        if bits & 0x10 == 0x10 {
            data[0].high().unwrap();
        }
        if bits & 0x20 == 0x20 {
            data[1].high().unwrap();
        }
        if bits & 0x40 == 0x40 {
            data[2].high().unwrap();
        }
        if bits & 0x80 == 0x80 {
            data[3].high().unwrap();
        }
        HD44780::e_wait();
        e.high().unwrap();
        HD44780::e_wait();
        e.low().unwrap();
        data[0].low().unwrap();
        data[1].low().unwrap();
        data[2].low().unwrap();
        data[3].low().unwrap();
        if bits & 0x01 == 0x01 {
            data[0].high().unwrap();
        }
        if bits & 0x02 == 0x02 {
            data[1].high().unwrap();
        }
        if bits & 0x04 == 0x04 {
            data[2].high().unwrap();
        }
        if bits & 0x08 == 0x08 {
            data[3].high().unwrap();
        }
        HD44780::e_wait();
        e.high().unwrap();
        HD44780::e_wait();
        e.low().unwrap();
    }
}
<|endoftext|>


<commit_before>use std::fmt::{self, Display};

/// a simple recursive type which is able to render its
/// components in a tree-like format
#[derive(Debug)]
pub struct Tree<D: Display>(D, Vec<Tree<D>>);

impl<D: Display> Tree<D> {
    pub fn new(root: D, leaves: Vec<Tree<D>>) -> Tree<D> {
        Tree(root, leaves)
    }

    pub fn root(root: D) -> Tree<D> {
        Tree(root, Vec::new())
    }

    pub fn push(&mut self, leaf: Tree<D>) -> &mut Self {
        self.1.push(leaf);
        self
    }

    fn display_leaves(
        f: &mut fmt::Formatter,
        leaves: &Vec<Tree<D>>,
        spaces: Vec<bool>,
    ) -> fmt::Result {
        for (i, leaf) in leaves.iter().enumerate() {
            let last = i >= leaves.len() - 1;
            let mut clone = spaces.clone();
            // print single line
            for s in &spaces {
                if *s {
                    write!(f, "    ")?;
                } else {
                    write!(f, "|   ")?;
                }
            }
            if last {
                writeln!(f, "└── {}", leaf.0)?;
            } else {
                writeln!(f, "├── {}", leaf.0)?;
            }

            // recurse
            if !leaf.1.is_empty() {
                clone.push(last);
                Self::display_leaves(f, &leaf.1, clone)?;
            }
        }
        write!(f, "")
    }
}

impl<D: Display> Display for Tree<D> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "{}", self.0)?;
        Self::display_leaves(f, &self.1, Vec::new())
    }
}

#[cfg(test)]
mod tests {
    use super::Tree;
    #[test]
    fn render_tree_root() {
        let tree = Tree::root("foo");
        assert_eq!(format!("{}", tree), "foo\n")
    }

    #[test]
    fn render_tree_with_leaves() {
        let tree = Tree::new("foo", vec![Tree::new("bar", vec![Tree::root("baz")])]);
        assert_eq!(
            format!("{}", tree),
            r#"foo
└── bar
    └── baz
"#
        )
    }
}
<commit_msg>perf: Only clone spaces when needed<commit_after>use std::fmt::{self, Display};

/// a simple recursive type which is able to render its
/// components in a tree-like format
#[derive(Debug)]
pub struct Tree<D: Display>(D, Vec<Tree<D>>);

impl<D: Display> Tree<D> {
    pub fn new(root: D, leaves: Vec<Tree<D>>) -> Tree<D> {
        Tree(root, leaves)
    }

    pub fn root(root: D) -> Tree<D> {
        Tree(root, Vec::new())
    }

    pub fn push(&mut self, leaf: Tree<D>) -> &mut Self {
        self.1.push(leaf);
        self
    }

    fn display_leaves(
        f: &mut fmt::Formatter,
        leaves: &Vec<Tree<D>>,
        spaces: Vec<bool>,
    ) -> fmt::Result {
        for (i, leaf) in leaves.iter().enumerate() {
            let last = i >= leaves.len() - 1;
            // print single line
            for s in &spaces {
                if *s {
                    write!(f, "    ")?;
                } else {
                    write!(f, "|   ")?;
                }
            }
            if last {
                writeln!(f, "└── {}", leaf.0)?;
            } else {
                writeln!(f, "├── {}", leaf.0)?;
            }

            // recurse
            if !leaf.1.is_empty() {
                let mut clone = spaces.clone();
                clone.push(last);
                Self::display_leaves(f, &leaf.1, clone)?;
            }
        }
        write!(f, "")
    }
}

impl<D: Display> Display for Tree<D> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "{}", self.0)?;
        Self::display_leaves(f, &self.1, Vec::new())
    }
}

#[cfg(test)]
mod tests {
    use super::Tree;
    #[test]
    fn render_tree_root() {
        let tree = Tree::root("foo");
        assert_eq!(format!("{}", tree), "foo\n")
    }

    #[test]
    fn render_tree_with_leaves() {
        let tree = Tree::new("foo", vec![Tree::new("bar", vec![Tree::root("baz")])]);
        assert_eq!(
            format!("{}", tree),
            r#"foo
└── bar
    └── baz
"#
        )
    }
}
<|endoftext|>


<commit_before>//! A crate to get images info and process them, including animated GIFs.
//!
//! Requires ImageMagick installed to function properly since some functions uses its command line
//! tools.
//!
//! # Example
//!
//! ```rust,ignore
//! extern crate image_utils;
//!
//! use std::path::Path;
//! use image_utils::{info, crop, resize};
//!
//! let path = Path::new("test.jpg");
//!
//! let inf = info(&path)?;
//! let cropped = crop(&path, 10, 10, 100, 100, &Path::new("cropped.jpg"), 5)?;
//! let resized = resize(&path, 200, 200, &Path::new("resized.jpg"), 5)?;
//!
//! println!("{:?} {:?} {:?}", inf, cropped, resized);
//! ```

#![deny(missing_docs)]

extern crate image;
extern crate gif;
extern crate wait_timeout;

use std::process::Command;
use std::error::Error;
use std::path::Path;
use std::fs;
use std::fs::File;
use std::io::prelude::*;
use std::time::Duration;
use image::{GenericImage, ImageFormat, ColorType, guess_format};
use gif::Decoder;
use wait_timeout::ChildExt;

/// Common image information
#[derive(Debug, PartialEq)]
pub struct Info {
    /// Image format
    pub format: ImageFormat,
    /// Image color type
    pub color: ColorType,
    /// Width in pixels
    pub width: u32,
    /// Height in pixels
    pub height: u32,
    /// Number of frames, can be greater than 1 for animated GIFs
    pub frames: u32,
}

/// Returns common information about image
///
/// `path` - image file to analyze
pub fn info(path: &Path) -> Result<Info, Box<Error>> {
    let mut im = File::open(path)?;
    let mut buf = [0; 16];
    im.read(&mut buf)?;
    let format = guess_format(&buf)?;

    let im = image::open(path)?;
    let color = im.color();
    let (width, height) = im.dimensions();

    let frames = match format {
        ImageFormat::GIF => {
            let decoder = Decoder::new(File::open(path)?);
            let mut reader = decoder.read_info().unwrap();
            let mut frames = 0;
            while let Some(_) = reader.next_frame_info().unwrap() {
                frames += 1;
            }
            frames
        }
        _ => 1,
    };

    Ok(Info {
        format: format,
        color: color,
        width: width,
        height: height,
        frames: frames,
    })
}

/// Crops image, panics if passed coordinates or cropped image size are out of bounds of existing image,
/// fails if timeout exceeded
///
/// `src` - source image file
///
/// `x` - width offset
///
/// `y` - height offset
///
/// `width` - crop width
///
/// `height` - crop height
///
/// `dest` - destination image file
///
/// `timeout` - function timeout in seconds
pub fn crop(src: &Path,
            x: u32,
            y: u32,
            width: u32,
            height: u32,
            dest: &Path,
            timeout: u32)
            -> Result<bool, Box<Error>> {
    let inf = info(src)?;

    if x + width > inf.width || y + height > inf.height {
        panic!("out of existing image bounds");
    }

    let srcs = src.to_str().unwrap();
    let dests = dest.to_str().unwrap();
    let dims = format!("{}x{}+{}+{}", width, height, x, y);

    let mut child = match inf.format {
        ImageFormat::GIF => {
            Command::new("convert").arg(srcs)
                .arg("-coalesce")
                .arg("-repage")
                .arg("0x0")
                .arg("-crop")
                .arg(dims)
                .arg("+repage")
                .arg(dests)
                .spawn()?
        }
        _ => {
            Command::new("convert").arg(srcs)
                .arg("-crop")
                .arg(dims)
                .arg(dests)
                .spawn()?
        }
    };

    let success = match child.wait_timeout(Duration::from_secs(timeout as u64))? {
        Some(status) => status.success(),
        None => {
            child.kill()?;
            child.wait()?.success()
        }
    };

    Ok(success)
}

/// Resizes image preserving its aspect ratio, fails if timeout exceeded
///
/// `src` - source image file
///
/// `width` - max width
///
/// `height` - max height
///
/// `dest` - destination image file
///
/// `timeout` - function timeout in seconds
pub fn resize(src: &Path,
              width: u32,
              height: u32,
              dest: &Path,
              timeout: u32)
              -> Result<bool, Box<Error>> {
    let inf = info(src)?;

    let mut srcs = src.to_str().unwrap();
    let dests = dest.to_str().unwrap();

    let duration = Duration::from_secs(timeout as u64);

    let temp = match inf.format {
        ImageFormat::GIF => {
            let mut child = Command::new("convert").arg(srcs)
                .arg("-coalesce")
                .arg(dests)
                .spawn()?;

            srcs = dests;

            match child.wait_timeout(duration)? {
                Some(status) => status.success(),
                None => {
                    child.kill()?;
                    child.wait()?.success()
                }
            }
        }
        _ => false,
    };

    let mut child = Command::new("convert").arg("-size")
        .arg(format!("{}x{}", inf.width, inf.height))
        .arg(srcs)
        .arg("-resize")
        .arg(format!("{}x{}", width, height))
        .arg(dests)
        .spawn()?;

    let success = match child.wait_timeout(duration)? {
        Some(status) => status.success(),
        None => {
            child.kill()?;
            child.wait()?.success()
        }
    };

    if temp && !success {
        fs::remove_file(dests)?;
    }

    Ok(success)
}
<commit_msg>docstrings<commit_after>//! A crate to get images info and process them, including animated GIFs.
//!
//! Requires ImageMagick installed to function properly since some functions uses its command line
//! tools.
//!
//! # Example
//!
//! ```rust,ignore
//! extern crate image_utils;
//!
//! use std::path::Path;
//! use image_utils::{info, crop, resize};
//!
//! let path = Path::new("test.jpg");
//!
//! let inf = info(&path)?;
//! let cropped = crop(&path, 10, 10, 100, 100, &Path::new("cropped.jpg"), 5)?;
//! let resized = resize(&path, 200, 200, &Path::new("resized.jpg"), 5)?;
//!
//! println!("{:?} {:?} {:?}", inf, cropped, resized);
//! ```

#![deny(missing_docs)]

extern crate image;
extern crate gif;
extern crate wait_timeout;

use std::process::Command;
use std::error::Error;
use std::path::Path;
use std::fs;
use std::fs::File;
use std::io::prelude::*;
use std::time::Duration;
use image::{GenericImage, ImageFormat, ColorType, guess_format};
use gif::Decoder;
use wait_timeout::ChildExt;

/// Common image information
#[derive(Debug, PartialEq)]
pub struct Info {
    /// Image format
    pub format: ImageFormat,
    /// Image color type
    pub color: ColorType,
    /// Width in pixels
    pub width: u32,
    /// Height in pixels
    pub height: u32,
    /// Number of frames, can be greater than 1 for animated GIFs
    pub frames: u32,
}

/// Returns common information about image
///
/// `path` - image file to analyze
///
/// Returns Info struct
pub fn info(path: &Path) -> Result<Info, Box<Error>> {
    let mut im = File::open(path)?;
    let mut buf = [0; 16];
    im.read(&mut buf)?;
    let format = guess_format(&buf)?;

    let im = image::open(path)?;
    let color = im.color();
    let (width, height) = im.dimensions();

    let frames = match format {
        ImageFormat::GIF => {
            let decoder = Decoder::new(File::open(path)?);
            let mut reader = decoder.read_info().unwrap();
            let mut frames = 0;
            while let Some(_) = reader.next_frame_info().unwrap() {
                frames += 1;
            }
            frames
        }
        _ => 1,
    };

    Ok(Info {
        format: format,
        color: color,
        width: width,
        height: height,
        frames: frames,
    })
}

/// Crops image, panics if passed coordinates or cropped image size are out of bounds of existing
/// image, fails if timeout exceeded
///
/// `src` - source image file
///
/// `x` - width offset
///
/// `y` - height offset
///
/// `width` - crop width
///
/// `height` - crop height
///
/// `dest` - destination image file
///
/// `timeout` - function timeout in seconds
///
/// Returns true on success
pub fn crop(src: &Path,
            x: u32,
            y: u32,
            width: u32,
            height: u32,
            dest: &Path,
            timeout: u32)
            -> Result<bool, Box<Error>> {
    let inf = info(src)?;

    if x + width > inf.width || y + height > inf.height {
        panic!("out of existing image bounds");
    }

    let srcs = src.to_str().unwrap();
    let dests = dest.to_str().unwrap();
    let dims = format!("{}x{}+{}+{}", width, height, x, y);

    let mut child = match inf.format {
        ImageFormat::GIF => {
            Command::new("convert").arg(srcs)
                .arg("-coalesce")
                .arg("-repage")
                .arg("0x0")
                .arg("-crop")
                .arg(dims)
                .arg("+repage")
                .arg(dests)
                .spawn()?
        }
        _ => {
            Command::new("convert").arg(srcs)
                .arg("-crop")
                .arg(dims)
                .arg(dests)
                .spawn()?
        }
    };

    let success = match child.wait_timeout(Duration::from_secs(timeout as u64))? {
        Some(status) => status.success(),
        None => {
            child.kill()?;
            child.wait()?.success()
        }
    };

    Ok(success)
}

/// Resizes image preserving its aspect ratio, fails if timeout exceeded
///
/// `src` - source image file
///
/// `width` - max width
///
/// `height` - max height
///
/// `dest` - destination image file
///
/// `timeout` - function timeout in seconds
///
/// Returns true on success
pub fn resize(src: &Path,
              width: u32,
              height: u32,
              dest: &Path,
              timeout: u32)
              -> Result<bool, Box<Error>> {
    let inf = info(src)?;

    let mut srcs = src.to_str().unwrap();
    let dests = dest.to_str().unwrap();

    let duration = Duration::from_secs(timeout as u64);

    let temp = match inf.format {
        ImageFormat::GIF => {
            let mut child = Command::new("convert").arg(srcs)
                .arg("-coalesce")
                .arg(dests)
                .spawn()?;

            srcs = dests;

            match child.wait_timeout(duration)? {
                Some(status) => status.success(),
                None => {
                    child.kill()?;
                    child.wait()?.success()
                }
            }
        }
        _ => false,
    };

    let mut child = Command::new("convert").arg("-size")
        .arg(format!("{}x{}", inf.width, inf.height))
        .arg(srcs)
        .arg("-resize")
        .arg(format!("{}x{}", width, height))
        .arg(dests)
        .spawn()?;

    let success = match child.wait_timeout(duration)? {
        Some(status) => status.success(),
        None => {
            child.kill()?;
            child.wait()?.success()
        }
    };

    if temp && !success {
        fs::remove_file(dests)?;
    }

    Ok(success)
}
<|endoftext|>


<commit_before>extern crate lmdb_rs as lmdb;

use lmdb::{FromMdbValue, ToMdbValue, MdbValue,
           DbFlags, DbHandle, Database, Environment, Cursor, MDB_val};
use lmdb::core::MdbResult;
use std::marker::PhantomData;

#[macro_export]
macro_rules! lmdb_not_found {
    (
        $x:expr
    ) => {
        match $x {
            Err(lmdb::MdbError::NotFound) => true,
            _ => false
        }
    };
}

#[macro_export]
macro_rules! impl_table {
    (
        $s:ident, $k:ty, $v:ty
    ) => {
        impl $s {
            pub fn table<'db>(db: ::lmdb::Database<'db>) -> ::lmdb::core::MdbResult<Table<'db, $k, $v>> {
                try!(Self::setup(&db));
                Ok(Table::new(db))
            }
        }
    };
}

/// Defines all neccessary information to create/open a database.
pub trait TableDef {
    fn name() -> &'static str;
    fn flags() -> DbFlags;
    fn setup(db: &Database) -> MdbResult<()>;

    fn open(env: &Environment, create: bool) -> MdbResult<DbHandle> {
        if create {
            env.create_db(Self::name(), Self::flags())
        } else {
            env.get_db(Self::name(), Self::flags())
        }
    }
}

/// Wraps a lmdb::Database, keeping type information for K and V.
pub struct Table<'db, K, V> {
    db: Database<'db>,
    k: PhantomData<K>,
    v: PhantomData<V>,
}

impl<'db, K, V> Table<'db, K, V>
where K: FromMdbValue + ToMdbValue,
      V: FromMdbValue + ToMdbValue,
{
    #[inline(always)]
    pub fn new(db: Database<'db>) -> Table<'db, K, V> {
        Table {db: db, k: PhantomData, v: PhantomData}
    }

    #[inline(always)]
    pub fn ref_db<'a>(&'a self) -> &'a Database<'db> {
        &self.db
    }

    #[inline(always)]
    pub fn set(&self, key: &K, value: &V) -> MdbResult<()> {
        self.db.set(key, value)
    }

    #[inline(always)]
    pub fn insert(&self, key: &K, value: &V) -> MdbResult<()> {
        self.db.insert(key, value)
    }

    /// Checks if the item exists.
    pub fn insert_item(&self, key: &K, value: &V) -> MdbResult<()> {
        if try!(self.has_item(key, value)) {
            return Err(::lmdb::MdbError::KeyExists);
        }
        self.set(key, value)
    }

    /// Returns true if item exists.
    pub fn has_item(&self, key: &K, value: &V) -> MdbResult<bool> {
        let mut cursor = try!(self.new_cursor());
        match cursor.to_item(key, value) {
            Ok(()) => Ok(true),
            Err(::lmdb::MdbError::NotFound) => Ok(false),
            Err(e) => Err(e),
        }
    }

    #[inline(always)]
    pub fn get(&self, key: &K) -> MdbResult<V> {
        self.db.get(key)
    }

    /// Returns ```alt``` if key was not found.
    #[inline(always)]
    pub fn get_or(&self, key: &K, alt: V) -> MdbResult<V> {
        match self.db.get(key) {
            Ok(v) => Ok(v),
            Err(::lmdb::MdbError::NotFound) => Ok(alt),
            Err(e) => Err(e),
        }
    }

    #[inline(always)]
    pub fn get_ref<'a, V2>(&self, key: &K) -> MdbResult<&'a V2> where &'a V2: FromMdbValue {
        self.db.get(key)
    }

    #[inline(always)]
    pub fn del(&self, key: &K) -> MdbResult<()> {
        self.db.del(key)
    }

    #[inline(always)]
    pub fn del_item(&self, key: &K, value: &V) -> MdbResult<()> {
        self.db.del_item(key, value)
    }

    #[inline(always)]
    pub fn new_cursor<'table>(&'table self) -> MdbResult<TypedCursor<'table, K, V>> {
        Ok(TypedCursor {cursor: try!(self.db.new_cursor()), k: PhantomData, v: PhantomData})
    }

    #[inline(always)]
    pub fn cursor_at_key<'table>(&'table self, k: &K) -> MdbResult<TypedCursor<'table, K, V>> {
        let mut cursor = TypedCursor {cursor: try!(self.db.new_cursor()), k: PhantomData, v: PhantomData};
        try!(cursor.to_key(k));
        Ok(cursor)
    }
}

/// Is a typed version of lmdb::Cursor.
pub struct TypedCursor<'table, K, V> {
    cursor: Cursor<'table>,
    k: PhantomData<K>,
    v: PhantomData<V>,
}

impl<'table, K: FromMdbValue+ToMdbValue, V: FromMdbValue+ToMdbValue> TypedCursor<'table, K, V> {
    #[inline(always)]
    pub fn to_first(&mut self) -> MdbResult<()> {
        self.cursor.to_first()
    }

    #[inline(always)]
    pub fn to_last(&mut self) -> MdbResult<()> {
        self.cursor.to_last()
    }

    #[inline(always)]
    pub fn to_key(&mut self, key: &K) -> MdbResult<()> {
        self.cursor.to_key(key)
    }

    #[inline(always)]
    pub fn to_gte_key(&mut self, key: &K) -> MdbResult<()> {
        self.cursor.to_gte_key(key)
    }

    #[inline(always)]
    pub fn to_next_key(&mut self) -> MdbResult<()> {
        self.cursor.to_next_key()
    }

    #[inline(always)]
    pub fn to_prev_key(&mut self) -> MdbResult<()> {
        self.cursor.to_prev_key()
    }

    #[inline(always)]
    pub fn to_item(&mut self, key: &K, value: &V) -> MdbResult<()> {
        self.cursor.to_item(key, value)
    }

    #[inline(always)]
    pub fn to_gte_item(&mut self, key: &K, value: &V) -> MdbResult<()> {
        self.cursor.to_gte_item(key, value)
    }

    #[inline(always)]
    pub fn to_first_item(&mut self) -> MdbResult<()> {
        self.cursor.to_first_item()
    }

    #[inline(always)]
    pub fn to_last_item(&mut self) -> MdbResult<()> {
        self.cursor.to_last_item()
    }

    #[inline(always)]
    pub fn to_next_item(&mut self) -> MdbResult<()> {
        self.cursor.to_next_item()
    }

    #[inline(always)]
    pub fn to_prev_item(&mut self) -> MdbResult<()> {
        self.cursor.to_prev_item()
    }

    #[inline(always)]
    pub fn item_count(&mut self) -> MdbResult<usize> {
        self.cursor.item_count()
    }

    #[inline(always)]
    pub fn get(&mut self) -> MdbResult<(K, V)> {
        self.cursor.get()
    }

    #[inline(always)]
    pub fn get_value(&mut self) -> MdbResult<V> {
        self.cursor.get_value()
    }

    #[inline(always)]
    pub fn get_value_ref<'a, V2>(&mut self) -> MdbResult<&'a V2> where &'a V2: FromMdbValue {
        self.cursor.get_value()
    }

    #[inline(always)]
    pub fn get_key(&mut self) -> MdbResult<K> {
        self.cursor.get_key()
    }

    #[inline(always)]
    pub fn replace(&mut self, value: &V) -> MdbResult<()> {
        self.cursor.replace(value)
    }

    #[inline(always)]
    pub fn add_item(&mut self, value: &V) -> MdbResult<()> {
        self.cursor.add_item(value)
    }

    #[inline(always)]
    pub fn del(&mut self) -> MdbResult<()> {
        self.cursor.del()
    }

    #[inline(always)]
    pub fn del_item(&mut self) -> MdbResult<()> {
        self.cursor.del_item()
    }

    #[inline(always)]
    pub fn del_all(&mut self) -> MdbResult<()> {
        self.cursor.del_all()
    }
}

pub extern "C" fn sort<T:FromMdbValue+Ord>(lhs_val: *const MDB_val, rhs_val: *const MDB_val) -> lmdb::c_int {
    let lhs = T::from_mdb_value(&unsafe{MdbValue::from_raw(lhs_val)});
    let rhs = T::from_mdb_value(&unsafe{MdbValue::from_raw(rhs_val)});

    let order: i8 = unsafe { std::mem::transmute(lhs.cmp(&rhs)) };
    order as lmdb::c_int
}

pub extern "C" fn sort_reverse<T:FromMdbValue+Ord>(lhs_val: *const MDB_val, rhs_val: *const MDB_val) -> lmdb::c_int {
    let lhs = T::from_mdb_value(&unsafe{MdbValue::from_raw(lhs_val)});
    let rhs = T::from_mdb_value(&unsafe{MdbValue::from_raw(rhs_val)});
    let order: i8 = unsafe { std::mem::transmute(lhs.cmp(&rhs).reverse()) };
    order as lmdb::c_int
}

#[test]
fn test_simple_table() {
    use std::path::Path;
    use lmdb::core::{DbIntKey, DbAllowDups, DbAllowIntDups, DbDupFixed};

    let env = lmdb::EnvBuilder::new().max_dbs(2).autocreate_dir(true).open(&Path::new("./test/db1"), 0o777).unwrap();

    struct MyFirstTable;
    impl TableDef for MyFirstTable {
        fn name() -> &'static str { "my_first_table" }
        fn flags() -> DbFlags { DbIntKey | DbAllowDups | DbAllowIntDups | DbDupFixed }
        fn setup(db: &Database) -> MdbResult<()> {
            db.set_dupsort(sort_reverse::<u64>)
        }
    }
    impl MyFirstTable {
        fn table<'db>(db: Database<'db>) -> MdbResult<Table<'db, u64, u64>> {
            try!(Self::setup(&db));
            Ok(Table{db: db, k: PhantomData, v: PhantomData})
        }
    }

    struct MyBlobTable;
    impl TableDef for MyBlobTable {
        fn name() -> &'static str { "my_blob_table" }
        fn flags() -> DbFlags { DbIntKey }
        fn setup(_db: &Database) -> MdbResult<()> { Ok(()) }
    }
    impl MyBlobTable {
        fn table<'db>(db: Database<'db>) -> MdbResult<Table<'db, u64, &[u8]>> {
            try!(Self::setup(&db));
            Ok(Table{db: db, k: PhantomData, v: PhantomData})
        }
    }

    // A Unique(Id64, Id64 DESC) table
    let table_handle = MyFirstTable::open(&env, true).unwrap();
    let blobs_handle = MyBlobTable::open(&env, true).unwrap();

    // prepare database
    {
        let txn = env.new_transaction().unwrap();
        {
            let table = MyFirstTable::table(txn.bind(&table_handle)).unwrap();
            let blobs = MyBlobTable::table(txn.bind(&blobs_handle)).unwrap();

            let big_blob: &[u8] = b"Test";
            blobs.set(&1, &big_blob).unwrap();

            let back: &[u8] = blobs.get(&1).unwrap();
            assert_eq!(&back[..], &b"Test"[..]);

            let key = 1;
            table.set(&key, &200).unwrap();
            table.set(&key, &200).unwrap();
            table.set(&key, &100).unwrap();
            table.set(&key, &2).unwrap();
            table.set(&key, &2).unwrap();
            table.set(&key, &2).unwrap();
            table.set(&key, &2).unwrap();
            table.set(&key, &1).unwrap();
            table.set(&key, &2).unwrap();
            table.set(&key, &3).unwrap();
            table.set(&key, &100).unwrap();
        }
        txn.commit().unwrap();
    }
    // read
    {
        let rdr = env.get_reader().unwrap();

        let table = MyFirstTable::table(rdr.bind(&table_handle)).unwrap();

        let mut cursor = table.new_cursor().unwrap();
        cursor.to_key(&1).unwrap(); //  positions on first item of key
        assert_eq!((1, 200), cursor.get().unwrap());

        cursor.to_next_item().unwrap();
        assert_eq!((1, 100), cursor.get().unwrap());

        cursor.to_next_item().unwrap();
        assert_eq!((1, 3), cursor.get().unwrap());

        cursor.to_next_item().unwrap();
        assert_eq!((1, 2), cursor.get().unwrap());

        cursor.to_next_item().unwrap();
        assert_eq!((1, 1), cursor.get().unwrap());

        assert!(lmdb_not_found!(cursor.to_next_item()));

        let mut cursor = table.new_cursor().unwrap();
        {
            assert!(lmdb_not_found!(cursor.to_item(&2, &3)));

            cursor.to_gte_item(&1, &4).unwrap();
            assert_eq!((1, 3), cursor.get().unwrap());

            cursor.to_next_item().unwrap();
            assert_eq!((1, 2), cursor.get().unwrap());

            cursor.to_next_item().unwrap();
            assert_eq!((1, 1), cursor.get().unwrap());

            assert!(lmdb_not_found!(cursor.to_next_item()));
        }
    }
}
<commit_msg>Change item_count() from usize to u64<commit_after>extern crate lmdb_rs as lmdb;

use lmdb::{FromMdbValue, ToMdbValue, MdbValue,
           DbFlags, DbHandle, Database, Environment, Cursor, MDB_val};
use lmdb::core::MdbResult;
use std::marker::PhantomData;

#[macro_export]
macro_rules! lmdb_not_found {
    (
        $x:expr
    ) => {
        match $x {
            Err(lmdb::MdbError::NotFound) => true,
            _ => false
        }
    };
}

#[macro_export]
macro_rules! impl_table {
    (
        $s:ident, $k:ty, $v:ty
    ) => {
        impl $s {
            pub fn table<'db>(db: ::lmdb::Database<'db>) -> ::lmdb::core::MdbResult<Table<'db, $k, $v>> {
                try!(Self::setup(&db));
                Ok(Table::new(db))
            }
        }
    };
}

/// Defines all neccessary information to create/open a database.
pub trait TableDef {
    fn name() -> &'static str;
    fn flags() -> DbFlags;
    fn setup(db: &Database) -> MdbResult<()>;

    fn open(env: &Environment, create: bool) -> MdbResult<DbHandle> {
        if create {
            env.create_db(Self::name(), Self::flags())
        } else {
            env.get_db(Self::name(), Self::flags())
        }
    }
}

/// Wraps a lmdb::Database, keeping type information for K and V.
pub struct Table<'db, K, V> {
    db: Database<'db>,
    k: PhantomData<K>,
    v: PhantomData<V>,
}

impl<'db, K, V> Table<'db, K, V>
where K: FromMdbValue + ToMdbValue,
      V: FromMdbValue + ToMdbValue,
{
    #[inline(always)]
    pub fn new(db: Database<'db>) -> Table<'db, K, V> {
        Table {db: db, k: PhantomData, v: PhantomData}
    }

    #[inline(always)]
    pub fn ref_db<'a>(&'a self) -> &'a Database<'db> {
        &self.db
    }

    #[inline(always)]
    pub fn set(&self, key: &K, value: &V) -> MdbResult<()> {
        self.db.set(key, value)
    }

    #[inline(always)]
    pub fn insert(&self, key: &K, value: &V) -> MdbResult<()> {
        self.db.insert(key, value)
    }

    /// Checks if the item exists.
    pub fn insert_item(&self, key: &K, value: &V) -> MdbResult<()> {
        if try!(self.has_item(key, value)) {
            return Err(::lmdb::MdbError::KeyExists);
        }
        self.set(key, value)
    }

    /// Returns true if item exists.
    pub fn has_item(&self, key: &K, value: &V) -> MdbResult<bool> {
        let mut cursor = try!(self.new_cursor());
        match cursor.to_item(key, value) {
            Ok(()) => Ok(true),
            Err(::lmdb::MdbError::NotFound) => Ok(false),
            Err(e) => Err(e),
        }
    }

    #[inline(always)]
    pub fn get(&self, key: &K) -> MdbResult<V> {
        self.db.get(key)
    }

    /// Returns ```alt``` if key was not found.
    #[inline(always)]
    pub fn get_or(&self, key: &K, alt: V) -> MdbResult<V> {
        match self.db.get(key) {
            Ok(v) => Ok(v),
            Err(::lmdb::MdbError::NotFound) => Ok(alt),
            Err(e) => Err(e),
        }
    }

    #[inline(always)]
    pub fn get_ref<'a, V2>(&self, key: &K) -> MdbResult<&'a V2> where &'a V2: FromMdbValue {
        self.db.get(key)
    }

    #[inline(always)]
    pub fn del(&self, key: &K) -> MdbResult<()> {
        self.db.del(key)
    }

    #[inline(always)]
    pub fn del_item(&self, key: &K, value: &V) -> MdbResult<()> {
        self.db.del_item(key, value)
    }

    #[inline(always)]
    pub fn new_cursor<'table>(&'table self) -> MdbResult<TypedCursor<'table, K, V>> {
        Ok(TypedCursor {cursor: try!(self.db.new_cursor()), k: PhantomData, v: PhantomData})
    }

    #[inline(always)]
    pub fn cursor_at_key<'table>(&'table self, k: &K) -> MdbResult<TypedCursor<'table, K, V>> {
        let mut cursor = TypedCursor {cursor: try!(self.db.new_cursor()), k: PhantomData, v: PhantomData};
        try!(cursor.to_key(k));
        Ok(cursor)
    }
}

/// Is a typed version of lmdb::Cursor.
pub struct TypedCursor<'table, K, V> {
    cursor: Cursor<'table>,
    k: PhantomData<K>,
    v: PhantomData<V>,
}

impl<'table, K: FromMdbValue+ToMdbValue, V: FromMdbValue+ToMdbValue> TypedCursor<'table, K, V> {
    #[inline(always)]
    pub fn to_first(&mut self) -> MdbResult<()> {
        self.cursor.to_first()
    }

    #[inline(always)]
    pub fn to_last(&mut self) -> MdbResult<()> {
        self.cursor.to_last()
    }

    #[inline(always)]
    pub fn to_key(&mut self, key: &K) -> MdbResult<()> {
        self.cursor.to_key(key)
    }

    #[inline(always)]
    pub fn to_gte_key(&mut self, key: &K) -> MdbResult<()> {
        self.cursor.to_gte_key(key)
    }

    #[inline(always)]
    pub fn to_next_key(&mut self) -> MdbResult<()> {
        self.cursor.to_next_key()
    }

    #[inline(always)]
    pub fn to_prev_key(&mut self) -> MdbResult<()> {
        self.cursor.to_prev_key()
    }

    #[inline(always)]
    pub fn to_item(&mut self, key: &K, value: &V) -> MdbResult<()> {
        self.cursor.to_item(key, value)
    }

    #[inline(always)]
    pub fn to_gte_item(&mut self, key: &K, value: &V) -> MdbResult<()> {
        self.cursor.to_gte_item(key, value)
    }

    #[inline(always)]
    pub fn to_first_item(&mut self) -> MdbResult<()> {
        self.cursor.to_first_item()
    }

    #[inline(always)]
    pub fn to_last_item(&mut self) -> MdbResult<()> {
        self.cursor.to_last_item()
    }

    #[inline(always)]
    pub fn to_next_item(&mut self) -> MdbResult<()> {
        self.cursor.to_next_item()
    }

    #[inline(always)]
    pub fn to_prev_item(&mut self) -> MdbResult<()> {
        self.cursor.to_prev_item()
    }

    #[inline(always)]
    pub fn item_count(&mut self) -> MdbResult<u64> {
        self.cursor.item_count()
    }

    #[inline(always)]
    pub fn get(&mut self) -> MdbResult<(K, V)> {
        self.cursor.get()
    }

    #[inline(always)]
    pub fn get_value(&mut self) -> MdbResult<V> {
        self.cursor.get_value()
    }

    #[inline(always)]
    pub fn get_value_ref<'a, V2>(&mut self) -> MdbResult<&'a V2> where &'a V2: FromMdbValue {
        self.cursor.get_value()
    }

    #[inline(always)]
    pub fn get_key(&mut self) -> MdbResult<K> {
        self.cursor.get_key()
    }

    #[inline(always)]
    pub fn replace(&mut self, value: &V) -> MdbResult<()> {
        self.cursor.replace(value)
    }

    #[inline(always)]
    pub fn add_item(&mut self, value: &V) -> MdbResult<()> {
        self.cursor.add_item(value)
    }

    #[inline(always)]
    pub fn del(&mut self) -> MdbResult<()> {
        self.cursor.del()
    }

    #[inline(always)]
    pub fn del_item(&mut self) -> MdbResult<()> {
        self.cursor.del_item()
    }

    #[inline(always)]
    pub fn del_all(&mut self) -> MdbResult<()> {
        self.cursor.del_all()
    }
}

pub extern "C" fn sort<T:FromMdbValue+Ord>(lhs_val: *const MDB_val, rhs_val: *const MDB_val) -> lmdb::c_int {
    let lhs = T::from_mdb_value(&unsafe{MdbValue::from_raw(lhs_val)});
    let rhs = T::from_mdb_value(&unsafe{MdbValue::from_raw(rhs_val)});

    let order: i8 = unsafe { std::mem::transmute(lhs.cmp(&rhs)) };
    order as lmdb::c_int
}

pub extern "C" fn sort_reverse<T:FromMdbValue+Ord>(lhs_val: *const MDB_val, rhs_val: *const MDB_val) -> lmdb::c_int {
    let lhs = T::from_mdb_value(&unsafe{MdbValue::from_raw(lhs_val)});
    let rhs = T::from_mdb_value(&unsafe{MdbValue::from_raw(rhs_val)});
    let order: i8 = unsafe { std::mem::transmute(lhs.cmp(&rhs).reverse()) };
    order as lmdb::c_int
}

#[test]
fn test_simple_table() {
    use std::path::Path;
    use lmdb::core::{DbIntKey, DbAllowDups, DbAllowIntDups, DbDupFixed};

    let env = lmdb::EnvBuilder::new().max_dbs(2).autocreate_dir(true).open(&Path::new("./test/db1"), 0o777).unwrap();

    struct MyFirstTable;
    impl TableDef for MyFirstTable {
        fn name() -> &'static str { "my_first_table" }
        fn flags() -> DbFlags { DbIntKey | DbAllowDups | DbAllowIntDups | DbDupFixed }
        fn setup(db: &Database) -> MdbResult<()> {
            db.set_dupsort(sort_reverse::<u64>)
        }
    }
    impl MyFirstTable {
        fn table<'db>(db: Database<'db>) -> MdbResult<Table<'db, u64, u64>> {
            try!(Self::setup(&db));
            Ok(Table{db: db, k: PhantomData, v: PhantomData})
        }
    }

    struct MyBlobTable;
    impl TableDef for MyBlobTable {
        fn name() -> &'static str { "my_blob_table" }
        fn flags() -> DbFlags { DbIntKey }
        fn setup(_db: &Database) -> MdbResult<()> { Ok(()) }
    }
    impl MyBlobTable {
        fn table<'db>(db: Database<'db>) -> MdbResult<Table<'db, u64, &[u8]>> {
            try!(Self::setup(&db));
            Ok(Table{db: db, k: PhantomData, v: PhantomData})
        }
    }

    // A Unique(Id64, Id64 DESC) table
    let table_handle = MyFirstTable::open(&env, true).unwrap();
    let blobs_handle = MyBlobTable::open(&env, true).unwrap();

    // prepare database
    {
        let txn = env.new_transaction().unwrap();
        {
            let table = MyFirstTable::table(txn.bind(&table_handle)).unwrap();
            let blobs = MyBlobTable::table(txn.bind(&blobs_handle)).unwrap();

            let big_blob: &[u8] = b"Test";
            blobs.set(&1, &big_blob).unwrap();

            let back: &[u8] = blobs.get(&1).unwrap();
            assert_eq!(&back[..], &b"Test"[..]);

            let key = 1;
            table.set(&key, &200).unwrap();
            table.set(&key, &200).unwrap();
            table.set(&key, &100).unwrap();
            table.set(&key, &2).unwrap();
            table.set(&key, &2).unwrap();
            table.set(&key, &2).unwrap();
            table.set(&key, &2).unwrap();
            table.set(&key, &1).unwrap();
            table.set(&key, &2).unwrap();
            table.set(&key, &3).unwrap();
            table.set(&key, &100).unwrap();
        }
        txn.commit().unwrap();
    }
    // read
    {
        let rdr = env.get_reader().unwrap();

        let table = MyFirstTable::table(rdr.bind(&table_handle)).unwrap();

        let mut cursor = table.new_cursor().unwrap();
        cursor.to_key(&1).unwrap(); //  positions on first item of key
        assert_eq!((1, 200), cursor.get().unwrap());

        cursor.to_next_item().unwrap();
        assert_eq!((1, 100), cursor.get().unwrap());

        cursor.to_next_item().unwrap();
        assert_eq!((1, 3), cursor.get().unwrap());

        cursor.to_next_item().unwrap();
        assert_eq!((1, 2), cursor.get().unwrap());

        cursor.to_next_item().unwrap();
        assert_eq!((1, 1), cursor.get().unwrap());

        assert!(lmdb_not_found!(cursor.to_next_item()));

        let mut cursor = table.new_cursor().unwrap();
        {
            assert!(lmdb_not_found!(cursor.to_item(&2, &3)));

            cursor.to_gte_item(&1, &4).unwrap();
            assert_eq!((1, 3), cursor.get().unwrap());

            cursor.to_next_item().unwrap();
            assert_eq!((1, 2), cursor.get().unwrap());

            cursor.to_next_item().unwrap();
            assert_eq!((1, 1), cursor.get().unwrap());

            assert!(lmdb_not_found!(cursor.to_next_item()));
        }
    }
}
<|endoftext|>


<commit_before>
#![feature(macro_rules, phase)]

extern crate graphics;
extern crate piston;
extern crate opengl_graphics;
extern crate serialize;
extern crate freetype;

pub use Widget = widget::Widget;
pub use Color = color::Color;
pub use Point = point::Point;
pub use UIContext = ui_context::UIContext;

pub mod macros;

pub mod button;
pub mod color;
pub mod glyph_cache;
pub mod label;
pub mod mouse_state;
pub mod point;
pub mod rectangle;
pub mod slider;
pub mod toggle;
pub mod ui_context;
pub mod utils;
pub mod widget;

<commit_msg>Added number_dialer module<commit_after>
#![feature(macro_rules, phase)]

extern crate graphics;
extern crate piston;
extern crate opengl_graphics;
extern crate serialize;
extern crate freetype;

pub use Widget = widget::Widget;
pub use Color = color::Color;
pub use Point = point::Point;
pub use UIContext = ui_context::UIContext;

pub mod macros;

pub mod button;
pub mod color;
pub mod glyph_cache;
pub mod label;
pub mod mouse_state;
pub mod number_dialer;
pub mod point;
pub mod rectangle;
pub mod slider;
pub mod toggle;
pub mod ui_context;
pub mod utils;
pub mod widget;

<|endoftext|>


<commit_before>#![allow(dead_code)]
#![feature(float_extras, vec_resize)]

//! # tray\_rust - A Toy Ray Tracer in Rust
//!
//! tray\_rust is a toy physically based ray tracer built off of the techniques
//! discussed in [Physically Based Rendering](http://pbrt.org/). It began life as a port of
//! [tray](https://github.com/Twinklebear/tray) to [Rust](http://www.rust-lang.org) to check out the language.
//! The renderer is currently capable of path tracing, supports triangle meshes (MTL support coming soon),
//! and various physically based material models (including measured data from the
//! [MERL BRDF Database](http://www.merl.com/brdf/)).
//!
//! ## Building
//!
//! Unfortunately the project does currently require Rust nightly as I make use of some unstable features
//! (eg. Vec::resize). I hope to get things running on stable Rust once these features get stabilized.
//!
//! [![Build Status](https://travis-ci.org/Twinklebear/tray_rust.svg?branch=master)](https://travis-ci.org/Twinklebear/tray_rust)
//!
//! ## Running
//!
//! Currently the scene data is hardcoded in `src/scene.rs`, in the future I plan to add support for some
//! kind of JSON based scene file format. I strongly recommend running the release build as the debug version
//! will be very very slow. Running and passing `--help` or `-h` will print out some options, currently
//! the image resolution and samples per pixel are also hardcoded, though these are in `src/main.rs`.
//!
//! ## Building Your Own Scenes
//!
//! Start at the documentation for the scene module.
//!
//! ## TODO
//!
//! - More material models (eg. more microfacet models, rough glass, etc.)
//! - Textures
//! - Support for using an OBJ's associated MTL files
//! - Bump mapping
//! - [Subsurface scattering?](http://en.wikipedia.org/wiki/Subsurface_scattering)
//! - [Vertex Connection and Merging?](http://iliyan.com/publications/VertexMerging)
//!
//! ## Sample Renders
//!
//! In the samples the the Buddha, Dragon, Bunny and Lucy statue are from
//! [The Stanford Scanning Repository](http://graphics.stanford.edu/data/3Dscanrep/).
//! The Rust logo model was made by
//! [Nylithius on BlenderArtists](http://blenderartists.org/forum/showthread.php?362836-Rust-language-3D-logo).
//! The Utah teapot used is from [Morgan McGuire's page](http://graphics.cs.williams.edu/data/meshes.xml) and
//! the monkey head is Blender's Suzanne. I've made minor tweaks to some of the models so for convenience
//! you can find versions that can be easily loaded into the sample scenes [here](https://drive.google.com/folderview?id=0B-l_lLEMo1YeflUzUndCd01hOHhRNUhrQUowM3hVd2pCc3JrSXRiS3FQSzRYLWtGcGM0eGc&usp=sharing), though the
//! cube model for the Cornell box scene is included.
//! The materials on the Rust logo, Buddha, Dragon and Lucy are from the
//! [MERL BRDF Database](http://www.merl.com/brdf/).
//!
//! Render times are formatted as hh:mm:ss and were measured using 144 threads on a machine with four
//! [Xeon E7-8890 v3](http://ark.intel.com/products/84685/Intel-Xeon-Processor-E7-8890-v3-45M-Cache-2_50-GHz)
//! CPUs. The machine is an early/engineering sample from Intel so your results may differ, but massive thanks to
//! Intel for the hardware! Some older images renders are shown as well without timing since they were
//! run on a different machine.
//!
[![Model gallery](http://i.imgur.com/Jgji1Y0.jpg)](http://i.imgur.com/Jgji1Y0.jpg)

1920x1080, 4096 samples/pixel. Rendering: 00:43:36.45.

The following images compare disk vs. sphere area lights.

[![Rust Logo with friends, disk](http://i.imgur.com/Z34BleZ.jpg)](http://i.imgur.com/Z34BleZ.jpg)
//!
//!
//!
//!
//!
//! 1920x1080, 4096 samples/pixel. Rendering: 00:43:36.45.
//!
//! The following images compare disk vs. sphere area lights.
//!
//!
//!
//!
//!
//! 1920x1080, 4096 samples/pixel. Rendering: 00:49:33.514.
//!
//!
//!
//!
//!
//! 1920x1080, 4096 samples/pixel. Rendering: 00:46:11.822.
//!
//!
//!
//!
//!
//! 800x600, 4096 samples/pixel. Rendering: 00:03:36.196.
//!
//!
//!
//!
//!
//! 1920x1080, 2048 samples/pixel.
//!
//!
//!
//!
//!
//! 800x600, 1024 samples/pixel.
//!
//!
//!
//!
//!
//! 800x600, 1024 samples/pixel.

extern crate enum_set as enum_set;
extern crate rand;
extern crate byteorder;
extern crate serde_json;

pub mod linalg;
pub mod film;
pub mod geometry;
pub mod sampler;
pub mod integrator;
pub mod scene;
pub mod bxdf;
pub mod material;
pub mod light;
pub mod mc;
pub mod partition;

<commit_msg>Forgot to remove the temporary copied code<commit_after>#![allow(dead_code)]
#![feature(float_extras, vec_resize)]

//! # tray\_rust - A Toy Ray Tracer in Rust
//!
//! tray\_rust is a toy physically based ray tracer built off of the techniques
//! discussed in [Physically Based Rendering](http://pbrt.org/). It began life as a port of
//! [tray](https://github.com/Twinklebear/tray) to [Rust](http://www.rust-lang.org) to check out the language.
//! The renderer is currently capable of path tracing, supports triangle meshes (MTL support coming soon),
//! and various physically based material models (including measured data from the
//! [MERL BRDF Database](http://www.merl.com/brdf/)).
//!
//! ## Building
//!
//! Unfortunately the project does currently require Rust nightly as I make use of some unstable features
//! (eg. Vec::resize). I hope to get things running on stable Rust once these features get stabilized.
//!
//! [![Build Status](https://travis-ci.org/Twinklebear/tray_rust.svg?branch=master)](https://travis-ci.org/Twinklebear/tray_rust)
//!
//! ## Running
//!
//! Currently the scene data is hardcoded in `src/scene.rs`, in the future I plan to add support for some
//! kind of JSON based scene file format. I strongly recommend running the release build as the debug version
//! will be very very slow. Running and passing `--help` or `-h` will print out some options, currently
//! the image resolution and samples per pixel are also hardcoded, though these are in `src/main.rs`.
//!
//! ## Building Your Own Scenes
//!
//! Start at the documentation for the scene module.
//!
//! ## TODO
//!
//! - More material models (eg. more microfacet models, rough glass, etc.)
//! - Textures
//! - Support for using an OBJ's associated MTL files
//! - Bump mapping
//! - [Subsurface scattering?](http://en.wikipedia.org/wiki/Subsurface_scattering)
//! - [Vertex Connection and Merging?](http://iliyan.com/publications/VertexMerging)
//!
//! ## Sample Renders
//!
//! In the samples the the Buddha, Dragon, Bunny and Lucy statue are from
//! [The Stanford Scanning Repository](http://graphics.stanford.edu/data/3Dscanrep/).
//! The Rust logo model was made by
//! [Nylithius on BlenderArtists](http://blenderartists.org/forum/showthread.php?362836-Rust-language-3D-logo).
//! The Utah teapot used is from [Morgan McGuire's page](http://graphics.cs.williams.edu/data/meshes.xml) and
//! the monkey head is Blender's Suzanne. I've made minor tweaks to some of the models so for convenience
//! you can find versions that can be easily loaded into the sample scenes [here](https://drive.google.com/folderview?id=0B-l_lLEMo1YeflUzUndCd01hOHhRNUhrQUowM3hVd2pCc3JrSXRiS3FQSzRYLWtGcGM0eGc&usp=sharing), though the
//! cube model for the Cornell box scene is included.
//! The materials on the Rust logo, Buddha, Dragon and Lucy are from the
//! [MERL BRDF Database](http://www.merl.com/brdf/).
//!
//! Render times are formatted as hh:mm:ss and were measured using 144 threads on a machine with four
//! [Xeon E7-8890 v3](http://ark.intel.com/products/84685/Intel-Xeon-Processor-E7-8890-v3-45M-Cache-2_50-GHz)
//! CPUs. The machine is an early/engineering sample from Intel so your results may differ, but massive thanks to
//! Intel for the hardware! Some older images renders are shown as well without timing since they were
//! run on a different machine.
//!
//!
//!
//!
//!
//! 1920x1080, 4096 samples/pixel. Rendering: 00:43:36.45.
//!
//! The following images compare disk vs. sphere area lights.
//!
//!
//!
//!
//!
//! 1920x1080, 4096 samples/pixel. Rendering: 00:49:33.514.
//!
//!
//!
//!
//!
//! 1920x1080, 4096 samples/pixel. Rendering: 00:46:11.822.
//!
//!
//!
//!
//!
//! 800x600, 4096 samples/pixel. Rendering: 00:03:36.196.
//!
//!
//!
//!
//!
//! 1920x1080, 2048 samples/pixel.
//!
//!
//!
//!
//!
//! 800x600, 1024 samples/pixel.
//!
//!
//!
//!
//!
//! 800x600, 1024 samples/pixel.

extern crate enum_set as enum_set;
extern crate rand;
extern crate byteorder;
extern crate serde_json;

pub mod linalg;
pub mod film;
pub mod geometry;
pub mod sampler;
pub mod integrator;
pub mod scene;
pub mod bxdf;
pub mod material;
pub mod light;
pub mod mc;
pub mod partition;

<|endoftext|>


<commit_before>//! # Half-precision conversion for Rust
//! This crate uses the fast table-based f32 <-> f16 conversions given in
//! "Fast Half Float Conversions" by Jeroen van der Zijp; see
//! `ftp://ftp.fox-toolkit.org/pub/fasthalffloatconversion.pdf`.

use std::mem::transmute;

#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug)]
pub struct f16 {
    pub bytes: u16,
}

impl PartialEq for f16 {
    fn eq(self: &f16, other: &f16) -> bool {
        return self.bytes == other.bytes;
    }
}

impl From<f32> for f16 {
    fn from(f: f32) -> f16 {
        unsafe {
            let base_table: *const u16 = transmute(include_bytes!("base_table.bin"));
            let shift_table: *const u8 = transmute(include_bytes!("shift_table.bin"));

            let ff: u32 = transmute(f);

            let bytes =
                *base_table.offset(((ff >> 23) & 0x1FF) as isize) +
                ((ff & 0x007FFFFF) >> *shift_table.offset(((ff >> 23) & 0x1FF) as isize)) as u16;
            f16 { bytes: bytes }
        }
    }
}

impl Into<f32> for f16 {
    fn into(self: f16) -> f32 {
        unsafe {
            let mantissa_table: *const u32 = transmute(include_bytes!("mantissa_table.bin"));
            let offset_table: *const u32 = transmute(include_bytes!("offset_table.bin"));
            let exponent_table: *const u32 = transmute(include_bytes!("exponent_table.bin"));

            let h0 = (self.bytes >> 10) as isize;
            let h1 = (self.bytes & 0x3FF) as u16 as isize;

            let mt_offset = *offset_table.offset(h0) as isize + h1;
            transmute(*mantissa_table.offset(mt_offset) + *exponent_table.offset(h0))
        }
    }
}

pub fn slice_to_f16(v: &[f32]) -> Vec<f16> {
    let mut tr = Vec::with_capacity(v.len());
    for it in v.iter() {
        tr.push(f16::from(*it));
    }
    tr
}

pub fn slice_to_f32(v: &[f16]) -> Vec<f32> {
    let mut tr = Vec::with_capacity(v.len());
    for it in v.iter() {
        tr.push((*it).into());
    }
    tr
}

#[test]
fn test() {
    for bytes in 0..(1 << 15) as u16 {
        let h0 = f16 { bytes: bytes };

        let f: f32 = h0.into();
        let h1 = f16::from(f);
        assert_eq!(h0, h1);
    }
}
<commit_msg>tests had insufficient coverage :(<commit_after>//! # Half-precision conversion for Rust
//! This crate uses the fast table-based f32 <-> f16 conversions given in
//! "Fast Half Float Conversions" by Jeroen van der Zijp; see
//! `ftp://ftp.fox-toolkit.org/pub/fasthalffloatconversion.pdf`.

use std::mem::transmute;

#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug)]
pub struct f16 {
    pub bytes: u16,
}

impl PartialEq for f16 {
    fn eq(self: &f16, other: &f16) -> bool {
        return self.bytes == other.bytes;
    }
}

impl From<f32> for f16 {
    fn from(f: f32) -> f16 {
        unsafe {
            let base_table: *const u16 = transmute(include_bytes!("base_table.bin"));
            let shift_table: *const u8 = transmute(include_bytes!("shift_table.bin"));

            let ff: u32 = transmute(f);

            let bytes =
                *base_table.offset(((ff >> 23) & 0x1FF) as isize) +
                ((ff & 0x007FFFFF) >> *shift_table.offset(((ff >> 23) & 0x1FF) as isize)) as u16;
            f16 { bytes: bytes }
        }
    }
}

impl Into<f32> for f16 {
    fn into(self: f16) -> f32 {
        unsafe {
            let mantissa_table: *const u32 = transmute(include_bytes!("mantissa_table.bin"));
            let offset_table: *const u32 = transmute(include_bytes!("offset_table.bin"));
            let exponent_table: *const u32 = transmute(include_bytes!("exponent_table.bin"));

            let h0 = (self.bytes >> 10) as isize;
            let h1 = (self.bytes & 0x3FF) as u16 as isize;

            let mt_offset = *offset_table.offset(h0) as isize + h1;
            transmute(*mantissa_table.offset(mt_offset) + *exponent_table.offset(h0))
        }
    }
}

pub fn slice_to_f16(v: &[f32]) -> Vec<f16> {
    let mut tr = Vec::with_capacity(v.len());
    for it in v.iter() {
        tr.push(f16::from(*it));
    }
    tr
}

pub fn slice_to_f32(v: &[f16]) -> Vec<f32> {
    let mut tr = Vec::with_capacity(v.len());
    for it in v.iter() {
        tr.push((*it).into());
    }
    tr
}

#[test]
fn test() {
    for bytes in 0..65535 as u16 {
        let h0 = f16 { bytes: bytes };

        let f: f32 = h0.into();
        let h1 = f16::from(f);
        assert_eq!(h0, h1);
    }
}
<|endoftext|>


<commit_before>#![warn(rust_2018_idioms)]
extern crate conduit;
extern crate route_recognizer as router;

#[macro_use]
extern crate tracing;

use std::collections::hash_map::{Entry, HashMap};
use std::error::Error;
use std::fmt;

use conduit::{box_error, Handler, HandlerResult, Method, RequestExt};
use router::{Match, Router};

#[derive(Default)]
pub struct RouteBuilder {
    routers: HashMap<Method, Router<WrappedHandler>>,
}

#[derive(Clone, Copy)]
pub struct RoutePattern(&'static str);

impl RoutePattern {
    pub fn pattern(&self) -> &str {
        self.0
    }
}

pub struct WrappedHandler {
    pattern: RoutePattern,
    handler: Box<dyn Handler>,
}

impl conduit::Handler for WrappedHandler {
    fn call(&self, request: &mut dyn RequestExt) -> HandlerResult {
        self.handler.call(request)
    }
}

#[derive(Debug)]
pub struct RouterError(String);

impl RouteBuilder {
    pub fn new() -> RouteBuilder {
        RouteBuilder {
            routers: HashMap::new(),
        }
    }

    #[instrument(level = "trace", skip(self))]
    #[allow(clippy::borrowed_box)]
    pub fn recognize<'a>(
        &'a self,
        method: &Method,
        path: &str,
    ) -> Result<Match<&WrappedHandler>, RouterError> {
        match self.routers.get(method) {
            Some(router) => router.recognize(path),
            None => Err(format!("No router found for {:?}", method)),
        }
        .map_err(RouterError)
    }

    #[instrument(level = "trace", skip(self, handler))]
    pub fn map<H: Handler>(
        &mut self,
        method: Method,
        pattern: &'static str,
        handler: H,
    ) -> &mut RouteBuilder {
        {
            let router = match self.routers.entry(method) {
                Entry::Occupied(e) => e.into_mut(),
                Entry::Vacant(e) => e.insert(Router::new()),
            };
            let wrapped_handler = WrappedHandler {
                pattern: RoutePattern(pattern),
                handler: Box::new(handler),
            };
            router.add(pattern, wrapped_handler);
        }
        self
    }

    pub fn get<H: Handler>(&mut self, pattern: &'static str, handler: H) -> &mut RouteBuilder {
        self.map(Method::GET, pattern, handler)
    }

    pub fn post<H: Handler>(&mut self, pattern: &'static str, handler: H) -> &mut RouteBuilder {
        self.map(Method::POST, pattern, handler)
    }

    pub fn put<H: Handler>(&mut self, pattern: &'static str, handler: H) -> &mut RouteBuilder {
        self.map(Method::PUT, pattern, handler)
    }

    pub fn delete<H: Handler>(&mut self, pattern: &'static str, handler: H) -> &mut RouteBuilder {
        self.map(Method::DELETE, pattern, handler)
    }

    pub fn head<H: Handler>(&mut self, pattern: &'static str, handler: H) -> &mut RouteBuilder {
        self.map(Method::HEAD, pattern, handler)
    }
}

impl conduit::Handler for RouteBuilder {
    #[instrument(level = "trace", skip(self, request))]
    fn call(&self, request: &mut dyn RequestExt) -> HandlerResult {
        let m = {
            let method = request.method();
            let path = request.path();

            match self.recognize(&method, path) {
                Ok(m) => m,
                Err(e) => {
                    info!("{}", e.0);
                    return Err(box_error(e));
                }
            }
        };

        let pattern = m.handler().pattern;
        debug!(pattern = pattern.0, "matching route handler found");

        {
            let extensions = request.mut_extensions();
            extensions.insert(pattern);
            extensions.insert(m.params().clone());
        }

        let span = trace_span!("handler", pattern = pattern.0);
        span.in_scope(|| m.handler().call(request))
    }
}

impl Error for RouterError {
    fn description(&self) -> &str {
        &self.0
    }
}

impl fmt::Display for RouterError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Display::fmt(&self.0, f)
    }
}

pub trait RequestParams<'a> {
    fn params(self) -> &'a router::Params;
}

pub fn params(req: &dyn RequestExt) -> &router::Params {
    req.extensions()
        .find::<router::Params>()
        .expect("Missing params")
}

impl<'a> RequestParams<'a> for &'a (dyn RequestExt + 'a) {
    fn params(self) -> &'a router::Params {
        params(self)
    }
}

#[cfg(test)]
mod tests {
    extern crate conduit_test;
    extern crate lazy_static;
    extern crate tracing_subscriber;

    use std::io;
    use std::net::SocketAddr;

    use {RequestParams, RouteBuilder, RoutePattern};

    use self::conduit_test::ResponseExt;
    use conduit::{
        Body, Extensions, Handler, HeaderMap, Host, Method, Response, Scheme, StatusCode, Version,
    };

    lazy_static::lazy_static! {
        static ref TRACING: () = {
            tracing_subscriber::FmtSubscriber::builder()
                .with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
                .with_span_events(tracing_subscriber::fmt::format::FmtSpan::FULL)
                .with_thread_names(true)
                .init();
        };
    }

    struct RequestSentinel {
        method: Method,
        path: String,
        extensions: conduit::Extensions,
    }

    impl RequestSentinel {
        fn new(method: Method, path: &'static str) -> RequestSentinel {
            RequestSentinel {
                path: path.to_string(),
                extensions: Extensions::new(),
                method,
            }
        }
    }

    impl conduit::RequestExt for RequestSentinel {
        fn http_version(&self) -> Version {
            unimplemented!()
        }
        fn method(&self) -> &Method {
            &self.method
        }
        fn scheme(&self) -> Scheme {
            unimplemented!()
        }
        fn host(&self) -> Host<'_> {
            unimplemented!()
        }
        fn virtual_root(&self) -> Option<&str> {
            unimplemented!()
        }
        fn path(&self) -> &str {
            &self.path
        }
        fn path_mut(&mut self) -> &mut String {
            &mut self.path
        }
        fn query_string(&self) -> Option<&str> {
            unimplemented!()
        }
        fn remote_addr(&self) -> SocketAddr {
            unimplemented!()
        }
        fn content_length(&self) -> Option<u64> {
            unimplemented!()
        }
        fn headers(&self) -> &HeaderMap {
            unimplemented!()
        }
        fn body(&mut self) -> &mut dyn io::Read {
            unimplemented!()
        }
        fn extensions(&self) -> &Extensions {
            &self.extensions
        }
        fn mut_extensions(&mut self) -> &mut Extensions {
            &mut self.extensions
        }
    }

    #[test]
    fn basic_get() {
        lazy_static::initialize(&TRACING);

        let router = test_router();
        let mut req = RequestSentinel::new(Method::GET, "/posts/1");
        let res = router.call(&mut req).expect("No response");

        assert_eq!(res.status(), StatusCode::OK);
        assert_eq!(*res.into_cow(), b"1, GET, /posts/:id"[..]);
    }

    #[test]
    fn basic_post() {
        lazy_static::initialize(&TRACING);

        let router = test_router();
        let mut req = RequestSentinel::new(Method::POST, "/posts/10");
        let res = router.call(&mut req).expect("No response");

        assert_eq!(res.status(), StatusCode::OK);
        assert_eq!(*res.into_cow(), b"10, POST, /posts/:id"[..]);
    }

    #[test]
    fn nonexistent_route() {
        lazy_static::initialize(&TRACING);

        let router = test_router();
        let mut req = RequestSentinel::new(Method::POST, "/nonexistent");
        router.call(&mut req).err().expect("No response");
    }

    #[test]
    fn catch_all() {
        let mut router = RouteBuilder::new();
        router.get("/*", test_handler);

        let mut req = RequestSentinel::new(Method::GET, "/foo");
        let res = router.call(&mut req).expect("No response");
        assert_eq!(res.status(), StatusCode::OK);
        assert_eq!(*res.into_cow(), b", GET, /*"[..]);
    }

    fn test_router() -> RouteBuilder {
        let mut router = RouteBuilder::new();
        router.post("/posts/:id", test_handler);
        router.get("/posts/:id", test_handler);
        router
    }

    fn test_handler(req: &mut dyn conduit::RequestExt) -> conduit::HttpResult {
        let res = vec![
            req.params().find("id").unwrap_or("").to_string(),
            format!("{:?}", req.method()),
            req.extensions()
                .find::<RoutePattern>()
                .unwrap()
                .pattern()
                .to_string(),
        ];

        let bytes = res.join(", ").into_bytes();
        Response::builder().body(Body::from_vec(bytes))
    }
}
<commit_msg>Switch to the test writer, to work with per-test output capturing<commit_after>#![warn(rust_2018_idioms)]
extern crate conduit;
extern crate route_recognizer as router;

#[macro_use]
extern crate tracing;

use std::collections::hash_map::{Entry, HashMap};
use std::error::Error;
use std::fmt;

use conduit::{box_error, Handler, HandlerResult, Method, RequestExt};
use router::{Match, Router};

#[derive(Default)]
pub struct RouteBuilder {
    routers: HashMap<Method, Router<WrappedHandler>>,
}

#[derive(Clone, Copy)]
pub struct RoutePattern(&'static str);

impl RoutePattern {
    pub fn pattern(&self) -> &str {
        self.0
    }
}

pub struct WrappedHandler {
    pattern: RoutePattern,
    handler: Box<dyn Handler>,
}

impl conduit::Handler for WrappedHandler {
    fn call(&self, request: &mut dyn RequestExt) -> HandlerResult {
        self.handler.call(request)
    }
}

#[derive(Debug)]
pub struct RouterError(String);

impl RouteBuilder {
    pub fn new() -> RouteBuilder {
        RouteBuilder {
            routers: HashMap::new(),
        }
    }

    #[instrument(level = "trace", skip(self))]
    #[allow(clippy::borrowed_box)]
    pub fn recognize<'a>(
        &'a self,
        method: &Method,
        path: &str,
    ) -> Result<Match<&WrappedHandler>, RouterError> {
        match self.routers.get(method) {
            Some(router) => router.recognize(path),
            None => Err(format!("No router found for {:?}", method)),
        }
        .map_err(RouterError)
    }

    #[instrument(level = "trace", skip(self, handler))]
    pub fn map<H: Handler>(
        &mut self,
        method: Method,
        pattern: &'static str,
        handler: H,
    ) -> &mut RouteBuilder {
        {
            let router = match self.routers.entry(method) {
                Entry::Occupied(e) => e.into_mut(),
                Entry::Vacant(e) => e.insert(Router::new()),
            };
            let wrapped_handler = WrappedHandler {
                pattern: RoutePattern(pattern),
                handler: Box::new(handler),
            };
            router.add(pattern, wrapped_handler);
        }
        self
    }

    pub fn get<H: Handler>(&mut self, pattern: &'static str, handler: H) -> &mut RouteBuilder {
        self.map(Method::GET, pattern, handler)
    }

    pub fn post<H: Handler>(&mut self, pattern: &'static str, handler: H) -> &mut RouteBuilder {
        self.map(Method::POST, pattern, handler)
    }

    pub fn put<H: Handler>(&mut self, pattern: &'static str, handler: H) -> &mut RouteBuilder {
        self.map(Method::PUT, pattern, handler)
    }

    pub fn delete<H: Handler>(&mut self, pattern: &'static str, handler: H) -> &mut RouteBuilder {
        self.map(Method::DELETE, pattern, handler)
    }

    pub fn head<H: Handler>(&mut self, pattern: &'static str, handler: H) -> &mut RouteBuilder {
        self.map(Method::HEAD, pattern, handler)
    }
}

impl conduit::Handler for RouteBuilder {
    #[instrument(level = "trace", skip(self, request))]
    fn call(&self, request: &mut dyn RequestExt) -> HandlerResult {
        let m = {
            let method = request.method();
            let path = request.path();

            match self.recognize(&method, path) {
                Ok(m) => m,
                Err(e) => {
                    info!("{}", e.0);
                    return Err(box_error(e));
                }
            }
        };

        let pattern = m.handler().pattern;
        debug!(pattern = pattern.0, "matching route handler found");

        {
            let extensions = request.mut_extensions();
            extensions.insert(pattern);
            extensions.insert(m.params().clone());
        }

        let span = trace_span!("handler", pattern = pattern.0);
        span.in_scope(|| m.handler().call(request))
    }
}

impl Error for RouterError {
    fn description(&self) -> &str {
        &self.0
    }
}

impl fmt::Display for RouterError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Display::fmt(&self.0, f)
    }
}

pub trait RequestParams<'a> {
    fn params(self) -> &'a router::Params;
}

pub fn params(req: &dyn RequestExt) -> &router::Params {
    req.extensions()
        .find::<router::Params>()
        .expect("Missing params")
}

impl<'a> RequestParams<'a> for &'a (dyn RequestExt + 'a) {
    fn params(self) -> &'a router::Params {
        params(self)
    }
}

#[cfg(test)]
mod tests {
    extern crate conduit_test;
    extern crate lazy_static;
    extern crate tracing_subscriber;

    use std::io;
    use std::net::SocketAddr;

    use {RequestParams, RouteBuilder, RoutePattern};

    use self::conduit_test::ResponseExt;
    use conduit::{
        Body, Extensions, Handler, HeaderMap, Host, Method, Response, Scheme, StatusCode, Version,
    };

    lazy_static::lazy_static! {
        static ref TRACING: () = {
            tracing_subscriber::FmtSubscriber::builder()
                .with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
                .with_span_events(tracing_subscriber::fmt::format::FmtSpan::FULL)
                .with_test_writer()
                .init();
        };
    }

    struct RequestSentinel {
        method: Method,
        path: String,
        extensions: conduit::Extensions,
    }

    impl RequestSentinel {
        fn new(method: Method, path: &'static str) -> RequestSentinel {
            RequestSentinel {
                path: path.to_string(),
                extensions: Extensions::new(),
                method,
            }
        }
    }

    impl conduit::RequestExt for RequestSentinel {
        fn http_version(&self) -> Version {
            unimplemented!()
        }
        fn method(&self) -> &Method {
            &self.method
        }
        fn scheme(&self) -> Scheme {
            unimplemented!()
        }
        fn host(&self) -> Host<'_> {
            unimplemented!()
        }
        fn virtual_root(&self) -> Option<&str> {
            unimplemented!()
        }
        fn path(&self) -> &str {
            &self.path
        }
        fn path_mut(&mut self) -> &mut String {
            &mut self.path
        }
        fn query_string(&self) -> Option<&str> {
            unimplemented!()
        }
        fn remote_addr(&self) -> SocketAddr {
            unimplemented!()
        }
        fn content_length(&self) -> Option<u64> {
            unimplemented!()
        }
        fn headers(&self) -> &HeaderMap {
            unimplemented!()
        }
        fn body(&mut self) -> &mut dyn io::Read {
            unimplemented!()
        }
        fn extensions(&self) -> &Extensions {
            &self.extensions
        }
        fn mut_extensions(&mut self) -> &mut Extensions {
            &mut self.extensions
        }
    }

    #[test]
    fn basic_get() {
        lazy_static::initialize(&TRACING);

        let router = test_router();
        let mut req = RequestSentinel::new(Method::GET, "/posts/1");
        let res = router.call(&mut req).expect("No response");

        assert_eq!(res.status(), StatusCode::OK);
        assert_eq!(*res.into_cow(), b"1, GET, /posts/:id"[..]);
    }

    #[test]
    fn basic_post() {
        lazy_static::initialize(&TRACING);

        let router = test_router();
        let mut req = RequestSentinel::new(Method::POST, "/posts/10");
        let res = router.call(&mut req).expect("No response");

        assert_eq!(res.status(), StatusCode::OK);
        assert_eq!(*res.into_cow(), b"10, POST, /posts/:id"[..]);
    }

    #[test]
    fn nonexistent_route() {
        lazy_static::initialize(&TRACING);

        let router = test_router();
        let mut req = RequestSentinel::new(Method::POST, "/nonexistent");
        router.call(&mut req).err().expect("No response");
    }

    #[test]
    fn catch_all() {
        let mut router = RouteBuilder::new();
        router.get("/*", test_handler);

        let mut req = RequestSentinel::new(Method::GET, "/foo");
        let res = router.call(&mut req).expect("No response");
        assert_eq!(res.status(), StatusCode::OK);
        assert_eq!(*res.into_cow(), b", GET, /*"[..]);
    }

    fn test_router() -> RouteBuilder {
        let mut router = RouteBuilder::new();
        router.post("/posts/:id", test_handler);
        router.get("/posts/:id", test_handler);
        router
    }

    fn test_handler(req: &mut dyn conduit::RequestExt) -> conduit::HttpResult {
        let res = vec![
            req.params().find("id").unwrap_or("").to_string(),
            format!("{:?}", req.method()),
            req.extensions()
                .find::<RoutePattern>()
                .unwrap()
                .pattern()
                .to_string(),
        ];

        let bytes = res.join(", ").into_bytes();
        Response::builder().body(Body::from_vec(bytes))
    }
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate rayon;
// extern crate crossbeam;

use self::rand::{thread_rng, Rng};
use std::sync::{Arc, Mutex, RwLock};
use rayon::prelude::*;

#[derive(Clone, PartialEq, Eq)]
pub struct GameCell {
	x: usize,
	y: usize,
	pub alive: bool,
}

impl GameCell {
	fn count_neighbors(&self, board: &Vec<GameCell>, size: usize) -> u8 {
		let ul = if self.y >= 1 && self.x != 0 { board[(self.y - 1) * size + self.x - 1].alive } else { false };
		let uu = if self.y >= 1 { board[(self.y - 1) * size + self.x + 0].alive } else { false };
		let ur = if self.y >= 1 && self.x != size - 1 { board[(self.y - 1) * size + self.x + 1].alive } else { false };
		let l  = if self.x != 0 { board[self.y * size + self.x - 1].alive } else { false };
		let r  = if self.x != size - 1 { board[self.y * size + self.x + 1].alive } else { false };
		let dl = if self.y != size - 1 && self.x != 0 { board[(self.y + 1) * size + self.x - 1].alive } else { false };
		let dd = if self.y != size - 1 { board[(self.y + 1) * size + self.x + 0].alive } else { false };
		let dr = if self.y != size - 1 && self.x != size - 1 { board[(self.y + 1) * size + self.x + 1].alive } else { false };

		let mut neighbors: u8 = 0;
		if ul == true { neighbors += 1; }
		if uu == true { neighbors += 1; }
		if ur == true { neighbors += 1; }
		if l  == true { neighbors += 1; }
		if r  == true { neighbors += 1; }
		if dl == true { neighbors += 1; }
		if dd == true { neighbors += 1; }
		if dr == true { neighbors += 1; }

		neighbors
	}
}

#[derive(Clone)]
pub struct Game {
	pub size: usize,
	current: Arc<RwLock< Vec<GameCell> >>,
	next: Arc<Mutex< Vec<bool> >>,
}

// impl From<Vec<State>> for Game {
// 	fn from(preset_game: Vec<State>) -> Self {
// 		let size: usize = (preset_game.len() as f64).sqrt() as usize;
// 		assert!(size >= 3);

// 		Game {
// 			size: size,
// 			current: Arc::new(RwLock::new(preset_game.clone())),
// 			next: Arc::new(Mutex::new(preset_game.clone()))
// 		}
// 	}
// }

impl Game {
	pub fn new(size: usize, percent_chance_for_cell_to_be_alive: f64) -> Game {
		assert!(size >= 3);
		assert!(percent_chance_for_cell_to_be_alive < 1.0);
		assert!(percent_chance_for_cell_to_be_alive >= 0.0);

		let mut board = vec![GameCell {x: 0, y: 0, alive: false}; size*size];

		for y in 0..size {
			for x in 0..size {
				let index = y * size + x;
				board[index].x = x;
				board[index].y = y;
				board[index].alive = match thread_rng().next_f64() {
					i if i < percent_chance_for_cell_to_be_alive => true,
					_ => false,
				};
			}
		}

		Game {
			size: size,
			current: Arc::new(RwLock::new(board)),
			next: Arc::new(Mutex::new(Vec::with_capacity(size))),
		}
	}

	pub fn get_current_read_lock(&self) -> std::sync::RwLockReadGuard< Vec<GameCell> > {
		self.current.read().unwrap()
	}

	fn get_next_state_from_current_cell_and_neighbor_count(game_cell: &GameCell, number_of_neighbors: u8) -> bool {
		match game_cell.alive {
			false => {
				if number_of_neighbors != 3 { false } else { true }
			},
			true => {
				if number_of_neighbors < 2 || number_of_neighbors > 3 { false } else { true }
			},
		}
	}

	pub fn advance(&self) {
		let mut next_guard = self.next.lock().unwrap();
		let current_guard = self.current.read().unwrap();

		current_guard.par_iter()
			.map(|game_cell| {
				let neighbor_count = game_cell.count_neighbors(&*current_guard, self.size);
				Game::get_next_state_from_current_cell_and_neighbor_count(game_cell, neighbor_count)
			})
			.collect_into(&mut *next_guard);

		// Exchange read lock for write lock
		drop(current_guard);
		let mut current_guard = self.current.write().unwrap();

		current_guard.par_iter_mut()
			.enumerate()
			.for_each(| (i, game_cell) | {
				game_cell.alive = next_guard[i];
			});
	}

	// pub fn advance_toroidally(&self) {
	// 	// Get read lock for 'current' and mutex lock for 'next'
	// 	// N.B. By locking 'next' first, this ensures that if another thread tries
	// 	// 		to call 'advance', that thread will block until this is done.
	// 	let mut next = self.next.lock().unwrap();
	// 	let current = self.current.read().unwrap();

	// 	for y in 0..self.size {
	// 		for x in 0..self.size {
	// 			let ul = if y >= 1 {
	// 				if x != 0 { current[(y - 1) * self.size + x - 1] } // normal case
	// 				else { current[y * self.size - 1] } // left edge
	// 			} else {
	// 				if x != 0 { current[(self.size - 1) * self.size + x - 1] } // top edge
	// 				else { current[self.size * self.size - 1] } // top-left corner
	// 			};

	// 			let uu = if y >= 1 {
	// 				current[(y - 1) * self.size + x + 0] // normal case
	// 			} else {
	// 				current[(self.size - 1) * self.size + x + 0] // top edge
	// 			};

	// 			let ur = if y >= 1 {
	// 				if x != self.size - 1 { current[(y - 1) * self.size + x + 1] } // normal case
	// 				else { current[(y - 1) * self.size + 0] } // right edge
	// 			} else {
	// 				if x != self.size - 1 { current[(self.size - 1) * self.size + x + 1] } // top edge
	// 				else { current[(self.size - 1) * self.size + 0] } // top-right corner
	// 			};

	// 			let l = if x != 0 {
	// 				current[y * self.size + x - 1] // normal case
	// 			} else {
	// 				current[(y + 1) * self.size - 1] // left edge
	// 			};

	// 			let r = if x != self.size - 1 {
	// 				current[y * self.size + x + 1] // normal case
	// 			} else {
	// 				current[y * self.size + 0] // right edge
	// 			};

	// 			let dl = if y != self.size - 1 {
	// 				if x != 0 { current[(y + 1) * self.size + x - 1] } // normal case
	// 				else { current[(y + 2) * self.size - 1] } // left edge
	// 			} else {
	// 				if x != 0 { current[x - 1] } // bottom edge
	// 				else { current[self.size - 1] } // bottom-left corner
	// 			};

	// 			let dd = if y != self.size - 1 {
	// 				current[(y + 1) * self.size + x + 0] // normal case
	// 			} else {
	// 				current[x + 0] // bottom edge
	// 			};

	// 			let dr = if y != self.size - 1 {
	// 				if x != self.size - 1 { current[(y + 1) * self.size + x + 1] } // normal case
	// 				else { current[(y + 1) * self.size] } // right edge
	// 			} else {
	// 				if x != self.size - 1 { current[x + 1] } // bottom edge
	// 				else { current[0] } // bottom-right corner
	// 			};

	// 			let mut neighbors: usize = 0;
	// 			if ul == State::Alive { neighbors += 1; }
	// 			if uu == State::Alive { neighbors += 1; }
	// 			if ur == State::Alive { neighbors += 1; }
	// 			if l == State::Alive { neighbors += 1; }
	// 			if r == State::Alive { neighbors += 1; }
	// 			if dl == State::Alive { neighbors += 1; }
	// 			if dd == State::Alive { neighbors += 1; }
	// 			if dr == State::Alive { neighbors += 1; }

	// 			next[y * self.size + x] = Game::get_next_cell_from_current_cell_and_neighbors(current[y * self.size + x], neighbors);
	// 		}
	// 	}

	// 	// Exchange read lock for write lock
	// 	drop(current);
	// 	let mut current = self.current.write().unwrap();

	// 	*current = next.clone();
	// }
}
<commit_msg>Relocate a Game member function to GameCell<commit_after>extern crate rand;
extern crate rayon;
// extern crate crossbeam;

use self::rand::{thread_rng, Rng};
use std::sync::{Arc, Mutex, RwLock};
use rayon::prelude::*;

#[derive(Clone, PartialEq, Eq)]
pub struct GameCell {
	x: usize,
	y: usize,
	pub alive: bool,
}

impl GameCell {
	fn count_neighbors(&self, board: &Vec<GameCell>, size: usize) -> u8 {
		let ul = if self.y >= 1 && self.x != 0 { board[(self.y - 1) * size + self.x - 1].alive } else { false };
		let uu = if self.y >= 1 { board[(self.y - 1) * size + self.x + 0].alive } else { false };
		let ur = if self.y >= 1 && self.x != size - 1 { board[(self.y - 1) * size + self.x + 1].alive } else { false };
		let l  = if self.x != 0 { board[self.y * size + self.x - 1].alive } else { false };
		let r  = if self.x != size - 1 { board[self.y * size + self.x + 1].alive } else { false };
		let dl = if self.y != size - 1 && self.x != 0 { board[(self.y + 1) * size + self.x - 1].alive } else { false };
		let dd = if self.y != size - 1 { board[(self.y + 1) * size + self.x + 0].alive } else { false };
		let dr = if self.y != size - 1 && self.x != size - 1 { board[(self.y + 1) * size + self.x + 1].alive } else { false };

		let mut neighbors: u8 = 0;
		if ul == true { neighbors += 1; }
		if uu == true { neighbors += 1; }
		if ur == true { neighbors += 1; }
		if l  == true { neighbors += 1; }
		if r  == true { neighbors += 1; }
		if dl == true { neighbors += 1; }
		if dd == true { neighbors += 1; }
		if dr == true { neighbors += 1; }

		neighbors
	}

	// Calculates the next state for this cell (but does not set it!)
	fn calculate_next_state_from_neighbor_count(&self, number_of_neighbors: u8) -> bool {
		match self.alive {
			false => {
				if number_of_neighbors != 3 { false } else { true }
			},
			true => {
				if number_of_neighbors < 2 || number_of_neighbors > 3 { false } else { true }
			},
		}
	}
}

#[derive(Clone)]
pub struct Game {
	pub size: usize,
	current: Arc<RwLock< Vec<GameCell> >>,
	next: Arc<Mutex< Vec<bool> >>,
}

// impl From<Vec<State>> for Game {
// 	fn from(preset_game: Vec<State>) -> Self {
// 		let size: usize = (preset_game.len() as f64).sqrt() as usize;
// 		assert!(size >= 3);

// 		Game {
// 			size: size,
// 			current: Arc::new(RwLock::new(preset_game.clone())),
// 			next: Arc::new(Mutex::new(preset_game.clone()))
// 		}
// 	}
// }

impl Game {
	pub fn new(size: usize, percent_chance_for_cell_to_be_alive: f64) -> Game {
		assert!(size >= 3);
		assert!(percent_chance_for_cell_to_be_alive < 1.0);
		assert!(percent_chance_for_cell_to_be_alive >= 0.0);

		let mut board = vec![GameCell {x: 0, y: 0, alive: false}; size*size];

		for y in 0..size {
			for x in 0..size {
				let index = y * size + x;
				board[index].x = x;
				board[index].y = y;
				board[index].alive = match thread_rng().next_f64() {
					i if i < percent_chance_for_cell_to_be_alive => true,
					_ => false,
				};
			}
		}

		Game {
			size: size,
			current: Arc::new(RwLock::new(board)),
			next: Arc::new(Mutex::new(Vec::with_capacity(size))),
		}
	}

	pub fn get_current_read_lock(&self) -> std::sync::RwLockReadGuard< Vec<GameCell> > {
		self.current.read().unwrap()
	}

	pub fn advance(&self) {
		let mut next_guard = self.next.lock().unwrap();
		let current_guard = self.current.read().unwrap();

		current_guard.par_iter()
			.map(|game_cell| {
				let neighbor_count = game_cell.count_neighbors(&*current_guard, self.size);
				game_cell.calculate_next_state_from_neighbor_count(neighbor_count)
			})
			.collect_into(&mut *next_guard);

		// Exchange read lock for write lock
		drop(current_guard);
		let mut current_guard = self.current.write().unwrap();

		current_guard.par_iter_mut()
			.enumerate()
			.for_each(| (i, game_cell) | {
				game_cell.alive = next_guard[i];
			});
	}

	// pub fn advance_toroidally(&self) {
	// 	// Get read lock for 'current' and mutex lock for 'next'
	// 	// N.B. By locking 'next' first, this ensures that if another thread tries
	// 	// 		to call 'advance', that thread will block until this is done.
	// 	let mut next = self.next.lock().unwrap();
	// 	let current = self.current.read().unwrap();

	// 	for y in 0..self.size {
	// 		for x in 0..self.size {
	// 			let ul = if y >= 1 {
	// 				if x != 0 { current[(y - 1) * self.size + x - 1] } // normal case
	// 				else { current[y * self.size - 1] } // left edge
	// 			} else {
	// 				if x != 0 { current[(self.size - 1) * self.size + x - 1] } // top edge
	// 				else { current[self.size * self.size - 1] } // top-left corner
	// 			};

	// 			let uu = if y >= 1 {
	// 				current[(y - 1) * self.size + x + 0] // normal case
	// 			} else {
	// 				current[(self.size - 1) * self.size + x + 0] // top edge
	// 			};

	// 			let ur = if y >= 1 {
	// 				if x != self.size - 1 { current[(y - 1) * self.size + x + 1] } // normal case
	// 				else { current[(y - 1) * self.size + 0] } // right edge
	// 			} else {
	// 				if x != self.size - 1 { current[(self.size - 1) * self.size + x + 1] } // top edge
	// 				else { current[(self.size - 1) * self.size + 0] } // top-right corner
	// 			};

	// 			let l = if x != 0 {
	// 				current[y * self.size + x - 1] // normal case
	// 			} else {
	// 				current[(y + 1) * self.size - 1] // left edge
	// 			};

	// 			let r = if x != self.size - 1 {
	// 				current[y * self.size + x + 1] // normal case
	// 			} else {
	// 				current[y * self.size + 0] // right edge
	// 			};

	// 			let dl = if y != self.size - 1 {
	// 				if x != 0 { current[(y + 1) * self.size + x - 1] } // normal case
	// 				else { current[(y + 2) * self.size - 1] } // left edge
	// 			} else {
	// 				if x != 0 { current[x - 1] } // bottom edge
	// 				else { current[self.size - 1] } // bottom-left corner
	// 			};

	// 			let dd = if y != self.size - 1 {
	// 				current[(y + 1) * self.size + x + 0] // normal case
	// 			} else {
	// 				current[x + 0] // bottom edge
	// 			};

	// 			let dr = if y != self.size - 1 {
	// 				if x != self.size - 1 { current[(y + 1) * self.size + x + 1] } // normal case
	// 				else { current[(y + 1) * self.size] } // right edge
	// 			} else {
	// 				if x != self.size - 1 { current[x + 1] } // bottom edge
	// 				else { current[0] } // bottom-right corner
	// 			};

	// 			let mut neighbors: usize = 0;
	// 			if ul == State::Alive { neighbors += 1; }
	// 			if uu == State::Alive { neighbors += 1; }
	// 			if ur == State::Alive { neighbors += 1; }
	// 			if l == State::Alive { neighbors += 1; }
	// 			if r == State::Alive { neighbors += 1; }
	// 			if dl == State::Alive { neighbors += 1; }
	// 			if dd == State::Alive { neighbors += 1; }
	// 			if dr == State::Alive { neighbors += 1; }

	// 			next[y * self.size + x] = Game::get_next_cell_from_current_cell_and_neighbors(current[y * self.size + x], neighbors);
	// 		}
	// 	}

	// 	// Exchange read lock for write lock
	// 	drop(current);
	// 	let mut current = self.current.write().unwrap();

	// 	*current = next.clone();
	// }
}
<|endoftext|>


<commit_before>//! ![Coinnect](https://raw.githubusercontent.com/hugues31/coinnect/master/coinnect.png)
//!
//! Coinnect is a Rust library aiming to provide a complete access to REST APIs for various
//! crypto-currencies exchanges (see below for a list of supported exchanges).
//! All methods consume HTTPS api. The purpose of this crate is not
//! to stream data (you should use websocket/FIX in that case).
//!
//! For optional parameters, most methods require an empty str (`""`) if you don't want to specify
//! them.
//!
//! ### Exchanges support:
//! - [x] Poloniex
//! - [x] Kraken
//! - [x] Bitstamp (partial)
//!
//! # WARNING
//! This library is highly experimental at the moment. Please do not invest what you
//! can't afford to loose. This is a personal project, I can not be held responsible for
//! the library malfunction, which can lead to a loss of money.

#[macro_use]
extern crate hyper;
extern crate crypto;
extern crate hyper_native_tls;
extern crate rustc_serialize;
extern crate serde_json;
extern crate time;

pub mod coinnect;
pub mod exchange;
pub mod error;
pub mod pair;
pub mod types;
mod helpers;

pub mod bitstamp;
pub mod poloniex;
pub mod kraken;

#[cfg(test)]
mod tests {}
<commit_msg>Remove unused mod tests{}<commit_after>//! ![Coinnect](https://raw.githubusercontent.com/hugues31/coinnect/master/coinnect.png)
//!
//! Coinnect is a Rust library aiming to provide a complete access to REST APIs for various
//! crypto-currencies exchanges (see below for a list of supported exchanges).
//! All methods consume HTTPS api. The purpose of this crate is not
//! to stream data (you should use websocket/FIX in that case).
//!
//! For optional parameters, most methods require an empty str (`""`) if you don't want to specify
//! them.
//!
//! ### Exchanges support:
//! - [x] Poloniex
//! - [x] Kraken
//! - [x] Bitstamp (partial)
//!
//! # WARNING
//! This library is highly experimental at the moment. Please do not invest what you
//! can't afford to loose. This is a personal project, I can not be held responsible for
//! the library malfunction, which can lead to a loss of money.

#[macro_use]
extern crate hyper;
extern crate crypto;
extern crate hyper_native_tls;
extern crate rustc_serialize;
extern crate serde_json;
extern crate time;

pub mod coinnect;
pub mod exchange;
pub mod error;
pub mod pair;
pub mod types;
mod helpers;

pub mod bitstamp;
pub mod poloniex;
pub mod kraken;<|endoftext|>