<commit_before>extern crate crossbeam;

use std::borrow::Cow;
use std::ffi::{OsStr, OsString};
use std::fs::File;
use std::io;
use std::io::prelude::*;
use std::path::Path;
use std::process::{Command, Output, ExitStatus};
use std::thread::JoinHandle;

mod pipe;

pub fn cmd<T: AsRef<OsStr>>(argv: &[T]) -> Expression<'static> {
    let argv_vec = argv.iter().map(|arg| arg.as_ref().to_owned()).collect();
    Expression {
        inner: ExpressionInner::ArgvCommand(argv_vec),
        ioargs: IoArgs::new(),
    }
}

pub fn sh<T: AsRef<OsStr>>(command: T) -> Expression<'static> {
    Expression {
        inner: ExpressionInner::ShCommand(command.as_ref().to_owned()),
        ioargs: IoArgs::new(),
    }
}

pub fn pipe<'a>(left: Expression<'a>, right: Expression<'a>) -> Expression<'a> {
    Expression {
        inner: ExpressionInner::Pipe(Box::new(left), Box::new(right)),
        ioargs: IoArgs::new(),
    }
}

pub fn then<'a>(left: Expression<'a>, right: Expression<'a>) -> Expression<'a> {
    Expression {
        inner: ExpressionInner::Then(Box::new(left), Box::new(right)),
        ioargs: IoArgs::new(),
    }
}

#[derive(Clone, Debug)]
pub struct Expression<'a> {
    // TODO: Make these private.
    pub inner: ExpressionInner<'a>,
    pub ioargs: IoArgs<'a>,
}

// TODO: Make this private.
#[derive(Clone, Debug)]
pub enum ExpressionInner<'a> {
    ArgvCommand(Vec<OsString>),
    ShCommand(OsString),
    Pipe(Box<Expression<'a>>, Box<Expression<'a>>),
    Then(Box<Expression<'a>>, Box<Expression<'a>>),
}

impl<'a> Expression<'a> {
    pub fn run(&self) -> Result<Output, Error> {
        unreachable!();
    }

    pub fn read(&self) -> Result<String, Error> {
        let (handle, reader) = pipe_with_reader_thread();
        let mut context = IoContext::new();
        context.stdout = handle;
        let status = try!(self.exec(context));
        let stdout_vec = try!(reader.join().unwrap());
        if !status.success() {
            return Err(Error::Status(Output {
                status: status,
                stdout: stdout_vec,
                stderr: Vec::new(),
            }));
        }
        let stdout_string = try!(std::str::from_utf8(&stdout_vec))
                                .trim_right_matches('\n')
                                .to_owned();
        Ok(stdout_string)
    }

    fn exec(&self, parent_context: IoContext) -> io::Result<ExitStatus> {
        self.ioargs.with_child_context(parent_context, |context| {
            match self.inner {
                ExpressionInner::ArgvCommand(ref argv) => exec_argv(argv, context),
                ExpressionInner::ShCommand(ref command) => exec_sh(command, context),
                ExpressionInner::Pipe(ref left, ref right) => exec_pipe(left, right, context),
                ExpressionInner::Then(ref left, ref right) => exec_then(left, right, context),
            }
        })
    }

    pub fn stdin(&mut self, arg: InputArg<'a>) -> &mut Self {
        self.ioargs.stdin = arg;
        self
    }

    pub fn stdout(&mut self, arg: OutputArg<'a>) -> &mut Self {
        self.ioargs.stdout = arg;
        self
    }

    pub fn stderr(&mut self, arg: OutputArg<'a>) -> &mut Self {
        self.ioargs.stderr = arg;
        self
    }
}

fn exec_argv(argv: &Vec<OsString>, context: IoContext) -> io::Result<ExitStatus> {
    let mut command = Command::new(&argv[0]);
    command.args(&argv[1..]);
    command.stdin(context.stdin.to_stdio());
    command.stdout(context.stdout.to_stdio());
    command.stderr(context.stderr.to_stdio());
    command.status()
}

fn exec_sh(command: &OsStr, context: IoContext) -> io::Result<ExitStatus> {
    // TODO: What shell should we be using here, really?
    // TODO: Figure out how cmd.exe works on Windows.
    let mut argv = Vec::new();
    argv.push("bash".into());
    argv.push("-c".into());
    argv.push(command.to_owned());
    exec_argv(&argv, context)
}

fn exec_pipe(left: &Expression, right: &Expression, context: IoContext) -> io::Result<ExitStatus> {
    let (read_pipe, write_pipe) = pipe::open_pipe();
    let left_context = IoContext {
        stdin: context.stdin,
        stdout: write_pipe,
        stderr: context.stderr.clone(),
    };
    let right_context = IoContext {
        stdin: read_pipe,
        stdout: context.stdout,
        stderr: context.stderr,
    };

    let (left_result, right_result) = crossbeam::scope(|scope| {
        let left_joiner = scope.spawn(|| left.exec(left_context));
        let right_result = right.exec(right_context);
        let left_result = left_joiner.join();
        (left_result, right_result)
    });

    let right_status = try!(right_result);
    let left_status = try!(left_result);
    if !right_status.success() {
        Ok(right_status)
    } else {
        Ok(left_status)
    }
}

fn exec_then(left: &Expression, right: &Expression, context: IoContext) -> io::Result<ExitStatus> {
    let status = try!(left.exec(context.clone()));
    if !status.success() {
        Ok(status)
    } else {
        right.exec(context)
    }
}

#[derive(Debug)]
pub enum Error {
    Io(io::Error),
    Utf8(std::str::Utf8Error),
    Status(Output),
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

impl From<std::str::Utf8Error> for Error {
    fn from(err: std::str::Utf8Error) -> Error {
        Error::Utf8(err)
    }
}

// IoArgs store the redirections and other settings associated with an expression. At execution
// time, IoArgs are used to modify an IoContext, which contains the actual pipes that child process
// TODO: Make this private.
#[derive(Clone, Debug)]
pub struct IoArgs<'a> {
    stdin: InputArg<'a>,
    stdout: OutputArg<'a>,
    stderr: OutputArg<'a>,
}

impl<'a> IoArgs<'a> {
    fn new() -> IoArgs<'static> {
        IoArgs {
            stdin: InputArg::Inherit,
            stdout: OutputArg::Inherit,
            stderr: OutputArg::Inherit,
        }
    }

    fn with_child_context<F, T>(&self, parent_context: IoContext, inner: F) -> io::Result<T>
        where F: FnOnce(IoContext) -> io::Result<T>
    {
        let (stdin, maybe_stdin_thread) = try!(self.stdin.update_handle(parent_context.stdin));
        let stdout = try!(self.stdout.update_handle(parent_context.stdout));
        let stderr = try!(self.stderr.update_handle(parent_context.stderr));
        let child_context = IoContext {
            stdin: stdin,
            stdout: stdout,
            stderr: stderr,
        };

        let result = try!(inner(child_context));

        if let Some(thread) = maybe_stdin_thread {
            try!(thread.join().unwrap());
        }

        Ok(result)
    }
}

#[derive(Clone, Debug)]
pub enum InputArg<'a> {
    Inherit,
    Null,
    Path(Cow<'a, Path>),
    Bytes(Cow<'a, [u8]>),
}

impl<'a> InputArg<'a> {
    fn update_handle(&self,
                     parent_handle: pipe::Handle)
                     -> io::Result<(pipe::Handle, Option<JoinHandle<io::Result<()>>>)> {
        let mut maybe_thread = None;
        let handle = match self {
            &InputArg::Inherit => parent_handle,
            &InputArg::Null => pipe::Handle::from_file(try!(File::open("/dev/null"))),  // TODO: Windows
            &InputArg::Path(ref p) => pipe::Handle::from_file(try!(File::open(&p))),
            &InputArg::Bytes(ref v) => {
                // TODO: figure out a way to get rid of this clone
                let (handle, thread) = pipe_with_writer_thread(v.clone().into_owned());
                maybe_thread = Some(thread);
                handle
            }
        };
        Ok((handle, maybe_thread))
    }
}

// TODO: stdout/stderr swaps
#[derive(  Clone, Debug)]
pub enum OutputArg<'a> {
    Inherit,
    Null,
    Path(Cow<'a, Path>),
}

impl<'a> OutputArg<'a> {
    fn update_handle(&self, parent_handle: pipe::Handle) -> io::Result<pipe::Handle> {
        let handle = match self {
            &OutputArg::Inherit => parent_handle,
            &OutputArg::Null => pipe::Handle::from_file(try!(File::create("/dev/null"))),  // TODO: Windows
            &OutputArg::Path(ref p) => pipe::Handle::from_file(try!(File::create(&p))),
        };
        Ok(handle)
    }
}

// An IoContext represents the file descriptors child processes are talking to at execution time.
// It's initialized in run(), with dups of the stdin/stdout/stderr pipes, and then passed down to
// sub-expressions. Compound expressions will clone() it, and pipes/redirections will modify it
// according to their IoArgs.
#[derive(Clone, Debug)]
pub struct IoContext {
    stdin: pipe::Handle,
    stdout: pipe::Handle,
    stderr: pipe::Handle,
}

impl IoContext {
    fn new() -> IoContext {
        IoContext {
            stdin: pipe::Handle::stdin(),
            stdout: pipe::Handle::stdout(),
            stderr: pipe::Handle::stderr(),
        }
    }
}

fn pipe_with_reader_thread() -> (pipe::Handle, JoinHandle<io::Result<Vec<u8>>>) {
    let (read_pipe, write_pipe) = pipe::open_pipe();
    let thread = std::thread::spawn(move || {
        let mut read_file = read_pipe.to_file();
        let mut output = Vec::new();
        try!(read_file.read_to_end(&mut output));
        Ok(output)
    });
    (write_pipe, thread)
}

fn pipe_with_writer_thread(input: Vec<u8>) -> (pipe::Handle, JoinHandle<io::Result<()>>) {
    let (read_pipe, write_pipe) = pipe::open_pipe();
    let thread = std::thread::spawn(move || {
        let mut write_file = write_pipe.to_file();
        try!(write_file.write_all(&input));
        Ok(())
    });
    (read_pipe, thread)
}

#[cfg(test)]
mod test {
    use super::{cmd, sh, pipe, then, InputArg, OutputArg};
    use std::borrow::Cow;
    use std::fs::File;
    use std::io::prelude::*;

    #[test]
    fn test_cmd() {
        let output = cmd(&["echo", "hi"]).read().unwrap();
        assert_eq!("hi", output);
    }

    #[test]
    fn test_sh() {
        let output = sh("echo hi").read().unwrap();
        assert_eq!("hi", output);
    }

    #[test]
    fn test_pipe() {
        let output = pipe(sh("echo hi"), sh("sed s/i/o/")).read().unwrap();
        assert_eq!("ho", output);
    }

    #[test]
    fn test_then() {
        let output = then(sh("echo -n hi"), sh("echo lo")).read().unwrap();
        assert_eq!("hilo", output);
    }

    #[test]
    fn test_input() {
        let mut expr = sh("sed s/f/g/");
        expr.stdin(InputArg::Bytes(Cow::Borrowed(b"foo")));
        let output = expr.read().unwrap();
        assert_eq!("goo", output);
    }

    #[test]
    fn test_null() {
        let mut expr = cmd(&["cat"]);
        expr.stdin(InputArg::Null);
        expr.stdout(OutputArg::Null);
        let output = expr.read().unwrap();
        assert_eq!("", output);
    }

    #[test]
    fn test_path() {
        let input_path = sh("mktemp").read().unwrap();
        let output_path = sh("mktemp").read().unwrap();
        println!("Here are the paths: {:?} {:?}", &input_path, &output_path);
        File::create(&input_path).unwrap().write_all(b"foo").unwrap();
        let mut expr = sh("sed s/o/a/g");
        expr.stdin(InputArg::Path(Cow::Borrowed(input_path.as_ref())));
        expr.stdout(OutputArg::Path(Cow::Borrowed(output_path.as_ref())));
        let output = expr.read().unwrap();
        assert_eq!("", output);
        let mut file_output = String::new();
        File::open(&output_path).unwrap().read_to_string(&mut file_output).unwrap();
        assert_eq!("faa", file_output);
    }
}
<commit_msg>get rid of some pubs we don't need anymore<commit_after>extern crate crossbeam;

use std::borrow::Cow;
use std::ffi::{OsStr, OsString};
use std::fs::File;
use std::io;
use std::io::prelude::*;
use std::path::Path;
use std::process::{Command, Output, ExitStatus};
use std::thread::JoinHandle;

mod pipe;

pub fn cmd<T: AsRef<OsStr>>(argv: &[T]) -> Expression<'static> {
    let argv_vec = argv.iter().map(|arg| arg.as_ref().to_owned()).collect();
    Expression {
        inner: ExpressionInner::ArgvCommand(argv_vec),
        ioargs: IoArgs::new(),
    }
}

pub fn sh<T: AsRef<OsStr>>(command: T) -> Expression<'static> {
    Expression {
        inner: ExpressionInner::ShCommand(command.as_ref().to_owned()),
        ioargs: IoArgs::new(),
    }
}

pub fn pipe<'a>(left: Expression<'a>, right: Expression<'a>) -> Expression<'a> {
    Expression {
        inner: ExpressionInner::Pipe(Box::new(left), Box::new(right)),
        ioargs: IoArgs::new(),
    }
}

pub fn then<'a>(left: Expression<'a>, right: Expression<'a>) -> Expression<'a> {
    Expression {
        inner: ExpressionInner::Then(Box::new(left), Box::new(right)),
        ioargs: IoArgs::new(),
    }
}

#[derive(Clone, Debug)]
pub struct Expression<'a> {
    inner: ExpressionInner<'a>,
    ioargs: IoArgs<'a>,
}

#[derive(Clone, Debug)]
enum ExpressionInner<'a> {
    ArgvCommand(Vec<OsString>),
    ShCommand(OsString),
    Pipe(Box<Expression<'a>>, Box<Expression<'a>>),
    Then(Box<Expression<'a>>, Box<Expression<'a>>),
}

impl<'a> Expression<'a> {
    pub fn run(&self) -> Result<Output, Error> {
        unreachable!();
    }

    pub fn read(&self) -> Result<String, Error> {
        let (handle, reader) = pipe_with_reader_thread();
        let mut context = IoContext::new();
        context.stdout = handle;
        let status = try!(self.exec(context));
        let stdout_vec = try!(reader.join().unwrap());
        if !status.success() {
            return Err(Error::Status(Output {
                status: status,
                stdout: stdout_vec,
                stderr: Vec::new(),
            }));
        }
        let stdout_string = try!(std::str::from_utf8(&stdout_vec))
                                .trim_right_matches('\n')
                                .to_owned();
        Ok(stdout_string)
    }

    fn exec(&self, parent_context: IoContext) -> io::Result<ExitStatus> {
        self.ioargs.with_child_context(parent_context, |context| {
            match self.inner {
                ExpressionInner::ArgvCommand(ref argv) => exec_argv(argv, context),
                ExpressionInner::ShCommand(ref command) => exec_sh(command, context),
                ExpressionInner::Pipe(ref left, ref right) => exec_pipe(left, right, context),
                ExpressionInner::Then(ref left, ref right) => exec_then(left, right, context),
            }
        })
    }

    pub fn stdin(&mut self, arg: InputArg<'a>) -> &mut Self {
        self.ioargs.stdin = arg;
        self
    }

    pub fn stdout(&mut self, arg: OutputArg<'a>) -> &mut Self {
        self.ioargs.stdout = arg;
        self
    }

    pub fn stderr(&mut self, arg: OutputArg<'a>) -> &mut Self {
        self.ioargs.stderr = arg;
        self
    }
}

fn exec_argv(argv: &Vec<OsString>, context: IoContext) -> io::Result<ExitStatus> {
    let mut command = Command::new(&argv[0]);
    command.args(&argv[1..]);
    command.stdin(context.stdin.to_stdio());
    command.stdout(context.stdout.to_stdio());
    command.stderr(context.stderr.to_stdio());
    command.status()
}

fn exec_sh(command: &OsStr, context: IoContext) -> io::Result<ExitStatus> {
    // TODO: What shell should we be using here, really?
    // TODO: Figure out how cmd.exe works on Windows.
    let mut argv = Vec::new();
    argv.push("bash".into());
    argv.push("-c".into());
    argv.push(command.to_owned());
    exec_argv(&argv, context)
}

fn exec_pipe(left: &Expression, right: &Expression, context: IoContext) -> io::Result<ExitStatus> {
    let (read_pipe, write_pipe) = pipe::open_pipe();
    let left_context = IoContext {
        stdin: context.stdin,
        stdout: write_pipe,
        stderr: context.stderr.clone(),
    };
    let right_context = IoContext {
        stdin: read_pipe,
        stdout: context.stdout,
        stderr: context.stderr,
    };

    let (left_result, right_result) = crossbeam::scope(|scope| {
        let left_joiner = scope.spawn(|| left.exec(left_context));
        let right_result = right.exec(right_context);
        let left_result = left_joiner.join();
        (left_result, right_result)
    });

    let right_status = try!(right_result);
    let left_status = try!(left_result);
    if !right_status.success() {
        Ok(right_status)
    } else {
        Ok(left_status)
    }
}

fn exec_then(left: &Expression, right: &Expression, context: IoContext) -> io::Result<ExitStatus> {
    let status = try!(left.exec(context.clone()));
    if !status.success() {
        Ok(status)
    } else {
        right.exec(context)
    }
}

#[derive(Debug)]
pub enum Error {
    Io(io::Error),
    Utf8(std::str::Utf8Error),
    Status(Output),
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

impl From<std::str::Utf8Error> for Error {
    fn from(err: std::str::Utf8Error) -> Error {
        Error::Utf8(err)
    }
}

// IoArgs store the redirections and other settings associated with an expression. At execution
// time, IoArgs are used to modify an IoContext, which contains the actual pipes that child process
#[derive(Clone, Debug)]
struct IoArgs<'a> {
    stdin: InputArg<'a>,
    stdout: OutputArg<'a>,
    stderr: OutputArg<'a>,
}

impl<'a> IoArgs<'a> {
    fn new() -> IoArgs<'static> {
        IoArgs {
            stdin: InputArg::Inherit,
            stdout: OutputArg::Inherit,
            stderr: OutputArg::Inherit,
        }
    }

    fn with_child_context<F, T>(&self, parent_context: IoContext, inner: F) -> io::Result<T>
        where F: FnOnce(IoContext) -> io::Result<T>
    {
        let (stdin, maybe_stdin_thread) = try!(self.stdin.update_handle(parent_context.stdin));
        let stdout = try!(self.stdout.update_handle(parent_context.stdout));
        let stderr = try!(self.stderr.update_handle(parent_context.stderr));
        let child_context = IoContext {
            stdin: stdin,
            stdout: stdout,
            stderr: stderr,
        };

        let result = try!(inner(child_context));

        if let Some(thread) = maybe_stdin_thread {
            try!(thread.join().unwrap());
        }

        Ok(result)
    }
}

#[derive(Clone, Debug)]
pub enum InputArg<'a> {
    Inherit,
    Null,
    Path(Cow<'a, Path>),
    Bytes(Cow<'a, [u8]>),
}

impl<'a> InputArg<'a> {
    fn update_handle(&self,
                     parent_handle: pipe::Handle)
                     -> io::Result<(pipe::Handle, Option<JoinHandle<io::Result<()>>>)> {
        let mut maybe_thread = None;
        let handle = match self {
            &InputArg::Inherit => parent_handle,
            &InputArg::Null => pipe::Handle::from_file(try!(File::open("/dev/null"))),  // TODO: Windows
            &InputArg::Path(ref p) => pipe::Handle::from_file(try!(File::open(&p))),
            &InputArg::Bytes(ref v) => {
                // TODO: figure out a way to get rid of this clone
                let (handle, thread) = pipe_with_writer_thread(v.clone().into_owned());
                maybe_thread = Some(thread);
                handle
            }
        };
        Ok((handle, maybe_thread))
    }
}

// TODO: stdout/stderr swaps
#[derive(  Clone, Debug)]
pub enum OutputArg<'a> {
    Inherit,
    Null,
    Path(Cow<'a, Path>),
}

impl<'a> OutputArg<'a> {
    fn update_handle(&self, parent_handle: pipe::Handle) -> io::Result<pipe::Handle> {
        let handle = match self {
            &OutputArg::Inherit => parent_handle,
            &OutputArg::Null => pipe::Handle::from_file(try!(File::create("/dev/null"))),  // TODO: Windows
            &OutputArg::Path(ref p) => pipe::Handle::from_file(try!(File::create(&p))),
        };
        Ok(handle)
    }
}

// An IoContext represents the file descriptors child processes are talking to at execution time.
// It's initialized in run(), with dups of the stdin/stdout/stderr pipes, and then passed down to
// sub-expressions. Compound expressions will clone() it, and pipes/redirections will modify it
// according to their IoArgs.
#[derive(Clone, Debug)]
pub struct IoContext {
    stdin: pipe::Handle,
    stdout: pipe::Handle,
    stderr: pipe::Handle,
}

impl IoContext {
    fn new() -> IoContext {
        IoContext {
            stdin: pipe::Handle::stdin(),
            stdout: pipe::Handle::stdout(),
            stderr: pipe::Handle::stderr(),
        }
    }
}

fn pipe_with_reader_thread() -> (pipe::Handle, JoinHandle<io::Result<Vec<u8>>>) {
    let (read_pipe, write_pipe) = pipe::open_pipe();
    let thread = std::thread::spawn(move || {
        let mut read_file = read_pipe.to_file();
        let mut output = Vec::new();
        try!(read_file.read_to_end(&mut output));
        Ok(output)
    });
    (write_pipe, thread)
}

fn pipe_with_writer_thread(input: Vec<u8>) -> (pipe::Handle, JoinHandle<io::Result<()>>) {
    let (read_pipe, write_pipe) = pipe::open_pipe();
    let thread = std::thread::spawn(move || {
        let mut write_file = write_pipe.to_file();
        try!(write_file.write_all(&input));
        Ok(())
    });
    (read_pipe, thread)
}

#[cfg(test)]
mod test {
    use super::{cmd, sh, pipe, then, InputArg, OutputArg};
    use std::borrow::Cow;
    use std::fs::File;
    use std::io::prelude::*;

    #[test]
    fn test_cmd() {
        let output = cmd(&["echo", "hi"]).read().unwrap();
        assert_eq!("hi", output);
    }

    #[test]
    fn test_sh() {
        let output = sh("echo hi").read().unwrap();
        assert_eq!("hi", output);
    }

    #[test]
    fn test_pipe() {
        let output = pipe(sh("echo hi"), sh("sed s/i/o/")).read().unwrap();
        assert_eq!("ho", output);
    }

    #[test]
    fn test_then() {
        let output = then(sh("echo -n hi"), sh("echo lo")).read().unwrap();
        assert_eq!("hilo", output);
    }

    #[test]
    fn test_input() {
        let mut expr = sh("sed s/f/g/");
        expr.stdin(InputArg::Bytes(Cow::Borrowed(b"foo")));
        let output = expr.read().unwrap();
        assert_eq!("goo", output);
    }

    #[test]
    fn test_null() {
        let mut expr = cmd(&["cat"]);
        expr.stdin(InputArg::Null);
        expr.stdout(OutputArg::Null);
        let output = expr.read().unwrap();
        assert_eq!("", output);
    }

    #[test]
    fn test_path() {
        let input_path = sh("mktemp").read().unwrap();
        let output_path = sh("mktemp").read().unwrap();
        println!("Here are the paths: {:?} {:?}", &input_path, &output_path);
        File::create(&input_path).unwrap().write_all(b"foo").unwrap();
        let mut expr = sh("sed s/o/a/g");
        expr.stdin(InputArg::Path(Cow::Borrowed(input_path.as_ref())));
        expr.stdout(OutputArg::Path(Cow::Borrowed(output_path.as_ref())));
        let output = expr.read().unwrap();
        assert_eq!("", output);
        let mut file_output = String::new();
        File::open(&output_path).unwrap().read_to_string(&mut file_output).unwrap();
        assert_eq!("faa", file_output);
    }
}
<|endoftext|>


<commit_before>//! FFI wrappers for the Linux Pluggable Authentication Modules (PAM)
//!
//! This crate provides raw access to the Linux-PAM API.
//! Constants, types and functions are supported and created with `bindgen`.
//!
//! Note: Currently only tested on linux as I lack access to other OSes at
//! the moment. Both `build.rs` and `wrapper.h` probably need to be customized
//! to exclude missing libraries such as `pam_misc` when they are not present.

#![allow(non_upper_case_globals, non_camel_case_types, non_snake_case)]

include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
<commit_msg>lib: disable deref_nullptr warnings<commit_after>//! FFI wrappers for the Linux Pluggable Authentication Modules (PAM)
//!
//! This crate provides raw access to the Linux-PAM API.
//! Constants, types and functions are supported and created with `bindgen`.
//!
//! Note: Currently only tested on linux as I lack access to other OSes at
//! the moment. Both `build.rs` and `wrapper.h` probably need to be customized
//! to exclude missing libraries such as `pam_misc` when they are not present.

#![allow(
    non_upper_case_globals,
    non_camel_case_types,
    non_snake_case,
    deref_nullptr
)]

include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
<|endoftext|>


<commit_before>extern crate futures;

use futures::{Async, Poll, Future, Stream};

pub type BoxStateStream<T, S, E> = Box<StateStream<Item = T, State = S, Error = E> + Send>;

pub enum StreamEvent<I, S> {
    Next(I),
    Done(S),
}

pub trait StateStream {
    type Item;
    type State;
    type Error;

    fn poll(&mut self) -> Poll<StreamEvent<Self::Item, Self::State>, Self::Error>;

    #[inline]
    fn boxed(self) -> BoxStateStream<Self::Item, Self::State, Self::Error>
        where Self: Sized + Send + 'static
    {
        Box::new(self)
    }

    #[inline]
    fn into_future(self) -> IntoFuture<Self>
        where Self: Sized
    {
        IntoFuture(Some(self))
    }

    #[inline]
    fn into_stream(self) -> IntoStream<Self>
        where Self: Sized
    {
        IntoStream(self)
    }
}

impl<S: ?Sized> StateStream for Box<S>
    where S: StateStream
{
    type Item = S::Item;
    type State = S::State;
    type Error = S::Error;

    #[inline]
    fn poll(&mut self) -> Poll<StreamEvent<S::Item, S::State>, S::Error> {
        S::poll(self)
    }
}

pub fn stream<S>(stream: S) -> FromStream<S>
    where S: Stream
{
    FromStream(stream)
}

pub struct FromStream<S>(S);

impl<S> StateStream for FromStream<S>
    where S: Stream
{
    type Item = S::Item;
    type State = ();
    type Error = S::Error;

    #[inline]
    fn poll(&mut self) -> Poll<StreamEvent<S::Item, ()>, S::Error> {
        self.0.poll().map(|a| {
            match a {
                Async::Ready(Some(i)) => Async::Ready(StreamEvent::Next(i)),
                Async::Ready(None) => Async::Ready(StreamEvent::Done(())),
                Async::NotReady => Async::NotReady,
            }
        })
    }
}

pub struct IntoFuture<S>(Option<S>);

impl<S> Future for IntoFuture<S>
    where S: StateStream
{
    type Item = (StreamEvent<S::Item, S::State>, S);
    type Error = (S::Error, S);

    #[inline]
    fn poll(&mut self) -> Poll<(StreamEvent<S::Item, S::State>, S), (S::Error, S)> {
        let item = match self.0.as_mut().expect("polling IntoFuture twice").poll() {
            Ok(Async::NotReady) => return Ok(Async::NotReady),
            Ok(Async::Ready(i)) => Ok(i),
            Err(e) => Err(e),
        };
        let stream = self.0.take().unwrap();
        match item {
            Ok(i) => Ok(Async::Ready((i, stream))),
            Err(e) => Err((e, stream)),
        }
    }
}

pub struct IntoStream<S>(S);

impl<S> Stream for IntoStream<S>
    where S: StateStream
{
    type Item = S::Item;
    type Error = S::Error;

    #[inline]
    fn poll(&mut self) -> Poll<Option<S::Item>, S::Error> {
        self.0.poll().map(|a| {
            match a {
                Async::Ready(StreamEvent::Next(i)) => Async::Ready(Some(i)),
                Async::Ready(StreamEvent::Done(_)) => Async::Ready(None),
                Async::NotReady => Async::NotReady,
            }
        })
    }
}<commit_msg>Add map<commit_after>extern crate futures;

use futures::{Async, Poll, Future, Stream};

pub type BoxStateStream<T, S, E> = Box<StateStream<Item = T, State = S, Error = E> + Send>;

pub enum StreamEvent<I, S> {
    Next(I),
    Done(S),
}

pub trait StateStream {
    type Item;
    type State;
    type Error;

    fn poll(&mut self) -> Poll<StreamEvent<Self::Item, Self::State>, Self::Error>;

    #[inline]
    fn boxed(self) -> BoxStateStream<Self::Item, Self::State, Self::Error>
        where Self: Sized + Send + 'static
    {
        Box::new(self)
    }

    #[inline]
    fn into_future(self) -> IntoFuture<Self>
        where Self: Sized
    {
        IntoFuture(Some(self))
    }

    #[inline]
    fn into_stream(self) -> IntoStream<Self>
        where Self: Sized
    {
        IntoStream(self)
    }

    #[inline]
    fn map<F, B>(self, f: F) -> Map<Self, F>
        where Self: Sized,
              F: FnMut(Self::Item) -> B
    {
        Map {
            stream: self,
            f: f,
        }
    }
}

impl<S: ?Sized> StateStream for Box<S>
    where S: StateStream
{
    type Item = S::Item;
    type State = S::State;
    type Error = S::Error;

    #[inline]
    fn poll(&mut self) -> Poll<StreamEvent<S::Item, S::State>, S::Error> {
        S::poll(self)
    }
}

pub fn stream<S>(stream: S) -> FromStream<S>
    where S: Stream
{
    FromStream(stream)
}

pub struct FromStream<S>(S);

impl<S> StateStream for FromStream<S>
    where S: Stream
{
    type Item = S::Item;
    type State = ();
    type Error = S::Error;

    #[inline]
    fn poll(&mut self) -> Poll<StreamEvent<S::Item, ()>, S::Error> {
        self.0.poll().map(|a| {
            match a {
                Async::Ready(Some(i)) => Async::Ready(StreamEvent::Next(i)),
                Async::Ready(None) => Async::Ready(StreamEvent::Done(())),
                Async::NotReady => Async::NotReady,
            }
        })
    }
}

pub struct IntoFuture<S>(Option<S>);

impl<S> Future for IntoFuture<S>
    where S: StateStream
{
    type Item = (StreamEvent<S::Item, S::State>, S);
    type Error = (S::Error, S);

    #[inline]
    fn poll(&mut self) -> Poll<(StreamEvent<S::Item, S::State>, S), (S::Error, S)> {
        let item = match self.0.as_mut().expect("polling IntoFuture twice").poll() {
            Ok(Async::NotReady) => return Ok(Async::NotReady),
            Ok(Async::Ready(i)) => Ok(i),
            Err(e) => Err(e),
        };
        let stream = self.0.take().unwrap();
        match item {
            Ok(i) => Ok(Async::Ready((i, stream))),
            Err(e) => Err((e, stream)),
        }
    }
}

pub struct IntoStream<S>(S);

impl<S> Stream for IntoStream<S>
    where S: StateStream
{
    type Item = S::Item;
    type Error = S::Error;

    #[inline]
    fn poll(&mut self) -> Poll<Option<S::Item>, S::Error> {
        self.0.poll().map(|a| {
            match a {
                Async::Ready(StreamEvent::Next(i)) => Async::Ready(Some(i)),
                Async::Ready(StreamEvent::Done(_)) => Async::Ready(None),
                Async::NotReady => Async::NotReady,
            }
        })
    }
}

pub struct Map<S, F> {
    stream: S,
    f: F,
}

impl<S, F, B> StateStream for Map<S, F>
    where S: StateStream,
          F: FnMut(S::Item) -> B
{
    type Item = B;
    type State = S::State;
    type Error = S::Error;

    #[inline]
    fn poll(&mut self) -> Poll<StreamEvent<B, S::State>, S::Error> {
        self.stream.poll().map(|a| {
            match a {
                Async::Ready(StreamEvent::Next(i)) => Async::Ready(StreamEvent::Next((self.f)(i))),
                Async::Ready(StreamEvent::Done(s)) => Async::Ready(StreamEvent::Done(s)),
                Async::NotReady => Async::NotReady,
            }
        })
    }
}
<|endoftext|>


<commit_before>//#![feature(test,associated_consts)]
#![cfg_attr(test, feature(test))]
#![cfg_attr(test, feature(step_by))]
#![doc(test(attr(allow(unused_variables), deny(warnings))))]

#[macro_use]
extern crate lazy_static;

#[macro_use]
extern crate fst;
extern crate byteorder;
extern crate memmap;
extern crate regex;
extern crate tempfile;
extern crate rustc_serialize;
extern crate combine;
extern crate atomicwrites;
extern crate tempdir;
extern crate bincode;
extern crate time;
extern crate serde;
extern crate libc;
extern crate lz4;
extern crate uuid;
extern crate num_cpus;

#[cfg(test)] extern crate test;
#[cfg(test)] extern crate rand;

mod core;

pub use core::index::Index;
pub use core::schema;
pub use core::schema::Term;
pub use core::schema::Document;
pub use core::collector;
pub use core::schema::DocId;
pub use core::reader::SegmentReader;
pub use core::searcher::SegmentLocalId;

#[cfg(test)]
mod tests {

    use super::*;
    use collector::Collector;

    // only make sense for a single segment
    struct TestCollector {
        docs: Vec<DocId>,
    }

    impl TestCollector {
        pub fn new() -> TestCollector {
            TestCollector {
                docs: Vec::new(),
            }
        }

        pub fn docs(self,) -> Vec<DocId> {
            self.docs
        }
    }

    impl Collector for TestCollector {

        fn set_segment(&mut self, _: SegmentLocalId, _: &SegmentReader) {}

        fn collect(&mut self, doc_id: DocId) {
            self.docs.push(doc_id);
        }
    }

    #[test]
    fn test_indexing() {
        let mut schema = schema::Schema::new();
        let text_fieldtype = schema::TextOptions::new().set_tokenized_indexed();
        let text_field = schema.add_text_field("text", &text_fieldtype);

        let index = Index::create_from_tempdir(schema).unwrap();

        {
            // writing the segment
            let mut index_writer = index.writer().unwrap();
            {
                let mut doc = Document::new();
                doc.set(&text_field, "af b");
                index_writer.add_document(doc).unwrap();
            }
            {
                let mut doc = Document::new();
                doc.set(&text_field, "a b c");
                index_writer.add_document(doc).unwrap();
            }
            {
                let mut doc = Document::new();
                doc.set(&text_field, "a b c d");
                index_writer.add_document(doc).unwrap();
            }

            let commit_result = index_writer.commit();
            assert!(commit_result.is_ok());
            // TODO reenable this test
            // let segment = commit_result.unwrap();
            // let segment_reader = SegmentReader::open(segment).unwrap();
            // assert_eq!(segment_reader.max_doc(), 3);
        }

    }

    #[test]
    fn test_searcher() {
        let mut schema = schema::Schema::new();
        let text_fieldtype = schema::TextOptions::new().set_tokenized_indexed();
        let text_field = schema.add_text_field("text", &text_fieldtype);
        let index = Index::create_from_tempdir(schema).unwrap();

        {
            // writing the segment
            let mut index_writer = index.writer().unwrap();
            {
                let mut doc = Document::new();
                doc.set(&text_field, "af b");
                index_writer.add_document(doc).unwrap();
            }
            {
                let mut doc = Document::new();
                doc.set(&text_field, "a b c");
                index_writer.add_document(doc).unwrap();
            }
            {
                let mut doc = Document::new();
                doc.set(&text_field, "a b c d");
                index_writer.add_document(doc).unwrap();
            }
            //let commit_result = index_writer.commit();
            index_writer.wait();
            //commit_result.unwrap();
        }
        {
            let searcher = index.searcher().unwrap();
            let get_doc_ids = |terms: Vec<Term>| {
                let mut collector = TestCollector::new();
                searcher.search(&terms, &mut collector);
                collector.docs()
            };
            {
                assert_eq!(
                    get_doc_ids(vec!(Term::from_field_text(&text_field, "a"))),
                    vec!(1, 2));
            }
            {
                assert_eq!(
                    get_doc_ids(vec!(Term::from_field_text(&text_field, "af"))),
                    vec!(0));
            }
            {
                assert_eq!(
                    get_doc_ids(vec!(Term::from_field_text(&text_field, "b"))),
                    vec!(0, 1, 2));
            }
            {
                assert_eq!(
                    get_doc_ids(vec!(Term::from_field_text(&text_field, "c"))),
                    vec!(1, 2));
            }
            {
                assert_eq!(
                    get_doc_ids(vec!(Term::from_field_text(&text_field, "d"))),
                    vec!(2));
            }
            {
                assert_eq!(
                    get_doc_ids(vec!(Term::from_field_text(&text_field, "b"), Term::from_field_text(&text_field, "a"), )),
                    vec!(1, 2));
            }
        }
    }
}
<commit_msg>Fixed test<commit_after>//#![feature(test,associated_consts)]
#![cfg_attr(test, feature(test))]
#![cfg_attr(test, feature(step_by))]
#![doc(test(attr(allow(unused_variables), deny(warnings))))]

#[macro_use]
extern crate lazy_static;

#[macro_use]
extern crate fst;
extern crate byteorder;
extern crate memmap;
extern crate regex;
extern crate tempfile;
extern crate rustc_serialize;
extern crate combine;
extern crate atomicwrites;
extern crate tempdir;
extern crate bincode;
extern crate time;
extern crate serde;
extern crate libc;
extern crate lz4;
extern crate uuid;
extern crate num_cpus;

#[cfg(test)] extern crate test;
#[cfg(test)] extern crate rand;

mod core;

pub use core::index::Index;
pub use core::schema;
pub use core::schema::Term;
pub use core::schema::Document;
pub use core::collector;
pub use core::schema::DocId;
pub use core::reader::SegmentReader;
pub use core::searcher::SegmentLocalId;

#[cfg(test)]
mod tests {

    use super::*;
    use collector::Collector;

    // only make sense for a single segment
    struct TestCollector {
        docs: Vec<DocId>,
    }

    impl TestCollector {
        pub fn new() -> TestCollector {
            TestCollector {
                docs: Vec::new(),
            }
        }

        pub fn docs(self,) -> Vec<DocId> {
            self.docs
        }
    }

    impl Collector for TestCollector {

        fn set_segment(&mut self, _: SegmentLocalId, _: &SegmentReader) {}

        fn collect(&mut self, doc_id: DocId) {
            self.docs.push(doc_id);
        }
    }

    #[test]
    fn test_indexing() {
        let mut schema = schema::Schema::new();
        let text_fieldtype = schema::TextOptions::new().set_tokenized_indexed();
        let text_field = schema.add_text_field("text", &text_fieldtype);

        let index = Index::create_from_tempdir(schema).unwrap();

        {
            // writing the segment
            let mut index_writer = index.writer_with_num_threads(1).unwrap();
            {
                let mut doc = Document::new();
                doc.set(&text_field, "af b");
                index_writer.add_document(doc).unwrap();
            }
            {
                let mut doc = Document::new();
                doc.set(&text_field, "a b c");
                index_writer.add_document(doc).unwrap();
            }
            {
                let mut doc = Document::new();
                doc.set(&text_field, "a b c d");
                index_writer.add_document(doc).unwrap();
            }

            let commit_result = index_writer.commit();
            assert!(commit_result.is_ok());
            // TODO reenable this test
            // let segment = commit_result.unwrap();
            // let segment_reader = SegmentReader::open(segment).unwrap();
            // assert_eq!(segment_reader.max_doc(), 3);
        }

    }

    #[test]
    fn test_searcher() {
        let mut schema = schema::Schema::new();
        let text_fieldtype = schema::TextOptions::new().set_tokenized_indexed();
        let text_field = schema.add_text_field("text", &text_fieldtype);
        let index = Index::create_from_tempdir(schema).unwrap();

        {
            // writing the segment
            let mut index_writer = index.writer_with_num_threads(1).unwrap();
            {
                let mut doc = Document::new();
                doc.set(&text_field, "af b");
                index_writer.add_document(doc).unwrap();
            }
            {
                let mut doc = Document::new();
                doc.set(&text_field, "a b c");
                index_writer.add_document(doc).unwrap();
            }
            {
                let mut doc = Document::new();
                doc.set(&text_field, "a b c d");
                index_writer.add_document(doc).unwrap();
            }
            //let commit_result = index_writer.commit();
            index_writer.wait();
            //commit_result.unwrap();
        }
        {
            let searcher = index.searcher().unwrap();
            let get_doc_ids = |terms: Vec<Term>| {
                let mut collector = TestCollector::new();
                searcher.search(&terms, &mut collector);
                collector.docs()
            };
            {
                assert_eq!(
                    get_doc_ids(vec!(Term::from_field_text(&text_field, "a"))),
                    vec!(1, 2));
            }
            {
                assert_eq!(
                    get_doc_ids(vec!(Term::from_field_text(&text_field, "af"))),
                    vec!(0));
            }
            {
                assert_eq!(
                    get_doc_ids(vec!(Term::from_field_text(&text_field, "b"))),
                    vec!(0, 1, 2));
            }
            {
                assert_eq!(
                    get_doc_ids(vec!(Term::from_field_text(&text_field, "c"))),
                    vec!(1, 2));
            }
            {
                assert_eq!(
                    get_doc_ids(vec!(Term::from_field_text(&text_field, "d"))),
                    vec!(2));
            }
            {
                assert_eq!(
                    get_doc_ids(vec!(Term::from_field_text(&text_field, "b"), Term::from_field_text(&text_field, "a"), )),
                    vec!(1, 2));
            }
        }
    }
}
<|endoftext|>


<commit_before>//! # Leaky Bucket Rate-Limiting (as a meter) in Rust
//! This crate implements
//! the
//! [generic cell rate algorithm](https://en.wikipedia.org/wiki/Generic_cell_rate_algorithm) (GCRA)
//! for rate-limiting and scheduling in Rust.
//!
//! ## Interface
//!
//! You construct a rate limiter using the `Limiter` builder:
//!
//! ``` rust
//! use std::time::Duration;
//! use ratelimit_meter::{Decider, GCRA, Decision};
//!
//! let mut lim = GCRA::for_capacity(50) // Allow 50 units of work
//!     .per(Duration::from_secs(1)) // We calculate per-second (this is the default).
//!     .cell_weight(1) // Each cell is one unit of work "heavy".
//!     .build(); // Construct a non-threadsafe GCRA decider.
//! assert_eq!(Decision::Yes, lim.check().unwrap());
//! ```
//!
//! The rate-limiter interface is intentionally geared towards only
//! providing callers with the information they need to make decisions
//! about what to do with each cell. Whenever possible, additional
//! information about why a cell should be denied - the `GCRA`
//! implementation will return a `time::Instant` alongside the decision to
//! allow callers to e.g. provide better error messages to users.
//!
//! Due to this, the `ratelimit_meter` crate does not provide any facility
//! to wait until a cell would be allowed - if you require this, you
//! should use the `Instant` returned with negative decisions and wait
//! in your own, e.g. event loop.
//!
//! ## Design and implementation
//!
//! Unlike some other token bucket algorithms, the GCRA one assumes that
//! all units of work are of the same "weight", and so allows some
//! optimizations which result in much more consise and fast code (it does
//! not even use multiplication or division in the "hot" path).
//!
//! The trade-off here this is that there is currently no support for
//! assigning different weights to incoming cells (say, particularly
//! heavy api calls vs. lightweight ones) using the same rate-limiter
//! structure.
//!
//! ## Thread-safe operation
//!
//! The default GCRA implementation can not be used across
//! threads. However, there is a wrapper struct `Threadsafe`, that wraps
//! the hot path in an atomically reference-counted mutex. It still
//! manages to be pretty fast (see the benchmarks above), but the lock
//! comes with an overhead even in single-threaded operation.
//!
//! Example:
//!
//! ```
//! use std::time::Duration;
//! use ratelimit_meter::{Decider, GCRA, Decision};
//!
//! let mut lim = GCRA::for_capacity(50) // Allow 50 units of work
//!     .per(Duration::from_secs(1)) // We calculate per-second (this is the default).
//!     .cell_weight(1) // Each cell is one unit of work "heavy".
//!     .build_sync(); // Construct a threadsafe GCRA decider.
//! assert_eq!(Decision::Yes, lim.check().unwrap());
//! ```

pub mod example_algorithms;
pub mod errors;
mod algorithms;

#[macro_use]
extern crate error_chain;

use std::time::{Instant};

pub use errors::*;
pub use self::algorithms::*;

#[derive(PartialEq, Debug)]
/// A decision on a single cell from the metered rate-limiter.
pub enum Decision<T> {
    /// The cell is conforming, allow it through.
    Yes,

    /// The cell is non-conforming. A rate-limiting algorithm
    /// implementation may return additional information for the
    /// caller, e.g. a time when the cell was expected to arrive.
    No(T),
}

impl<T> Decision<T> {
    /// Check if a decision on a cell indicates the cell is compliant
    /// or not. Returns `true` iff the cell was compliant, i.e. the
    /// decision was `Decision::Yes`.
    ///
    /// Note: This method is mostly useful in tests.
    pub fn is_compliant(&self) -> bool {
        match self {
            &Decision::Yes => true,
            &Decision::No(_) => false,
        }
    }
}

/// The trait that implementations of the metered rate-limiter
/// interface have to implement. Users of this library should rely on
/// [Decider](trait.Decider.html) for the external interface.
pub trait DeciderImpl {
    /// The (optional) type for additional information on negative
    /// decisions.
    type T;

    /// Tests if a single cell can be accomodated in the rate limiter
    /// at the instant `at` and updates the rate-limiter to account
    /// for the weight of the cell.
    ///
    /// This method is not meant to be called by users,
    fn test_and_update(&mut self, at: Instant) -> Result<Decision<Self::T>>;
}

/// The external interface offered by all rate-limiting implementations.
pub trait Decider: DeciderImpl {
    /// Tests if a single cell can be accomodated at
    /// `Instant::now()`. See [`check_at`](#method.check_at).
    fn check(&mut self) -> Result<Decision<Self::T>> {
        self.test_and_update(Instant::now())
    }

    /// Tests is a single cell can be accomodated at the given time
    /// stamp.
    fn check_at(&mut self, at: Instant) -> Result<Decision<Self::T>> {
        self.test_and_update(at)
    }
}
<commit_msg>Update docs for dangling `Limiter` reference.<commit_after>//! # Leaky Bucket Rate-Limiting (as a meter) in Rust
//! This crate implements
//! the
//! [generic cell rate algorithm](https://en.wikipedia.org/wiki/Generic_cell_rate_algorithm) (GCRA)
//! for rate-limiting and scheduling in Rust.
//!
//! ## Interface
//!
//! There is currently one rate limiter implementation in this crate,
//! the Generic Cell Rate Algorithm. Use it by creating a builder from
//! the [`GCRA`](struct.GCRA.html) struct:
//!
//! ``` rust
//! use std::time::Duration;
//! use ratelimit_meter::{Decider, GCRA, Decision};
//!
//! let mut lim = GCRA::for_capacity(50) // Allow 50 units of work
//!     .per(Duration::from_secs(1)) // We calculate per-second (this is the default).
//!     .cell_weight(1) // Each cell is one unit of work "heavy".
//!     .build(); // Construct a non-threadsafe GCRA decider.
//! assert_eq!(Decision::Yes, lim.check().unwrap());
//! ```
//!
//! The rate-limiter interface is intentionally geared towards only
//! providing callers with the information they need to make decisions
//! about what to do with each cell. Whenever possible, additional
//! information about why a cell should be denied - the `GCRA`
//! implementation will return a `time::Instant` alongside the decision to
//! allow callers to e.g. provide better error messages to users.
//!
//! Due to this, the `ratelimit_meter` crate does not provide any facility
//! to wait until a cell would be allowed - if you require this, you
//! should use the `Instant` returned with negative decisions and wait
//! in your own, e.g. event loop.
//!
//! ## Design and implementation
//!
//! Unlike some other token bucket algorithms, the GCRA one assumes that
//! all units of work are of the same "weight", and so allows some
//! optimizations which result in much more consise and fast code (it does
//! not even use multiplication or division in the "hot" path).
//!
//! The trade-off here this is that there is currently no support for
//! assigning different weights to incoming cells (say, particularly
//! heavy api calls vs. lightweight ones) using the same rate-limiter
//! structure.
//!
//! ## Thread-safe operation
//!
//! The default GCRA implementation can not be used across
//! threads. However, there is a wrapper struct `Threadsafe`, that wraps
//! the hot path in an atomically reference-counted mutex. It still
//! manages to be pretty fast (see the benchmarks above), but the lock
//! comes with an overhead even in single-threaded operation.
//!
//! Example:
//!
//! ```
//! use std::time::Duration;
//! use ratelimit_meter::{Decider, GCRA, Decision};
//!
//! let mut lim = GCRA::for_capacity(50) // Allow 50 units of work
//!     .per(Duration::from_secs(1)) // We calculate per-second (this is the default).
//!     .cell_weight(1) // Each cell is one unit of work "heavy".
//!     .build_sync(); // Construct a threadsafe GCRA decider.
//! assert_eq!(Decision::Yes, lim.check().unwrap());
//! ```

pub mod example_algorithms;
pub mod errors;
mod algorithms;

#[macro_use]
extern crate error_chain;

use std::time::{Instant};

pub use errors::*;
pub use self::algorithms::*;

#[derive(PartialEq, Debug)]
/// A decision on a single cell from the metered rate-limiter.
pub enum Decision<T> {
    /// The cell is conforming, allow it through.
    Yes,

    /// The cell is non-conforming. A rate-limiting algorithm
    /// implementation may return additional information for the
    /// caller, e.g. a time when the cell was expected to arrive.
    No(T),
}

impl<T> Decision<T> {
    /// Check if a decision on a cell indicates the cell is compliant
    /// or not. Returns `true` iff the cell was compliant, i.e. the
    /// decision was `Decision::Yes`.
    ///
    /// Note: This method is mostly useful in tests.
    pub fn is_compliant(&self) -> bool {
        match self {
            &Decision::Yes => true,
            &Decision::No(_) => false,
        }
    }
}

/// The trait that implementations of the metered rate-limiter
/// interface have to implement. Users of this library should rely on
/// [Decider](trait.Decider.html) for the external interface.
pub trait DeciderImpl {
    /// The (optional) type for additional information on negative
    /// decisions.
    type T;

    /// Tests if a single cell can be accomodated in the rate limiter
    /// at the instant `at` and updates the rate-limiter to account
    /// for the weight of the cell.
    ///
    /// This method is not meant to be called by users,
    fn test_and_update(&mut self, at: Instant) -> Result<Decision<Self::T>>;
}

/// The external interface offered by all rate-limiting implementations.
pub trait Decider: DeciderImpl {
    /// Tests if a single cell can be accomodated at
    /// `Instant::now()`. See [`check_at`](#method.check_at).
    fn check(&mut self) -> Result<Decision<Self::T>> {
        self.test_and_update(Instant::now())
    }

    /// Tests is a single cell can be accomodated at the given time
    /// stamp.
    fn check_at(&mut self, at: Instant) -> Result<Decision<Self::T>> {
        self.test_and_update(at)
    }
}
<|endoftext|>


<commit_before>#![feature(custom_derive, plugin, const_fn, type_ascription)]
#![plugin(serde_macros)]
#![deny(missing_docs,
        missing_debug_implementations, missing_copy_implementations,
        trivial_casts, trivial_numeric_casts,
        unused_import_braces, unused_qualifications,
        warnings)]

//! Implementation of the build engine. This contains entry points and some misc utils for launchers.

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;

extern crate bincode;
extern crate byteorder;
extern crate either;
extern crate env_logger;
extern crate hlua;
extern crate mio;
extern crate serde;
extern crate slab;

pub mod net;
pub mod script;

use std::sync::atomic::{AtomicBool, Ordering};
use std::error::Error;
use std::fmt::{Display, Error as FmtError, Formatter};
use std::io;
use std::net::SocketAddr;

use mio::tcp::TcpListener;

use net::{EventLoop, EventLoopImpl, MAX_CONNECTIONS, client};
use net::client::Client;

/// The current version of buildengine. Fallows Semantic Versioning.
pub const VERSION: &'static str = "0.0.1";

/// If the game is allowed to crash in the event of a semi-handleable error, such as a bad network packet or a peer crashing.
///
/// Programming mistakes however, will still panic.
static SHOULD_CRASH: AtomicBool = AtomicBool::new(true);    // Basically Erlang's too_big_to_fail process_flag.

/// Main game struct. Contains all state nescary to work.
///
/// While you may never need the fields exposed, they are exposed if you ever want to inspect the game state.
/// You probably, however don't want to mutate the state directly. That can mess up client-server syncronization.
#[derive(Debug)]
pub struct Engine {
    /// The clientside or serverside state.
    ///
    /// Currently a Some if it is a client, or None if server.
    pub client_or_server: Option<Client>,

    /// The networking event loop. Mostly used in other functions for sending, adding, and killing connections.
    ///
    /// Also contains all state relating to networking.
    pub event_loop: Box<EventLoop>,
}

impl Engine {
    /// Creates a new client game.
    pub fn new_client(server_address: SocketAddr) -> Result<Self, InitError> {
        let mut event_loop = try!(EventLoopImpl::new(MAX_CONNECTIONS, Vec::new()));
        let client = try!(Client::spawn_client(server_address, &mut event_loop));
        Ok(Engine {
            event_loop: Box::new(event_loop),
            client_or_server: Some(client),
        })
    }

    /// Creates a new server.
    pub fn new_server(server_address: &SocketAddr) -> Result<Self, InitError> {
        let event_loop = try!(EventLoopImpl::new(MAX_CONNECTIONS, Vec::new()));
        let listener = try!(TcpListener::bind(server_address));
        event_loop.add_listener(listener);
        Ok(Engine {
            event_loop: Box::new(event_loop),
            client_or_server: None,
        })
    }
}

/// An error hapened while initing the game.
#[derive(Debug)]
pub enum InitError {
    /// An error occoured when initalising the client code.
    ClientInitError(client::InitError),
    /// An std::io::Error. Who knows where this comes up.
    IoError(io::Error),
}

impl Display for InitError {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
        match *self {
            InitError::ClientInitError(ref err) => write!(fmt, "ClientInitError: {}", err),
            InitError::IoError(ref err) => write!(fmt, "IoError: {}", err),
        }
    }
}

impl Error for InitError {
    fn description(&self) -> &str {
        match *self {
            InitError::ClientInitError(ref err) => err.description(),
            InitError::IoError(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            InitError::ClientInitError(ref err) => Some(err),
            InitError::IoError(ref err) => Some(err),
        }
    }
}

impl From<client::InitError> for InitError {
    fn from(err: client::InitError) -> Self {
        InitError::ClientInitError(err)
    }
}

impl From<io::Error> for InitError {
    fn from(err: io::Error) -> Self {
        InitError::IoError(err)
    }
}

/// Initalizes the global parts of the engine.
///
/// Currently it only inits the logger, but later may do other things.
///
/// #Panics
/// * Calling the function once it has already been called.
pub fn global_init() {
    env_logger::init().expect("Already inited the logging server!");
}

/// Prints "Hello World!" to stdout. Will be removed in future versions.
pub fn print_hello_world() {
    println!("Hello World!");
}

fn check_should_crash() -> bool {
    SHOULD_CRASH.load(Ordering::Relaxed)
}
<commit_msg>Expose the script engine in the ::Engine struct<commit_after>#![feature(custom_derive, plugin, const_fn, type_ascription)]
#![plugin(serde_macros)]
#![deny(missing_docs,
        missing_debug_implementations, missing_copy_implementations,
        trivial_casts, trivial_numeric_casts,
        unused_import_braces, unused_qualifications,
        warnings)]

//! Implementation of the build engine. This contains entry points and some misc utils for launchers.

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;

extern crate bincode;
extern crate byteorder;
extern crate either;
extern crate env_logger;
extern crate hlua;
extern crate mio;
extern crate serde;
extern crate slab;

pub mod net;
pub mod script;

use std::sync::atomic::{AtomicBool, Ordering};
use std::error::Error;
use std::fmt::{Display, Error as FmtError, Formatter};
use std::io;
use std::net::SocketAddr;

use mio::tcp::TcpListener;

use net::{EventLoop, EventLoopImpl, MAX_CONNECTIONS, client};
use net::client::Client;

/// The current version of buildengine. Fallows Semantic Versioning.
pub const VERSION: &'static str = "0.0.1";

/// If the game is allowed to crash in the event of a semi-handleable error, such as a bad network packet or a peer crashing.
///
/// Programming mistakes however, will still panic.
static SHOULD_CRASH: AtomicBool = AtomicBool::new(true);    // Basically Erlang's too_big_to_fail process_flag.

/// Main game struct. Contains all state nescary to work.
///
/// While you may never need the fields exposed, they are exposed if you ever want to inspect the game state.
/// You probably, however don't want to mutate the state directly. That can mess up client-server syncronization.
#[derive(Debug)]
pub struct Engine<'be> {
    /// The clientside or serverside networking state.
    ///
    /// Currently a Some if it is a client, or None if server.
    pub net_state: Option<Client>,

    /// The networking event loop. Mostly used in other functions for sending, adding, and killing connections.
    ///
    /// Also contains all state relating to networking.
    pub event_loop: Box<EventLoop>,

    /// The scripting backend for the engine.
    ///
    /// Not present on a client, for security reasons.
    pub script_engine: Option<script::Engine<'be>>,
}

impl<'be> Engine<'be> {
    /// Creates a new client game.
    pub fn new_client(server_address: SocketAddr) -> Result<Self, InitError> {
        let mut event_loop = try!(EventLoopImpl::new(MAX_CONNECTIONS, Vec::new()));
        let client = try!(Client::spawn_client(server_address, &mut event_loop));
        Ok(Engine {
            event_loop: Box::new(event_loop),
            net_state: Some(client),
            script_engine: None,
        })
    }

    /// Creates a new server.
    pub fn new_server(server_address: &SocketAddr, game_scripts: Vec<&str>) -> Result<Self, InitError> {
        let event_loop = try!(EventLoopImpl::new(MAX_CONNECTIONS, Vec::new()));
        let listener = try!(TcpListener::bind(server_address));
        event_loop.add_listener(listener);
        Ok(Engine {
            event_loop: Box::new(event_loop),
            net_state: None,
            script_engine: Some(script::Engine::new(game_scripts)),
        })
    }
}

/// An error hapened while initing the game.
#[derive(Debug)]
pub enum InitError {
    /// An error occoured when initalising the client code.
    ClientInitError(client::InitError),
    /// An std::io::Error. Who knows where this comes up.
    IoError(io::Error),
}

impl Display for InitError {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
        match *self {
            InitError::ClientInitError(ref err) => write!(fmt, "ClientInitError: {}", err),
            InitError::IoError(ref err) => write!(fmt, "IoError: {}", err),
        }
    }
}

impl Error for InitError {
    fn description(&self) -> &str {
        match *self {
            InitError::ClientInitError(ref err) => err.description(),
            InitError::IoError(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            InitError::ClientInitError(ref err) => Some(err),
            InitError::IoError(ref err) => Some(err),
        }
    }
}

impl From<client::InitError> for InitError {
    fn from(err: client::InitError) -> Self {
        InitError::ClientInitError(err)
    }
}

impl From<io::Error> for InitError {
    fn from(err: io::Error) -> Self {
        InitError::IoError(err)
    }
}

/// Initalizes the global parts of the engine.
///
/// Currently it only inits the logger, but later may do other things.
///
/// #Panics
/// * Calling the function once it has already been called.
pub fn global_init() {
    env_logger::init().expect("Already inited the logging server!");
}

/// Prints "Hello World!" to stdout. Will be removed in future versions.
pub fn print_hello_world() {
    println!("Hello World!");
}

fn check_should_crash() -> bool {
    SHOULD_CRASH.load(Ordering::Relaxed)
}
<|endoftext|>


<commit_before>// Copyright 2016 Hroi Sigurdsson
//
// Licensed under the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed except according to those terms.

#![feature(test)]
#![feature(alloc)]

//! # Fast IP lookup table for IPv4/IPv6 prefixes
//!
//! This crate provides a datastructure for fast IP address lookups.
//! It aims at fast lookup times, and a small memory footprint.
//! A full IPv4 BGP table of more than 600k entries fits in less than 5 MB. A full IPv6 BGP table of more than 25k entries fits in less than 1 MB.
//!
//! Longest match lookups on full BGP IP tables take on the order of 100ns.
//!
//! The internal datastructure is based on the Tree-bitmap algorithm described by W. Eatherton, Z. Dittia, G. Varghes.
//!

#[macro_use]
#[cfg(test)]
extern crate lazy_static;
extern crate alloc; // for RawVec
extern crate test;
use std::net::{Ipv4Addr, Ipv6Addr};
use std::marker::PhantomData;

mod tree_bitmap;
use tree_bitmap::TreeBitmap;

mod address;
use address::Address;

///The operations defined on the lookup table.
pub trait IpLookupTableOps<Addr, T> {
    /// Insert a value for the prefix designated by ip and masklen. If prefix existed previously, the old value is returned.
    /// # Example
    /// ```
    /// use treebitmap::{IpLookupTable, IpLookupTableOps};
    /// use std::net::Ipv6Addr;
    ///
    /// let mut table: IpLookupTable<Ipv6Addr,&str> = IpLookupTable::new();
    /// let prefix = Ipv6Addr::new(0x2001, 0xdb8, 0xdead, 0xbeef, 0, 0, 0, 0);
    /// let masklen = 32;
    ///
    /// assert_eq!(table.insert(prefix, masklen, "foo"), None);
    /// // Insert duplicate
    /// assert_eq!(table.insert(prefix, masklen, "bar"), Some("foo"));
    /// ```
    fn insert(&mut self, ip: Addr, masklen: u32, value: T) -> Option<T>;

    /// Remove an entry from the lookup table. If the prefix existed previously, the value is returned.
    /// # Example
    /// ```
    /// use treebitmap::{IpLookupTable, IpLookupTableOps};
    /// use std::net::Ipv6Addr;
    ///
    /// let mut table: IpLookupTable<Ipv6Addr,&str> = IpLookupTable::new();
    /// let prefix = Ipv6Addr::new(0x2001, 0xdb8, 0xdead, 0xbeef, 0, 0, 0, 0);
    /// let masklen = 32;
    /// table.insert(prefix, masklen, "foo");
    ///
    /// assert_eq!(table.remove(prefix, masklen), Some("foo"));
    /// // Remove non-existant
    /// assert_eq!(table.remove(prefix, masklen), None);
    /// ```
    fn remove(&mut self, ip: Addr, masklen: u32) -> Option<T>;

    /// Perform exact match lookup of ```ip```/```masklen``` and return the value.
    /// # Example
    /// ```
    /// use treebitmap::{IpLookupTable, IpLookupTableOps};
    /// use std::net::Ipv6Addr;
    ///
    /// let mut table: IpLookupTable<Ipv6Addr,&str> = IpLookupTable::new();
    /// let prefix = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0);
    /// let masklen = 32;
    /// table.insert(prefix, masklen, "foo");
    ///
    /// assert_eq!(table.exact_match(prefix, masklen), Some(&"foo"));
    /// // differing mask
    /// assert_eq!(table.exact_match(prefix, 48), None);
    fn exact_match(&self, ip: Addr, masklen: u32) -> Option<&T>;
    /// Perform longest match lookup of ```ip``` and return the best matching prefix, designated by ip, masklen, along with its value.
    /// # Example
    /// ```
    /// use treebitmap::{IpLookupTable, IpLookupTableOps};
    /// use std::net::Ipv6Addr;
    ///
    /// let mut table: IpLookupTable<Ipv6Addr,&str> = IpLookupTable::new();
    /// let less_specific = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0);
    /// let more_specific = Ipv6Addr::new(0x2001, 0xdb8, 0xdead, 0, 0, 0, 0, 0);
    /// table.insert(less_specific, 32, "foo");
    /// table.insert(more_specific, 48, "bar");
    ///
    /// let lookupip = Ipv6Addr::new(0x2001, 0xdb8, 0xdead, 0xbeef, 0xcafe, 0xbabe, 0, 1);
    /// let result = table.longest_match(lookupip);
    /// assert_eq!(result, Some((more_specific, 48, &"bar")));
    ///
    /// let lookupip = Ipv6Addr::new(0x2001, 0xdb8, 0xcafe, 0xf00, 0xf00, 0xf00, 0, 1);
    /// let result = table.longest_match(lookupip);
    /// assert_eq!(result, Some((less_specific, 32, &"foo")));
    /// ```
    fn longest_match(&self, ip: Addr) -> Option<(Addr, u32, &T)>;
}

/// A fast, compressed IP lookup table.
pub struct IpLookupTable<A, T> {
    inner: TreeBitmap<T>,
    _addrtype: PhantomData<A>,
}

impl<A, T> IpLookupTable<A, T> {
    /// Initialize an empty lookup table with no preallocation.
    pub fn new() -> Self {
        IpLookupTable {
            inner: TreeBitmap::new(),
            _addrtype: PhantomData,
        }
    }

    /// Initialize an empty lookup table with pre-allocated buffers.
    pub fn with_capacity(n: usize) -> Self {
        IpLookupTable {
            inner: TreeBitmap::with_capacity(n),
            _addrtype: PhantomData,
        }
    }

    /// Return the bytes used by nodes and results.
    pub fn mem_usage(&self) -> (usize, usize) {
        self.inner.mem_usage()
    }
}

macro_rules! impl_ops {
    ($addr_type:ty) => {
        impl<T: Sized> IpLookupTableOps<$addr_type, T> for IpLookupTable<$addr_type, T> {

            fn insert(&mut self, ip: $addr_type, masklen: u32, value: T) -> Option<T>{
                self.inner.insert(&ip.nibbles(), masklen, value)
            }

            fn remove(&mut self, ip: $addr_type, masklen: u32) -> Option<T>{
                self.inner.remove(&ip.nibbles(), masklen)
            }

            fn exact_match(&self, ip: $addr_type, masklen: u32) -> Option<&T> {
                self.inner.exact_match(&ip.nibbles(), masklen)
            }

            fn longest_match(&self, ip: $addr_type) -> Option<($addr_type, u32, &T)> {
                match self.inner.longest_match(&ip.nibbles()) {
                    Some((bits_matched,value)) => Some((ip.mask(bits_matched), bits_matched, value)),
                    None => None
                }
            }
        }
    }
}

impl_ops!(Ipv4Addr);
impl_ops!(Ipv6Addr);

#[cfg(test)]
mod tests;
#[cfg(all(test, feature = "full-bgp-tests"))]
mod full_bgp_tests;

<commit_msg>formatting<commit_after>// Copyright 2016 Hroi Sigurdsson
//
// Licensed under the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed except according to those terms.

#![feature(test)]
#![feature(alloc)]

//! # Fast IP lookup table for IPv4/IPv6 prefixes
//!
//! This crate provides a datastructure for fast IP address lookups.
//! It aims at fast lookup times, and a small memory footprint.
//! A full IPv4 BGP table of more than 600k entries fits in less than 5 MB. A full IPv6 BGP table of more than 25k entries fits in less than 1 MB.
//!
//! Longest match lookups on full BGP IP tables take on the order of 100ns.
//!
//! The internal datastructure is based on the Tree-bitmap algorithm described by W. Eatherton, Z. Dittia, G. Varghes.
//!

#[macro_use]
#[cfg(test)]
extern crate lazy_static;
extern crate alloc; // for RawVec
extern crate test;
use std::net::{Ipv4Addr, Ipv6Addr};
use std::marker::PhantomData;

mod tree_bitmap;
use tree_bitmap::TreeBitmap;

mod address;
use address::Address;

///The operations defined on the lookup table.
pub trait IpLookupTableOps<Addr, T> {
    /// Insert a value for the prefix designated by ip and masklen. If prefix existed previously, the old value is returned.
    /// # Example
    /// ```
    /// use treebitmap::{IpLookupTable, IpLookupTableOps};
    /// use std::net::Ipv6Addr;
    ///
    /// let mut table: IpLookupTable<Ipv6Addr,&str> = IpLookupTable::new();
    /// let prefix = Ipv6Addr::new(0x2001, 0xdb8, 0xdead, 0xbeef, 0, 0, 0, 0);
    /// let masklen = 32;
    ///
    /// assert_eq!(table.insert(prefix, masklen, "foo"), None);
    /// // Insert duplicate
    /// assert_eq!(table.insert(prefix, masklen, "bar"), Some("foo"));
    /// ```
    fn insert(&mut self, ip: Addr, masklen: u32, value: T) -> Option<T>;

    /// Remove an entry from the lookup table. If the prefix existed previously, the value is returned.
    /// # Example
    /// ```
    /// use treebitmap::{IpLookupTable, IpLookupTableOps};
    /// use std::net::Ipv6Addr;
    ///
    /// let mut table: IpLookupTable<Ipv6Addr,&str> = IpLookupTable::new();
    /// let prefix = Ipv6Addr::new(0x2001, 0xdb8, 0xdead, 0xbeef, 0, 0, 0, 0);
    /// let masklen = 32;
    /// table.insert(prefix, masklen, "foo");
    ///
    /// assert_eq!(table.remove(prefix, masklen), Some("foo"));
    /// // Remove non-existant
    /// assert_eq!(table.remove(prefix, masklen), None);
    /// ```
    fn remove(&mut self, ip: Addr, masklen: u32) -> Option<T>;

    /// Perform exact match lookup of ```ip```/```masklen``` and return the value.
    /// # Example
    /// ```
    /// use treebitmap::{IpLookupTable, IpLookupTableOps};
    /// use std::net::Ipv6Addr;
    ///
    /// let mut table: IpLookupTable<Ipv6Addr,&str> = IpLookupTable::new();
    /// let prefix = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0);
    /// let masklen = 32;
    /// table.insert(prefix, masklen, "foo");
    ///
    /// assert_eq!(table.exact_match(prefix, masklen), Some(&"foo"));
    /// // differing mask
    /// assert_eq!(table.exact_match(prefix, 48), None);
    /// ```
    fn exact_match(&self, ip: Addr, masklen: u32) -> Option<&T>;

    /// Perform longest match lookup of ```ip``` and return the best matching prefix, designated by ip, masklen, along with its value.
    /// # Example
    /// ```
    /// use treebitmap::{IpLookupTable, IpLookupTableOps};
    /// use std::net::Ipv6Addr;
    ///
    /// let mut table: IpLookupTable<Ipv6Addr,&str> = IpLookupTable::new();
    /// let less_specific = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0);
    /// let more_specific = Ipv6Addr::new(0x2001, 0xdb8, 0xdead, 0, 0, 0, 0, 0);
    /// table.insert(less_specific, 32, "foo");
    /// table.insert(more_specific, 48, "bar");
    ///
    /// let lookupip = Ipv6Addr::new(0x2001, 0xdb8, 0xdead, 0xbeef, 0xcafe, 0xbabe, 0, 1);
    /// let result = table.longest_match(lookupip);
    /// assert_eq!(result, Some((more_specific, 48, &"bar")));
    ///
    /// let lookupip = Ipv6Addr::new(0x2001, 0xdb8, 0xcafe, 0xf00, 0xf00, 0xf00, 0, 1);
    /// let result = table.longest_match(lookupip);
    /// assert_eq!(result, Some((less_specific, 32, &"foo")));
    /// ```
    fn longest_match(&self, ip: Addr) -> Option<(Addr, u32, &T)>;
}

/// A fast, compressed IP lookup table.
pub struct IpLookupTable<A, T> {
    inner: TreeBitmap<T>,
    _addrtype: PhantomData<A>,
}

impl<A, T> IpLookupTable<A, T> {
    /// Initialize an empty lookup table with no preallocation.
    pub fn new() -> Self {
        IpLookupTable {
            inner: TreeBitmap::new(),
            _addrtype: PhantomData,
        }
    }

    /// Initialize an empty lookup table with pre-allocated buffers.
    pub fn with_capacity(n: usize) -> Self {
        IpLookupTable {
            inner: TreeBitmap::with_capacity(n),
            _addrtype: PhantomData,
        }
    }

    /// Return the bytes used by nodes and results.
    pub fn mem_usage(&self) -> (usize, usize) {
        self.inner.mem_usage()
    }
}

macro_rules! impl_ops {
    ($addr_type:ty) => {
        impl<T: Sized> IpLookupTableOps<$addr_type, T> for IpLookupTable<$addr_type, T> {

            fn insert(&mut self, ip: $addr_type, masklen: u32, value: T) -> Option<T>{
                self.inner.insert(&ip.nibbles(), masklen, value)
            }

            fn remove(&mut self, ip: $addr_type, masklen: u32) -> Option<T>{
                self.inner.remove(&ip.nibbles(), masklen)
            }

            fn exact_match(&self, ip: $addr_type, masklen: u32) -> Option<&T> {
                self.inner.exact_match(&ip.nibbles(), masklen)
            }

            fn longest_match(&self, ip: $addr_type) -> Option<($addr_type, u32, &T)> {
                match self.inner.longest_match(&ip.nibbles()) {
                    Some((bits_matched,value)) => Some((ip.mask(bits_matched), bits_matched, value)),
                    None => None
                }
            }
        }
    }
}

impl_ops!(Ipv4Addr);
impl_ops!(Ipv6Addr);

#[cfg(test)]
mod tests;
#[cfg(all(test, feature = "full-bgp-tests"))]
mod full_bgp_tests;

<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

static S: [u8, ..256] = [
    0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13,
    0x62, 0xA7, 0x05, 0xF3, 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, 0x82, 0xCA,
    0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12,
    0xBE, 0x4E, 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, 0xBB, 0x2F, 0xEE, 0x7A,
    0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21,
    0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03,
    0xFF, 0x19, 0x30, 0xB3, 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, 0xAA, 0xC6,
    0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1,
    0x45, 0x9D, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, 0xE6, 0x2D, 0xA8, 0x02,
    0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F,
    0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C, 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26,
    0x2C, 0x53, 0x0D, 0x6E, 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, 0x4D, 0x52,
    0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A,
    0x78, 0x88, 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE, 0x3B, 0x00, 0x1D, 0x39,
    0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
    0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14
];

#[inline]
fn md2_memcpy(dst: &mut [u8], src: &[u8]) {
    assert!(dst.len() == src.len());

    // Slow but safe memcpy() implementation.
    for (i, byte) in dst.iter_mut().enumerate() { *byte = src[i] }
}

#[inline]
fn md2_pad(msg: &[u8]) -> Vec<u8> {
    let mut msg = msg.to_vec();
    let pad = 16 - msg.len() % 16;
    msg.grow_fn(pad, |_| pad as u8);
    msg
}

#[inline]
fn md2_checksum(msg: &[u8]) -> [u8, ..16] {
    let mut checksum = [0u8, ..16];
    let mut last = 0u8;

    for chunk in msg.chunks(16) {
        for (i, byte) in checksum.iter_mut().enumerate() {
            *byte ^= S[(chunk[i] ^ last) as uint];
            last = *byte;
        }
    }

    checksum
}

#[inline]
fn md2_compress(state: &[u8], msg: &[u8]) -> [u8, ..16] {
    // Two 128 bit blocks in, one 128 bit block out.
    assert!(state.len() == 16 && msg.len() == 16);

    let mut x = [0u8, ..48];
    let mut result = [0u8, ..16];

    // Copy over the previous state.
    md2_memcpy(x.slice_mut(0, 16), state);

    // Copy over the message block.
    md2_memcpy(x.slice_mut(16, 32), msg);

    // XOR the previous state and the message block.
    for (i, byte) in msg.iter().enumerate() {
        x[32 + i] = *byte ^ x[i];
    }

    // Encrypt block (18 rounds).
    let mut t = 0u8;
    for i in range(0, 18) {
        for byte in x.iter_mut() {
            *byte ^= S[t as uint];
            t = *byte;
        }
        t += i;
    }

    // Copy the new state.
    md2_memcpy(&mut result, x.slice(0, 16));
    result
}

pub fn md2(msg: &[u8]) -> [u8, ..16] {
    // Pad the message to be a multiple of 16 bytes long.
    let msg = md2_pad(msg);
    assert!(msg.len() % 16 == 0);

    // Compress all message blocks.
    let state = msg.chunks(16).fold([0u8, ..16], |s, m| md2_compress(&s, m));

    // Compute the checksum.
    let checksum = md2_checksum(msg.as_slice());

    // Compress checksum and return.
    md2_compress(&state, &checksum)
}

#[cfg(test)]
mod test {
    use md2;

    fn hex(buf: &[u8]) -> String {
        buf.iter().fold(String::new(), |a, &b| format!("{}{:02x}", a, b))
    }

    fn cmp(d: &str, s: &str) {
        assert_eq!(d.to_string(), hex(&md2(s.as_bytes())));
    }

    #[test]
    fn test_md2() {
        cmp("8350e5a3e24c153df2275c9f80692773", "");
        cmp("32ec01ec4a6dac72c0ab96fb34c0b5d1", "a");
        cmp("da853b0d3f88d99b30283a69e6ded6bb", "abc");
        cmp("ab4f496bfb2a530b219ff33031fe06b0", "message digest");
        cmp("4e8ddff3650292ab5a4108c3aa47940b", "abcdefghijklmnopqrstuvwxyz");
        cmp("da33def2a42df13975352846c30338cd", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
        cmp("d5976f79d83d3a0dc9806c3c66f3efd8", "12345678901234567890123456789012345678901234567890123456789012345678901234567890");
    }
}
<commit_msg>use copy_memory()<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::slice::bytes::copy_memory;

static S: [u8, ..256] = [
    0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13,
    0x62, 0xA7, 0x05, 0xF3, 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, 0x82, 0xCA,
    0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12,
    0xBE, 0x4E, 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, 0xBB, 0x2F, 0xEE, 0x7A,
    0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21,
    0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03,
    0xFF, 0x19, 0x30, 0xB3, 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, 0xAA, 0xC6,
    0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1,
    0x45, 0x9D, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, 0xE6, 0x2D, 0xA8, 0x02,
    0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F,
    0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C, 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26,
    0x2C, 0x53, 0x0D, 0x6E, 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, 0x4D, 0x52,
    0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A,
    0x78, 0x88, 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE, 0x3B, 0x00, 0x1D, 0x39,
    0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
    0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14
];

#[inline]
fn md2_pad(msg: &[u8]) -> Vec<u8> {
    let mut msg = msg.to_vec();
    let pad = 16 - msg.len() % 16;
    msg.grow_fn(pad, |_| pad as u8);
    msg
}

#[inline]
fn md2_checksum(msg: &[u8]) -> [u8, ..16] {
    let mut checksum = [0u8, ..16];
    let mut last = 0u8;

    for chunk in msg.chunks(16) {
        for (i, byte) in checksum.iter_mut().enumerate() {
            *byte ^= S[(chunk[i] ^ last) as uint];
            last = *byte;
        }
    }

    checksum
}

#[inline]
fn md2_compress(state: &[u8], msg: &[u8]) -> [u8, ..16] {
    // Two 128 bit blocks in, one 128 bit block out.
    assert!(state.len() == 16 && msg.len() == 16);

    let mut x = [0u8, ..48];
    let mut result = [0u8, ..16];

    // Copy over the previous state.
    copy_memory(x.slice_mut(0, 16), state);

    // Copy over the message block.
    copy_memory(x.slice_mut(16, 32), msg);

    // XOR the previous state and the message block.
    for (i, byte) in msg.iter().enumerate() {
        x[32 + i] = *byte ^ x[i];
    }

    // Encrypt block (18 rounds).
    let mut t = 0u8;
    for i in range(0, 18) {
        for byte in x.iter_mut() {
            *byte ^= S[t as uint];
            t = *byte;
        }
        t += i;
    }

    // Copy the new state.
    copy_memory(&mut result, x.slice(0, 16));
    result
}

pub fn md2(msg: &[u8]) -> [u8, ..16] {
    // Pad the message to be a multiple of 16 bytes long.
    let msg = md2_pad(msg);
    assert!(msg.len() % 16 == 0);

    // Compress all message blocks.
    let state = msg.chunks(16).fold([0u8, ..16], |s, m| md2_compress(&s, m));

    // Compute the checksum.
    let checksum = md2_checksum(msg.as_slice());

    // Compress checksum and return.
    md2_compress(&state, &checksum)
}

#[cfg(test)]
mod test {
    use md2;

    fn hex(buf: &[u8]) -> String {
        buf.iter().fold(String::new(), |a, &b| format!("{}{:02x}", a, b))
    }

    fn cmp(d: &str, s: &str) {
        assert_eq!(d.to_string(), hex(&md2(s.as_bytes())));
    }

    #[test]
    fn test_md2() {
        cmp("8350e5a3e24c153df2275c9f80692773", "");
        cmp("32ec01ec4a6dac72c0ab96fb34c0b5d1", "a");
        cmp("da853b0d3f88d99b30283a69e6ded6bb", "abc");
        cmp("ab4f496bfb2a530b219ff33031fe06b0", "message digest");
        cmp("4e8ddff3650292ab5a4108c3aa47940b", "abcdefghijklmnopqrstuvwxyz");
        cmp("da33def2a42df13975352846c30338cd", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
        cmp("d5976f79d83d3a0dc9806c3c66f3efd8", "12345678901234567890123456789012345678901234567890123456789012345678901234567890");
    }
}
<|endoftext|>


<commit_before>use std::ops::{ Mul, Div };

pub trait Unit: Sized {
    type Data: Mul<Output=Self::Data> + Div<Output=Self::Data>;
    type Base: Unit<Data=Self::Data, Base=Self::Base>;

    fn factor() -> Self::Data;
    fn value(&self) -> Self::Data;
    fn new(data: Self::Data) -> Self;

    fn to<T>(self) -> T where
        T: Unit<Data=Self::Data, Base=Self::Base>
    {
        T::from_base(self.to_base())
    }

    // To get the value contained by the base unit type, we multiply the value contained by the
    // derived unit type.
    fn to_base(self) -> Self::Base {
        <Self::Base as Unit>::new(self.value() / Self::factor())
    }

    // Here we reverse the process we used to get the base unit in the first place.
    fn from_base<T>(base: Self::Base) -> T where
        T: Unit<Data=Self::Data, Base=Self::Base>
    {
        T::new(base.value() * Self::factor())
    }
}

// #[macro_export] // not sure this ought to be exported; it's kind of lame...

// For my viewers, I'll explain what I mean: this macro doesn't derive `Eq` because of the
// possibility that your data type will be `f64`, in which case it's not possible to get
// an implementation of `Eq` at all. If I were going to make a serious library for doing
// this and export a macro to build a unit type for my users, I'd want it to be smart
// enough to deal with non-`Eq` types like that.
macro_rules! unit {
    ($typename:ident, $basetype:ident, $datatype:ty, $factor:expr) => {
        struct $typename($datatype);

        impl Unit for $typename {
            type Data = $datatype;
            type Base = $basetype;

            fn factor() -> Self::Data { $factor }
            fn value(&self) -> Self::Data { self.0 }

            fn new(data: Self::Data) -> Self {
                $typename(data)
            }
        }

        impl<T> ::std::ops::Add<T> for $typename where
            T: Unit<Data=<$typename as Unit>::Data, Base=<$typename as Unit>::Base>
        {
            type Output = $typename;
            fn add(self, rhs: T) -> Self::Output {
                Self::new(self.value() + rhs.to::<$typename>().value())
            }
        }

        impl ::std::ops::Add<$datatype> for $typename {
            type Output = $typename;
            fn add(self, rhs: $datatype) -> Self::Output {
                Self::new(self.value() + rhs)
            }
        }

        impl<T> ::std::ops::Sub<T> for $typename where
            T: Unit<Data=<$typename as Unit>::Data, Base=<$typename as Unit>::Base>
        {
            type Output = $typename;
            fn sub(self, rhs: T) -> Self::Output {
                Self::new(self.value() - rhs.to::<$typename>().value())
            }
        }

        impl ::std::ops::Sub<$datatype> for $typename {
            type Output = $typename;
            fn sub(self, rhs: $datatype) -> Self::Output {
                Self::new(self.value() - rhs)
            }
        }

        impl<T> ::std::ops::Mul<T> for $typename where
            T: Unit<Data=<$typename as Unit>::Data, Base=<$typename as Unit>::Base>
        {
            type Output = $typename;
            fn mul(self, rhs: T) -> Self::Output {
                Self::new(self.value() * rhs.to::<$typename>().value())
            }
        }

        impl ::std::ops::Mul<$datatype> for $typename {
            type Output = $typename;
            fn mul(self, rhs: $datatype) -> Self::Output {
                Self::new(self.value() * rhs)
            }
        }

        impl<T> ::std::ops::Div<T> for $typename where
            T: Unit<Data=<$typename as Unit>::Data, Base=<$typename as Unit>::Base>
        {
            type Output = $typename;
            fn div(self, rhs: T) -> Self::Output {
                Self::new(self.value() / rhs.to::<$typename>().value())
            }
        }

        impl ::std::ops::Div<$datatype> for $typename {
            type Output = $typename;
            fn div(self, rhs: $datatype) -> Self::Output {
                Self::new(self.value() / rhs)
            }
        }
    }
}

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

    unit!(Meters, Self, f64, 1.0);
    unit!(Centimeters, Meters, f64, 100.0);
    unit!(Yards, Meters, f64, 1.09361);
    unit!(Feet, Self, f64, 1.0);
    unit!(Inches, Feet, f64, 1.0);

    #[test]
    fn can_convert_centimeters_to_meters() {
        assert!(2.0 == (Centimeters(100.0).to::<Meters>() + Meters(1.0)).value());
    }

    #[test]
    fn can_convert_yards_to_meters() {
        let yards_to_meters = format!("{:.4}", Yards(1.0).to::<Meters>().value());
        assert!("0.9144" == &yards_to_meters);
    }

    // This test doesn't even compile -- correctly so
    // #[test]
    // fn can_convert_feet_to_yards() {
    //     let feet_to_yards = Feet(3.0).to::<Yards>().value();
    //     assert!(1.0 == feet_to_yards);
    // }
}
<commit_msg>Correct inches conversion factor, add test<commit_after>use std::ops::{ Mul, Div };

pub trait Unit: Sized {
    type Data: Mul<Output=Self::Data> + Div<Output=Self::Data>;
    type Base: Unit<Data=Self::Data, Base=Self::Base>;

    fn factor() -> Self::Data;
    fn value(&self) -> Self::Data;
    fn new(data: Self::Data) -> Self;

    fn to<T>(self) -> T where
        T: Unit<Data=Self::Data, Base=Self::Base>
    {
        T::from_base(self.to_base())
    }

    // To get the value contained by the base unit type, we multiply the value contained by the
    // derived unit type.
    fn to_base(self) -> Self::Base {
        <Self::Base as Unit>::new(self.value() / Self::factor())
    }

    // Here we reverse the process we used to get the base unit in the first place.
    fn from_base<T>(base: Self::Base) -> T where
        T: Unit<Data=Self::Data, Base=Self::Base>
    {
        T::new(base.value() * Self::factor())
    }
}

// #[macro_export] // not sure this ought to be exported; it's kind of lame...

// For my viewers, I'll explain what I mean: this macro doesn't derive `Eq` because of the
// possibility that your data type will be `f64`, in which case it's not possible to get
// an implementation of `Eq` at all. If I were going to make a serious library for doing
// this and export a macro to build a unit type for my users, I'd want it to be smart
// enough to deal with non-`Eq` types like that.
macro_rules! unit {
    ($typename:ident, $basetype:ident, $datatype:ty, $factor:expr) => {
        struct $typename($datatype);

        impl Unit for $typename {
            type Data = $datatype;
            type Base = $basetype;

            fn factor() -> Self::Data { $factor }
            fn value(&self) -> Self::Data { self.0 }

            fn new(data: Self::Data) -> Self {
                $typename(data)
            }
        }

        impl<T> ::std::ops::Add<T> for $typename where
            T: Unit<Data=<$typename as Unit>::Data, Base=<$typename as Unit>::Base>
        {
            type Output = $typename;
            fn add(self, rhs: T) -> Self::Output {
                Self::new(self.value() + rhs.to::<$typename>().value())
            }
        }

        impl ::std::ops::Add<$datatype> for $typename {
            type Output = $typename;
            fn add(self, rhs: $datatype) -> Self::Output {
                Self::new(self.value() + rhs)
            }
        }

        impl<T> ::std::ops::Sub<T> for $typename where
            T: Unit<Data=<$typename as Unit>::Data, Base=<$typename as Unit>::Base>
        {
            type Output = $typename;
            fn sub(self, rhs: T) -> Self::Output {
                Self::new(self.value() - rhs.to::<$typename>().value())
            }
        }

        impl ::std::ops::Sub<$datatype> for $typename {
            type Output = $typename;
            fn sub(self, rhs: $datatype) -> Self::Output {
                Self::new(self.value() - rhs)
            }
        }

        impl<T> ::std::ops::Mul<T> for $typename where
            T: Unit<Data=<$typename as Unit>::Data, Base=<$typename as Unit>::Base>
        {
            type Output = $typename;
            fn mul(self, rhs: T) -> Self::Output {
                Self::new(self.value() * rhs.to::<$typename>().value())
            }
        }

        impl ::std::ops::Mul<$datatype> for $typename {
            type Output = $typename;
            fn mul(self, rhs: $datatype) -> Self::Output {
                Self::new(self.value() * rhs)
            }
        }

        impl<T> ::std::ops::Div<T> for $typename where
            T: Unit<Data=<$typename as Unit>::Data, Base=<$typename as Unit>::Base>
        {
            type Output = $typename;
            fn div(self, rhs: T) -> Self::Output {
                Self::new(self.value() / rhs.to::<$typename>().value())
            }
        }

        impl ::std::ops::Div<$datatype> for $typename {
            type Output = $typename;
            fn div(self, rhs: $datatype) -> Self::Output {
                Self::new(self.value() / rhs)
            }
        }
    }
}

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

    unit!(Meters, Self, f64, 1.0);
    unit!(Centimeters, Meters, f64, 100.0);
    unit!(Yards, Meters, f64, 1.09361);
    unit!(Feet, Self, f64, 1.0);
    unit!(Inches, Feet, f64, 12.0);

    #[test]
    fn can_convert_centimeters_to_meters() {
        assert!(2.0 == (Centimeters(100.0).to::<Meters>() + Meters(1.0)).value());
    }

    #[test]
    fn can_convert_inches_to_feet() {
        assert!(2.0 == Inches(24.0).to::<Feet>().value());
    }

    #[test]
    fn can_convert_yards_to_meters() {
        let yards_to_meters = format!("{:.4}", Yards(1.0).to::<Meters>().value());
        assert!("0.9144" == &yards_to_meters);
    }

    // This test doesn't even compile -- correctly so
    // #[test]
    // fn can_convert_feet_to_yards() {
    //     let feet_to_yards = Feet(3.0).to::<Yards>().value();
    //     assert!(1.0 == feet_to_yards);
    // }
}
<|endoftext|>