<commit_before>extern crate rustc_serialize;
extern crate time;
extern crate tiny_http;
extern crate url;

pub use assets::match_assets;
pub use log::LogEntry;

use std::str::FromStr;
use std::sync::Mutex;

pub mod input;

mod assets;
mod log;
mod router;

pub enum RouteError {
    /// Couldn't find a way to handle this request.
    NoRouteFound,

    WrongInput,
}

pub struct Server {
    #[inline]
    server: tiny_http::Server,
}

impl Server {
    pub fn start() -> Server {
        Server {
            server: tiny_http::ServerBuilder::new().with_port(8000).build().unwrap(),
        }
    }
}

impl IntoIterator for Server {
    type Item = Request;
    type IntoIter = IncomingRequests;

    #[inline]
    fn into_iter(self) -> IncomingRequests {
        IncomingRequests { server: self.server }
    }
}

pub struct IncomingRequests {
    server: tiny_http::Server,
}

impl Iterator for IncomingRequests {
    type Item = Request;

    #[inline]
    fn next(&mut self) -> Option<Request> {
        let request = self.server.recv().unwrap();

        Some(Request {
            url: request.url().to_owned(),
            request: Mutex::new(Some(request)),
            data: Mutex::new(None),
        })
    }
}

/// Represents a request made by the client.
pub struct Request {
    url: String,
    request: Mutex<Option<tiny_http::Request>>,     // TODO: when Mutex gets "into_inner", remove the Option
    data: Mutex<Option<Vec<u8>>>,
}

impl Request {
    /// Returns the URL requested by the client. It is not decoded and thus can contain `%20` or
    /// other characters.
    #[inline]
    pub fn url(&self) -> &str {
        &self.url
    }

    /// Returns the value of a header of the request.
    #[inline]
    pub fn header(&self, key: &str) -> Option<String> {
        self.request.lock().unwrap().as_ref().unwrap().headers().iter()
                    .find(|h| h.field.as_str() == key).map(|h| h.value.as_str().to_owned())
    }

    /// Returns the data of the request.
    pub fn data(&self) -> Vec<u8> {
        let mut data = self.data.lock().unwrap();

        if let Some(ref mut data) = *data {
            return data.clone();
        }

        let mut read = Vec::new();
        let _ = self.request.lock().unwrap().as_mut().unwrap()
                            .as_reader().read_to_end(&mut read);
        let read_clone = read.clone();
        *data = Some(read);
        read_clone
    }

    /// Consumes the `Request` and sends the response to the client.
    #[inline]
    pub fn respond(self, response: Response) {
        self.request.lock().unwrap().take().unwrap().respond(response.response)
    }

    /// Utility function similar to `respond`, but builds the "default" response corresponding to
    /// the `RouteError`.
    #[inline]
    pub fn respond_to_error(self, err: &RouteError) {
        let response = match err {
            &RouteError::NoRouteFound => tiny_http::Response::empty(404),
            &RouteError::WrongInput => tiny_http::Response::empty(400),
        };

        self.request.lock().unwrap().take().unwrap().respond(response);
    }
}

/// Contains a prototype of a response. The response is only sent when you call `Request::respond`.
pub struct Response {
    response: tiny_http::ResponseBox,
}

impl Response {
    /// Builds a `Response` that redirects the user to another URL.
    #[inline]
    pub fn redirect(target: &str) -> Response {
        let response = tiny_http::Response::empty(303);
        // TODO: slow \|/
        let response = response.with_header(tiny_http::Header::from_str(&format!("Location: {}", target)).unwrap());

        Response { response: response.boxed() }
    }

    /// Builds a `Response` that outputs HTML.
    #[inline]
    pub fn html(content: &[u8]) -> Response {
        let response = tiny_http::Response::from_data(content);
        // TODO: slow \|/
        let response = response.with_header(tiny_http::Header::from_str("Content-Type: text/html; charset=utf8").unwrap());

        Response { response: response.boxed() }
    }
}
<commit_msg>Implement some missing traits<commit_after>extern crate rustc_serialize;
extern crate time;
extern crate tiny_http;
extern crate url;

pub use assets::match_assets;
pub use log::LogEntry;

use std::str::FromStr;
use std::sync::Mutex;

pub mod input;

mod assets;
mod log;
mod router;

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum RouteError {
    /// Couldn't find a way to handle this request.
    NoRouteFound,

    WrongInput,
}

pub struct Server {
    #[inline]
    server: tiny_http::Server,
}

impl Server {
    pub fn start() -> Server {
        Server {
            server: tiny_http::ServerBuilder::new().with_port(8000).build().unwrap(),
        }
    }
}

impl IntoIterator for Server {
    type Item = Request;
    type IntoIter = IncomingRequests;

    #[inline]
    fn into_iter(self) -> IncomingRequests {
        IncomingRequests { server: self.server }
    }
}

pub struct IncomingRequests {
    server: tiny_http::Server,
}

impl Iterator for IncomingRequests {
    type Item = Request;

    #[inline]
    fn next(&mut self) -> Option<Request> {
        let request = self.server.recv().unwrap();

        Some(Request {
            url: request.url().to_owned(),
            request: Mutex::new(Some(request)),
            data: Mutex::new(None),
        })
    }
}

/// Represents a request made by the client.
pub struct Request {
    url: String,
    request: Mutex<Option<tiny_http::Request>>,     // TODO: when Mutex gets "into_inner", remove the Option
    data: Mutex<Option<Vec<u8>>>,
}

impl Request {
    /// Returns the URL requested by the client. It is not decoded and thus can contain `%20` or
    /// other characters.
    #[inline]
    pub fn url(&self) -> &str {
        &self.url
    }

    /// Returns the value of a header of the request.
    #[inline]
    pub fn header(&self, key: &str) -> Option<String> {
        self.request.lock().unwrap().as_ref().unwrap().headers().iter()
                    .find(|h| h.field.as_str() == key).map(|h| h.value.as_str().to_owned())
    }

    /// Returns the data of the request.
    pub fn data(&self) -> Vec<u8> {
        let mut data = self.data.lock().unwrap();

        if let Some(ref mut data) = *data {
            return data.clone();
        }

        let mut read = Vec::new();
        let _ = self.request.lock().unwrap().as_mut().unwrap()
                            .as_reader().read_to_end(&mut read);
        let read_clone = read.clone();
        *data = Some(read);
        read_clone
    }

    /// Consumes the `Request` and sends the response to the client.
    #[inline]
    pub fn respond(self, response: Response) {
        self.request.lock().unwrap().take().unwrap().respond(response.response)
    }

    /// Utility function similar to `respond`, but builds the "default" response corresponding to
    /// the `RouteError`.
    #[inline]
    pub fn respond_to_error(self, err: &RouteError) {
        let response = match err {
            &RouteError::NoRouteFound => tiny_http::Response::empty(404),
            &RouteError::WrongInput => tiny_http::Response::empty(400),
        };

        self.request.lock().unwrap().take().unwrap().respond(response);
    }
}

/// Contains a prototype of a response. The response is only sent when you call `Request::respond`.
pub struct Response {
    response: tiny_http::ResponseBox,
}

impl Response {
    /// Builds a `Response` that redirects the user to another URL.
    #[inline]
    pub fn redirect(target: &str) -> Response {
        let response = tiny_http::Response::empty(303);
        // TODO: slow \|/
        let response = response.with_header(tiny_http::Header::from_str(&format!("Location: {}", target)).unwrap());

        Response { response: response.boxed() }
    }

    /// Builds a `Response` that outputs HTML.
    #[inline]
    pub fn html(content: &[u8]) -> Response {
        let response = tiny_http::Response::from_data(content);
        // TODO: slow \|/
        let response = response.with_header(tiny_http::Header::from_str("Content-Type: text/html; charset=utf8").unwrap());

        Response { response: response.boxed() }
    }
}
<|endoftext|>


<commit_before>#![deny(missing_debug_implementations,
        trivial_casts, trivial_numeric_casts,
        unstable_features,
        unused_import_braces, unused_qualifications)]

extern crate libc;
extern crate nix;
extern crate pty;
extern crate termios;
extern crate mio;

use std::{fmt, io, result, thread, process};
use std::io::{Read, Write};

pub use self::error::*;
pub use self::terminal::*;
use self::raw_handler::*;
use self::winsize::Winsize;

pub mod error;
pub mod terminal;
pub mod winsize;

mod raw_handler;
mod command;

pub type Result<T> = result::Result<T, Error>;

pub trait PtyHandler {
    fn input(&mut self, _data: &[u8]) {}
    fn output(&mut self, _data: &[u8]) {}
    fn resize(&mut self, _winsize: &Winsize) {}
    fn shutdown(&mut self) {}
}

pub trait PtyProxy {
    fn exec<S: AsRef<str>>(&self, shell: S) -> Result<()>;
    fn proxy<H: PtyHandler>(&self, handler: H) -> Result<()>;
    fn do_proxy<H: PtyHandler>(&self, handler: H) -> Result<()>;
}

impl PtyProxy for pty::Child {
    fn exec<S: AsRef<str>>(&self, shell: S) -> Result<()> {
        if self.pid() == 0 {
            command::exec(shell);
        }

        Ok(())
    }

    fn proxy<H: PtyHandler + 'static>(&self, handler: H) -> Result<()> {
        if self.pid() != 0 {
            try!(setup_terminal(self.pty().unwrap()));
            try!(self.do_proxy(handler));
        }

        Ok(())
    }

    fn do_proxy<H: PtyHandler + 'static>(&self, handler: H) -> Result<()> {
        let mut event_loop = try!(mio::EventLoop::new());

        let mut writer = self.pty().unwrap();
        let (input_reader, mut input_writer) = try!(mio::unix::pipe());

        thread::spawn(move || {
            handle_input(&mut writer, &mut input_writer).unwrap_or_else(|e| {
                println!("{:?}", e);
                process::exit(1);
            });
        });

        let mut reader = self.pty().unwrap();
        let (output_reader, mut output_writer) = try!(mio::unix::pipe());
        let message_sender = event_loop.channel();

        thread::spawn(move || {
            handle_output(&mut reader, &mut output_writer).unwrap_or_else(|e| {
                println!("{:?}", e);
                process::exit(1);
            });

            message_sender.send(Message::Shutdown).unwrap();
        });

        try!(event_loop.register(&input_reader, INPUT, mio::EventSet::readable(), mio::PollOpt::level()));
        try!(event_loop.register(&output_reader, OUTPUT, mio::EventSet::readable(), mio::PollOpt::level()));

        RawHandler::register_sigwinch_handler();

        let mut raw_handler = RawHandler::new(input_reader, output_reader, self.pty().unwrap(), Box::new(handler));

        try!(event_loop.run(&mut raw_handler));

        Ok(())
    }
}

pub struct PtyCallback {
    input_handler: Box<FnMut(&[u8])>,
    output_handler: Box<FnMut(&[u8])>,
}

impl PtyCallback {
    pub fn new<I, O>(input_handler: I, output_handler: O) -> Self
        where I: FnMut(&[u8]) + 'static, O: FnMut(&[u8]) + 'static
    {
        PtyCallback {
            input_handler: Box::new(input_handler),
            output_handler: Box::new(output_handler),
        }
    }
}

impl fmt::Debug for PtyCallback {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "(PtyCallback)")
    }
}

impl PtyHandler for PtyCallback {
    fn input(&mut self, data: &[u8]) {
        (&mut *self.input_handler)(data);
    }

    fn output(&mut self, data: &[u8]) {
        (&mut *self.output_handler)(data);
    }
}

fn handle_input(writer: &mut pty::ChildPTY, handler_writer: &mut mio::unix::PipeWriter) -> Result<()> {
    let mut input = io::stdin();
    let mut buf   = [0; 128];

    loop {
        let nread = try!(input.read(&mut buf));

        try!(writer.write(&buf[..nread]));
        try!(handler_writer.write(&buf[..nread]));
    }
}

fn handle_output(reader: &mut pty::ChildPTY, handler_writer: &mut mio::unix::PipeWriter) -> Result<()> {
    let mut output = io::stdout();
    let mut buf    = [0; 1024 * 10];

    loop {
        let nread = try!(reader.read(&mut buf));

        if nread <= 0 {
            break;
        } else {
            try!(output.write(&buf[..nread]));
            let _ = output.flush();

            try!(handler_writer.write(&buf[..nread]));
        }
    }

    Ok(())
}

#[cfg(test)]
mod tests {
    extern crate pty;

    use PtyProxy;
    use PtyHandler;
    use terminal::restore_termios;

    struct TestHandler;
    impl PtyHandler for TestHandler {
        fn output(&mut self, data: &[u8]) {
            assert!(data.len() != 0);
        }
    }

    #[test]
    fn it_can_spawn() {
        let child = pty::fork().unwrap();
        restore_termios();

        child.exec("pwd").unwrap();

        assert!(child.wait().is_ok());
    }

    #[test]
    fn it_can_hook_stdout_with_handler() {
        let child = pty::fork().unwrap();
        restore_termios();

        child.proxy(TestHandler).unwrap();
        child.exec("pwd").unwrap();

        assert!(child.wait().is_ok());
    }

    #[test]
    fn it_can_hook_stdout_with_callback() {
        use PtyCallback;

        let child = pty::fork().unwrap();
        restore_termios();

        child.proxy(PtyCallback::new(
            |_input| {},
            |output| assert!(output.len() != 0),
        )).unwrap();
        child.exec("pwd").unwrap();

        assert!(child.wait().is_ok());
    }
}
<commit_msg>Offer the PtyCallback as a builder<commit_after>#![deny(missing_debug_implementations,
        trivial_casts, trivial_numeric_casts,
        unstable_features,
        unused_import_braces, unused_qualifications)]

extern crate libc;
extern crate nix;
extern crate pty;
extern crate termios;
extern crate mio;

use std::{fmt, io, result, thread, process};
use std::io::{Read, Write};

pub use self::error::*;
pub use self::terminal::*;
use self::raw_handler::*;
use self::winsize::Winsize;

pub mod error;
pub mod terminal;
pub mod winsize;

mod raw_handler;
mod command;

pub type Result<T> = result::Result<T, Error>;

pub trait PtyHandler {
    fn input(&mut self, _data: &[u8]) {}
    fn output(&mut self, _data: &[u8]) {}
    fn resize(&mut self, _winsize: &Winsize) {}
    fn shutdown(&mut self) {}
}

pub trait PtyProxy {
    fn exec<S: AsRef<str>>(&self, shell: S) -> Result<()>;
    fn proxy<H: PtyHandler>(&self, handler: H) -> Result<()>;
    fn do_proxy<H: PtyHandler>(&self, handler: H) -> Result<()>;
}

impl PtyProxy for pty::Child {
    fn exec<S: AsRef<str>>(&self, shell: S) -> Result<()> {
        if self.pid() == 0 {
            command::exec(shell);
        }

        Ok(())
    }

    fn proxy<H: PtyHandler + 'static>(&self, handler: H) -> Result<()> {
        if self.pid() != 0 {
            try!(setup_terminal(self.pty().unwrap()));
            try!(self.do_proxy(handler));
        }

        Ok(())
    }

    fn do_proxy<H: PtyHandler + 'static>(&self, handler: H) -> Result<()> {
        let mut event_loop = try!(mio::EventLoop::new());

        let mut writer = self.pty().unwrap();
        let (input_reader, mut input_writer) = try!(mio::unix::pipe());

        thread::spawn(move || {
            handle_input(&mut writer, &mut input_writer).unwrap_or_else(|e| {
                println!("{:?}", e);
                process::exit(1);
            });
        });

        let mut reader = self.pty().unwrap();
        let (output_reader, mut output_writer) = try!(mio::unix::pipe());
        let message_sender = event_loop.channel();

        thread::spawn(move || {
            handle_output(&mut reader, &mut output_writer).unwrap_or_else(|e| {
                println!("{:?}", e);
                process::exit(1);
            });

            message_sender.send(Message::Shutdown).unwrap();
        });

        try!(event_loop.register(&input_reader, INPUT, mio::EventSet::readable(), mio::PollOpt::level()));
        try!(event_loop.register(&output_reader, OUTPUT, mio::EventSet::readable(), mio::PollOpt::level()));

        RawHandler::register_sigwinch_handler();

        let mut raw_handler = RawHandler::new(input_reader, output_reader, self.pty().unwrap(), Box::new(handler));

        try!(event_loop.run(&mut raw_handler));

        Ok(())
    }
}

fn handle_input(writer: &mut pty::ChildPTY, handler_writer: &mut mio::unix::PipeWriter) -> Result<()> {
    let mut input = io::stdin();
    let mut buf   = [0; 128];

    loop {
        let nread = try!(input.read(&mut buf));

        try!(writer.write(&buf[..nread]));
        try!(handler_writer.write(&buf[..nread]));
    }
}

fn handle_output(reader: &mut pty::ChildPTY, handler_writer: &mut mio::unix::PipeWriter) -> Result<()> {
    let mut output = io::stdout();
    let mut buf    = [0; 1024 * 10];

    loop {
        let nread = try!(reader.read(&mut buf));

        if nread <= 0 {
            break;
        } else {
            try!(output.write(&buf[..nread]));
            let _ = output.flush();

            try!(handler_writer.write(&buf[..nread]));
        }
    }

    Ok(())
}

pub struct PtyCallbackData {
    input_handler: Box<FnMut(&[u8])>,
    output_handler: Box<FnMut(&[u8])>,
    resize_handler: Box<FnMut(&Winsize)>,
    shutdown_handler: Box<FnMut()>,
}

impl fmt::Debug for PtyCallbackData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "(PtyCallbackData)")
    }
}

impl PtyHandler for PtyCallbackData {
    fn input(&mut self, data: &[u8]) {
        (&mut *self.input_handler)(data);
    }

    fn output(&mut self, data: &[u8]) {
        (&mut *self.output_handler)(data);
    }

    fn resize(&mut self, size: &Winsize) {
        (&mut *self.resize_handler)(size);
    }

    fn shutdown(&mut self) {
        (&mut *self.shutdown_handler)();
    }
}

#[derive(Debug)]
struct PtyCallbackBuilder(PtyCallbackData);

impl PtyCallbackBuilder {
    pub fn new() -> Self {
        let data = PtyCallbackData {
            input_handler: Box::new(|_| {}),
            output_handler: Box::new(|_| {}),
            resize_handler: Box::new(|_| {}),
            shutdown_handler: Box::new(|| {}),
        };

        PtyCallbackBuilder(data)
    }

    pub fn input<F>(mut self, handler: F) -> Self
        where F: FnMut(&[u8]) + 'static {
            self.0.input_handler = Box::new(handler);

            self
    }

    pub fn output<F>(mut self, handler: F) -> Self
        where F: FnMut(&[u8]) + 'static {
            self.0.output_handler = Box::new(handler);

            self
    }

    pub fn resize<F>(mut self, handler: F) -> Self
        where F: FnMut(&Winsize) + 'static {
            self.0.resize_handler = Box::new(handler);

            self
    }

    pub fn shutdown<F>(mut self, handler: F) -> Self
        where F: FnMut() + 'static {
            self.0.shutdown_handler = Box::new(handler);

            self
    }

    pub fn build(self) -> PtyCallbackData {
        self.0
    }
}

pub type PtyCallback = PtyCallbackBuilder;

#[cfg(test)]
mod tests {
    extern crate pty;

    use PtyProxy;
    use PtyHandler;
    use terminal::restore_termios;

    struct TestHandler;
    impl PtyHandler for TestHandler {
        fn output(&mut self, data: &[u8]) {
            assert!(data.len() != 0);
        }
    }

    #[test]
    fn it_can_spawn() {
        let child = pty::fork().unwrap();
        restore_termios();

        child.exec("pwd").unwrap();

        assert!(child.wait().is_ok());
    }

    #[test]
    fn it_can_hook_stdout_with_handler() {
        let child = pty::fork().unwrap();
        restore_termios();

        child.proxy(TestHandler).unwrap();
        child.exec("pwd").unwrap();

        assert!(child.wait().is_ok());
    }

    #[test]
    fn it_can_hook_stdout_with_callback() {
        use PtyCallback;

        let child = pty::fork().unwrap();
        restore_termios();

        child.proxy(
            PtyCallback::new()
                .output(|data| assert!(data.len() != 0))
                .build()
        ).unwrap();
        child.exec("pwd").unwrap();

        assert!(child.wait().is_ok());
    }
}
<|endoftext|>


<commit_before>pub mod session_handler {
    pub fn create(pName: &str) {
        println!("Creating session for profile \"{}\"...", pName);
    }

    pub fn show() {
        println!("Showing sessions...");
    }

    pub fn refresh() {
        println!("Refreshing sessions...");
    }

    pub fn clean() {
        println!("Cleaning sessions...");
    }
}
<commit_msg>Add function reads AWS config file<commit_after>pub mod session_handler {
    use std::fs::File;
    use std::io::BufReader;
    use std::io::prelude::*;
    use std::env;

    pub fn create(pName: &str) {
        println!("Creating session for profile \"{}\"...", pName);
        println!("{}",read_aws_config_file());
    }

    pub fn show() {
        println!("Showing sessions...");
    }

    pub fn refresh() {
        println!("Refreshing sessions...");
    }

    pub fn clean() {
        println!("Cleaning sessions...");
    }

    fn read_aws_config_file() -> String {
        let mut path = match env::home_dir() {
            Some(path) => path,
            None => panic!("Could not retrieve user's home directory."),
        };
        let config_file_path = format!("{}/.aws/config", path.display());

        let f = File::open(config_file_path).expect("Could not find AWS config file.");
        let mut buf_reader = BufReader::new(f);
        let mut contents = String::new();
        buf_reader.read_to_string(&mut contents).expect("Found config file but could not read it.");

        contents
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate log;

use std::collections::{BTreeMap, BTreeSet};

/// The version type alias used to uniquely reference migrations.
pub type Version = i64;

/// All migrations will implement this trait, and a migration trait specific to the chosen adapter.
/// This trait defines the metadata for tracking migration sequence and for human reference.
pub trait Migration {
    /// An ordered (but not necessarily sequential), unique identifier for this migration.
    /// Registered migrations will be applied in ascending order by version.
    fn version(&self) -> Version;

    /// A message describing the effects of this migration.
    fn description(&self) -> &'static str;
}

/// Efficiently implement the `Migration` trait for a given type.
///
/// ## Example
///
/// ```rust
/// # #[macro_use]
/// # extern crate schemamama;
/// struct MyMigration;
/// migration!(MyMigration, 100, "create some lovely database tables");
///
/// # fn main() {
/// use schemamama::Migration;
/// let m = MyMigration;
/// assert_eq!(m.version(), 100);
/// assert_eq!(m.description(), "create some lovely database tables");
/// # }
/// ```
#[macro_export]
macro_rules! migration {
    ($ty:ident, $version:expr, $description:expr) => {
        impl $crate::Migration for $ty {
            fn version(&self) -> $crate::Version { $version }
            fn description(&self) -> &'static str { $description }
        }
    }
}

/// Use this trait to connect the migrator to your chosen database technology.
pub trait Adapter {
    /// An alias to a specific trait that extends `Migration`. Typically, the aforementioned trait
    /// will declare functions that the adapter will use to migrate upwards and downwards.
    type MigrationType: Migration + ?Sized;

    /// Returns the latest migration version, or `None` if no migrations have been recorded. Can
    /// panic if necessary.
    fn current_version(&self) -> Option<Version>;

    /// Returns a set of the versions of all of the currently applied migrations. Can panic if
    /// necessary.
    fn migrated_versions(&self) -> BTreeSet<Version>;

    /// Applies the specified migration. Can panic if necessary.
    fn apply_migration(&self, migration: &Self::MigrationType);

    /// Reverts the specified migration. Can panic if necessary.
    fn revert_migration(&self, migration: &Self::MigrationType);
}

/// Maintains an ordered collection of migrations to utilize.
pub struct Migrator<T: Adapter> {
    adapter: T,
    migrations: BTreeMap<Version, Box<T::MigrationType>>
}

impl<T: Adapter> Migrator<T> {
    /// Create a migrator with a given adapter.
    pub fn new(adapter: T) -> Migrator<T> {
        Migrator { adapter: adapter, migrations: BTreeMap::new() }
    }

    /// Get a reference to the adapter.
    pub fn adapter(&self) -> &T {
        &self.adapter
    }

    /// Register a migration. If a migration with the same version is already registered, a warning
    /// is logged and the registration fails.
    pub fn register(&mut self, migration: Box<T::MigrationType>) {
        let version = migration.version();
        if self.version_registered(version) {
            warn!("Migration with version {:?} is already registered", version);
        } else {
            self.migrations.insert(version, migration);
        }
    }

    /// Returns true is a migration with the provided version has been registered.
    pub fn version_registered(&self, version: Version) -> bool {
        self.migrations.contains_key(&version)
    }

    /// Returns the lowest version of the registered migrations, or `None` if no migrations have
    /// been registered.
    pub fn first_version(&self) -> Option<Version> {
        self.migrations.keys().next().map(|v| *v)
    }

    /// Returns the highest version of the registered migrations, or `None` if no migrations have
    /// been registered.
    pub fn last_version(&self) -> Option<Version> {
        self.migrations.keys().last().map(|v| *v)
    }

    /// Returns the latest migration version, or `None` if no migrations have been recorded.
    ///
    /// ## Panics
    ///
    /// Panics if there is an underlying problem retrieving the current version from the adapter.
    pub fn current_version(&self) -> Option<Version> {
        self.adapter.current_version()
    }

    /// Returns a set of the versions of all of the currently applied migrations.
    ///
    /// ## Panics
    ///
    /// Panics if there is an underlying problem retrieving the current versions from the adapter.
    pub fn migrated_versions(&self) -> BTreeSet<Version> {
        self.adapter.migrated_versions()
    }

    /// Rollback to the specified version (exclusive), or rollback to the state before any
    /// registered migrations were applied if `None` is specified.
    ///
    /// ## Panics
    ///
    /// Panics if there is an underlying problem reverting any of the matched migrations.
    pub fn down(&self, to: Option<Version>) {
        let from = match self.current_version() {
            Some(version) => version,
            None => return,
        };

        let migrated_versions = self.migrated_versions();
        let targets = self.migrations.iter().rev().filter(|&(v, _)| within_range(*v, to, from));
        for (version, migration) in targets {
            if !migrated_versions.contains(version) {
                continue;
            }
            info!("Reverting migration {:?}: {}", version, migration.description());
            self.adapter.revert_migration(migration);
        }
    }

    /// Migrate to the specified version (inclusive).
    ///
    /// ## Panics
    ///
    /// Panics if there is an underlying problem applying any of the matched migrations.
    pub fn up(&self, to: Version) {
        let migrated_versions = self.migrated_versions();
        let targets = self.migrations.iter().filter(|&(v, _)| within_range(*v, None, to));
        for (version, migration) in targets {
            if migrated_versions.contains(version) {
                continue;
            }
            info!("Applying migration {:?}: {}", version, migration.description());
            self.adapter.apply_migration(migration);
        }
    }
}

// Tests whether a `Version` is within a range defined by the exclusive `low` and the inclusive
// `high` bounds.
fn within_range(version: Version, low: Option<Version>, high: Version) -> bool {
    // Inclusive upper bound:
    if version > high {
        return false;
    }

    // Exclusive lower bound:
    match low {
        Some(low) => version > low,
        None => true,
    }
}

#[test]
fn test_within_range() {
    assert!(within_range(0, None, 5));
    assert!(within_range(5, None, 5));
    assert!(!within_range(6, None, 5));
    assert!(!within_range(1, Some(2), 5));
    assert!(!within_range(2, Some(2), 5));
    assert!(within_range(3, Some(2), 5));
    assert!(within_range(5, Some(2), 5));
    assert!(!within_range(6, Some(2), 5));
}
<commit_msg>(enhance) Document/refactor migration application<commit_after>#[macro_use]
extern crate log;

use std::collections::{BTreeMap, BTreeSet};

/// The version type alias used to uniquely reference migrations.
pub type Version = i64;

/// All migrations will implement this trait, and a migration trait specific to the chosen adapter.
/// This trait defines the metadata for tracking migration sequence and for human reference.
pub trait Migration {
    /// An ordered (but not necessarily sequential), unique identifier for this migration.
    /// Registered migrations will be applied in ascending order by version.
    fn version(&self) -> Version;

    /// A message describing the effects of this migration.
    fn description(&self) -> &'static str;
}

/// Efficiently implement the `Migration` trait for a given type.
///
/// ## Example
///
/// ```rust
/// # #[macro_use]
/// # extern crate schemamama;
/// struct MyMigration;
/// migration!(MyMigration, 100, "create some lovely database tables");
///
/// # fn main() {
/// use schemamama::Migration;
/// let m = MyMigration;
/// assert_eq!(m.version(), 100);
/// assert_eq!(m.description(), "create some lovely database tables");
/// # }
/// ```
#[macro_export]
macro_rules! migration {
    ($ty:ident, $version:expr, $description:expr) => {
        impl $crate::Migration for $ty {
            fn version(&self) -> $crate::Version { $version }
            fn description(&self) -> &'static str { $description }
        }
    }
}

/// Use this trait to connect the migrator to your chosen database technology.
pub trait Adapter {
    /// An alias to a specific trait that extends `Migration`. Typically, the aforementioned trait
    /// will declare functions that the adapter will use to migrate upwards and downwards.
    type MigrationType: Migration + ?Sized;

    /// Returns the latest migration version, or `None` if no migrations have been recorded. Can
    /// panic if necessary.
    fn current_version(&self) -> Option<Version>;

    /// Returns a set of the versions of all of the currently applied migrations. Can panic if
    /// necessary.
    fn migrated_versions(&self) -> BTreeSet<Version>;

    /// Applies the specified migration. Can panic if necessary.
    fn apply_migration(&self, migration: &Self::MigrationType);

    /// Reverts the specified migration. Can panic if necessary.
    fn revert_migration(&self, migration: &Self::MigrationType);
}

/// Maintains an ordered collection of migrations to utilize.
pub struct Migrator<T: Adapter> {
    adapter: T,
    migrations: BTreeMap<Version, Box<T::MigrationType>>
}

impl<T: Adapter> Migrator<T> {
    /// Create a migrator with a given adapter.
    pub fn new(adapter: T) -> Migrator<T> {
        Migrator { adapter: adapter, migrations: BTreeMap::new() }
    }

    /// Get a reference to the adapter.
    pub fn adapter(&self) -> &T {
        &self.adapter
    }

    /// Register a migration. If a migration with the same version is already registered, a warning
    /// is logged and the registration fails.
    pub fn register(&mut self, migration: Box<T::MigrationType>) {
        let version = migration.version();
        if self.version_registered(version) {
            warn!("Migration with version {:?} is already registered", version);
        } else {
            self.migrations.insert(version, migration);
        }
    }

    /// Returns true is a migration with the provided version has been registered.
    pub fn version_registered(&self, version: Version) -> bool {
        self.migrations.contains_key(&version)
    }

    /// Returns the lowest version of the registered migrations, or `None` if no migrations have
    /// been registered.
    pub fn first_version(&self) -> Option<Version> {
        self.migrations.keys().next().map(|v| *v)
    }

    /// Returns the highest version of the registered migrations, or `None` if no migrations have
    /// been registered.
    pub fn last_version(&self) -> Option<Version> {
        self.migrations.keys().last().map(|v| *v)
    }

    /// Returns the latest migration version, or `None` if no migrations have been recorded.
    ///
    /// ## Panics
    ///
    /// Panics if there is an underlying problem retrieving the current version from the adapter.
    pub fn current_version(&self) -> Option<Version> {
        self.adapter.current_version()
    }

    /// Returns a set of the versions of all of the currently applied migrations.
    ///
    /// ## Panics
    ///
    /// Panics if there is an underlying problem retrieving the current versions from the adapter.
    pub fn migrated_versions(&self) -> BTreeSet<Version> {
        self.adapter.migrated_versions()
    }

    /// Rollback to the specified version (exclusive), or rollback to the state before any
    /// registered migrations were applied if `None` is specified.
    ///
    /// ## Panics
    ///
    /// Panics if there is an underlying problem reverting any of the matched migrations.
    pub fn down(&self, to: Option<Version>) {
        let from = match self.current_version() {
            Some(version) => version,
            None => return,
        };

        let migrated_versions = self.migrated_versions();
        let targets = self.migrations.iter()
            // Rollback migrations from latest to oldest:
            .rev()
            // Rollback the current version, and all versions downwards until the specified version
            // (exclusive):
            .filter(|&(&v, _)| within_range(v, to, from))
            // Rollback only the migrations that are actually already migrated (in the case that
            // some intermediary migrations were never executed).
            .filter(|&(v, _)| migrated_versions.contains(v));

        for (version, migration) in targets {
            info!("Reverting migration {:?}: {}", version, migration.description());
            self.adapter.revert_migration(migration);
        }
    }

    /// Migrate to the specified version (inclusive).
    ///
    /// ## Panics
    ///
    /// Panics if there is an underlying problem applying any of the matched migrations.
    pub fn up(&self, to: Version) {
        let migrated_versions = self.migrated_versions();
        let targets = self.migrations.iter()
            // Execute all versions upwards until the specified version (inclusive):
            .filter(|&(&v, _)| within_range(v, None, to))
            // Execute only the migrations that are actually not already migrated (in the case that
            // some intermediary migrations were previously executed).
            .filter(|&(v, _)| !migrated_versions.contains(v));

        for (version, migration) in targets {
            info!("Applying migration {:?}: {}", version, migration.description());
            self.adapter.apply_migration(migration);
        }
    }
}

// Tests whether a `Version` is within a range defined by the exclusive `low` and the inclusive
// `high` bounds.
fn within_range(version: Version, low: Option<Version>, high: Version) -> bool {
    // Inclusive upper bound:
    if version > high {
        return false;
    }

    // Exclusive lower bound:
    match low {
        Some(low) => version > low,
        None => true,
    }
}

#[test]
fn test_within_range() {
    assert!(within_range(0, None, 5));
    assert!(within_range(5, None, 5));
    assert!(!within_range(6, None, 5));
    assert!(!within_range(1, Some(2), 5));
    assert!(!within_range(2, Some(2), 5));
    assert!(within_range(3, Some(2), 5));
    assert!(within_range(5, Some(2), 5));
    assert!(!within_range(6, Some(2), 5));
}
<|endoftext|>


<commit_before>/*!
# Kiss3d

Keep It Simple, Stupid 3d graphics engine.

This library is born from the frustration in front of the fact that today’s 3D
graphics library are:

* either too low level: you have to write your own shaders and opening a
  window steals you 8 hours, 300 lines of code and 10L of coffee.
* or high level but too hard to understand/use: those are libraries made to
  write beautiful animations or games. They have a lot of feature; too much
  feature if you only want to draw a few geometries on the screen.

**kiss3d** is not designed to be feature-complete or fast.
It is designed to be able to draw simple geometric figures and play with them
with one-liners.

An on-line version of this documentation is available [here](http://kiss3d.org).

## Features
Most features are one-liners.

* WASM compatibility.
* open a window with a default arc-ball camera and a point light.
* a first-person camera is available too and user-defined cameras are possible.
* display boxes, spheres, cones, cylinders, quads and lines.
* change an object color or texture.
* change an object transform (we use the [nalgebra](http://nalgebra.org) library
  to do that).
* create basic post-processing effects.

As an example, having a red, rotating cube with the light attached to the camera is as simple as (NOTE: this will **not** compile when targeting WASM):

```no_run
extern crate kiss3d;
extern crate nalgebra as na;

use na::{Vector3, UnitQuaternion};
use kiss3d::window::Window;
use kiss3d::light::Light;

fn main() {
    let mut window = Window::new("Kiss3d: cube");
    let mut c      = window.add_cube(1.0, 1.0, 1.0);

    c.set_color(1.0, 0.0, 0.0);

    window.set_light(Light::StickToCamera);

    let rot = UnitQuaternion::from_axis_angle(&Vector3::y_axis(), 0.014);

    while window.render() {
        c.prepend_to_local_rotation(&rot);
    }
}
```

The same example, but that will compile for both WASM and native platforms is slightly more complicated because **kiss3d** must control the render loop:

```no_run
extern crate kiss3d;
extern crate nalgebra as na;

use kiss3d::light::Light;
use kiss3d::scene::SceneNode;
use kiss3d::window::{State, Window};
use na::{UnitQuaternion, Vector3};

struct AppState {
    c: SceneNode,
    rot: UnitQuaternion<f32>,
}

impl State for AppState {
    fn step(&mut self, _: &mut Window) {
        self.c.prepend_to_local_rotation(&self.rot)
    }
}

fn main() {
    let mut window = Window::new("Kiss3d: wasm example");
    let mut c = window.add_cube(1.0, 1.0, 1.0);

    c.set_color(1.0, 0.0, 0.0);

    window.set_light(Light::StickToCamera);

    let rot = UnitQuaternion::from_axis_angle(&Vector3::y_axis(), 0.014);
    let state = AppState { c, rot };

    window.render_loop(state)
}
```

Some controls are handled by default by the engine (they can be overridden by the user):

* `scroll`: zoom in / zoom out.
* `left click + drag`: look around.
* `right click + drag`: translate the view point.
* `enter`: look at the origin (0.0, 0.0, 0.0).

## Compilation
You will need the last stable build of the [rust compiler](http://www.rust-lang.org)
and the official package manager: [cargo](https://github.com/rust-lang/cargo).

Simply add the following to your `Cargo.toml` file:

```text
[dependencies]
kiss3d = "0.24"
```

## Contributions
I’d love to see people improving this library for their own needs. However, keep in mind that
**kiss3d** is KISS. One-liner features (from the user point of view) are preferred.

## Acknowledgements

Thanks to all the Rustaceans for their help, and their OpenGL bindings.
*/

#![deny(non_camel_case_types)]
#![deny(unused_parens)]
#![warn(non_upper_case_globals)] // FIXME: should be denied.
#![deny(unused_qualifications)]
#![warn(missing_docs)] // FIXME: should be denied.
#![warn(unused_results)]
#![allow(unused_unsafe)] // FIXME: should be denied
#![allow(missing_copy_implementations)]
#![doc(html_root_url = "http://kiss3d.org/doc")]

#[macro_use]
extern crate bitflags;
extern crate nalgebra as na;
extern crate num_traits as num;
extern crate rusttype;
#[macro_use]
extern crate serde_derive;
extern crate serde;

#[cfg(not(any(target_arch = "wasm32", target_arch = "asmjs")))]
extern crate gl;
#[cfg(not(any(target_arch = "wasm32", target_arch = "asmjs")))]
extern crate glutin;
#[cfg(any(target_arch = "wasm32", target_arch = "asmjs"))]
#[macro_use]
extern crate stdweb;
#[cfg(any(target_arch = "wasm32", target_arch = "asmjs"))]
#[macro_use]
extern crate stdweb_derive;
#[cfg(feature = "conrod")]
pub extern crate conrod_core as conrod;
extern crate instant;
#[cfg(feature = "conrod")]
pub use conrod::widget_ids;

pub use nalgebra;
pub use ncollide3d as ncollide;

#[deprecated(note = "Use the `renderer` module instead.")]
pub use crate::renderer::line_renderer;
#[deprecated(note = "Use the `renderer` module instead.")]
pub use crate::renderer::point_renderer;

pub mod builtin;
pub mod camera;
pub mod context;
mod error;
pub mod event;
pub mod light;
pub mod loader;
pub mod planar_camera;
pub mod planar_line_renderer;
pub mod post_processing;
pub mod renderer;
pub mod resource;
pub mod scene;
pub mod text;
pub mod window;
<commit_msg>Export ncollide3d without alias.<commit_after>/*!
# Kiss3d

Keep It Simple, Stupid 3d graphics engine.

This library is born from the frustration in front of the fact that today’s 3D
graphics library are:

* either too low level: you have to write your own shaders and opening a
  window steals you 8 hours, 300 lines of code and 10L of coffee.
* or high level but too hard to understand/use: those are libraries made to
  write beautiful animations or games. They have a lot of feature; too much
  feature if you only want to draw a few geometries on the screen.

**kiss3d** is not designed to be feature-complete or fast.
It is designed to be able to draw simple geometric figures and play with them
with one-liners.

An on-line version of this documentation is available [here](http://kiss3d.org).

## Features
Most features are one-liners.

* WASM compatibility.
* open a window with a default arc-ball camera and a point light.
* a first-person camera is available too and user-defined cameras are possible.
* display boxes, spheres, cones, cylinders, quads and lines.
* change an object color or texture.
* change an object transform (we use the [nalgebra](http://nalgebra.org) library
  to do that).
* create basic post-processing effects.

As an example, having a red, rotating cube with the light attached to the camera is as simple as (NOTE: this will **not** compile when targeting WASM):

```no_run
extern crate kiss3d;
extern crate nalgebra as na;

use na::{Vector3, UnitQuaternion};
use kiss3d::window::Window;
use kiss3d::light::Light;

fn main() {
    let mut window = Window::new("Kiss3d: cube");
    let mut c      = window.add_cube(1.0, 1.0, 1.0);

    c.set_color(1.0, 0.0, 0.0);

    window.set_light(Light::StickToCamera);

    let rot = UnitQuaternion::from_axis_angle(&Vector3::y_axis(), 0.014);

    while window.render() {
        c.prepend_to_local_rotation(&rot);
    }
}
```

The same example, but that will compile for both WASM and native platforms is slightly more complicated because **kiss3d** must control the render loop:

```no_run
extern crate kiss3d;
extern crate nalgebra as na;

use kiss3d::light::Light;
use kiss3d::scene::SceneNode;
use kiss3d::window::{State, Window};
use na::{UnitQuaternion, Vector3};

struct AppState {
    c: SceneNode,
    rot: UnitQuaternion<f32>,
}

impl State for AppState {
    fn step(&mut self, _: &mut Window) {
        self.c.prepend_to_local_rotation(&self.rot)
    }
}

fn main() {
    let mut window = Window::new("Kiss3d: wasm example");
    let mut c = window.add_cube(1.0, 1.0, 1.0);

    c.set_color(1.0, 0.0, 0.0);

    window.set_light(Light::StickToCamera);

    let rot = UnitQuaternion::from_axis_angle(&Vector3::y_axis(), 0.014);
    let state = AppState { c, rot };

    window.render_loop(state)
}
```

Some controls are handled by default by the engine (they can be overridden by the user):

* `scroll`: zoom in / zoom out.
* `left click + drag`: look around.
* `right click + drag`: translate the view point.
* `enter`: look at the origin (0.0, 0.0, 0.0).

## Compilation
You will need the last stable build of the [rust compiler](http://www.rust-lang.org)
and the official package manager: [cargo](https://github.com/rust-lang/cargo).

Simply add the following to your `Cargo.toml` file:

```text
[dependencies]
kiss3d = "0.24"
```

## Contributions
I’d love to see people improving this library for their own needs. However, keep in mind that
**kiss3d** is KISS. One-liner features (from the user point of view) are preferred.

## Acknowledgements

Thanks to all the Rustaceans for their help, and their OpenGL bindings.
*/

#![deny(non_camel_case_types)]
#![deny(unused_parens)]
#![warn(non_upper_case_globals)] // FIXME: should be denied.
#![deny(unused_qualifications)]
#![warn(missing_docs)] // FIXME: should be denied.
#![warn(unused_results)]
#![allow(unused_unsafe)] // FIXME: should be denied
#![allow(missing_copy_implementations)]
#![doc(html_root_url = "http://kiss3d.org/doc")]

#[macro_use]
extern crate bitflags;
extern crate nalgebra as na;
extern crate num_traits as num;
extern crate rusttype;
#[macro_use]
extern crate serde_derive;
extern crate serde;

#[cfg(not(any(target_arch = "wasm32", target_arch = "asmjs")))]
extern crate gl;
#[cfg(not(any(target_arch = "wasm32", target_arch = "asmjs")))]
extern crate glutin;
#[cfg(any(target_arch = "wasm32", target_arch = "asmjs"))]
#[macro_use]
extern crate stdweb;
#[cfg(any(target_arch = "wasm32", target_arch = "asmjs"))]
#[macro_use]
extern crate stdweb_derive;
#[cfg(feature = "conrod")]
pub extern crate conrod_core as conrod;
extern crate instant;
#[cfg(feature = "conrod")]
pub use conrod::widget_ids;

pub use nalgebra;
pub use ncollide3d;

#[deprecated(note = "Use the `renderer` module instead.")]
pub use crate::renderer::line_renderer;
#[deprecated(note = "Use the `renderer` module instead.")]
pub use crate::renderer::point_renderer;

pub mod builtin;
pub mod camera;
pub mod context;
mod error;
pub mod event;
pub mod light;
pub mod loader;
pub mod planar_camera;
pub mod planar_line_renderer;
pub mod post_processing;
pub mod renderer;
pub mod resource;
pub mod scene;
pub mod text;
pub mod window;
<|endoftext|>


<commit_before>use std::net::{SocketAddrV4, SocketAddrV6};

pub enum WirelessMode {
    Auto,       /* Let the driver decide */
    AdHoc,      /* Single cell network */
    Infra,      /* Multi cell network, roaming, ... */
    Master,     /* Synchronisation master or Access Point */
    Repeat,     /* Wireless Repeater (forwarder) */
    Second,     /* Secondary master/repeater (backup) */
    Monitor     /* Passive monitor (listen only) */
}

pub struct IwQuality {
    quality: u8,
    level: u8,
    noise: u8
}

pub struct IwStats {
    status: uint16,
    quality: IwQuality,
}

pub struct WirelessKey {
    key: &[u8],
    size: u32,
    flags: i32
}

pub struct WirelessNetwork {
    ap_addr4: Option<SocketAddrV4>,
    ap_addr6: Option<SocketAddrV6>,
    stats: Option<IwStats>,
    maxbitrate: Option<i32>,
    name: String,
    freq: Option<f64>,
    key: Option<WirelessKey>,
    essid: Option<String>,
    mode: Option<WirelessMode>
}

struct priv_iw_quality {
    qual: uint8_t,
    level: uint8_t,
    noise: uint8_t,
    updated: uint8_t
}

struct priv_iw_freq {
    m: int32_t,
    e: int16_t,
    i: uint8_t,
    flags: uint8_t
}

#[repr(C)]
struct  iw_range {
    /* Informative stuff (to choose between different interface) */
    throughput: uint32_t,   /* To give an idea... */
    /* In theory this value should be the maximum benchmarked
     * TCP/IP throughput, because with most of these devices the
     * bit rate is meaningless (overhead an co) to estimate how
     * fast the connection will go and pick the fastest one.
     * I suggest people to play with Netperf or any benchmark...
     */

    /* NWID (or domain id) */
    min_nwid: uint32_t, /* Minimal NWID we are able to set */
    max_nwid: uint32_t, /* Maximal NWID we are able to set */

    /* Old Frequency (backward compat - moved lower ) */
    old_num_channels: uint16_t,
    old_num_frequency: uint8_t,

    /* Wireless event capability bitmasks */
    event_capa: [uint32_t, 6],

    /* signal level threshold range */
    sensitivity: int32_t,

    /* Quality of link & SNR stuff */
    /* Quality range (link, level, noise)
     * If the quality is absolute, it will be in the range [0 , max_qual],
     * if the quality is dBm, it will be in the range [max_qual , 0].
     * Don't forget that we use 8 bit arithmetics... */
    max_qual: priv_iw_quality,  /* Quality of the link */
    /* This should contain the average/typical values of the quality
     * indicator. This should be the threshold between a "good" and
     * a "bad" link (example : monitor going from green to orange).
     * Currently, user space apps like quality monitors don't have any
     * way to calibrate the measurement. With this, they can split
     * the range between 0 and max_qual in different quality level
     * (using a geometric subdivision centered on the average).
     * I expect that people doing the user space apps will feedback
     * us on which value we need to put in each driver... */
    avg_qual: priv_iw_quality,  /* Quality of the link */

    /* Rates */
    num_bitrates: uint8_t,  /* Number of entries in the list */
    bitrate: [int32_t; IW_MAX_BITRATES],    /* list, in bps */

    /* RTS threshold */
    min_rts: int32_t,   /* Minimal RTS threshold */
    max_rts: int32_t,   /* Maximal RTS threshold */

    /* Frag threshold */
    min_frag: int32_t,  /* Minimal frag threshold */
    max_frag: int32_t,  /* Maximal frag threshold */

    /* Power Management duration & timeout */
    min_pmp: int32_t,   /* Minimal PM period */
    max_pmp: int32_t,   /* Maximal PM period */
    min_pmt: int32_t,   /* Minimal PM timeout */
    max_pmt: int32_t,   /* Maximal PM timeout */
    pmp_flags: uint16_t,    /* How to decode max/min PM period */
    pmt_flags uint16_t, /* How to decode max/min PM timeout */
    pm_capa: uint16_t,  /* What PM options are supported */

    /* Encoder stuff */
    encoding_size: [uint16_t; IW_MAX_ENCODING_SIZES],   /* Different token sizes */
    num_encoding_sizes: uint8_t,    /* Number of entry in the list */
    max_encoding_tokens: uint8_t,   /* Max number of tokens */
    /* For drivers that need a "login/passwd" form */
    encoding_login_index: uint8_t,  /* token index for login token */

    /* Transmit power */
    txpower_capa: uint16_t, /* What options are supported */
    num_txpower: uint8_t,   /* Number of entries in the list */
    txpower: [int32_t; IW_MAX_TXPOWER], /* list, in bps */

    /* Wireless Extension version info */
    we_version_compiled: uint8_t,   /* Must be WIRELESS_EXT */
    we_version_source: uint8_t, /* Last update of source */

    /* Retry limits and lifetime */
    retry_capa: uint16_t,   /* What retry options are supported */
    retry_flags: uint16_t,  /* How to decode max/min retry limit */
    r_time_flags: uint16_t, /* How to decode max/min retry life */
    min_retry: int32_t, /* Minimal number of retries */
    max_retry: int32_t, /* Maximal number of retries */
    min_r_time: int32_t,    /* Minimal retry lifetime */
    max_r_time: int32_t,    /* Maximal retry lifetime */

    /* Frequency */
    num_channels: uint16_t, /* Number of channels [0, num - 1] */
    num_frequency: uint8_t, /* Number of entry in the list */
    freq: [priv_iw_freq; IW_MAX_FREQUENCIES],   /* list */
    /* Note : this frequency list doesn't need to fit channel numbers,
     * because each entry contain its channel index */

    enc_capa: uint32_t, /* IW_ENC_CAPA_* bit field */

    /* More power management stuff */
    min_pms: int32_t,   /* Minimal PM saving */
    max_pms: int32_t,   /* Maximal PM saving */
    pms_flags: int16_t, /* How to decode max/min PM saving */

    /* All available modulations for driver (hw may support less) */
    modul_capa: uint32_t,   /* IW_MODUL_* bit field */

    /* More bitrate stuff */
    bitrate_capa: uint32_t, /* Types of bitrates supported */
}

pub struct WifiScan {
    networks: Vec<WirelessNetwork>
}

impl WifiScan {
    pub fn new() {
        WifiScan{ networks: Vec::new() }
    }

    pub fn scan() {
        // Scan things here
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<commit_msg>Fix typos and bugs<commit_after>extern crate libc;

use std::net::{SocketAddrV4, SocketAddrV6};
use libc::*;

pub enum WirelessMode {
    Auto, /* Let the driver decide */
    AdHoc, /* Single cell network */
    Infra, /* Multi cell network, roaming, ... */
    Master, /* Synchronisation master or Access Point */
    Repeat, /* Wireless Repeater (forwarder) */
    Second, /* Secondary master/repeater (backup) */
    Monitor, /* Passive monitor (listen only) */
}

pub struct IwQuality {
    quality: u8,
    level: u8,
    noise: u8,
}

pub struct IwStats {
    status: uint16_t,
    quality: IwQuality,
}

pub struct WirelessKey<'a> {
    key: &'a [u8],
    size: u32,
    flags: i32,
}

pub struct WirelessNetwork<'a> {
    ap_addr4: Option<SocketAddrV4>,
    ap_addr6: Option<SocketAddrV6>,
    stats: Option<IwStats>,
    maxbitrate: Option<i32>,
    name: String,
    freq: Option<f64>,
    key: Option<WirelessKey<'a>>,
    essid: Option<String>,
    mode: Option<WirelessMode>,
}

struct priv_iw_quality {
    qual: uint8_t,
    level: uint8_t,
    noise: uint8_t,
    updated: uint8_t,
}

struct priv_iw_freq {
    m: int32_t,
    e: int16_t,
    i: uint8_t,
    flags: uint8_t,
}

#[repr(C)]
struct iw_range {
    /* Informative stuff (to choose between different interface) */
    throughput: uint32_t, /* To give an idea... */
    /* In theory this value should be the maximum benchmarked
     * TCP/IP throughput, because with most of these devices the
     * bit rate is meaningless (overhead an co) to estimate how
     * fast the connection will go and pick the fastest one.
     * I suggest people to play with Netperf or any benchmark...
     */

    /* NWID (or domain id) */
    min_nwid: uint32_t, /* Minimal NWID we are able to set */
    max_nwid: uint32_t, /* Maximal NWID we are able to set */

    /* Old Frequency (backward compat - moved lower ) */
    old_num_channels: uint16_t,
    old_num_frequency: uint8_t,

    /* Wireless event capability bitmasks */
    event_capa: [uint32_t; 6],

    /* signal level threshold range */
    sensitivity: int32_t,

    /* Quality of link & SNR stuff */
    /* Quality range (link, level, noise)
     * If the quality is absolute, it will be in the range [0 , max_qual],
     * if the quality is dBm, it will be in the range [max_qual , 0].
     * Don't forget that we use 8 bit arithmetics... */
    max_qual: priv_iw_quality, /* Quality of the link */
    /* This should contain the average/typical values of the quality
     * indicator. This should be the threshold between a "good" and
     * a "bad" link (example : monitor going from green to orange).
     * Currently, user space apps like quality monitors don't have any
     * way to calibrate the measurement. With this, they can split
     * the range between 0 and max_qual in different quality level
     * (using a geometric subdivision centered on the average).
     * I expect that people doing the user space apps will feedback
     * us on which value we need to put in each driver... */
    avg_qual: priv_iw_quality, /* Quality of the link */

    /* Rates */
    num_bitrates: uint8_t, /* Number of entries in the list */
    bitrate: [int32_t; IW_MAX_BITRATES], /* list, in bps */

    /* RTS threshold */
    min_rts: int32_t, /* Minimal RTS threshold */
    max_rts: int32_t, /* Maximal RTS threshold */

    /* Frag threshold */
    min_frag: int32_t, /* Minimal frag threshold */
    max_frag: int32_t, /* Maximal frag threshold */

    /* Power Management duration & timeout */
    min_pmp: int32_t, /* Minimal PM period */
    max_pmp: int32_t, /* Maximal PM period */
    min_pmt: int32_t, /* Minimal PM timeout */
    max_pmt: int32_t, /* Maximal PM timeout */
    pmp_flags: uint16_t, /* How to decode max/min PM period */
    pmt_flags: uint16_t, /* How to decode max/min PM timeout */
    pm_capa: uint16_t, /* What PM options are supported */

    /* Encoder stuff */
    encoding_size: [uint16_t; IW_MAX_ENCODING_SIZES], /* Different token sizes */
    num_encoding_sizes: uint8_t, /* Number of entry in the list */
    max_encoding_tokens: uint8_t, /* Max number of tokens */
    /* For drivers that need a "login/passwd" form */
    encoding_login_index: uint8_t, /* token index for login token */

    /* Transmit power */
    txpower_capa: uint16_t, /* What options are supported */
    num_txpower: uint8_t, /* Number of entries in the list */
    txpower: [int32_t; IW_MAX_TXPOWER], /* list, in bps */

    /* Wireless Extension version info */
    we_version_compiled: uint8_t, /* Must be WIRELESS_EXT */
    we_version_source: uint8_t, /* Last update of source */

    /* Retry limits and lifetime */
    retry_capa: uint16_t, /* What retry options are supported */
    retry_flags: uint16_t, /* How to decode max/min retry limit */
    r_time_flags: uint16_t, /* How to decode max/min retry life */
    min_retry: int32_t, /* Minimal number of retries */
    max_retry: int32_t, /* Maximal number of retries */
    min_r_time: int32_t, /* Minimal retry lifetime */
    max_r_time: int32_t, /* Maximal retry lifetime */

    /* Frequency */
    num_channels: uint16_t, /* Number of channels [0, num - 1] */
    num_frequency: uint8_t, /* Number of entry in the list */
    freq: [priv_iw_freq; IW_MAX_FREQUENCIES], /* list */
    /* Note : this frequency list doesn't need to fit channel numbers,
     * because each entry contain its channel index */
    enc_capa: uint32_t, /* IW_ENC_CAPA_* bit field */

    /* More power management stuff */
    min_pms: int32_t, /* Minimal PM saving */
    max_pms: int32_t, /* Maximal PM saving */
    pms_flags: int16_t, /* How to decode max/min PM saving */

    /* All available modulations for driver (hw may support less) */
    modul_capa: uint32_t, /* IW_MODUL_* bit field */

    /* More bitrate stuff */
    bitrate_capa: uint32_t, /* Types of bitrates supported */
}

pub struct WifiScan<'a> {
    networks: Vec<WirelessNetwork<'a>>,
}

impl<'a> WifiScan<'a> {
    pub fn new() -> WifiScan {
        WifiScan { networks: Vec::new() }
    }

    pub fn scan() {
        // Scan things here
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {}
}
<|endoftext|>


<commit_before>trait DOMNode {}
impl<'a, T: DOMNode> DOMNode for &'a T {}

trait DOMLevel {
    type NodeType: DOMNode;
    type ChildrenType: DOMChildren;
}
impl<T: DOMNode> DOMLevel for T {
    type NodeType = T;
    type ChildrenType = ();
}

trait DOMChildrenProcessor {
    type State;
    fn get_processor<T: DOMLevel>() -> fn(&mut Self::State, T) -> ();
}

trait DOMChildren {
    fn process_all<P: DOMChildrenProcessor>(&self, processor: &mut P::State) -> ();
}
impl DOMChildren for () {
    fn process_all<P: DOMChildrenProcessor>(&self, _processor: &mut P::State) -> () {}
}

impl<'a, T: DOMChildren> DOMChildren for &'a T {
    fn process_all<P: DOMChildrenProcessor>(&self, processor: &mut P::State) -> () {
        (*self).process_all::<P>(processor);
    }
}

// Credit to @shepmaster for structure of recursive tuple macro
macro_rules! tuple_impls {
    () => {};

    // Copywrite @shepmaster
    (($idx:tt => $typ:ident), $( ($nidx:tt => $ntyp:ident), )*) => {
        /*
         * Invoke recursive reversal of list that ends in the macro expansion implementation
         * of the reversed list
        */
        tuple_impls!([($idx, $typ);] $( ($nidx => $ntyp), )*);
        tuple_impls!($( ($nidx => $ntyp), )*); // invoke macro on tail
    };

    /*
     * ([accumulatedList], listToReverse); recursively calls tuple_impls until the list to reverse
     + is empty (see next pattern)
    */
    ([$(($accIdx: tt, $accTyp: ident);)+]  ($idx:tt => $typ:ident), $( ($nidx:tt => $ntyp:ident), )*) => {
      tuple_impls!([($idx, $typ); $(($accIdx, $accTyp); )*] $( ($nidx => $ntyp), ) *);
    };

    // Finally expand into the implementation
    ([($idx:tt, $typ:ident); $( ($nidx:tt, $ntyp:ident); )*]) => {
        impl<$typ, $( $ntyp ),*> DOMChildren for ($typ, $( $ntyp ),*)
            where $typ: DOMLevel + Copy,
                  $( $ntyp: DOMLevel + Copy ),*
        {
            fn process_all<P>(&self, state: &mut P::State) -> ()
                    where P: DOMChildrenProcessor {
                P::get_processor()(state, self.$idx);
                $(
                    P::get_processor()(state, self.$nidx);
                )*
            }
        }
    }
}

tuple_impls!(
    (9 => J),
    (8 => I),
    (7 => H),
    (6 => G),
    (5 => F),
    (4 => E),
    (3 => D),
    (2 => C),
    (1 => B),
    (0 => A),
);

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

    #[derive(Copy, Clone)]
    struct BogusOne;
    impl DOMNode for BogusOne {}

    struct BogusTwo;
    impl DOMNode for BogusTwo {}

    struct ChildCounter;
    impl DOMChildrenProcessor for ChildCounter {
        type State = usize;

        fn get_processor<T: DOMLevel>() -> fn(&mut Self::State, T) -> () {
            fn incr<T: DOMLevel>(state: &mut usize, _level: T) {
                *state += 1;
            }
            incr
        }
    }

    #[test]
    fn counts_children() {
        let mut count = 0;
        (BogusOne, &BogusOne, &BogusTwo).process_all::<ChildCounter>(&mut count);
        assert_eq!(3, count);
    }
}
<commit_msg>Changed DOMChildrenProcessor to take a reference to DOMLevel<commit_after>trait DOMNode {}
impl<'a, T: DOMNode> DOMNode for &'a T {}

trait DOMLevel {
    type NodeType: DOMNode;
    type ChildrenType: DOMChildren;
}
impl<T: DOMNode> DOMLevel for T {
    type NodeType = T;
    type ChildrenType = ();
}

trait DOMChildrenProcessor {
    type State;
    fn get_processor<T: DOMLevel>() -> fn(&mut Self::State, &T) -> ();
}

trait DOMChildren {
    fn process_all<P: DOMChildrenProcessor>(&self, processor: &mut P::State) -> ();
}
impl DOMChildren for () {
    fn process_all<P: DOMChildrenProcessor>(&self, _processor: &mut P::State) -> () {}
}

// Credit to @shepmaster for structure of recursive tuple macro
macro_rules! tuple_impls {
    () => {};

    // Copywrite @shepmaster
    (($idx:tt => $typ:ident), $( ($nidx:tt => $ntyp:ident), )*) => {
        /*
         * Invoke recursive reversal of list that ends in the macro expansion implementation
         * of the reversed list
        */
        tuple_impls!([($idx, $typ);] $( ($nidx => $ntyp), )*);
        tuple_impls!($( ($nidx => $ntyp), )*); // invoke macro on tail
    };

    /*
     * ([accumulatedList], listToReverse); recursively calls tuple_impls until the list to reverse
     + is empty (see next pattern)
    */
    ([$(($accIdx: tt, $accTyp: ident);)+]  ($idx:tt => $typ:ident), $( ($nidx:tt => $ntyp:ident), )*) => {
      tuple_impls!([($idx, $typ); $(($accIdx, $accTyp); )*] $( ($nidx => $ntyp), ) *);
    };

    // Finally expand into the implementation
    ([($idx:tt, $typ:ident); $( ($nidx:tt, $ntyp:ident); )*]) => {
        impl<$typ, $( $ntyp ),*> DOMChildren for ($typ, $( $ntyp ),*)
            where $typ: DOMLevel + Copy,
                  $( $ntyp: DOMLevel + Copy ),*
        {
            fn process_all<P>(&self, state: &mut P::State) -> ()
                    where P: DOMChildrenProcessor {
                P::get_processor()(state, &self.$idx);
                $(
                    P::get_processor()(state, &self.$nidx);
                )*
            }
        }
    }
}

tuple_impls!(
    (9 => J),
    (8 => I),
    (7 => H),
    (6 => G),
    (5 => F),
    (4 => E),
    (3 => D),
    (2 => C),
    (1 => B),
    (0 => A),
);

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

    #[derive(Copy, Clone)]
    struct BogusOne;
    impl DOMNode for BogusOne {}

    struct BogusTwo;
    impl DOMNode for BogusTwo {}

    struct ChildCounter;
    impl DOMChildrenProcessor for ChildCounter {
        type State = usize;

        fn get_processor<T: DOMLevel>() -> fn(&mut Self::State, &T) -> () {
            fn incr<T: DOMLevel>(state: &mut usize, _level: &T) {
                *state += 1;
            }
            incr
        }
    }

    #[test]
    fn counts_children() {
        let mut count = 0;
        (BogusOne, &BogusOne, &BogusTwo).process_all::<ChildCounter>(&mut count);
        assert_eq!(3, count);
    }
}
<|endoftext|>


<commit_before>use std::io::prelude::*;
use std::io::{Error, ErrorKind};

pub struct VariableSizeByteWriter {
    buf: Vec<u8>,
    bits: u32,
}

impl VariableSizeByteWriter {
    pub fn new(cap: usize) -> VariableSizeByteWriter {
        VariableSizeByteWriter {
            buf: vec![0; cap],
            bits: 0,
        }
    }

    #[inline]
    pub fn complete_bytes(&mut self) -> usize {
        (self.bits / 8) as usize
    }

    #[inline]
    pub fn partial_bits(&mut self) -> u32 {
        (self.bits % 8)
    }

    pub fn get_complete_bytes(&mut self) -> &[u8] {
        let bytes = self.complete_bytes();
        &self.buf[..bytes]
    }

    pub fn get_all_bytes(&mut self, partial_bits: &mut u32) -> &[u8] {
        let bytes = self.complete_bytes();
        *partial_bits = self.partial_bits();
        if *partial_bits > 0 {
            &self.buf[..bytes + 1]
        } else {
            &self.buf[..bytes]
        }
    }

    pub fn get_partial_byte(&mut self) -> Option<(u8, u32)> {
        let bytes = self.complete_bytes();
        let partial_bits = self.partial_bits();
        let partial = self.buf[bytes];
        if partial_bits > 0 {
            Some((partial, partial_bits as u32))
        } else {
            None
        }
    }

    pub fn erase_complete_bytes(&mut self) {
        let bytes = self.complete_bytes();
        let possible_partial = self.buf[bytes];
        self.buf[..bytes + 1].iter_mut().for_each(|n| *n = 0);
        self.buf[0] = possible_partial;
        self.bits = self.partial_bits() as u32;
    }

    pub fn erase_all_bytes(&mut self) {
        let bytes = self.complete_bytes();
        self.buf[..bytes + 1].iter_mut().for_each(|n| *n = 0);
        self.bits = 0;
    }

    pub fn move_range_to_start(&mut self, from: usize, to: usize) {
        let mut offset = 0;
        while from + offset < to {
            self.buf[offset] = self.buf[from + offset];
        }
        self.bits -= 8 * (to - from) as u32;
    }

    pub fn write_range<T>(&mut self, writer: &mut T, from: usize, to: usize, written: &mut usize) -> std::io::Result<()>
        where T: Write
    {
        *written = 0;
        while from + *written < to {
            match writer.write(&self.buf[from + *written..to]) {
                Ok(0) => return Err(Error::new(ErrorKind::WriteZero, "zero bytes written")),
                Ok(bytes) => *written += bytes,
                Err(ref err) if err.kind() == ErrorKind::Interrupted => {}
                Err(err) => return Err(err),
            }
        }
        Ok(())
    }

    pub fn insert_32(&mut self, variable: u32, bits: u32) {
        let byte: usize = self.complete_bytes();
        let offset: u32 = self.partial_bits();

		self.buf[byte] |= (variable << offset) as u8;
        let variable = variable >> 8 - offset;
		self.buf[byte + 1] |= variable as u8;
        let variable = variable >> 8;
		self.buf[byte + 2] |= variable as u8;
        let variable = variable >> 8;
		self.buf[byte + 3] |= variable as u8;
        let variable = variable >> 8;
		self.buf[byte + 4] |= variable as u8;

        self.bits += bits;
    }

    pub fn insert_32_unchecked(&mut self, variable: u32, bits: u32) {
        let byte: usize = self.complete_bytes();
        let offset: u32 = self.partial_bits();

        unsafe {
            let i = self.buf.get_unchecked_mut(byte as usize);
		    *i |= (variable << offset) as u8;
        }
        let variable = variable >> 8 - offset;
        unsafe {
            let i = self.buf.get_unchecked_mut(byte + 1 as usize);
		    *i |= variable as u8;
        }
        let variable = variable >> 8;
        unsafe {
            let i = self.buf.get_unchecked_mut(byte + 2 as usize);
		    *i |= variable as u8;
        }
        let variable = variable >> 8;
        unsafe {
            let i = self.buf.get_unchecked_mut(byte + 3 as usize);
		    *i |= variable as u8;
        }
        let variable = variable >> 8;
        unsafe {
            let i = self.buf.get_unchecked_mut(byte + 4 as usize);
		    *i |= variable as u8;
        }

        self.bits += bits;
    }

    pub fn insert_16(&mut self, variable: u16, bits: u32) {
        let byte: usize = self.complete_bytes();
        let offset: u32 = self.partial_bits();

		self.buf[byte] |= (variable << offset) as u8;
        let variable = variable >> 8 - offset;
		self.buf[byte + 1] |= variable as u8;
        let variable = variable >> 8;
		self.buf[byte + 2] |= variable as u8;

        self.bits += bits;
    }

    pub fn insert_16_unchecked(&mut self, variable: u16, bits: u32) {
        let byte: usize = self.complete_bytes();
        let offset: u32 = self.partial_bits();

        unsafe {
            let i = self.buf.get_unchecked_mut(byte as usize);
		    *i |= (variable << offset) as u8;
        }
        let variable = variable >> 8 - offset;
        unsafe {
            let i = self.buf.get_unchecked_mut(byte + 1 as usize);
		    *i |= variable as u8;
        }
        let variable = variable >> 8;
        unsafe {
            let i = self.buf.get_unchecked_mut(byte + 2 as usize);
		    *i |= variable as u8;
        }

        self.bits += bits;
    }
}

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

    #[test]
    fn test_complete_bytes() {
        let mut writer = VariableSizeByteWriter::new(6);
        writer.buf[3] = 0xFF;
        writer.buf[4] = 0xF;
        writer.bits = 36;
        assert_eq!(writer.complete_bytes(), 4);
    }

    #[test]
    fn test_partial_bits() {
        let mut writer = VariableSizeByteWriter::new(6);
        writer.buf[3] = 0xFF;
        writer.buf[4] = 0xF;
        writer.bits = 36;
        assert_eq!(writer.partial_bits(), 4);
    }

    #[test]
    fn test_get_complete_bytes() {
        let mut writer = VariableSizeByteWriter::new(16);
        writer.buf[0] = 0xAA;
        writer.buf[3] = 0xFF;
        writer.buf[4] = 0xF;
        writer.bits = 36;
        assert_eq!(writer.get_complete_bytes(), [0xAA, 0, 0, 0xFF]);
    }

    #[test]
    fn test_get_all_bytes() {
        let mut writer = VariableSizeByteWriter::new(16);
        writer.buf[0] = 0xAA;
        writer.buf[3] = 0xFF;
        writer.buf[4] = 0xF;
        writer.bits = 36;
        let mut partial_bits = 0;
        assert_eq!(writer.get_all_bytes(&mut partial_bits), [0xAA, 0, 0, 0xFF, 0xF]);
        assert_eq!(partial_bits, 4);
    }

    #[test]
    fn test_get_partial_byte() {
        let mut writer = VariableSizeByteWriter::new(16);
        writer.buf[0] = 0xAA;
        writer.buf[3] = 0xFF;
        writer.buf[4] = 0xF;
        writer.bits = 36;
        let ret = writer.get_partial_byte();
        assert_eq!(ret, Some((0xF, 4)));

        let mut writer = VariableSizeByteWriter::new(16);
        writer.buf[0] = 0xAA;
        writer.buf[3] = 0xFF;
        writer.bits = 32;
        let ret = writer.get_partial_byte();
        assert_eq!(ret, None);
    }

    #[test]
    fn test_erase_complete_bytes() {
        let mut writer = VariableSizeByteWriter::new(6);
        writer.buf[3] = 0xFF;
        writer.buf[4] = 0xF;
        writer.bits = 36;
        writer.erase_complete_bytes();
        assert_eq!(writer.bits, 4);
        assert_eq!(writer.buf[..], [0xF, 0, 0, 0, 0, 0]);

        let mut writer = VariableSizeByteWriter::new(6);
        writer.buf[3] = 0xFF;
        writer.bits = 32;
        writer.erase_complete_bytes();
        assert_eq!(writer.bits, 0);
        assert_eq!(writer.buf[..], [0, 0, 0, 0, 0, 0]);
    }

    #[test]
    fn test_erase_all_bytes() {
        let mut writer = VariableSizeByteWriter::new(6);
        writer.buf[3] = 0xFF;
        writer.buf[4] = 0xF;
        writer.bits = 36;
        writer.erase_all_bytes();
        assert_eq!(writer.bits, 0);
        assert_eq!(writer.buf[..], [0, 0, 0, 0, 0, 0]);
    }

    #[test]
    fn test_move_range_to_start() {
        let mut writer = VariableSizeByteWriter::new(12);
        writer.buf[10] = 0xAB;
        writer.buf[11] = 0xF;
        writer.bits = 92;
        writer.move_range_to_start(7, 12);
        assert_eq!(writer.bits, 44);
        assert_eq!(writer.buf[..], [0, 0, 0, 0, 0xAB, 0xF]);
    }

    #[test]
    fn test_write_range() {
        let mut writer = VariableSizeByteWriter::new(6);
        writer.buf[3] = 0xFF;
        writer.buf[4] = 0xF;
        writer.bits = 36;

        let mut target = std::io::Cursor::new(vec![]);
        let mut written: usize = 0;
        writer.write_range(&mut target, 0, 4, &mut written).unwrap();
        assert_eq!(written, 4);
        assert_eq!(&target.get_ref()[..4], [0, 0, 0, 0xFF]);

        let mut target = std::io::Cursor::new(vec![]);
        let mut written: usize = 0;
        writer.write_range(&mut target, 2, 4, &mut written).unwrap();
        assert_eq!(written, 2);
        assert_eq!(&target.get_ref()[..2], [0, 0xFF]);
    }

    #[test]
    fn test_insert_32() {
        let mut writer = VariableSizeByteWriter::new(16);
        writer.insert_32(0xF, 4);
        assert_eq!(writer.buf[0..2], [0xF, 0]);
        assert_eq!(writer.bits, 4);

        writer.insert_32(0xFA, 8);
        assert_eq!(writer.buf[0..3], [0xAF, 0xF, 0]);
        assert_eq!(writer.bits, 12);

        writer.insert_32(0x1FFFBB, 21);
        assert_eq!(writer.buf[0..6], [0xAF, 0xBF, 0xFB, 0xFF, 0x1, 0]);
        assert_eq!(writer.bits, 33);
    }

    #[test]
    fn test_insert_32_unchecked() {
        let mut writer = VariableSizeByteWriter::new(16);
        writer.insert_32_unchecked(0xF, 4);
        assert_eq!(writer.buf[0..2], [0xF, 0]);
        assert_eq!(writer.bits, 4);

        writer.insert_32_unchecked(0xFA, 8);
        assert_eq!(writer.buf[0..3], [0xAF, 0xF, 0]);
        assert_eq!(writer.bits, 12);

        writer.insert_32_unchecked(0x1FFFBB, 21);
        assert_eq!(writer.buf[0..6], [0xAF, 0xBF, 0xFB, 0xFF, 0x1, 0]);
        assert_eq!(writer.bits, 33);
    }

    #[test]
    fn test_insert_16() {
        let mut writer = VariableSizeByteWriter::new(16);
        writer.insert_16(0xF, 4);
        assert_eq!(writer.buf[0..2], [0xF, 0]);
        assert_eq!(writer.bits, 4);

        writer.insert_16(0xFA, 8);
        assert_eq!(writer.buf[0..3], [0xAF, 0xF, 0]);
        assert_eq!(writer.bits, 12);

        writer.insert_16(0x1FBB, 13);
        assert_eq!(writer.buf[0..6], [0xAF, 0xBF, 0xFB, 0x1, 0, 0]);
        assert_eq!(writer.bits, 25);
    }

    #[test]
    fn test_insert_16_unchecked() {
        let mut writer = VariableSizeByteWriter::new(16);
        writer.insert_16_unchecked(0xF, 4);
        assert_eq!(writer.buf[0..2], [0xF, 0]);
        assert_eq!(writer.bits, 4);

        writer.insert_16_unchecked(0xFA, 8);
        assert_eq!(writer.buf[0..3], [0xAF, 0xF, 0]);
        assert_eq!(writer.bits, 12);

        writer.insert_16_unchecked(0x1FBB, 13);
        assert_eq!(writer.buf[0..6], [0xAF, 0xBF, 0xFB, 0x1, 0, 0]);
        assert_eq!(writer.bits, 25);
    }
}<commit_msg>fixed move_range_to_start function and its test<commit_after>use std::io::prelude::*;
use std::io::{Error, ErrorKind};

pub struct VariableSizeByteWriter {
    buf: Vec<u8>,
    bits: u32,
}

impl VariableSizeByteWriter {
    pub fn new(cap: usize) -> VariableSizeByteWriter {
        VariableSizeByteWriter {
            buf: vec![0; cap],
            bits: 0,
        }
    }

    #[inline]
    pub fn complete_bytes(&mut self) -> usize {
        (self.bits / 8) as usize
    }

    #[inline]
    pub fn partial_bits(&mut self) -> u32 {
        (self.bits % 8)
    }

    pub fn get_complete_bytes(&mut self) -> &[u8] {
        let bytes = self.complete_bytes();
        &self.buf[..bytes]
    }

    pub fn get_all_bytes(&mut self, partial_bits: &mut u32) -> &[u8] {
        let bytes = self.complete_bytes();
        *partial_bits = self.partial_bits();
        if *partial_bits > 0 {
            &self.buf[..bytes + 1]
        } else {
            &self.buf[..bytes]
        }
    }

    pub fn get_partial_byte(&mut self) -> Option<(u8, u32)> {
        let bytes = self.complete_bytes();
        let partial_bits = self.partial_bits();
        let partial = self.buf[bytes];
        if partial_bits > 0 {
            Some((partial, partial_bits as u32))
        } else {
            None
        }
    }

    pub fn erase_complete_bytes(&mut self) {
        let bytes = self.complete_bytes();
        let possible_partial = self.buf[bytes];
        self.buf[..bytes + 1].iter_mut().for_each(|n| *n = 0);
        self.buf[0] = possible_partial;
        self.bits = self.partial_bits() as u32;
    }

    pub fn erase_all_bytes(&mut self) {
        let bytes = self.complete_bytes();
        self.buf[..bytes + 1].iter_mut().for_each(|n| *n = 0);
        self.bits = 0;
    }

    pub fn move_range_to_start(&mut self, from: usize, to: usize) {
        let mut offset = 0;
        while from + offset < to {
            self.buf[offset] = self.buf[from + offset];
            self.buf[from + offset] = 0;
            offset += 1;
        }
        self.bits -= 8 * (to - from) as u32;
    }

    pub fn write_range<T>(&mut self, writer: &mut T, from: usize, to: usize, written: &mut usize) -> std::io::Result<()>
        where T: Write
    {
        *written = 0;
        while from + *written < to {
            match writer.write(&self.buf[from + *written..to]) {
                Ok(0) => return Err(Error::new(ErrorKind::WriteZero, "zero bytes written")),
                Ok(bytes) => *written += bytes,
                Err(ref err) if err.kind() == ErrorKind::Interrupted => {}
                Err(err) => return Err(err),
            }
        }
        Ok(())
    }

    pub fn insert_32(&mut self, variable: u32, bits: u32) {
        let byte: usize = self.complete_bytes();
        let offset: u32 = self.partial_bits();

		self.buf[byte] |= (variable << offset) as u8;
        let variable = variable >> 8 - offset;
		self.buf[byte + 1] |= variable as u8;
        let variable = variable >> 8;
		self.buf[byte + 2] |= variable as u8;
        let variable = variable >> 8;
		self.buf[byte + 3] |= variable as u8;
        let variable = variable >> 8;
		self.buf[byte + 4] |= variable as u8;

        self.bits += bits;
    }

    pub fn insert_32_unchecked(&mut self, variable: u32, bits: u32) {
        let byte: usize = self.complete_bytes();
        let offset: u32 = self.partial_bits();

        unsafe {
            let i = self.buf.get_unchecked_mut(byte as usize);
		    *i |= (variable << offset) as u8;
        }
        let variable = variable >> 8 - offset;
        unsafe {
            let i = self.buf.get_unchecked_mut(byte + 1 as usize);
		    *i |= variable as u8;
        }
        let variable = variable >> 8;
        unsafe {
            let i = self.buf.get_unchecked_mut(byte + 2 as usize);
		    *i |= variable as u8;
        }
        let variable = variable >> 8;
        unsafe {
            let i = self.buf.get_unchecked_mut(byte + 3 as usize);
		    *i |= variable as u8;
        }
        let variable = variable >> 8;
        unsafe {
            let i = self.buf.get_unchecked_mut(byte + 4 as usize);
		    *i |= variable as u8;
        }

        self.bits += bits;
    }

    pub fn insert_16(&mut self, variable: u16, bits: u32) {
        let byte: usize = self.complete_bytes();
        let offset: u32 = self.partial_bits();

		self.buf[byte] |= (variable << offset) as u8;
        let variable = variable >> 8 - offset;
		self.buf[byte + 1] |= variable as u8;
        let variable = variable >> 8;
		self.buf[byte + 2] |= variable as u8;

        self.bits += bits;
    }

    pub fn insert_16_unchecked(&mut self, variable: u16, bits: u32) {
        let byte: usize = self.complete_bytes();
        let offset: u32 = self.partial_bits();

        unsafe {
            let i = self.buf.get_unchecked_mut(byte as usize);
		    *i |= (variable << offset) as u8;
        }
        let variable = variable >> 8 - offset;
        unsafe {
            let i = self.buf.get_unchecked_mut(byte + 1 as usize);
		    *i |= variable as u8;
        }
        let variable = variable >> 8;
        unsafe {
            let i = self.buf.get_unchecked_mut(byte + 2 as usize);
		    *i |= variable as u8;
        }

        self.bits += bits;
    }
}

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

    #[test]
    fn test_complete_bytes() {
        let mut writer = VariableSizeByteWriter::new(6);
        writer.buf[3] = 0xFF;
        writer.buf[4] = 0xF;
        writer.bits = 36;
        assert_eq!(writer.complete_bytes(), 4);
    }

    #[test]
    fn test_partial_bits() {
        let mut writer = VariableSizeByteWriter::new(6);
        writer.buf[3] = 0xFF;
        writer.buf[4] = 0xF;
        writer.bits = 36;
        assert_eq!(writer.partial_bits(), 4);
    }

    #[test]
    fn test_get_complete_bytes() {
        let mut writer = VariableSizeByteWriter::new(16);
        writer.buf[0] = 0xAA;
        writer.buf[3] = 0xFF;
        writer.buf[4] = 0xF;
        writer.bits = 36;
        assert_eq!(writer.get_complete_bytes(), [0xAA, 0, 0, 0xFF]);
    }

    #[test]
    fn test_get_all_bytes() {
        let mut writer = VariableSizeByteWriter::new(16);
        writer.buf[0] = 0xAA;
        writer.buf[3] = 0xFF;
        writer.buf[4] = 0xF;
        writer.bits = 36;
        let mut partial_bits = 0;
        assert_eq!(writer.get_all_bytes(&mut partial_bits), [0xAA, 0, 0, 0xFF, 0xF]);
        assert_eq!(partial_bits, 4);
    }

    #[test]
    fn test_get_partial_byte() {
        let mut writer = VariableSizeByteWriter::new(16);
        writer.buf[0] = 0xAA;
        writer.buf[3] = 0xFF;
        writer.buf[4] = 0xF;
        writer.bits = 36;
        let ret = writer.get_partial_byte();
        assert_eq!(ret, Some((0xF, 4)));

        let mut writer = VariableSizeByteWriter::new(16);
        writer.buf[0] = 0xAA;
        writer.buf[3] = 0xFF;
        writer.bits = 32;
        let ret = writer.get_partial_byte();
        assert_eq!(ret, None);
    }

    #[test]
    fn test_erase_complete_bytes() {
        let mut writer = VariableSizeByteWriter::new(6);
        writer.buf[3] = 0xFF;
        writer.buf[4] = 0xF;
        writer.bits = 36;
        writer.erase_complete_bytes();
        assert_eq!(writer.bits, 4);
        assert_eq!(writer.buf[..], [0xF, 0, 0, 0, 0, 0]);

        let mut writer = VariableSizeByteWriter::new(6);
        writer.buf[3] = 0xFF;
        writer.bits = 32;
        writer.erase_complete_bytes();
        assert_eq!(writer.bits, 0);
        assert_eq!(writer.buf[..], [0, 0, 0, 0, 0, 0]);
    }

    #[test]
    fn test_erase_all_bytes() {
        let mut writer = VariableSizeByteWriter::new(6);
        writer.buf[3] = 0xFF;
        writer.buf[4] = 0xF;
        writer.bits = 36;
        writer.erase_all_bytes();
        assert_eq!(writer.bits, 0);
        assert_eq!(writer.buf[..], [0, 0, 0, 0, 0, 0]);
    }

    #[test]
    fn test_move_range_to_start() {
        let mut writer = VariableSizeByteWriter::new(6);
        writer.buf[4] = 0xAB;
        writer.buf[5] = 0xF;
        writer.bits = 44;
        writer.move_range_to_start(3, 6);
        assert_eq!(writer.bits, 20);
        assert_eq!(writer.buf[..], [0, 0xAB, 0xF, 0, 0, 0]);
    }

    #[test]
    fn test_write_range() {
        let mut writer = VariableSizeByteWriter::new(6);
        writer.buf[3] = 0xFF;
        writer.buf[4] = 0xF;
        writer.bits = 36;

        let mut target = std::io::Cursor::new(vec![]);
        let mut written: usize = 0;
        writer.write_range(&mut target, 0, 4, &mut written).unwrap();
        assert_eq!(written, 4);
        assert_eq!(&target.get_ref()[..4], [0, 0, 0, 0xFF]);

        let mut target = std::io::Cursor::new(vec![]);
        let mut written: usize = 0;
        writer.write_range(&mut target, 2, 4, &mut written).unwrap();
        assert_eq!(written, 2);
        assert_eq!(&target.get_ref()[..2], [0, 0xFF]);
    }

    #[test]
    fn test_insert_32() {
        let mut writer = VariableSizeByteWriter::new(16);
        writer.insert_32(0xF, 4);
        assert_eq!(writer.buf[0..2], [0xF, 0]);
        assert_eq!(writer.bits, 4);

        writer.insert_32(0xFA, 8);
        assert_eq!(writer.buf[0..3], [0xAF, 0xF, 0]);
        assert_eq!(writer.bits, 12);

        writer.insert_32(0x1FFFBB, 21);
        assert_eq!(writer.buf[0..6], [0xAF, 0xBF, 0xFB, 0xFF, 0x1, 0]);
        assert_eq!(writer.bits, 33);
    }

    #[test]
    fn test_insert_32_unchecked() {
        let mut writer = VariableSizeByteWriter::new(16);
        writer.insert_32_unchecked(0xF, 4);
        assert_eq!(writer.buf[0..2], [0xF, 0]);
        assert_eq!(writer.bits, 4);

        writer.insert_32_unchecked(0xFA, 8);
        assert_eq!(writer.buf[0..3], [0xAF, 0xF, 0]);
        assert_eq!(writer.bits, 12);

        writer.insert_32_unchecked(0x1FFFBB, 21);
        assert_eq!(writer.buf[0..6], [0xAF, 0xBF, 0xFB, 0xFF, 0x1, 0]);
        assert_eq!(writer.bits, 33);
    }

    #[test]
    fn test_insert_16() {
        let mut writer = VariableSizeByteWriter::new(16);
        writer.insert_16(0xF, 4);
        assert_eq!(writer.buf[0..2], [0xF, 0]);
        assert_eq!(writer.bits, 4);

        writer.insert_16(0xFA, 8);
        assert_eq!(writer.buf[0..3], [0xAF, 0xF, 0]);
        assert_eq!(writer.bits, 12);

        writer.insert_16(0x1FBB, 13);
        assert_eq!(writer.buf[0..6], [0xAF, 0xBF, 0xFB, 0x1, 0, 0]);
        assert_eq!(writer.bits, 25);
    }

    #[test]
    fn test_insert_16_unchecked() {
        let mut writer = VariableSizeByteWriter::new(16);
        writer.insert_16_unchecked(0xF, 4);
        assert_eq!(writer.buf[0..2], [0xF, 0]);
        assert_eq!(writer.bits, 4);

        writer.insert_16_unchecked(0xFA, 8);
        assert_eq!(writer.buf[0..3], [0xAF, 0xF, 0]);
        assert_eq!(writer.bits, 12);

        writer.insert_16_unchecked(0x1FBB, 13);
        assert_eq!(writer.buf[0..6], [0xAF, 0xBF, 0xFB, 0x1, 0, 0]);
        assert_eq!(writer.bits, 25);
    }
}<|endoftext|>


<commit_before>extern crate libc;

use std::os::raw;
use std::ffi::CString;
use std::mem::transmute;

#[link(name = "rust")]
extern {
  fn klee_make_symbolic(data: *const raw::c_void, length: libc::size_t, name: *const raw::c_char);
}

pub fn any(data: *const raw::c_void, length: usize, name: &str) {
  let name_cstr = CString::new(name).unwrap();
  unsafe {
    klee_make_symbolic(data, length as libc::size_t, name_cstr.as_ptr());
  }
}

pub fn i32(data: *const i32, name: &str) {
  unsafe { any(transmute(data), 4, name); }
}

pub fn u32(data: *const u32, name: &str) {
  unsafe { any(transmute(data), 4, name); }
}

pub fn str(data: &str, name: &str) {
  unsafe { any(transmute(data.as_ptr()), data.len(), name); }
}

pub fn bytes(data: &[u8], name: &str) {
  unsafe { any(transmute(data.as_ptr()), data.len(), name); }
}
<commit_msg>Update lib.rs<commit_after>extern crate libc;

use std::os::raw;
use std::ffi::CString;
use std::mem::{transmute, size_of};

#[link(name = "rust")]
extern {
  fn klee_make_symbolic(data: *const raw::c_void, length: libc::size_t, name: *const raw::c_char);
}

pub fn any(data: *const raw::c_void, length: usize, name: &str) {
  let name_cstr = CString::new(name).unwrap();
  unsafe {
    klee_make_symbolic(data, length as libc::size_t, name_cstr.as_ptr());
  }
}

pub fn i32(data: *const i32, name: &str) {
  unsafe { any(transmute(data), std::mem::sizeof::<i32>(), name); }
}

pub fn u32(data: *const u32, name: &str) {
  unsafe { any(transmute(data), std::mem::sizeof::<u32>(), name); }
}

pub fn i64(data: *const i64, name: &str) {
  unsafe { any(transmute(data), std::mem::sizeof::<i64>(), name); }
}

pub fn u64(data: *const u64, name: &str) {
  unsafe { any(transmute(data), std::mem::sizeof::<u64>(), name); }
}

pub fn str(data: &str, name: &str) {
  unsafe { any(transmute(data.as_ptr()), data.len(), name); }
}

pub fn bytes(data: &[u8], name: &str) {
  unsafe { any(transmute(data.as_ptr()), data.len(), name); }
}
<|endoftext|>


<commit_before>#![feature(libc)]
#![feature(collections)]
#![feature(std_misc)]
extern crate libc;
use libc::{c_char, c_int, size_t};
//use libc::types::common::c95::FILE;

use std::ffi::{CString, CStr};
use std::string::as_string;
use std::str::from_utf8_unchecked;
use std::ptr;

#[repr(C)]
pub struct GetLine;
/*pub struct ExpandFile;
pub struct FileExpansion {
    exists: c_int,
    nfile: c_int,
    files: *mut char,
}
pub struct WordCompletion;
*/
// will add functions as needed
#[link(name = "tecla")]
extern {
    // fn libtecla_version(major: *mut c_int, minor: *mut c_int, micro: *mut c_int);
    fn new_GetLine(linelen: size_t, histlen: size_t) -> *mut GetLine;
    fn del_GetLine(gl: *mut GetLine) -> *mut GetLine;
    fn gl_get_line(gl: *mut GetLine,
                   prompt: *const c_char,
                   start_line: *const c_char,
                   start_pos: c_int) -> *const c_char;
    fn gl_query_char(gl: *mut GetLine, prompt: *const c_char, defchar: c_char) -> c_int;
    // fn gl_read_char(gl: *mut GetLine) -> c_int;
    // fn gl_configure_getline(gl: *mut GetLine, app_string: *const c_char,
    //                        app_file: *const c_char, user_file: *const c_char) -> c_int;
    // fn gl_bind_keyseq() -> c_int;
    // fn new_ExpandFile() -> *mut ExpandFile;
    // fn del_ExpandFile(ef: *mut ExpandFile) -> *mut ExpandFile;
    // fn ef_expand_file(ef: *mut ExpandFile,
    //                  path: *const c_char,
    //                  pathlen: c_int) -> *mut FileExpansion;
    // fn el_list_expansions(result: *mut FileExpansion,
    //                      fp: *mut FILE,
    //                      term_width: c_int) -> c_int;
    // fn ef_last_error(ef: *mut ExpandFile) -> *const c_char;
    // fn new_WordCompletion() -> *mut WordCompletion;
    // fn del_WordCompletion(cpl: *mut WordCompletion) -> WordCompletion;
    /*fn gl_completion_action(gl: *mut GetLine,
                            data: *const void,
                            match_fn: CplMatchFn,
                            list_only: c_int,
                            name: *const c_char,
                            keyseq: *const c_char) -> c_int;*/
    fn gl_save_history(gl: *mut GetLine,
                       filename: *const c_char,
                       comment: *const c_char,
                       max_lines: c_int);
    fn gl_load_history(gl: *mut GetLine,
                       filename: *const c_char,
                       comment: *const c_char);
    fn gl_ignore_signal(gl: *mut GetLine, signo: c_int);
    fn gl_erase_terminal(gl: *mut GetLine) -> c_int;
}

pub fn new_gl(linelen: usize, histlen: usize) -> *mut GetLine {
    let line = linelen as size_t;
    let hist = histlen as size_t;
    let mut res: *mut GetLine;
    unsafe {
        res = new_GetLine(line, hist);
    }
    res
}

pub fn del_gl(gl: *mut GetLine) -> *mut GetLine {
    unsafe {
        del_GetLine(gl)
    }
}

pub fn get_line(gl: *mut GetLine, prompt: &str) -> String {
    let c_prompt = CString::new(prompt.as_bytes()).unwrap();
    let start: *const i8 = ptr::null();
    let mut res: &str;
    unsafe {
        let out = CStr::from_ptr(gl_get_line(gl, c_prompt.as_ptr(), start, -1));
        res = from_utf8_unchecked(out.to_bytes());
    }
    as_string(res).clone()
}

///Returns the character read, or 0 if unreadable
pub fn query_char(gl: *mut GetLine, prompt: &str, defchar: char) -> char {
    let c_prompt = CString::new(prompt.as_bytes()).unwrap();
    let mut res: u8;
    unsafe {
        let out = gl_query_char(gl, c_prompt.as_ptr(), defchar as c_char);
        if out > 0 {
            res = out as u8;
        } else {
            res = 0;
        }
    }
    res as char
}

pub fn save_history(gl: *mut GetLine, file: &str, comment: &str, max: usize) {
    let c_file = CString::new(file.as_bytes()).unwrap();
    let c_comment = CString::new(comment.as_bytes()).unwrap();
    let c_max = max as c_int;
    unsafe {
        gl_save_history(gl, c_file.as_ptr(), c_comment.as_ptr(), c_max)
    }
}

pub fn load_history(gl: *mut GetLine, file: &str, comment: &str) {
    let c_file = CString::new(file.as_bytes()).unwrap();
    let c_comment = CString::new(comment.as_bytes()).unwrap();
    unsafe {
        gl_load_history(gl, c_file.as_ptr(), c_comment.as_ptr())
    }
}

pub fn ignore(gl: *mut GetLine, sig: isize) {
    unsafe {
        gl_ignore_signal(gl, sig as c_int)
    }
}

pub fn clear(gl: *mut GetLine) -> i32 {
    unsafe {
        gl_erase_terminal(gl)
    }
}

/*#[test]
fn it_works() {
}*/
<commit_msg>changed type of new_getline inputs to match actual type; still works<commit_after>#![feature(libc)]
#![feature(collections)]
#![feature(std_misc)]
extern crate libc;
use libc::{c_char, c_int, size_t};
//use libc::types::common::c95::FILE;

use std::ffi::{CString, CStr};
use std::string::as_string;
use std::str::from_utf8_unchecked;
use std::ptr;

#[repr(C)]
pub struct GetLine;
/*pub struct ExpandFile;
pub struct FileExpansion {
    exists: c_int,
    nfile: c_int,
    files: *mut char,
}
pub struct WordCompletion;
*/
// will add functions as needed
#[link(name = "tecla")]
extern {
    // fn libtecla_version(major: *mut c_int, minor: *mut c_int, micro: *mut c_int);
    fn new_GetLine(linelen: size_t, histlen: size_t) -> *mut GetLine;
    fn del_GetLine(gl: *mut GetLine) -> *mut GetLine;
    fn gl_get_line(gl: *mut GetLine,
                   prompt: *const c_char,
                   start_line: *const c_char,
                   start_pos: c_int) -> *const c_char;
    fn gl_query_char(gl: *mut GetLine, prompt: *const c_char, defchar: c_char) -> c_int;
    // fn gl_read_char(gl: *mut GetLine) -> c_int;
    // fn gl_configure_getline(gl: *mut GetLine, app_string: *const c_char,
    //                        app_file: *const c_char, user_file: *const c_char) -> c_int;
    // fn gl_bind_keyseq() -> c_int;
    // fn new_ExpandFile() -> *mut ExpandFile;
    // fn del_ExpandFile(ef: *mut ExpandFile) -> *mut ExpandFile;
    // fn ef_expand_file(ef: *mut ExpandFile,
    //                  path: *const c_char,
    //                  pathlen: c_int) -> *mut FileExpansion;
    // fn el_list_expansions(result: *mut FileExpansion,
    //                      fp: *mut FILE,
    //                      term_width: c_int) -> c_int;
    // fn ef_last_error(ef: *mut ExpandFile) -> *const c_char;
    // fn new_WordCompletion() -> *mut WordCompletion;
    // fn del_WordCompletion(cpl: *mut WordCompletion) -> WordCompletion;
    /*fn gl_completion_action(gl: *mut GetLine,
                            data: *const void,
                            match_fn: CplMatchFn,
                            list_only: c_int,
                            name: *const c_char,
                            keyseq: *const c_char) -> c_int;*/
    fn gl_save_history(gl: *mut GetLine,
                       filename: *const c_char,
                       comment: *const c_char,
                       max_lines: c_int);
    fn gl_load_history(gl: *mut GetLine,
                       filename: *const c_char,
                       comment: *const c_char);
    fn gl_ignore_signal(gl: *mut GetLine, signo: c_int);
    fn gl_erase_terminal(gl: *mut GetLine) -> c_int;
}

pub fn new_gl(linelen: u64, histlen: u64) -> *mut GetLine {
    //let line = linelen as size_t;
    //let hist = histlen as size_t;
    let mut res: *mut GetLine;
    unsafe {
        res = new_GetLine(linelen, histlen);
    }
    res
}

pub fn del_gl(gl: *mut GetLine) -> *mut GetLine {
    unsafe {
        del_GetLine(gl)
    }
}

pub fn get_line(gl: *mut GetLine, prompt: &str) -> String {
    let c_prompt = CString::new(prompt.as_bytes()).unwrap();
    let start: *const i8 = ptr::null();
    let mut res: &str;
    unsafe {
        let out = CStr::from_ptr(gl_get_line(gl, c_prompt.as_ptr(), start, -1));
        res = from_utf8_unchecked(out.to_bytes());
    }
    as_string(res).clone()
}

///Returns the character read, or 0 if unreadable
pub fn query_char(gl: *mut GetLine, prompt: &str, defchar: char) -> char {
    let c_prompt = CString::new(prompt.as_bytes()).unwrap();
    let mut res: u8;
    unsafe {
        let out = gl_query_char(gl, c_prompt.as_ptr(), defchar as c_char);
        if out > 0 {
            res = out as u8;
        } else {
            res = 0;
        }
    }
    res as char
}

pub fn save_history(gl: *mut GetLine, file: &str, comment: &str, max: usize) {
    let c_file = CString::new(file.as_bytes()).unwrap();
    let c_comment = CString::new(comment.as_bytes()).unwrap();
    let c_max = max as c_int;
    unsafe {
        gl_save_history(gl, c_file.as_ptr(), c_comment.as_ptr(), c_max)
    }
}

pub fn load_history(gl: *mut GetLine, file: &str, comment: &str) {
    let c_file = CString::new(file.as_bytes()).unwrap();
    let c_comment = CString::new(comment.as_bytes()).unwrap();
    unsafe {
        gl_load_history(gl, c_file.as_ptr(), c_comment.as_ptr())
    }
}

pub fn ignore(gl: *mut GetLine, sig: isize) {
    unsafe {
        gl_ignore_signal(gl, sig as c_int)
    }
}

pub fn clear(gl: *mut GetLine) -> i32 {
    unsafe {
        gl_erase_terminal(gl)
    }
}

/*#[test]
fn it_works() {
}*/
<|endoftext|>