<commit_before>/// A macro that takes a struct-like definition that takes an array type and (row, column)
/// size arguments and implements the required methods.
///
/// Usage:
/// #impl_matrix!{
/// #    struct MyMatrix([f32; (3, 3)]);
/// #};
///
/// #let mut matrix =  MyMatrix([0.0; 9]);
/// #matrix[(2,1)] = 8.1;
/// #println!("{:?}", matrix);
/// #println!("{}", m.row());
///
/// The matrix methods are based on the [`generic_matrix`] crate which uses an internal Vec<T> to
/// hold data.
///
/// [`generic_matrix`]: http://gifnksm.github.io/generic-matrix-rs/generic_matrix/index.html
#[macro_export]
macro_rules! impl_matrix {
    ($st:ident([$t:ty; ($row:expr, $col:expr)])) => {
        use std::ops::{Index, IndexMut};

        #[derive(Debug)]
        struct $st([$t; $row * $col]);

        impl ArrayMatrix for $st {
            fn row(&self) -> usize {
                $row
            }

            fn column(&self) -> usize {
                $col
            }

            fn size(&self) -> (usize, usize) {
                (self.row(), self.column())
            }
        }

        impl Index<(usize, usize)> for $st {
            type Output = $t;

            #[inline]
            fn index(&self, (i, j): (usize, usize)) -> &$t {
                assert!(i < $row && j < $col);
                &self.0[i * $col + j]
            }
        }

        impl IndexMut<(usize, usize)> for $st {

            #[inline]
            fn index_mut(&mut self, (i, j): (usize, usize)) -> &mut $t {
                assert!(i < $row && j < $col);
                &mut self.0[i * $col + j]
            }
        }
    }
}

trait ArrayMatrix {
    fn row(&self) -> usize;
    fn column(&self) -> usize;
    fn size(&self) -> (usize, usize);
}

// Non-macro test implementation

//#[derive(Debug)]
//struct MyMatrix([f32; 9]);
//
//impl Matrix for MyMatrix {
//    fn row(&self) -> usize {
//        3
//    }
//
//    fn column(&self) -> usize {
//        self.0.len() / self.row()
//    }
//
//    fn size(&self) -> (usize, usize) {
//        (self.row(), self.column())
//    }
//}
//
//impl Index<(usize, usize)> for MyMatrix {
//    type Output = f32;
//
//    #[inline]
//    fn index(&self, (i, j): (usize, usize)) -> &f32 {
//        assert!(i < self.row() && j < self.column());
//        &self.0[i * self.column() + j]
//    }
//}
//
//impl IndexMut<(usize, usize)> for MyMatrix {
//    #[inline]
//    fn index_mut(&mut self, (i, j): (usize, usize)) -> &mut f32 {
//        let column_len = self.column();
//        assert!(i < self.row() && j < column_len);
//        &mut self.0[i * column_len + j]
//    }
//}
//
//#[test]
//fn test_matrix() {
//    let mut m = MyMatrix([3.; 9]);
//    m[(2,1)] = 8.1;
//    println!("{:?}", m);
//    println!("{}", m.row());
//    assert_eq!(m.row(), 3);
//    assert_eq!(m.column(), 3);
//}

#[test]
fn test_impl_matrix() {
    const ROW: usize = 3;
    const COLUMN: usize = 3;

    impl_matrix!(TestMatrix([i32; (ROW, COLUMN)]));

    let mut m = TestMatrix([1, 2, 3, 4, 5, 6, 7, 8, 9]);

    println!("{:?}", m);

    assert_eq!(m[(1, 2)], 6);
    m[(1, 2)] = 30;
    assert_eq!(m[(1, 2)], 30);
    assert_eq!(m.row(), ROW);
    assert_eq!(m.column(), COLUMN);
}
<commit_msg>Update trait to public.<commit_after>/// A macro that takes a struct-like definition that takes an array type and (row, column)
/// size arguments and implements the required methods.
///
/// Usage:
/// #impl_matrix!{
/// #    struct MyMatrix([f32; (3, 3)]);
/// #};
///
/// #let mut matrix =  MyMatrix([0.0; 9]);
/// #matrix[(2,1)] = 8.1;
/// #println!("{:?}", matrix);
/// #println!("{}", m.row());
///
/// The matrix methods are based on the [`generic_matrix`] crate which uses an internal Vec<T> to
/// hold data.
///
/// [`generic_matrix`]: http://gifnksm.github.io/generic-matrix-rs/generic_matrix/index.html
#[macro_export]
macro_rules! impl_matrix {
    ($st:ident([$t:ty; ($row:expr, $col:expr)])) => {
        use std::ops::{Index, IndexMut};

        #[derive(Debug)]
        struct $st([$t; $row * $col]);

        impl ArrayMatrix for $st {
            fn row(&self) -> usize {
                $row
            }

            fn column(&self) -> usize {
                $col
            }

            fn size(&self) -> (usize, usize) {
                (self.row(), self.column())
            }
        }

        impl Index<(usize, usize)> for $st {
            type Output = $t;

            #[inline]
            fn index(&self, (i, j): (usize, usize)) -> &$t {
                assert!(i < $row && j < $col);
                &self.0[i * $col + j]
            }
        }

        impl IndexMut<(usize, usize)> for $st {

            #[inline]
            fn index_mut(&mut self, (i, j): (usize, usize)) -> &mut $t {
                assert!(i < $row && j < $col);
                &mut self.0[i * $col + j]
            }
        }
    }
}

/// Basic matrix trait.
pub trait ArrayMatrix {
    fn row(&self) -> usize;
    fn column(&self) -> usize;
    fn size(&self) -> (usize, usize);
}

// Non-macro test implementation

//#[derive(Debug)]
//struct MyMatrix([f32; 9]);
//
//impl Matrix for MyMatrix {
//    fn row(&self) -> usize {
//        3
//    }
//
//    fn column(&self) -> usize {
//        self.0.len() / self.row()
//    }
//
//    fn size(&self) -> (usize, usize) {
//        (self.row(), self.column())
//    }
//}
//
//impl Index<(usize, usize)> for MyMatrix {
//    type Output = f32;
//
//    #[inline]
//    fn index(&self, (i, j): (usize, usize)) -> &f32 {
//        assert!(i < self.row() && j < self.column());
//        &self.0[i * self.column() + j]
//    }
//}
//
//impl IndexMut<(usize, usize)> for MyMatrix {
//    #[inline]
//    fn index_mut(&mut self, (i, j): (usize, usize)) -> &mut f32 {
//        let column_len = self.column();
//        assert!(i < self.row() && j < column_len);
//        &mut self.0[i * column_len + j]
//    }
//}
//
//#[test]
//fn test_matrix() {
//    let mut m = MyMatrix([3.; 9]);
//    m[(2,1)] = 8.1;
//    println!("{:?}", m);
//    println!("{}", m.row());
//    assert_eq!(m.row(), 3);
//    assert_eq!(m.column(), 3);
//}

#[test]
fn test_impl_matrix() {
    const ROW: usize = 3;
    const COLUMN: usize = 3;

    impl_matrix!(TestMatrix([i32; (ROW, COLUMN)]));

    let mut m = TestMatrix([1, 2, 3, 4, 5, 6, 7, 8, 9]);

    println!("{:?}", m);

    assert_eq!(m[(1, 2)], 6);
    m[(1, 2)] = 30;
    assert_eq!(m[(1, 2)], 30);
    assert_eq!(m.row(), ROW);
    assert_eq!(m.column(), COLUMN);
}
<|endoftext|>


<commit_before>#![feature(collections, std_misc)]

extern crate tcod;

pub mod engine;
pub mod gui;
pub mod util;
<commit_msg>Remove unused collections feature gate<commit_after>#![feature(std_misc)]

extern crate tcod;

pub mod engine;
pub mod gui;
pub mod util;
<|endoftext|>


<commit_before>#![no_std]
#![feature(globs, phase, asm)]

#[phase(plugin, link)] extern crate "os_std" as std;
pub use std::prelude::*;

mod multiboot;
mod init;

#[no_mangle]
pub fn main(multiboot: *const multiboot::Information) {

    unsafe{init::frame_stack(multiboot)};

    unsafe{asm!("sti")};
    let x = box 5i;

    let y = 0xb8000 as *mut u64;
    unsafe{*y = 0xffffffffffffffff};

    print!("test");
    print!("test\n");
    println!("newline {}", x);

    loop {
        panic!("end of os!");
        // Add code here
    }
}

/* Interrupt Handlers */

#[no_mangle]
pub extern "C" fn interrupt_handler(interrupt_number: u64, error_code: u64, rsp:u64) -> u64 {
    match interrupt_number {
        13 if error_code != 0 => panic!(
            "General Protection Fault: Segment error at segment 0x{:x}", error_code),
        32 => {},
        33 => print!("k"),
        _ => panic!("unknown interrupt! number: {}, error_code: {:x}",interrupt_number, error_code),
    };

    rsp
}

#[no_mangle]
pub extern "C" fn pagefault_handler(address: u64, error_code: u64, rsp:u64) -> u64 {
    panic!("page fault: address: {:x}, error_code: {:b}, rsp: {:x}", address, error_code, rsp);
}<commit_msg>use new init<commit_after>#![no_std]
#![feature(globs, phase, asm)]

#[phase(plugin, link)] extern crate "os_std" as std;
pub use std::prelude::*;

mod multiboot;
mod init;

#[no_mangle]
pub fn main(multiboot: *const multiboot::Information) {

    unsafe{init::init_frame_stack(multiboot)};

    unsafe{asm!("sti")};
    print!("test\n\niuaeiae");
    let x = box 5i;

    let y = 0xb8000 as *mut u64;
    unsafe{*y = 0xffffffffffffffff};

    print!("test");
    print!("test\n");
    println!("newline {}", x);

    loop {
        panic!("end of os!");
        // Add code here
    }
}

/* Interrupt Handlers */

#[no_mangle]
pub extern "C" fn interrupt_handler(interrupt_number: u64, error_code: u64, rsp:u64) -> u64 {
    match interrupt_number {
        13 if error_code != 0 => panic!(
            "General Protection Fault: Segment error at segment 0x{:x}", error_code),
        32 => {},
        33 => print!("k"),
        _ => panic!("unknown interrupt! number: {}, error_code: {:x}",interrupt_number, error_code),
    };

    rsp
}

#[no_mangle]
pub extern "C" fn pagefault_handler(address: u64, error_code: u64, rsp:u64) -> u64 {
    panic!("page fault: address: {:x}, error_code: {:b}, rsp: {:x}", address, error_code, rsp);
}<|endoftext|>


<commit_before>#![crate_name = "tiny-http"]
#![crate_type = "lib"]
#![license = "Apache"]

extern crate semver;
extern crate url;

use std::io::{Acceptor, BufferedReader, IoResult, Listener, RefReader, RefWriter};
use std::io::net::ip;
use std::io::net::tcp;
use std::io::util::LimitReader;
use std::sync;

pub use common::Header;
pub use common::Method;
pub use common::StatusCode;
pub use response::Response;

mod client;
mod common;
mod response;

/// The main class of this library.
/// Create a new server using `Server::new()`.
pub struct Server {
    connections_receiver: Receiver<IoResult<client::ClientConnection>>,
    requests_receiver: sync::Mutex<Vec<Receiver<Request>>>,
}

/// Represents an HTTP request made by a client.
pub struct Request {
    read_socket: LimitReader<BufferedReader<tcp::TcpStream>>,
    write_socket: tcp::TcpStream,
    method: Method,
    path: url::Path,
    http_version: semver::Version,
    headers: Vec<Header>,
    body_length: uint,
}

impl Server {
    /// Builds a new server on port 80 that listens to all inputs.
    pub fn new() -> IoResult<Server> {
        Server::new_with_port(80)
    }

    /// Builds a new server on a given port and that listens to all inputs.
    pub fn new_with_port(port: ip::Port) -> IoResult<Server> {
        Server::new_with_addr(&ip::SocketAddr{ip: ip::Ipv4Addr(0, 0, 0, 0), port: port})
    }

    /// Builds a new server that listens on the specified address.
    pub fn new_with_addr(addr: &ip::SocketAddr) -> IoResult<Server> {
        // building the TcpAcceptor
        let server = try!(tcp::TcpListener::bind(
            format!("{}", addr.ip).as_slice(), addr.port).listen());

        // creating a task where server.accept() is continuously called
        // and ClientConnection objects are returned in the receiver
        let (tx, rx) = channel();
        spawn(proc() {
            let mut server = server;

            loop {
                let val = server.accept().map(|sock| client::ClientConnection::new(sock));

                match tx.send_opt(val) {
                    Err(_) => break,
                    _ => ()
                }
            }
        });

        // result
        Ok(Server {
            connections_receiver: rx,
            requests_receiver: sync::Mutex::new(Vec::new()),
        })
    }

    /// Returns the number of clients currently connected to the server.
    pub fn get_num_connections(&self) -> uint {
        self.requests_receiver.lock().len()
    }

    /// Blocks until an HTTP request has been submitted and returns it.
    pub fn recv(&self) -> Request {
        loop {
            match self.try_recv() {
                Some(rq) => return rq,
                None => ()
            };
        }
    }

    /// Same as `recv()` but doesn't block.
    pub fn try_recv(&self) -> Option<Request> {
        self.process_new_clients();

        // TODO: rewrite this
        {
            let mut locked_receivers = self.requests_receiver.lock();
            for rx in locked_receivers.iter() {
                let attempt = rx.try_recv();
                if attempt.is_ok() {       // TODO: remove the channel if it is closed
                    return Some(attempt.unwrap());
                }
            }
        }

        None
    }

    /// Does not block.
    fn process_new_clients(&self) {
        let mut new_clients = Vec::new();

        // we add all the elements available on connections_receiver to new_clients
        loop {
            match self.connections_receiver.try_recv() {
                Ok(client) => new_clients.push(client),
                Err(_) => break
            }
        }

        // for each new client, spawning a task that will
        // continuously try to read a Request
        for client in new_clients.move_iter().filter_map(|c| c.ok()) {
            let (tx, rx) = channel();
            spawn(proc() {
                let mut client = client;
                // TODO: when the channel is being closed, immediatly notify the task
                client.advance(|rq| tx.send_opt(rq).is_ok());
            });
            self.requests_receiver.lock().push(rx);
        }
    }
}

impl Request {
    /// Returns the method requested by the client (eg. GET, POST, etc.)
    pub fn get_method<'a>(&'a self) -> &'a Method {
        &self.method
    }

    /// Returns the resource requested by the client.
    pub fn get_url<'a>(&'a self) -> &'a url::Path {
        &self.path
    }

    /// Returns a list of all headers sent by the client.
    pub fn get_headers<'a>(&'a self) -> &'a [Header] {
        self.headers.as_slice()
    }

    /// Returns the length of the body in bytes.
    pub fn get_body_length(&self) -> uint {
        self.body_length
    }

    /// Allows to read the body of the request.
    pub fn as_reader<'a>(&'a mut self)
        -> RefReader<'a, LimitReader<BufferedReader<tcp::TcpStream>>>
    {
        fn as_reader_impl<'a, R: Reader>(elem: &'a mut R) -> RefReader<'a, R> {
            elem.by_ref()
        }
        as_reader_impl(&mut self.read_socket)
    }

    // TODO: turn this into a function that consumes the Request
    fn as_raw_writer<'a>(&'a mut self) -> RefWriter<'a, tcp::TcpStream> {
        Request::as_raw_writer_impl(&mut self.write_socket)
    }

    fn as_raw_writer_impl<'a, W: Writer>(elem: &'a mut W) -> RefWriter<'a, W> {
        elem.by_ref()
    }

    /// Sends a response to this request.
    pub fn respond<R: Reader>(self, response: Response<R>) {
        Request::finish_reading(self.read_socket);

        match response.raw_print(self.write_socket) {
            Ok(_) => (),
            Err(err) => println!("error while sending answer: {}", err)     // TODO: handle better?
        }
    }

    /// Consumes the rest of the request's body in the TcpStream.
    fn finish_reading(reader: LimitReader<BufferedReader<tcp::TcpStream>>) {
        let remaining_to_read = reader.limit();
        let underlying = reader.unwrap().consume(remaining_to_read);
    }
}

impl std::fmt::Show for Request {
    fn fmt(&self, formatter: &mut std::fmt::Formatter)
        -> Result<(), std::fmt::FormatError>
    {
        (format!("Request({} {})",
            self.method, self.path)).fmt(formatter)
    }
}
<commit_msg>Implement Request::into_writer<commit_after>#![crate_name = "tiny-http"]
#![crate_type = "lib"]
#![license = "Apache"]

extern crate semver;
extern crate url;

use std::io::{Acceptor, BufferedReader, IoResult, Listener, RefReader, RefWriter};
use std::io::net::ip;
use std::io::net::tcp;
use std::io::util::LimitReader;
use std::sync;

pub use common::Header;
pub use common::Method;
pub use common::StatusCode;
pub use response::Response;

mod client;
mod common;
mod response;

/// The main class of this library.
/// Create a new server using `Server::new()`.
pub struct Server {
    connections_receiver: Receiver<IoResult<client::ClientConnection>>,
    requests_receiver: sync::Mutex<Vec<Receiver<Request>>>,
}

/// Represents an HTTP request made by a client.
pub struct Request {
    read_socket: LimitReader<BufferedReader<tcp::TcpStream>>,
    write_socket: tcp::TcpStream,
    method: Method,
    path: url::Path,
    http_version: semver::Version,
    headers: Vec<Header>,
    body_length: uint,
}

pub struct ResponseWriter {
    writer: tcp::TcpStream
}

impl Server {
    /// Builds a new server on port 80 that listens to all inputs.
    pub fn new() -> IoResult<Server> {
        Server::new_with_port(80)
    }

    /// Builds a new server on a given port and that listens to all inputs.
    pub fn new_with_port(port: ip::Port) -> IoResult<Server> {
        Server::new_with_addr(&ip::SocketAddr{ip: ip::Ipv4Addr(0, 0, 0, 0), port: port})
    }

    /// Builds a new server that listens on the specified address.
    pub fn new_with_addr(addr: &ip::SocketAddr) -> IoResult<Server> {
        // building the TcpAcceptor
        let server = try!(tcp::TcpListener::bind(
            format!("{}", addr.ip).as_slice(), addr.port).listen());

        // creating a task where server.accept() is continuously called
        // and ClientConnection objects are returned in the receiver
        let (tx, rx) = channel();
        spawn(proc() {
            let mut server = server;

            loop {
                let val = server.accept().map(|sock| client::ClientConnection::new(sock));

                match tx.send_opt(val) {
                    Err(_) => break,
                    _ => ()
                }
            }
        });

        // result
        Ok(Server {
            connections_receiver: rx,
            requests_receiver: sync::Mutex::new(Vec::new()),
        })
    }

    /// Returns the number of clients currently connected to the server.
    pub fn get_num_connections(&self) -> uint {
        self.requests_receiver.lock().len()
    }

    /// Blocks until an HTTP request has been submitted and returns it.
    pub fn recv(&self) -> Request {
        loop {
            match self.try_recv() {
                Some(rq) => return rq,
                None => ()
            };
        }
    }

    /// Same as `recv()` but doesn't block.
    pub fn try_recv(&self) -> Option<Request> {
        self.process_new_clients();

        // TODO: rewrite this
        {
            let mut locked_receivers = self.requests_receiver.lock();
            for rx in locked_receivers.iter() {
                let attempt = rx.try_recv();
                if attempt.is_ok() {       // TODO: remove the channel if it is closed
                    return Some(attempt.unwrap());
                }
            }
        }

        None
    }

    /// Does not block.
    fn process_new_clients(&self) {
        let mut new_clients = Vec::new();

        // we add all the elements available on connections_receiver to new_clients
        loop {
            match self.connections_receiver.try_recv() {
                Ok(client) => new_clients.push(client),
                Err(_) => break
            }
        }

        // for each new client, spawning a task that will
        // continuously try to read a Request
        for client in new_clients.move_iter().filter_map(|c| c.ok()) {
            let (tx, rx) = channel();
            spawn(proc() {
                let mut client = client;
                // TODO: when the channel is being closed, immediatly notify the task
                client.advance(|rq| tx.send_opt(rq).is_ok());
            });
            self.requests_receiver.lock().push(rx);
        }
    }
}

impl Request {
    /// Returns the method requested by the client (eg. GET, POST, etc.)
    pub fn get_method<'a>(&'a self) -> &'a Method {
        &self.method
    }

    /// Returns the resource requested by the client.
    pub fn get_url<'a>(&'a self) -> &'a url::Path {
        &self.path
    }

    /// Returns a list of all headers sent by the client.
    pub fn get_headers<'a>(&'a self) -> &'a [Header] {
        self.headers.as_slice()
    }

    /// Returns the length of the body in bytes.
    pub fn get_body_length(&self) -> uint {
        self.body_length
    }

    /// Allows to read the body of the request.
    pub fn as_reader<'a>(&'a mut self)
        -> RefReader<'a, LimitReader<BufferedReader<tcp::TcpStream>>>
    {
        fn as_reader_impl<'a, R: Reader>(elem: &'a mut R) -> RefReader<'a, R> {
            elem.by_ref()
        }
        as_reader_impl(&mut self.read_socket)
    }

    /// Turns the Request into a writer.
    /// The writer has a raw access to the stream to the user.
    /// This function is useful for things like CGI.
    pub fn into_writer(self) -> ResponseWriter {
        Request::finish_reading(self.read_socket);

        ResponseWriter { writer: self.write_socket }
    }

    /// Sends a response to this request.
    pub fn respond<R: Reader>(self, response: Response<R>) {
        Request::finish_reading(self.read_socket);

        match response.raw_print(self.write_socket) {
            Ok(_) => (),
            Err(err) => println!("error while sending answer: {}", err)     // TODO: handle better?
        }
    }

    /// Consumes the rest of the request's body in the TcpStream.
    fn finish_reading(reader: LimitReader<BufferedReader<tcp::TcpStream>>) {
        let remaining_to_read = reader.limit();
        let underlying = reader.unwrap().consume(remaining_to_read);
    }
}

impl Writer for ResponseWriter {
    #[inline]
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        self.writer.write(buf)
    }

    #[inline]
    fn flush(&mut self) -> IoResult<()> {
        self.writer.flush()
    }

    #[inline]
    fn write_fmt(&mut self, fmt: &::std::fmt::Arguments) -> IoResult<()> {
        self.writer.write_fmt(fmt)
    }

    #[inline]
    fn write_str(&mut self, s: &str) -> IoResult<()> {
        self.writer.write_str(s)
    }

    #[inline]
    fn write_line(&mut self, s: &str) -> IoResult<()> {
        self.writer.write_line(s)
    }

    #[inline]
    fn write_char(&mut self, c: char) -> IoResult<()> {
        self.writer.write_char(c)
    }

    #[inline]
    fn write_int(&mut self, n: int) -> IoResult<()> {
        self.writer.write_int(n)
    }

    #[inline]
    fn write_uint(&mut self, n: uint) -> IoResult<()> {
        self.writer.write_uint(n)
    }

    #[inline]
    fn write_le_uint(&mut self, n: uint) -> IoResult<()> {
        self.writer.write_le_uint(n)
    }

    #[inline]
    fn write_le_int(&mut self, n: int) -> IoResult<()> {
        self.writer.write_le_int(n)
    }

    #[inline]
    fn write_be_uint(&mut self, n: uint) -> IoResult<()> {
        self.writer.write_be_uint(n)
    }

    #[inline]
    fn write_be_int(&mut self, n: int) -> IoResult<()> {
        self.writer.write_be_int(n)
    }

    #[inline]
    fn write_be_u64(&mut self, n: u64) -> IoResult<()> {
        self.writer.write_be_u64(n)
    }

    #[inline]
    fn write_be_u32(&mut self, n: u32) -> IoResult<()> {
        self.writer.write_be_u32(n)
    }

    #[inline]
    fn write_be_u16(&mut self, n: u16) -> IoResult<()> {
        self.writer.write_be_u16(n)
    }

    #[inline]
    fn write_be_i64(&mut self, n: i64) -> IoResult<()> {
        self.writer.write_be_i64(n)
    }

    #[inline]
    fn write_be_i32(&mut self, n: i32) -> IoResult<()> {
        self.writer.write_be_i32(n)
    }

    #[inline]
    fn write_be_i16(&mut self, n: i16) -> IoResult<()> {
        self.writer.write_be_i16(n)
    }

    #[inline]
    fn write_be_f64(&mut self, f: f64) -> IoResult<()> {
        self.writer.write_be_f64(f)
    }

    #[inline]
    fn write_be_f32(&mut self, f: f32) -> IoResult<()> {
        self.writer.write_be_f32(f)
    }

    #[inline]
    fn write_le_u64(&mut self, n: u64) -> IoResult<()> {
        self.writer.write_le_u64(n)
    }

    #[inline]
    fn write_le_u32(&mut self, n: u32) -> IoResult<()> {
        self.writer.write_le_u32(n)
    }

    #[inline]
    fn write_le_u16(&mut self, n: u16) -> IoResult<()> {
        self.writer.write_le_u16(n)
    }

    #[inline]
    fn write_le_i64(&mut self, n: i64) -> IoResult<()> {
        self.writer.write_le_i64(n)
    }

    #[inline]
    fn write_le_i32(&mut self, n: i32) -> IoResult<()> {
        self.writer.write_le_i32(n)
    }

    #[inline]
    fn write_le_i16(&mut self, n: i16) -> IoResult<()> {
        self.writer.write_le_i16(n)
    }

    #[inline]
    fn write_le_f64(&mut self, f: f64) -> IoResult<()> {
        self.writer.write_le_f64(f)
    }

    #[inline]
    fn write_le_f32(&mut self, f: f32) -> IoResult<()> {
        self.writer.write_le_f32(f)
    }

    #[inline]
    fn write_u8(&mut self, n: u8) -> IoResult<()> {
        self.writer.write_u8(n)
    }

    #[inline]
    fn write_i8(&mut self, n: i8) -> IoResult<()> {
        self.writer.write_i8(n)
    }
}

impl std::fmt::Show for Request {
    fn fmt(&self, formatter: &mut std::fmt::Formatter)
        -> Result<(), std::fmt::FormatError>
    {
        (format!("Request({} {})",
            self.method, self.path)).fmt(formatter)
    }
}
<|endoftext|>


<commit_before>#![no_std]

extern crate embedded_hal;
extern crate nb;

use embedded_hal::serial;
use embedded_hal::blocking::serial::write::Default;
use embedded_hal::prelude::*;
use nb::{Result};

pub mod prelude {
    pub use super::{ThermalPrinter, Command, Justification};
}

#[derive(Debug)]
pub enum Command {
    ESC = 27,
    DC2 = 18,
    LF = 10,
    DASH = 45,
    EXCL = 69,
    SPACE = 0x20
}

#[derive(Debug)]
pub enum Justification {
    Left = 0,
    Center = 1,
    Right = 2
}

#[derive(Clone)]
pub struct ThermalPrinter<T> where T: serial::Write<u8> {
    port: T,

    dot_print_time: u64,
    dot_feed_time: u64,
}

impl <T> ThermalPrinter<T> where T: serial::Write<u8> {
    pub fn new(port: T) -> ThermalPrinter<T> {
        // The default times here are copied from adafruit's thermal printer arduino library
        return ThermalPrinter {
            port,
            dot_print_time: 30000u64,
            dot_feed_time: 2100u64,
        }
    }

    pub fn configure(&mut self, dots: u8, time: u8, interval: u8) -> Result<(), T::Error> {
        // LF 7
        let cmd = [Command::ESC as u8, 55u8, dots, time, interval];
        self.write_all(&cmd)?;
        self.flush()
    }

    pub fn run_test(&mut self) -> Result<(), T::Error> {
        self.justify(Justification::Center)?;

        let out = [Command::DC2 as u8, 'T' as u8];
        self.write_all(&out)?;
        self.flush()
    }

    pub fn justify(&mut self, just: Justification) -> Result<(), T::Error> {
        let cmd = [Command::ESC as u8, 97u8, just as u8];

        self.write_all(&cmd)?;
        self.flush()
    }

    pub fn feed(&mut self) -> Result<(), T::Error> {
        self.feed_n(1)
    }

    pub fn feed_n(&mut self, n: u8) -> Result<(), T::Error> {
        let cmd = [Command::ESC as u8, 'd' as u8, n];

        self.write_all(&cmd)?;
        self.flush()
    }

    pub fn set_underline(&mut self, n: u8) -> Result<(), T::Error> {
        let cmd = [Command::ESC as u8, Command::DASH as u8, n];
        self.write_all(&cmd)?;
        self.flush()
    }

    pub fn set_bold(&mut self, flag: bool) -> Result<(), T::Error> {
        let cmd = [Command::ESC as u8, Command::EXCL as u8, flag as u8];
        self.write_all(&cmd)?;
        self.flush()
    }

    /// Consume the printer, freeing the underlying serial port
    pub fn free(self) -> T {
        self.port
    }

    fn write_all(&mut self, buffer: &[u8]) -> Result<(), T::Error> {
        self.bwrite_all(buffer).map_err(|e| nb::Error::Other(e))
    }
}

impl <T> serial::Write<u8> for ThermalPrinter<T> where T: serial::Write<u8> {
    type Error = T::Error;

    fn write(&mut self, word: u8) -> Result<(), Self::Error> {
        self.port.write(word)
    }

    fn flush(&mut self) -> Result<(), Self::Error> {
        self.port.flush()
    }
}

impl <T> Default<u8> for ThermalPrinter<T> where T: serial::Write<u8> {}
<commit_msg>remove unnecessary extern<commit_after>#![no_std]

use embedded_hal::serial;
use embedded_hal::blocking::serial::write::Default;
use embedded_hal::prelude::*;
use nb::{Result};

pub mod prelude {
    pub use super::{ThermalPrinter, Command, Justification};
    pub use embedded_hal::serial::Write as _thermal_printer_serial_Write;
}

#[derive(Debug)]
pub enum Command {
    ESC = 27,
    DC2 = 18,
    LF = 10,
    DASH = 45,
    EXCL = 69,
    SPACE = 0x20
}

#[derive(Debug)]
pub enum Justification {
    Left = 0,
    Center = 1,
    Right = 2
}

#[derive(Clone)]
pub struct ThermalPrinter<T> where T: serial::Write<u8> {
    port: T,

    dot_print_time: u64,
    dot_feed_time: u64,
}

impl <T> ThermalPrinter<T> where T: serial::Write<u8> {
    pub fn new(port: T) -> ThermalPrinter<T> {
        // The default times here are copied from adafruit's thermal printer arduino library
        return ThermalPrinter {
            port,
            dot_print_time: 30000u64,
            dot_feed_time: 2100u64,
        }
    }

    pub fn configure(&mut self, dots: u8, time: u8, interval: u8) -> Result<(), T::Error> {
        // LF 7
        let cmd = [Command::ESC as u8, 55u8, dots, time, interval];
        self.write_all(&cmd)?;
        self.flush()
    }

    pub fn run_test(&mut self) -> Result<(), T::Error> {
        self.justify(Justification::Center)?;

        let out = [Command::DC2 as u8, 'T' as u8];
        self.write_all(&out)?;
        self.flush()
    }

    pub fn justify(&mut self, just: Justification) -> Result<(), T::Error> {
        let cmd = [Command::ESC as u8, 97u8, just as u8];

        self.write_all(&cmd)?;
        self.flush()
    }

    pub fn feed(&mut self) -> Result<(), T::Error> {
        self.feed_n(1)
    }

    pub fn feed_n(&mut self, n: u8) -> Result<(), T::Error> {
        let cmd = [Command::ESC as u8, 'd' as u8, n];

        self.write_all(&cmd)?;
        self.flush()
    }

    pub fn set_underline(&mut self, n: u8) -> Result<(), T::Error> {
        let cmd = [Command::ESC as u8, Command::DASH as u8, n];
        self.write_all(&cmd)?;
        self.flush()
    }

    pub fn set_bold(&mut self, flag: bool) -> Result<(), T::Error> {
        let cmd = [Command::ESC as u8, Command::EXCL as u8, flag as u8];
        self.write_all(&cmd)?;
        self.flush()
    }

    /// Consume the printer, freeing the underlying serial port
    pub fn free(self) -> T {
        self.port
    }

    fn write_all(&mut self, buffer: &[u8]) -> Result<(), T::Error> {
        self.bwrite_all(buffer).map_err(|e| nb::Error::Other(e))
    }
}

impl <T> serial::Write<u8> for ThermalPrinter<T> where T: serial::Write<u8> {
    type Error = T::Error;

    fn write(&mut self, word: u8) -> Result<(), Self::Error> {
        self.port.write(word)
    }

    fn flush(&mut self) -> Result<(), Self::Error> {
        self.port.flush()
    }
}

impl <T> Default<u8> for ThermalPrinter<T> where T: serial::Write<u8> {}
<|endoftext|>


<commit_before>/*!
Simple persistent generic HashMap/Key-value store, using file locking to limit
writing between threads.

This is in a beta state at the moment.

Basic usage:

```
extern crate typedb;

use typedb::{ KV, Value };

fn main() {
    let mut test_store = KV::<String, Value>::new("./basic.cab").unwrap();

    let _ = test_store.insert("key".to_string(), Value::String("value".to_string()));
    println!("{:?}", test_store.get("key".to_string()));
    let _ = test_store.remove("key".to_string());
}
```

Usage with user defined Key and Value types:

```
#[macro_use]
extern crate typedb;
#[macro_use]
extern crate serde_derive;

use typedb::KV;

key!(MyKey:
    String(String),
    Int(i32),
);

value!(MyValue:
    String(String),
    Int(i32),
);

fn main() {
    let mut test_store = KV::<MyKey, MyValue>::new("./types.cab").unwrap();

    let _ = test_store.insert(MyKey::Int(1i32), MyValue::String("value".to_string()));
    println!("{:?}", test_store.get(MyKey::Int(1i32)));
    let _ = test_store.remove(MyKey::Int(1i32));
}
```

*/

#![deny(missing_docs)]

extern crate bincode;
#[macro_use]
extern crate log;
extern crate persy;
extern crate serde;
#[macro_use]
extern crate serde_derive;

/// Macros for simplifying custom key and value types definition
pub mod macros;

use std::collections::HashMap;
use std::hash::Hash;
use std::io::ErrorKind;

use bincode::{deserialize, serialize};
use serde::ser::Serialize;
use serde::de::Deserialize;

use persy::{Config, PRes, Persy, PersyError};

/// A default value type to use with KV
#[derive(Clone, Serialize, Deserialize, PartialEq, Debug)]
pub enum Value {
    /// Cab default Value type for strings
    String(String),
    /// Cab default Value type for intergers
    Int(i32),
    /// Cab default Value type for floats
    Float(f32),
    /// Cab default Value type for a sub map
    Map(HashMap<String, Value>),
    /// Cab default Value type for list
    List(Vec<Value>),
}

/// Type alias for results from KV
type KVResult = PRes<bool>;

/// Type alias for PersyError
type KVError = PersyError;

/// The type that represents the key-value store
pub struct KV<K, V> {
    cab: HashMap<K, V>,
    persy: Persy,
}

impl<K, V> KV<K, V>
where
    K: Clone + Serialize + for<'kde> Deserialize<'kde> + Eq + Hash,
    V: Clone + Serialize + for<'vde> Deserialize<'vde>,
{
    /// Creates a new instance of the KV store
    pub fn new(p: &'static str) -> Result<KV<K, V>, PersyError> {
        // create the KV instance
        match Persy::create(p) {
            Ok(o) => o,
            Err(PersyError::IO(ref e)) if e.kind() == ErrorKind::AlreadyExists => (),
            Err(e) => return Err(e),
        }
        let persy = Persy::open(p, Config::new())?;

        let mut store = KV {
            cab: HashMap::new(),
            persy: persy,
        };

        store.load_from_persist()?;

        Ok(store)
    }

    /// Inserta a key, value pair into the key-value store
    pub fn insert(&mut self, key: K, value: V) -> KVResult {
        // make sure mem version up to date
        self.load_from_persist()?;
        // insert into the HashMap
        self.cab.insert(key, value);
        // persist
        self.write_to_persist()
    }

    /// Get the value from a key
    pub fn get(&mut self, key: K) -> Result<Option<V>, KVError> {
        // make sure mem version up to date
        self.load_from_persist()?;
        // get the value from the cab
        match self.cab.get(&key) {
            Some(v) => Ok(Some((*v).clone())),
            None => Ok(None),
        }
    }

    /// Removes a key and associated value from the key-value Store
    pub fn remove(&mut self, key: K) -> KVResult {
        // make sure mem version up to date
        self.load_from_persist()?;
        // remove from the HashMap
        self.cab.remove(&key);
        // persist
        self.write_to_persist()
    }

    /// get all the keys contained in the KV Store
    pub fn keys(&mut self) -> Result<Vec<K>, KVError> {
        // make sure mem version up to date
        self.load_from_persist()?;
        // create a vec from the cabs keys
        Ok(self.cab.keys().map(|k| k.clone()).collect())
    }

    /// Writes the key-value Store to file
    fn write_to_persist(&mut self) -> KVResult {
        // attempt to write to the cab
        let mut tx = self.persy.begin()?;
        // if the segment doesn't exist create
        // TODO poss move to db creation
        if !self.persy.exists_segment("tdb")? {
            self.persy.create_segment(&mut tx, "tdb")?;
        }

        // serialize the cab as a u8 vec
        let byte_vec: Vec<u8> = match serialize(&mut self.cab) {
            Ok(bv) => bv,
            Err(e) => {
                error!("serialize: {}", e);
                return Err(PersyError::Err("Couldn't encode".to_string()));
            }
        };

        self.persy.insert_record(&mut tx, "tdb", &byte_vec)?;

        let prepared = self.persy.prepare_commit(tx)?;
        self.persy.commit(prepared)?;

        Ok(true)
    }

    /// Loads key-value store from file
    fn load_from_persist(&mut self) -> KVResult {
        if self.persy.exists_segment("tdb")? {
            for rec in self.persy.scan_records("tdb")? {
                let byte_vec = rec.content;
                // deserialize u8 vec back into HashMap
                match deserialize(byte_vec.as_slice()) {
                    Ok(f) => {
                        // assign read HashMap back to self
                        self.cab = f;
                    }
                    Err(e) => {
                        error!("{}", e);
                        return Err(PersyError::Err("Couldn't decode cab".to_string()));
                    }
                };
            }
        }

        Ok(true)
    }
}
<commit_msg>Create segment on creation rather than every write<commit_after>/*!
Simple persistent generic HashMap/Key-value store, using file locking to limit
writing between threads.

This is in a beta state at the moment.

Basic usage:

```
extern crate typedb;

use typedb::{ KV, Value };

fn main() {
    let mut test_store = KV::<String, Value>::new("./basic.cab").unwrap();

    let _ = test_store.insert("key".to_string(), Value::String("value".to_string()));
    println!("{:?}", test_store.get("key".to_string()));
    let _ = test_store.remove("key".to_string());
}
```

Usage with user defined Key and Value types:

```
#[macro_use]
extern crate typedb;
#[macro_use]
extern crate serde_derive;

use typedb::KV;

key!(MyKey:
    String(String),
    Int(i32),
);

value!(MyValue:
    String(String),
    Int(i32),
);

fn main() {
    let mut test_store = KV::<MyKey, MyValue>::new("./types.cab").unwrap();

    let _ = test_store.insert(MyKey::Int(1i32), MyValue::String("value".to_string()));
    println!("{:?}", test_store.get(MyKey::Int(1i32)));
    let _ = test_store.remove(MyKey::Int(1i32));
}
```

*/

#![deny(missing_docs)]

extern crate bincode;
#[macro_use]
extern crate log;
extern crate persy;
extern crate serde;
#[macro_use]
extern crate serde_derive;

/// Macros for simplifying custom key and value types definition
pub mod macros;

use std::collections::HashMap;
use std::hash::Hash;
use std::io::ErrorKind;

use bincode::{deserialize, serialize};
use serde::ser::Serialize;
use serde::de::Deserialize;

use persy::{Config, PRes, Persy, PersyError};

/// A default value type to use with KV
#[derive(Clone, Serialize, Deserialize, PartialEq, Debug)]
pub enum Value {
    /// Cab default Value type for strings
    String(String),
    /// Cab default Value type for intergers
    Int(i32),
    /// Cab default Value type for floats
    Float(f32),
    /// Cab default Value type for a sub map
    Map(HashMap<String, Value>),
    /// Cab default Value type for list
    List(Vec<Value>),
}

/// Type alias for results from KV
type KVResult = PRes<bool>;

/// Type alias for PersyError
type KVError = PersyError;

/// The type that represents the key-value store
pub struct KV<K, V> {
    cab: HashMap<K, V>,
    persy: Persy,
}

impl<K, V> KV<K, V>
where
    K: Clone + Serialize + for<'kde> Deserialize<'kde> + Eq + Hash,
    V: Clone + Serialize + for<'vde> Deserialize<'vde>,
{
    /// Creates a new instance of the KV store
    pub fn new(p: &'static str) -> Result<KV<K, V>, PersyError> {
        // create the KV instance
        match Persy::create(p) {
            Ok(o) => o,
            Err(PersyError::IO(ref e)) if e.kind() == ErrorKind::AlreadyExists => (),
            Err(e) => return Err(e),
        }
        let persy = Persy::open(p, Config::new())?;

        // if the segment doesn't exist create
        if !persy.exists_segment("tdb")? {
            let mut tx = persy.begin()?;
            persy.create_segment(&mut tx, "tdb")?;
            let prepared = persy.prepare_commit(tx)?;
            persy.commit(prepared)?;
        }

        let mut store = KV {
            cab: HashMap::new(),
            persy: persy,
        };

        store.load_from_persist()?;

        Ok(store)
    }

    /// Inserta a key, value pair into the key-value store
    pub fn insert(&mut self, key: K, value: V) -> KVResult {
        // make sure mem version up to date
        self.load_from_persist()?;
        // insert into the HashMap
        self.cab.insert(key, value);
        // persist
        self.write_to_persist()
    }

    /// Get the value from a key
    pub fn get(&mut self, key: K) -> Result<Option<V>, KVError> {
        // make sure mem version up to date
        self.load_from_persist()?;
        // get the value from the cab
        match self.cab.get(&key) {
            Some(v) => Ok(Some((*v).clone())),
            None => Ok(None),
        }
    }

    /// Removes a key and associated value from the key-value Store
    pub fn remove(&mut self, key: K) -> KVResult {
        // make sure mem version up to date
        self.load_from_persist()?;
        // remove from the HashMap
        self.cab.remove(&key);
        // persist
        self.write_to_persist()
    }

    /// get all the keys contained in the KV Store
    pub fn keys(&mut self) -> Result<Vec<K>, KVError> {
        // make sure mem version up to date
        self.load_from_persist()?;
        // create a vec from the cabs keys
        Ok(self.cab.keys().map(|k| k.clone()).collect())
    }

    /// Writes the key-value Store to file
    fn write_to_persist(&mut self) -> KVResult {
        // attempt to write to the cab
        let mut tx = self.persy.begin()?;

        // serialize the cab as a u8 vec
        let byte_vec: Vec<u8> = match serialize(&mut self.cab) {
            Ok(bv) => bv,
            Err(e) => {
                error!("serialize: {}", e);
                return Err(PersyError::Err("Couldn't encode".to_string()));
            }
        };

        self.persy.insert_record(&mut tx, "tdb", &byte_vec)?;

        let prepared = self.persy.prepare_commit(tx)?;
        self.persy.commit(prepared)?;

        Ok(true)
    }

    /// Loads key-value store from file
    fn load_from_persist(&mut self) -> KVResult {
        if self.persy.exists_segment("tdb")? {
            for rec in self.persy.scan_records("tdb")? {
                let byte_vec = rec.content;
                // deserialize u8 vec back into HashMap
                match deserialize(byte_vec.as_slice()) {
                    Ok(f) => {
                        // assign read HashMap back to self
                        self.cab = f;
                    }
                    Err(e) => {
                        error!("{}", e);
                        return Err(PersyError::Err("Couldn't decode cab".to_string()));
                    }
                };
            }
        }

        Ok(true)
    }
}
<|endoftext|>


<commit_before>#![feature(trace_macros)]
#![feature(log_syntax)]

//trace_macros!(true);

#[macro_export]
macro_rules! impl_op {
    ($op:tt |$lhs_i:ident : &mut $lhs:path, $rhs_i:ident : &$rhs:path| $body:block) => (_parse_assignment_op!($op, $lhs, $rhs, |$lhs_i : &mut $lhs, $rhs_i : &$rhs| $body););
    ($op:tt |$lhs_i:ident : &$lhs:path|  -> $out:path $body:block) => (_parse_unary_op!($op, $lhs, $out, |$lhs_i : &$lhs| -> $out {$body}););
    ($op:tt |$lhs_i:ident : &$lhs:path, $rhs_i:ident : &$rhs:path| -> $out:path $body:block) => (_parse_binary_op!($op, $lhs, $rhs, $out, |$lhs_i : &$lhs, $rhs_i : &$rhs| -> $out {$body}););
}

#[macro_export]
macro_rules! impl_op_commutative {
    ($op:tt |$lhs_i:ident : &$lhs:path, $rhs_i:ident : &$rhs:path| -> $out:path $body:block) => (_parse_binary_op!($op, [commutative], $lhs, $rhs, $out, |$lhs_i : &$lhs, $rhs_i : &$rhs| -> $out {$body}););
}

#[macro_export]
macro_rules! _parse_binary_op {
    (+, $($t:tt)+) => (_impl_binary_op_internal!(Add, add, $($t)+););
    (-, $($t:tt)+) => (_impl_binary_op_internal!(Sub, sub, $($t)+););
    (*, $($t:tt)+) => (_impl_binary_op_internal!(Mul, mul, $($t)+););
    (/, $($t:tt)+) => (_impl_binary_op_internal!(Div, div, $($t)+););
    (%, $($t:tt)+) => (_impl_binary_op_internal!(Rem, rem, $($t)+););
    (&, $($t:tt)+) => (_impl_binary_op_internal!(BitAnd, bitand, $($t)+););
    (|, $($t:tt)+) => (_impl_binary_op_internal!(BitOr, bitor, $($t)+););
    (^, $($t:tt)+) => (_impl_binary_op_internal!(BitXor, bitxor, $($t)+););
    (<<, $($t:tt)+) => (_impl_binary_op_internal!(Shl, shl, $($t)+););
    (>>, $($t:tt)+) => (_impl_binary_op_internal!(Shr, shr, $($t)+););
}

#[macro_export]
macro_rules! _parse_assignment_op {
    (+=, $($t:tt)+) => (_impl_assignment_op_internal!(AddAssign, add_assign, $($t)+););
    (-=, $($t:tt)+) => (_impl_assignment_op_internal!(SubAssign, sub_assign, $($t)+););
    (*=, $($t:tt)+) => (_impl_assignment_op_internal!(MulAssign, mul_assign, $($t)+););
    (/=, $($t:tt)+) => (_impl_assignment_op_internal!(DivAssign, div_assign, $($t)+););
    (%=, $($t:tt)+) => (_impl_assignment_op_internal!(RemAssign, rem_assign, $($t)+););
    (&=, $($t:tt)+) => (_impl_assignment_op_internal!(BitAndAssign, bitand_assign, $($t)+););
    (|=, $($t:tt)+) => (_impl_assignment_op_internal!(BitOrAssign, bitor_assign, $($t)+););
    (^=, $($t:tt)+) => (_impl_assignment_op_internal!(BitXorAssign, bitxor_assign, $($t)+););
    (<<=, $($t:tt)+) => (_impl_assignment_op_internal!(ShlAssign, shl_assign, $($t)+););
    (>>=, $($t:tt)+) => (_impl_assignment_op_internal!(ShrAssign, shr_assign, $($t)+););
}

#[macro_export]
macro_rules! _parse_unary_op {
    (-, $($t:tt)+) => (_impl_unary_op_internal!(Neg, neg, $($t)+););
    (!, $($t:tt)+) => (_impl_unary_op_internal!(Not, not, $($t)+););
}

#[macro_export]
macro_rules! _impl_binary_op_internal {
    ($ops_trait:ident, $ops_fn:ident, $lhs:ty, $rhs:ty, $out:ty, $fn:expr) => (
        impl ops::$ops_trait<$rhs> for $lhs {
            type Output = $out;

            fn $ops_fn(self, rhs: $rhs) -> Self::Output {
                $fn(&self, &rhs)
            }
        }

        impl<'a> ops::$ops_trait<&'a $rhs> for $lhs {
            type Output = $out;

            fn $ops_fn(self, rhs: &'a $rhs) -> Self::Output {
                $fn(&self, rhs)
            }
        }

        impl<'a> ops::$ops_trait<$rhs> for &'a $lhs {
            type Output = $out;

            fn $ops_fn(self, rhs: $rhs) -> Self::Output {
                $fn(self, &rhs)
            }
        }

        impl<'a> ops::$ops_trait<&'a $rhs> for &'a $lhs {
            type Output = $out;

            fn $ops_fn(self, rhs: &'a $rhs) -> Self::Output {
                $fn(self, rhs)
            }
        }
    );
    ($ops_trait:ident, $ops_fn:ident, [commutative], $lhs:ty, $rhs:ty, $out:ty, $fn:expr) => (
        _impl_binary_op_internal!($ops_trait, $ops_fn, $lhs, $rhs, $out, $fn);

        impl ops::$ops_trait<$lhs> for $rhs {
            type Output = $out;

            fn $ops_fn(self, rhs: $lhs) -> Self::Output {
                $fn(&rhs, &self)
            }
        }

        impl<'a> ops::$ops_trait<&'a $lhs> for $rhs {
            type Output = $out;

            fn $ops_fn(self, rhs: &'a $lhs) -> Self::Output {
                $fn(rhs, &self)
            }
        }

        impl<'a> ops::$ops_trait<$lhs> for &'a $rhs {
            type Output = $out;

            fn $ops_fn(self, rhs: $lhs) -> Self::Output {
                $fn(&rhs, self)
            }
        }

        impl<'a> ops::$ops_trait<&'a $lhs> for &'a $rhs {
            type Output = $out;

            fn $ops_fn(self, rhs: &'a $lhs) -> Self::Output {
                $fn(rhs, self)
            }
        }
    );
}

#[macro_export]
macro_rules! _impl_assignment_op_internal {
    ($ops_trait:ident, $ops_fn:ident, $lhs:ty, $rhs:ty, $fn:expr) => (
        impl ops::$ops_trait<$rhs> for $lhs {
            fn $ops_fn(&mut self, rhs: $rhs) {
                $fn(self, &rhs)
            }
        }

        impl<'a> ops::$ops_trait<&'a $rhs> for $lhs {
            fn $ops_fn(&mut self, rhs: &$rhs) {
                $fn(self, rhs)
            }
        }

    );
}

#[macro_export]
macro_rules! _impl_unary_op_internal {
    ($ops_trait:ident, $ops_fn:ident, $lhs:ty, $out:ty, $fn:expr) => (
        impl ops::$ops_trait for $lhs {
            type Output = $out;

            fn $ops_fn(self) -> Self::Output {
                $fn(&self)
            }
        }

        impl<'a> ops::$ops_trait for &'a $lhs {
            type Output = $out;

            fn $ops_fn(self) -> Self::Output {
                $fn(self)
            }
        }
    );
}
<commit_msg>commenting out debugging features<commit_after>//#![feature(trace_macros)]
//#![feature(log_syntax)]

//trace_macros!(true);

#[macro_export]
macro_rules! impl_op {
    ($op:tt |$lhs_i:ident : &mut $lhs:path, $rhs_i:ident : &$rhs:path| $body:block) => (_parse_assignment_op!($op, $lhs, $rhs, |$lhs_i : &mut $lhs, $rhs_i : &$rhs| $body););
    ($op:tt |$lhs_i:ident : &$lhs:path|  -> $out:path $body:block) => (_parse_unary_op!($op, $lhs, $out, |$lhs_i : &$lhs| -> $out {$body}););
    ($op:tt |$lhs_i:ident : &$lhs:path, $rhs_i:ident : &$rhs:path| -> $out:path $body:block) => (_parse_binary_op!($op, $lhs, $rhs, $out, |$lhs_i : &$lhs, $rhs_i : &$rhs| -> $out {$body}););
}

#[macro_export]
macro_rules! impl_op_commutative {
    ($op:tt |$lhs_i:ident : &$lhs:path, $rhs_i:ident : &$rhs:path| -> $out:path $body:block) => (_parse_binary_op!($op, [commutative], $lhs, $rhs, $out, |$lhs_i : &$lhs, $rhs_i : &$rhs| -> $out {$body}););
}

#[macro_export]
macro_rules! _parse_binary_op {
    (+, $($t:tt)+) => (_impl_binary_op_internal!(Add, add, $($t)+););
    (-, $($t:tt)+) => (_impl_binary_op_internal!(Sub, sub, $($t)+););
    (*, $($t:tt)+) => (_impl_binary_op_internal!(Mul, mul, $($t)+););
    (/, $($t:tt)+) => (_impl_binary_op_internal!(Div, div, $($t)+););
    (%, $($t:tt)+) => (_impl_binary_op_internal!(Rem, rem, $($t)+););
    (&, $($t:tt)+) => (_impl_binary_op_internal!(BitAnd, bitand, $($t)+););
    (|, $($t:tt)+) => (_impl_binary_op_internal!(BitOr, bitor, $($t)+););
    (^, $($t:tt)+) => (_impl_binary_op_internal!(BitXor, bitxor, $($t)+););
    (<<, $($t:tt)+) => (_impl_binary_op_internal!(Shl, shl, $($t)+););
    (>>, $($t:tt)+) => (_impl_binary_op_internal!(Shr, shr, $($t)+););
}

#[macro_export]
macro_rules! _parse_assignment_op {
    (+=, $($t:tt)+) => (_impl_assignment_op_internal!(AddAssign, add_assign, $($t)+););
    (-=, $($t:tt)+) => (_impl_assignment_op_internal!(SubAssign, sub_assign, $($t)+););
    (*=, $($t:tt)+) => (_impl_assignment_op_internal!(MulAssign, mul_assign, $($t)+););
    (/=, $($t:tt)+) => (_impl_assignment_op_internal!(DivAssign, div_assign, $($t)+););
    (%=, $($t:tt)+) => (_impl_assignment_op_internal!(RemAssign, rem_assign, $($t)+););
    (&=, $($t:tt)+) => (_impl_assignment_op_internal!(BitAndAssign, bitand_assign, $($t)+););
    (|=, $($t:tt)+) => (_impl_assignment_op_internal!(BitOrAssign, bitor_assign, $($t)+););
    (^=, $($t:tt)+) => (_impl_assignment_op_internal!(BitXorAssign, bitxor_assign, $($t)+););
    (<<=, $($t:tt)+) => (_impl_assignment_op_internal!(ShlAssign, shl_assign, $($t)+););
    (>>=, $($t:tt)+) => (_impl_assignment_op_internal!(ShrAssign, shr_assign, $($t)+););
}

#[macro_export]
macro_rules! _parse_unary_op {
    (-, $($t:tt)+) => (_impl_unary_op_internal!(Neg, neg, $($t)+););
    (!, $($t:tt)+) => (_impl_unary_op_internal!(Not, not, $($t)+););
}

#[macro_export]
macro_rules! _impl_binary_op_internal {
    ($ops_trait:ident, $ops_fn:ident, $lhs:ty, $rhs:ty, $out:ty, $fn:expr) => (
        impl ops::$ops_trait<$rhs> for $lhs {
            type Output = $out;

            fn $ops_fn(self, rhs: $rhs) -> Self::Output {
                $fn(&self, &rhs)
            }
        }

        impl<'a> ops::$ops_trait<&'a $rhs> for $lhs {
            type Output = $out;

            fn $ops_fn(self, rhs: &'a $rhs) -> Self::Output {
                $fn(&self, rhs)
            }
        }

        impl<'a> ops::$ops_trait<$rhs> for &'a $lhs {
            type Output = $out;

            fn $ops_fn(self, rhs: $rhs) -> Self::Output {
                $fn(self, &rhs)
            }
        }

        impl<'a> ops::$ops_trait<&'a $rhs> for &'a $lhs {
            type Output = $out;

            fn $ops_fn(self, rhs: &'a $rhs) -> Self::Output {
                $fn(self, rhs)
            }
        }
    );
    ($ops_trait:ident, $ops_fn:ident, [commutative], $lhs:ty, $rhs:ty, $out:ty, $fn:expr) => (
        _impl_binary_op_internal!($ops_trait, $ops_fn, $lhs, $rhs, $out, $fn);

        impl ops::$ops_trait<$lhs> for $rhs {
            type Output = $out;

            fn $ops_fn(self, rhs: $lhs) -> Self::Output {
                $fn(&rhs, &self)
            }
        }

        impl<'a> ops::$ops_trait<&'a $lhs> for $rhs {
            type Output = $out;

            fn $ops_fn(self, rhs: &'a $lhs) -> Self::Output {
                $fn(rhs, &self)
            }
        }

        impl<'a> ops::$ops_trait<$lhs> for &'a $rhs {
            type Output = $out;

            fn $ops_fn(self, rhs: $lhs) -> Self::Output {
                $fn(&rhs, self)
            }
        }

        impl<'a> ops::$ops_trait<&'a $lhs> for &'a $rhs {
            type Output = $out;

            fn $ops_fn(self, rhs: &'a $lhs) -> Self::Output {
                $fn(rhs, self)
            }
        }
    );
}

#[macro_export]
macro_rules! _impl_assignment_op_internal {
    ($ops_trait:ident, $ops_fn:ident, $lhs:ty, $rhs:ty, $fn:expr) => (
        impl ops::$ops_trait<$rhs> for $lhs {
            fn $ops_fn(&mut self, rhs: $rhs) {
                $fn(self, &rhs)
            }
        }

        impl<'a> ops::$ops_trait<&'a $rhs> for $lhs {
            fn $ops_fn(&mut self, rhs: &$rhs) {
                $fn(self, rhs)
            }
        }

    );
}

#[macro_export]
macro_rules! _impl_unary_op_internal {
    ($ops_trait:ident, $ops_fn:ident, $lhs:ty, $out:ty, $fn:expr) => (
        impl ops::$ops_trait for $lhs {
            type Output = $out;

            fn $ops_fn(self) -> Self::Output {
                $fn(&self)
            }
        }

        impl<'a> ops::$ops_trait for &'a $lhs {
            type Output = $out;

            fn $ops_fn(self) -> Self::Output {
                $fn(self)
            }
        }
    );
}
<|endoftext|>


<commit_before>#![allow(non_camel_case_types, non_upper_case_globals, non_snake_case)]

extern crate libc;

use libc::{c_char, c_int, c_uchar, c_void};
use libc::size_t;

macro_rules! opaque {
    ($name:ident) => {
        #[repr(C)]
        pub struct $name {
            _private: [u8; 0]
        }
    };
}

// These are opaque types that LevelDB uses.
opaque!(leveldb_t);
opaque!(leveldb_cache_t);
opaque!(leveldb_comparator_t);
opaque!(leveldb_env_t);
opaque!(leveldb_filelock_t);
opaque!(leveldb_filterpolicy_t);
opaque!(leveldb_iterator_t);
opaque!(leveldb_logger_t);
opaque!(leveldb_options_t);
opaque!(leveldb_randomfile_t);
opaque!(leveldb_readoptions_t);
opaque!(leveldb_seqfile_t);
opaque!(leveldb_snapshot_t);
opaque!(leveldb_writablefile_t);
opaque!(leveldb_writebatch_t);
opaque!(leveldb_writeoptions_t);

#[repr(C)]
#[derive(Copy,Clone)]
pub enum Compression {
  No = 0,
  Snappy = 1
}

extern "C" {
    // DB operations
    /// Open the database at path `name` with the configurations set in `options`.
    ///
    /// If this operation fails,
    /// - `leveldb_t` is a nullpointer
    /// - `errptr` contains more information about the error reason
    pub fn leveldb_open(options: *const leveldb_options_t, name: *const c_char, errptr: *mut *mut c_char) -> *mut leveldb_t;
    /// Close the database at path `name`.
    ///
    /// Note that this operation cannot fail.
    pub fn leveldb_close(db: *mut leveldb_t);
    pub fn leveldb_put(db: *mut leveldb_t, options: *const leveldb_writeoptions_t, key: *const c_char, keylen: size_t, val: *const c_char, vallen: size_t, errptr: *mut *mut c_char);
    pub fn leveldb_delete(db: *mut leveldb_t, options: *const leveldb_writeoptions_t, key: *const c_char, keylen: size_t, errptr: *mut *mut c_char);
    pub fn leveldb_write(db: *mut leveldb_t, options: *const leveldb_writeoptions_t, batch: *mut leveldb_writebatch_t, errptr: *mut *mut c_char);
    pub fn leveldb_get(db: *mut leveldb_t, options: *const leveldb_readoptions_t, key: *const c_char, keylen: size_t, vallen: *mut size_t, errptr: *mut *mut c_char) -> *mut c_char;
    pub fn leveldb_create_iterator(db: *mut leveldb_t, options: *const leveldb_readoptions_t) -> *mut leveldb_iterator_t;
    pub fn leveldb_create_snapshot(db: *mut leveldb_t) -> *mut leveldb_snapshot_t;
    pub fn leveldb_release_snapshot(db: *mut leveldb_t, snapshot: *const leveldb_snapshot_t);
    pub fn leveldb_property_value(db: *mut leveldb_t, propname: *const c_char) -> *mut c_char;

    // TODO: const'ness of pointers here is in question
    pub fn leveldb_approximate_sizes(db: *mut leveldb_t, num_ranges: c_int, range_start_key: *const *const c_char, range_start_key_len: *const size_t, range_limit_key: *const *const c_char, range_limit_key_len: *const size_t, sizes: *mut u64);
    pub fn leveldb_compact_range(db: *mut leveldb_t, start_key: *const c_char, start_key_len: size_t, limit_key: *const c_char, limit_key_len: size_t);

    // Management operations
    pub fn leveldb_destroy_db(options: *const leveldb_options_t, name: *const c_char, errptr: *mut *mut c_char);
    pub fn leveldb_repair_db(options: *const leveldb_options_t, name: *const c_char, errptr: *mut *mut c_char);

    // Iterator
    pub fn leveldb_iter_destroy(it: *mut leveldb_iterator_t);
    pub fn leveldb_iter_valid(it: *const leveldb_iterator_t) -> c_uchar;
    pub fn leveldb_iter_seek_to_first(it: *mut leveldb_iterator_t);
    pub fn leveldb_iter_seek_to_last(it: *mut leveldb_iterator_t);
    pub fn leveldb_iter_seek(it: *mut leveldb_iterator_t, k: *const c_char, klen: size_t);
    pub fn leveldb_iter_next(it: *mut leveldb_iterator_t);
    pub fn leveldb_iter_prev(it: *mut leveldb_iterator_t);
    pub fn leveldb_iter_key(it: *const leveldb_iterator_t, klen: *const size_t) -> *const c_char;
    pub fn leveldb_iter_value(it: *const leveldb_iterator_t, vlen: *const size_t) -> *const c_char;
    pub fn leveldb_iter_get_error(it: *const leveldb_iterator_t, errptr: *const *const c_char);

    // Write batch
    pub fn leveldb_writebatch_create() -> *mut leveldb_writebatch_t;
    pub fn leveldb_writebatch_destroy(b: *mut leveldb_writebatch_t);
    pub fn leveldb_writebatch_clear(b: *mut leveldb_writebatch_t);
    pub fn leveldb_writebatch_put(b: *mut leveldb_writebatch_t, key: *const c_char, keylen: size_t, val: *const c_char, vallen: size_t);
    pub fn leveldb_writebatch_delete(b: *mut leveldb_writebatch_t, key: *const c_char, keylen: size_t);
    pub fn leveldb_writebatch_iterate(
        b: *mut leveldb_writebatch_t,
        state: *mut c_void,
        put: extern fn(*mut c_void, *const c_char, size_t, *const c_char, size_t),
        deleted: extern fn(*mut c_void, *const c_char, size_t)
    );

    // Options
    /// Create a new `leveldb_options_t` (not the database, but the database *configuration*!)
    pub fn leveldb_options_create() -> *mut leveldb_options_t;
    /// Deallocate `o` (not the database!)
    pub fn leveldb_options_destroy(o: *mut leveldb_options_t);
    pub fn leveldb_options_set_comparator(o: *mut leveldb_options_t, c: *mut leveldb_comparator_t);
    pub fn leveldb_options_set_filter_policy(o: *mut leveldb_options_t, c: *mut leveldb_filterpolicy_t);
    /// Modify `o` to specify whether a new database should be created if none exists yet
    ///
    /// - If `val` is != 0, new database creation is enabled
    /// - If `val` is 0,    no new database will be created if none exists yet
    pub fn leveldb_options_set_create_if_missing(o: *mut leveldb_options_t, val: c_uchar);
    pub fn leveldb_options_set_error_if_exists(o: *mut leveldb_options_t, val: c_uchar);
    pub fn leveldb_options_set_paranoid_checks(o: *mut leveldb_options_t, val: c_uchar);
    pub fn leveldb_options_set_env(o: *mut leveldb_options_t, env: *mut leveldb_env_t);
    pub fn leveldb_options_set_info_log(o: *mut leveldb_options_t, logger: *mut leveldb_logger_t);
    pub fn leveldb_options_set_write_buffer_size(o: *mut leveldb_options_t, size: size_t);
    pub fn leveldb_options_set_max_open_files(o: *mut leveldb_options_t, num: c_int);
    pub fn leveldb_options_set_cache(o: *mut leveldb_options_t, cache: *mut leveldb_cache_t);
    pub fn leveldb_options_set_block_size(o: *mut leveldb_options_t, size: size_t);
    pub fn leveldb_options_set_block_restart_interval(o: *mut leveldb_options_t, interval: c_int);
    pub fn leveldb_options_set_compression(o: *mut leveldb_options_t, val: Compression);

    // Comparator
    pub fn leveldb_comparator_create(
        state: *mut c_void,
        destructor: extern fn(*mut c_void),
        compare: extern fn(*mut c_void, *const c_char, size_t, *const c_char, size_t) -> c_int,
        name: extern fn(*mut c_void) -> *const c_char
    ) -> *mut leveldb_comparator_t;
    pub fn leveldb_comparator_destroy(c: *mut leveldb_comparator_t);

    // Filter policy
    //pub leveldb_filterpolicy_create(state: *mut c_void, /* TODO */) -> *mut leveldb_filterpolicy_t;
    /*
        extern leveldb_filterpolicy_t* leveldb_filterpolicy_create(
            void* state,
            void (*destructor)(void*),
            char* (*create_filter)(
                void*,
                const char* const* key_array, const size_t* key_length_array,
                int num_keys,
                size_t* filter_length),
            unsigned char (*key_may_match)(
                void*,
                const char* key, size_t length,
                const char* filter, size_t filter_length),
            const char* (*name)(void*));
    */
    pub fn leveldb_filterpolicy_destroy(p: *mut leveldb_filterpolicy_t);
    pub fn leveldb_filterpolicy_create_bloom(bits_per_key: c_int) -> *mut leveldb_filterpolicy_t;

    // Read options
    pub fn leveldb_readoptions_create() -> *mut leveldb_readoptions_t;
    pub fn leveldb_readoptions_destroy(o: *mut leveldb_readoptions_t);
    pub fn leveldb_readoptions_set_verify_checksums(o: *mut leveldb_readoptions_t, val: c_uchar);
    pub fn leveldb_readoptions_set_fill_cache(o: *mut leveldb_readoptions_t, val: c_uchar);
    pub fn leveldb_readoptions_set_snapshot(o: *mut leveldb_readoptions_t, snapshot: *const leveldb_snapshot_t);

    // Write options
    pub fn leveldb_writeoptions_create() -> *mut leveldb_writeoptions_t;
    pub fn leveldb_writeoptions_destroy(o: *mut leveldb_writeoptions_t);
    pub fn leveldb_writeoptions_set_sync(o: *mut leveldb_writeoptions_t, val: c_uchar);

    // Cache
    pub fn leveldb_cache_create_lru(capacity: size_t) -> *mut leveldb_cache_t;
    pub fn leveldb_cache_destroy(c: *mut leveldb_cache_t);

    // Env
    pub fn leveldb_create_default_env() -> *mut leveldb_env_t;
    pub fn leveldb_env_destroy(e: *mut leveldb_env_t);

    // Utility
    pub fn leveldb_free(ptr: *mut c_void);

    // Versioning
    pub fn leveldb_major_version() -> c_int;
    pub fn leveldb_minor_version() -> c_int;
}
<commit_msg>extend opaque! macro so we can document opaque structs<commit_after>#![allow(non_camel_case_types, non_upper_case_globals, non_snake_case)]

extern crate libc;

use libc::{c_char, c_int, c_uchar, c_void};
use libc::size_t;

macro_rules! opaque {
    ($name:ident) => {
        #[repr(C)]
        pub struct $name {
            _private: [u8; 0]
        }
    };

    ($name:ident, $doc:expr) => {
        #[doc=$doc]
        #[repr(C)]
        pub struct $name {
            _private: [u8; 0]
        }
    };
}

// These are opaque types that LevelDB uses.
opaque!(leveldb_t, "Opaque handle representing an opened database. The handle is thread-safe.");
opaque!(leveldb_cache_t);
opaque!(leveldb_comparator_t);
opaque!(leveldb_env_t);
opaque!(leveldb_filelock_t);
opaque!(leveldb_filterpolicy_t);
opaque!(leveldb_iterator_t);
opaque!(leveldb_logger_t);
opaque!(leveldb_options_t, "Opaque handle representing database options");
opaque!(leveldb_randomfile_t);
opaque!(leveldb_readoptions_t);
opaque!(leveldb_seqfile_t);
opaque!(leveldb_snapshot_t);
opaque!(leveldb_writablefile_t);
opaque!(leveldb_writebatch_t);
opaque!(leveldb_writeoptions_t);

#[repr(C)]
#[derive(Copy,Clone)]
pub enum Compression {
  No = 0,
  Snappy = 1
}

extern "C" {
    // DB operations
    /// Open the database at path `name` with the configurations set in `options`.
    ///
    /// If this operation fails,
    /// - `leveldb_t` is a nullpointer
    /// - `errptr` contains more information about the error reason
    pub fn leveldb_open(options: *const leveldb_options_t, name: *const c_char, errptr: *mut *mut c_char) -> *mut leveldb_t;
    /// Close the database at path `name`.
    ///
    /// Note that this operation cannot fail.
    pub fn leveldb_close(db: *mut leveldb_t);
    pub fn leveldb_put(db: *mut leveldb_t, options: *const leveldb_writeoptions_t, key: *const c_char, keylen: size_t, val: *const c_char, vallen: size_t, errptr: *mut *mut c_char);
    pub fn leveldb_delete(db: *mut leveldb_t, options: *const leveldb_writeoptions_t, key: *const c_char, keylen: size_t, errptr: *mut *mut c_char);
    pub fn leveldb_write(db: *mut leveldb_t, options: *const leveldb_writeoptions_t, batch: *mut leveldb_writebatch_t, errptr: *mut *mut c_char);
    pub fn leveldb_get(db: *mut leveldb_t, options: *const leveldb_readoptions_t, key: *const c_char, keylen: size_t, vallen: *mut size_t, errptr: *mut *mut c_char) -> *mut c_char;
    pub fn leveldb_create_iterator(db: *mut leveldb_t, options: *const leveldb_readoptions_t) -> *mut leveldb_iterator_t;
    pub fn leveldb_create_snapshot(db: *mut leveldb_t) -> *mut leveldb_snapshot_t;
    pub fn leveldb_release_snapshot(db: *mut leveldb_t, snapshot: *const leveldb_snapshot_t);
    pub fn leveldb_property_value(db: *mut leveldb_t, propname: *const c_char) -> *mut c_char;

    // TODO: const'ness of pointers here is in question
    pub fn leveldb_approximate_sizes(db: *mut leveldb_t, num_ranges: c_int, range_start_key: *const *const c_char, range_start_key_len: *const size_t, range_limit_key: *const *const c_char, range_limit_key_len: *const size_t, sizes: *mut u64);
    pub fn leveldb_compact_range(db: *mut leveldb_t, start_key: *const c_char, start_key_len: size_t, limit_key: *const c_char, limit_key_len: size_t);

    // Management operations
    pub fn leveldb_destroy_db(options: *const leveldb_options_t, name: *const c_char, errptr: *mut *mut c_char);
    pub fn leveldb_repair_db(options: *const leveldb_options_t, name: *const c_char, errptr: *mut *mut c_char);

    // Iterator
    pub fn leveldb_iter_destroy(it: *mut leveldb_iterator_t);
    pub fn leveldb_iter_valid(it: *const leveldb_iterator_t) -> c_uchar;
    pub fn leveldb_iter_seek_to_first(it: *mut leveldb_iterator_t);
    pub fn leveldb_iter_seek_to_last(it: *mut leveldb_iterator_t);
    pub fn leveldb_iter_seek(it: *mut leveldb_iterator_t, k: *const c_char, klen: size_t);
    pub fn leveldb_iter_next(it: *mut leveldb_iterator_t);
    pub fn leveldb_iter_prev(it: *mut leveldb_iterator_t);
    pub fn leveldb_iter_key(it: *const leveldb_iterator_t, klen: *const size_t) -> *const c_char;
    pub fn leveldb_iter_value(it: *const leveldb_iterator_t, vlen: *const size_t) -> *const c_char;
    pub fn leveldb_iter_get_error(it: *const leveldb_iterator_t, errptr: *const *const c_char);

    // Write batch
    pub fn leveldb_writebatch_create() -> *mut leveldb_writebatch_t;
    pub fn leveldb_writebatch_destroy(b: *mut leveldb_writebatch_t);
    pub fn leveldb_writebatch_clear(b: *mut leveldb_writebatch_t);
    pub fn leveldb_writebatch_put(b: *mut leveldb_writebatch_t, key: *const c_char, keylen: size_t, val: *const c_char, vallen: size_t);
    pub fn leveldb_writebatch_delete(b: *mut leveldb_writebatch_t, key: *const c_char, keylen: size_t);
    pub fn leveldb_writebatch_iterate(
        b: *mut leveldb_writebatch_t,
        state: *mut c_void,
        put: extern fn(*mut c_void, *const c_char, size_t, *const c_char, size_t),
        deleted: extern fn(*mut c_void, *const c_char, size_t)
    );

    // Options
    /// Create a new `leveldb_options_t` (not the database, but the database *configuration*!)
    pub fn leveldb_options_create() -> *mut leveldb_options_t;
    /// Deallocate `o` (not the database!)
    pub fn leveldb_options_destroy(o: *mut leveldb_options_t);
    pub fn leveldb_options_set_comparator(o: *mut leveldb_options_t, c: *mut leveldb_comparator_t);
    pub fn leveldb_options_set_filter_policy(o: *mut leveldb_options_t, c: *mut leveldb_filterpolicy_t);
    /// Modify `o` to specify whether a new database should be created if none exists yet
    ///
    /// - If `val` is != 0, new database creation is enabled
    /// - If `val` is 0,    no new database will be created if none exists yet
    pub fn leveldb_options_set_create_if_missing(o: *mut leveldb_options_t, val: c_uchar);
    pub fn leveldb_options_set_error_if_exists(o: *mut leveldb_options_t, val: c_uchar);
    pub fn leveldb_options_set_paranoid_checks(o: *mut leveldb_options_t, val: c_uchar);
    pub fn leveldb_options_set_env(o: *mut leveldb_options_t, env: *mut leveldb_env_t);
    pub fn leveldb_options_set_info_log(o: *mut leveldb_options_t, logger: *mut leveldb_logger_t);
    pub fn leveldb_options_set_write_buffer_size(o: *mut leveldb_options_t, size: size_t);
    pub fn leveldb_options_set_max_open_files(o: *mut leveldb_options_t, num: c_int);
    pub fn leveldb_options_set_cache(o: *mut leveldb_options_t, cache: *mut leveldb_cache_t);
    pub fn leveldb_options_set_block_size(o: *mut leveldb_options_t, size: size_t);
    pub fn leveldb_options_set_block_restart_interval(o: *mut leveldb_options_t, interval: c_int);
    pub fn leveldb_options_set_compression(o: *mut leveldb_options_t, val: Compression);

    // Comparator
    pub fn leveldb_comparator_create(
        state: *mut c_void,
        destructor: extern fn(*mut c_void),
        compare: extern fn(*mut c_void, *const c_char, size_t, *const c_char, size_t) -> c_int,
        name: extern fn(*mut c_void) -> *const c_char
    ) -> *mut leveldb_comparator_t;
    pub fn leveldb_comparator_destroy(c: *mut leveldb_comparator_t);

    // Filter policy
    //pub leveldb_filterpolicy_create(state: *mut c_void, /* TODO */) -> *mut leveldb_filterpolicy_t;
    /*
        extern leveldb_filterpolicy_t* leveldb_filterpolicy_create(
            void* state,
            void (*destructor)(void*),
            char* (*create_filter)(
                void*,
                const char* const* key_array, const size_t* key_length_array,
                int num_keys,
                size_t* filter_length),
            unsigned char (*key_may_match)(
                void*,
                const char* key, size_t length,
                const char* filter, size_t filter_length),
            const char* (*name)(void*));
    */
    pub fn leveldb_filterpolicy_destroy(p: *mut leveldb_filterpolicy_t);
    pub fn leveldb_filterpolicy_create_bloom(bits_per_key: c_int) -> *mut leveldb_filterpolicy_t;

    // Read options
    pub fn leveldb_readoptions_create() -> *mut leveldb_readoptions_t;
    pub fn leveldb_readoptions_destroy(o: *mut leveldb_readoptions_t);
    pub fn leveldb_readoptions_set_verify_checksums(o: *mut leveldb_readoptions_t, val: c_uchar);
    pub fn leveldb_readoptions_set_fill_cache(o: *mut leveldb_readoptions_t, val: c_uchar);
    pub fn leveldb_readoptions_set_snapshot(o: *mut leveldb_readoptions_t, snapshot: *const leveldb_snapshot_t);

    // Write options
    pub fn leveldb_writeoptions_create() -> *mut leveldb_writeoptions_t;
    pub fn leveldb_writeoptions_destroy(o: *mut leveldb_writeoptions_t);
    pub fn leveldb_writeoptions_set_sync(o: *mut leveldb_writeoptions_t, val: c_uchar);

    // Cache
    pub fn leveldb_cache_create_lru(capacity: size_t) -> *mut leveldb_cache_t;
    pub fn leveldb_cache_destroy(c: *mut leveldb_cache_t);

    // Env
    pub fn leveldb_create_default_env() -> *mut leveldb_env_t;
    pub fn leveldb_env_destroy(e: *mut leveldb_env_t);

    // Utility
    pub fn leveldb_free(ptr: *mut c_void);

    // Versioning
    pub fn leveldb_major_version() -> c_int;
    pub fn leveldb_minor_version() -> c_int;
}
<|endoftext|>


<commit_before>//! [![logo](http://i.imgur.com/dnpEXyh.jpg)](http://i.imgur.com/RUEw8EW.png)
//!
//! bspline
//! ===
//! A library for computing B-spline interpolating curves on generic control points. bspline can
//! be used to evaluate B-splines of varying orders on any type that can be linearly interpolated,
//! ranging from floats, positions, RGB colors to transformation matrices and so on.
//!
//! The bspline logo was generated using this library with a cubic B-spline in 2D for the positioning
//! of the curve and a quadratic B-spline in RGB space to color it (check out the
//! [logo](https://github.com/Twinklebear/bspline/blob/master/examples/logo.rs) example!). Other
//! much simpler examples of 1D and 2D quadratic, cubic and quartic B-splines can also be found in
//! the [examples](https://github.com/Twinklebear/bspline/tree/master/examples).
//!
//! # 1D Example
//!
//! This example shows how to create the 1D cardinal cubic B-spline example shown on [Wikipedia's
//! B-splines page](https://en.wikipedia.org/wiki/B-spline). For examples of evaluating the spline
//! to an image and saving the output see the [examples](https://github.com/Twinklebear/bspline/tree/master/examples).
//!
//! ```rust
//! let points = vec![0.0, 0.0, 0.0, 6.0, 0.0, 0.0, 0.0]
//! let knots = vec![-2.0, -2.0, -2.0, -2.0, -1.0, 0.0, 1.0, 2.0, 2.0, 2.0, 2.0];
//! let degree = 3;
//! let spline = bspline::BSpline::new(degree, points, knots);
//! ```
//!
//! # Readings on B-splines
//!
//! The library assumes you are familiar at some level with how B-splines work, e.g. how
//! control points and knots and effect the curve produced. No interactive
//! editor is provided (at least currently). Some good places to start reading about B-splines to
//! effectively use this library can be found below.
//!
//! - [Wikipedia page on B-splines](https://en.wikipedia.org/wiki/B-spline)
//! - [Fundamentals of Computer Graphics](http://www.amazon.com/Fundamentals-Computer-Graphics-Peter-Shirley/dp/1568814690)
//! (has a good chapter on curves)
//! - [Splines and B-splines: An Introduction](http://www.uio.no/studier/emner/matnat/ifi/INF-MAT5340/v07/undervisningsmateriale/kap1.pdf)
//! - [Geometric Modeling](http://atrey.karlin.mff.cuni.cz/projekty/vrr/doc/grafika/geometric%20modelling.pdf)
//! - [A nice set of interactive examples](https://www.ibiblio.org/e-notes/Splines/Intro.htm)
//!

use std::ops::{Mul, Add};
use std::fmt::Debug;
use std::slice::Iter;

/// The interpolate trait is used to linearly interpolate between two types (or in the
/// case of Quaternions, spherically linearly interpolate). The B-spline curve uses this
/// trait to compute points on the curve for the given parameter value.
///
/// A default implementation of this trait is provided for all `T` that are `Mul<f32, Output = T>
/// + Add<Output = T> + Copy` since the interpolation provided by the trait is expected to be
/// a simple linear interpolation.
pub trait Interpolate {
    /// Linearly interpolate between `self` and `other` using `t`, for example with floats:
    ///
    /// ```text
    /// self * (1.0 - t) + other * t
    /// ```
    ///
    /// If the result returned is not a correct linear interpolation of the values the
    /// curve produced using the value may not be correct.
    fn interpolate(&self, other: &Self, t: f32) -> Self;
}

impl<T: Mul<f32, Output = T> + Add<Output = T> + Copy> Interpolate for T {
    fn interpolate(&self, other: &Self, t: f32) -> Self {
        *self * (1.0 - t) + *other * t
    }
}

/// Represents a B-spline that will use polynomials of the specified degree to interpolate
/// between the control points given the knots.
pub struct BSpline<T: Interpolate + Copy + Debug> {
    /// Degree of the polynomial that we use to make the curve segments
    degree: usize,
    /// Control points for the curve
    control_points: Vec<T>,
    /// The knot vector
    knots: Vec<f32>,
}

impl<T: Interpolate + Copy + Debug> BSpline<T> {
    /// Create a new B-spline curve of the desired `degree` that will interpolate
    /// the `control_points` using the `knots`. The knots should be sorted in non-decreasing
    /// order, otherwise they will be sorted for you which may lead to undesired knots
    /// for control points. Note that this is in terms of the interpolating polynomial degree,
    /// if you are familiar with the convention of "B-spline curve order" the degree is `curve_order - 1`.
    ///
    /// Your curve must have a valid number of control points and knots or the function will panic. A B-spline
    /// curve requires at least as many control points as the degree (`control_points.len() >=
    /// degree`) and the number of knots should be equal to `control_points.len() + degree + 1`.
    pub fn new(degree: usize, control_points: Vec<T>, mut knots: Vec<f32>) -> BSpline<T> {
        if control_points.len() < degree {
            panic!("Too few control points for curve");
        }
        if knots.len() != control_points.len() + degree + 1 {
            panic!(format!("Invalid number of knots, got {}, expected {}", knots.len(),
                control_points.len() + degree + 1));
        }
        knots.sort_by(|a, b| a.partial_cmp(b).unwrap());
        BSpline { degree: degree, control_points: control_points, knots: knots }
    }
    /// Compute a point on the curve at `t`, the parameter **must** be in the inclusive range
    /// of values returned by `knot_domain`. If `t` is out of bounds this function will assert
    /// on debug builds and on release builds you'll likely get an out of bounds crash.
    pub fn point(&self, t: f32) -> T {
        debug_assert!(t >= self.knot_domain().0 && t <= self.knot_domain().1);
        // Find the first index with a knot value greater than the t we're searching for. We want
        // to find i such that: knot[i] <= t < knot[i + 1]
        let i = match upper_bounds(&self.knots[..], t) {
            Some(x) if x == 0 => self.degree,
            Some(x) => x,
            None => self.knots.len() - self.degree - 1,
        };
        self.de_boor_iterative(t, i)
    }
    /// Get an iterator over the control points.
    pub fn control_points(&self) -> Iter<T> {
        self.control_points.iter()
    }
    /// Get an iterator over the knots.
    pub fn knots(&self) -> Iter<f32> {
        self.knots.iter()
    }
    /// Get the min and max knot domain values for finding the `t` range to compute
    /// the curve over. The curve is only defined over this (inclusive) range, passing
    /// a `t` value out of this range will assert on debug builds and likely result in
    /// a crash on release builds.
    pub fn knot_domain(&self) -> (f32, f32) {
        (self.knots[self.degree], self.knots[self.knots.len() - 1 - self.degree])
    }
    /// Iteratively compute de Boor's B-spline algorithm, this computes the recursive
    /// de Boor algorithm tree from the bottom up. At each level we use the results
    /// from the previous one to compute this level and store the results in the
    /// array indices we no longer need to compute the current level (the left one
    /// used computing node j).
    fn de_boor_iterative(&self, t: f32, i_start: usize) -> T {
        let mut tmp = Vec::with_capacity(self.degree + 1);
        for j in 0..self.degree + 1 {
            let p = j + i_start - self.degree - 1;
            tmp.push(self.control_points[p]);
        }
        for lvl in 0..self.degree {
            let k = lvl + 1;
            for j in 0..self.degree - lvl {
                let i = j + k + i_start - self.degree;
                let alpha = (t - self.knots[i - 1]) / (self.knots[i + self.degree - k] - self.knots[i - 1]);
                tmp[j] = tmp[j].interpolate(&tmp[j + 1], alpha);
            }
        }
        tmp[0]
    }
}

/// Return the index of the first element greater than the value passed.
/// The data **must** be sorted.
/// If no element greater than the value passed is found the function returns None.
fn upper_bounds(data: &[f32], value: f32) -> Option<usize> {
    let mut first = 0usize;
    let mut step;
    let mut count = data.len() as isize;
    while count > 0 {
        step = count / 2;
        let it = first + step as usize;
        if !value.lt(&data[it]) {
            first = it + 1;
            count -= step + 1;
        } else {
            count = step;
        }
    }
    // If we didn't find an element greater than value
    if first == data.len() {
        None
    } else {
        Some(first)
    }
}

#[cfg(test)]
mod test {
    use super::BSpline;

    /// Check that the bspline returns the values we expect it to at various t values
    fn check_bspline(spline: &BSpline<f32>, expect: &Vec<(f32, f32)>) -> bool {
        expect.iter().fold(true, |ac, &(t, x)| ac && spline.point(t) == x)
    }

    #[test]
    fn linear_bspline() {
        let expect = vec![(0.0, 0.0), (0.2, 0.2), (0.4, 0.4), (0.6, 0.6),
                          (0.8, 0.8), (1.0, 1.0)];
        let points = vec![0.0, 1.0];
        let knots = vec![0.0, 0.0, 1.0, 1.0];
        let degree = 1;
        let spline = BSpline::new(degree, points, knots);
        assert!(check_bspline(&spline, &expect));
    }
    #[test]
    fn quadratic_bspline() {
        let expect = vec![(0.0, 0.0), (0.5, 0.125), (1.0, 0.5), (1.4, 0.74), (1.5, 0.75),
                          (1.6, 0.74), (2.0, 0.5), (2.5, 0.125), (3.0, 0.0)];
        let points = vec![0.0, 0.0, 1.0, 0.0, 0.0];
        let knots = vec![0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 3.0, 3.0];
        let degree = 2;
        let spline = BSpline::new(degree, points, knots);
        assert!(check_bspline(&spline, &expect));
    }
    #[test]
    fn cubic_bspline() {
        let expect = vec![(-2.0, 0.0), (-1.5, 0.125), (-1.0, 1.0), (-0.6, 2.488),
                           (0.0, 4.0), (0.5, 2.875), (1.5, 0.12500001), (2.0, 0.0)];
        let points = vec![0.0, 0.0, 0.0, 6.0, 0.0, 0.0, 0.0];
        let knots = vec![-2.0, -2.0, -2.0, -2.0, -1.0, 0.0, 1.0, 2.0, 2.0, 2.0, 2.0];
        let degree = 3;
        let spline = BSpline::new(degree, points, knots);
        assert!(check_bspline(&spline, &expect));
    }
    #[test]
    fn quartic_bspline() {
        let expect = vec![(0.0, 0.0), (0.4, 0.0010666668), (1.0, 0.041666668),
                          (1.5, 0.19791667), (2.0, 0.4583333), (2.5, 0.5989583),
                          (3.0, 0.4583333), (3.2, 0.35206667), (4.1, 0.02733751),
                          (4.5, 0.002604167), (5.0, 0.0)];
        let points = vec![0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0];
        let knots = vec![0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 5.0, 5.0, 5.0, 5.0];
        let degree = 4;
        let spline = BSpline::new(degree, points, knots);
        assert!(check_bspline(&spline, &expect));
    }
}

<commit_msg>Forgot about doc tests<commit_after>//! [![logo](http://i.imgur.com/dnpEXyh.jpg)](http://i.imgur.com/RUEw8EW.png)
//!
//! bspline
//! ===
//! A library for computing B-spline interpolating curves on generic control points. bspline can
//! be used to evaluate B-splines of varying orders on any type that can be linearly interpolated,
//! ranging from floats, positions, RGB colors to transformation matrices and so on.
//!
//! The bspline logo was generated using this library with a cubic B-spline in 2D for the positioning
//! of the curve and a quadratic B-spline in RGB space to color it (check out the
//! [logo](https://github.com/Twinklebear/bspline/blob/master/examples/logo.rs) example!). Other
//! much simpler examples of 1D and 2D quadratic, cubic and quartic B-splines can also be found in
//! the [examples](https://github.com/Twinklebear/bspline/tree/master/examples).
//!
//! # 1D Example
//!
//! This example shows how to create the 1D cardinal cubic B-spline example shown on [Wikipedia's
//! B-splines page](https://en.wikipedia.org/wiki/B-spline). For examples of evaluating the spline
//! to an image and saving the output see the [examples](https://github.com/Twinklebear/bspline/tree/master/examples).
//!
//! ```rust
//! let points = vec![0.0, 0.0, 0.0, 6.0, 0.0, 0.0, 0.0];
//! let knots = vec![-2.0, -2.0, -2.0, -2.0, -1.0, 0.0, 1.0, 2.0, 2.0, 2.0, 2.0];
//! let degree = 3;
//! let spline = bspline::BSpline::new(degree, points, knots);
//! ```
//!
//! # Readings on B-splines
//!
//! The library assumes you are familiar at some level with how B-splines work, e.g. how
//! control points and knots and effect the curve produced. No interactive
//! editor is provided (at least currently). Some good places to start reading about B-splines to
//! effectively use this library can be found below.
//!
//! - [Wikipedia page on B-splines](https://en.wikipedia.org/wiki/B-spline)
//! - [Fundamentals of Computer Graphics](http://www.amazon.com/Fundamentals-Computer-Graphics-Peter-Shirley/dp/1568814690)
//! (has a good chapter on curves)
//! - [Splines and B-splines: An Introduction](http://www.uio.no/studier/emner/matnat/ifi/INF-MAT5340/v07/undervisningsmateriale/kap1.pdf)
//! - [Geometric Modeling](http://atrey.karlin.mff.cuni.cz/projekty/vrr/doc/grafika/geometric%20modelling.pdf)
//! - [A nice set of interactive examples](https://www.ibiblio.org/e-notes/Splines/Intro.htm)
//!

use std::ops::{Mul, Add};
use std::fmt::Debug;
use std::slice::Iter;

/// The interpolate trait is used to linearly interpolate between two types (or in the
/// case of Quaternions, spherically linearly interpolate). The B-spline curve uses this
/// trait to compute points on the curve for the given parameter value.
///
/// A default implementation of this trait is provided for all `T` that are `Mul<f32, Output = T>
/// + Add<Output = T> + Copy` since the interpolation provided by the trait is expected to be
/// a simple linear interpolation.
pub trait Interpolate {
    /// Linearly interpolate between `self` and `other` using `t`, for example with floats:
    ///
    /// ```text
    /// self * (1.0 - t) + other * t
    /// ```
    ///
    /// If the result returned is not a correct linear interpolation of the values the
    /// curve produced using the value may not be correct.
    fn interpolate(&self, other: &Self, t: f32) -> Self;
}

impl<T: Mul<f32, Output = T> + Add<Output = T> + Copy> Interpolate for T {
    fn interpolate(&self, other: &Self, t: f32) -> Self {
        *self * (1.0 - t) + *other * t
    }
}

/// Represents a B-spline that will use polynomials of the specified degree to interpolate
/// between the control points given the knots.
pub struct BSpline<T: Interpolate + Copy + Debug> {
    /// Degree of the polynomial that we use to make the curve segments
    degree: usize,
    /// Control points for the curve
    control_points: Vec<T>,
    /// The knot vector
    knots: Vec<f32>,
}

impl<T: Interpolate + Copy + Debug> BSpline<T> {
    /// Create a new B-spline curve of the desired `degree` that will interpolate
    /// the `control_points` using the `knots`. The knots should be sorted in non-decreasing
    /// order, otherwise they will be sorted for you which may lead to undesired knots
    /// for control points. Note that this is in terms of the interpolating polynomial degree,
    /// if you are familiar with the convention of "B-spline curve order" the degree is `curve_order - 1`.
    ///
    /// Your curve must have a valid number of control points and knots or the function will panic. A B-spline
    /// curve requires at least as many control points as the degree (`control_points.len() >=
    /// degree`) and the number of knots should be equal to `control_points.len() + degree + 1`.
    pub fn new(degree: usize, control_points: Vec<T>, mut knots: Vec<f32>) -> BSpline<T> {
        if control_points.len() < degree {
            panic!("Too few control points for curve");
        }
        if knots.len() != control_points.len() + degree + 1 {
            panic!(format!("Invalid number of knots, got {}, expected {}", knots.len(),
                control_points.len() + degree + 1));
        }
        knots.sort_by(|a, b| a.partial_cmp(b).unwrap());
        BSpline { degree: degree, control_points: control_points, knots: knots }
    }
    /// Compute a point on the curve at `t`, the parameter **must** be in the inclusive range
    /// of values returned by `knot_domain`. If `t` is out of bounds this function will assert
    /// on debug builds and on release builds you'll likely get an out of bounds crash.
    pub fn point(&self, t: f32) -> T {
        debug_assert!(t >= self.knot_domain().0 && t <= self.knot_domain().1);
        // Find the first index with a knot value greater than the t we're searching for. We want
        // to find i such that: knot[i] <= t < knot[i + 1]
        let i = match upper_bounds(&self.knots[..], t) {
            Some(x) if x == 0 => self.degree,
            Some(x) => x,
            None => self.knots.len() - self.degree - 1,
        };
        self.de_boor_iterative(t, i)
    }
    /// Get an iterator over the control points.
    pub fn control_points(&self) -> Iter<T> {
        self.control_points.iter()
    }
    /// Get an iterator over the knots.
    pub fn knots(&self) -> Iter<f32> {
        self.knots.iter()
    }
    /// Get the min and max knot domain values for finding the `t` range to compute
    /// the curve over. The curve is only defined over this (inclusive) range, passing
    /// a `t` value out of this range will assert on debug builds and likely result in
    /// a crash on release builds.
    pub fn knot_domain(&self) -> (f32, f32) {
        (self.knots[self.degree], self.knots[self.knots.len() - 1 - self.degree])
    }
    /// Iteratively compute de Boor's B-spline algorithm, this computes the recursive
    /// de Boor algorithm tree from the bottom up. At each level we use the results
    /// from the previous one to compute this level and store the results in the
    /// array indices we no longer need to compute the current level (the left one
    /// used computing node j).
    fn de_boor_iterative(&self, t: f32, i_start: usize) -> T {
        let mut tmp = Vec::with_capacity(self.degree + 1);
        for j in 0..self.degree + 1 {
            let p = j + i_start - self.degree - 1;
            tmp.push(self.control_points[p]);
        }
        for lvl in 0..self.degree {
            let k = lvl + 1;
            for j in 0..self.degree - lvl {
                let i = j + k + i_start - self.degree;
                let alpha = (t - self.knots[i - 1]) / (self.knots[i + self.degree - k] - self.knots[i - 1]);
                tmp[j] = tmp[j].interpolate(&tmp[j + 1], alpha);
            }
        }
        tmp[0]
    }
}

/// Return the index of the first element greater than the value passed.
/// The data **must** be sorted.
/// If no element greater than the value passed is found the function returns None.
fn upper_bounds(data: &[f32], value: f32) -> Option<usize> {
    let mut first = 0usize;
    let mut step;
    let mut count = data.len() as isize;
    while count > 0 {
        step = count / 2;
        let it = first + step as usize;
        if !value.lt(&data[it]) {
            first = it + 1;
            count -= step + 1;
        } else {
            count = step;
        }
    }
    // If we didn't find an element greater than value
    if first == data.len() {
        None
    } else {
        Some(first)
    }
}

#[cfg(test)]
mod test {
    use super::BSpline;

    /// Check that the bspline returns the values we expect it to at various t values
    fn check_bspline(spline: &BSpline<f32>, expect: &Vec<(f32, f32)>) -> bool {
        expect.iter().fold(true, |ac, &(t, x)| ac && spline.point(t) == x)
    }

    #[test]
    fn linear_bspline() {
        let expect = vec![(0.0, 0.0), (0.2, 0.2), (0.4, 0.4), (0.6, 0.6),
                          (0.8, 0.8), (1.0, 1.0)];
        let points = vec![0.0, 1.0];
        let knots = vec![0.0, 0.0, 1.0, 1.0];
        let degree = 1;
        let spline = BSpline::new(degree, points, knots);
        assert!(check_bspline(&spline, &expect));
    }
    #[test]
    fn quadratic_bspline() {
        let expect = vec![(0.0, 0.0), (0.5, 0.125), (1.0, 0.5), (1.4, 0.74), (1.5, 0.75),
                          (1.6, 0.74), (2.0, 0.5), (2.5, 0.125), (3.0, 0.0)];
        let points = vec![0.0, 0.0, 1.0, 0.0, 0.0];
        let knots = vec![0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 3.0, 3.0];
        let degree = 2;
        let spline = BSpline::new(degree, points, knots);
        assert!(check_bspline(&spline, &expect));
    }
    #[test]
    fn cubic_bspline() {
        let expect = vec![(-2.0, 0.0), (-1.5, 0.125), (-1.0, 1.0), (-0.6, 2.488),
                           (0.0, 4.0), (0.5, 2.875), (1.5, 0.12500001), (2.0, 0.0)];
        let points = vec![0.0, 0.0, 0.0, 6.0, 0.0, 0.0, 0.0];
        let knots = vec![-2.0, -2.0, -2.0, -2.0, -1.0, 0.0, 1.0, 2.0, 2.0, 2.0, 2.0];
        let degree = 3;
        let spline = BSpline::new(degree, points, knots);
        assert!(check_bspline(&spline, &expect));
    }
    #[test]
    fn quartic_bspline() {
        let expect = vec![(0.0, 0.0), (0.4, 0.0010666668), (1.0, 0.041666668),
                          (1.5, 0.19791667), (2.0, 0.4583333), (2.5, 0.5989583),
                          (3.0, 0.4583333), (3.2, 0.35206667), (4.1, 0.02733751),
                          (4.5, 0.002604167), (5.0, 0.0)];
        let points = vec![0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0];
        let knots = vec![0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 5.0, 5.0, 5.0, 5.0];
        let degree = 4;
        let spline = BSpline::new(degree, points, knots);
        assert!(check_bspline(&spline, &expect));
    }
}

<|endoftext|>