<commit_before>use std::fmt;
use std::thread;
use std::time::{SystemTime, UNIX_EPOCH, Duration, Instant};

pub mod units;

/// A thin wrapper behind the Instant api from [std::time](https://doc.rust-lang.org/nightly/std/time/).
///The timer is for timing different parts of a program
pub struct Timer{
    /// The actual timer See [std::time::Instant](https://doc.rust-lang.org/nightly/std/time/struct.Instant.html)
    pub time: Instant
}

impl Timer{

    ///Creates and starts the timer.
    ///
    ///# Examples
    ///
    ///```
    ///use chroniker::Timer;
    ///
    ///let timer = Timer::new();
    ///```
    pub fn new() -> Timer{
        Timer{time: Instant::now()}
    }

    ///Similar to elapsed_millis. Gets the elapsed time in the unit passed.
    ///# Examples
    ///
    ///```
    ///use chroniker::Timer;
    ///use chroniker::units::TimeUnit;
    ///
    ///let timer = Timer::new();
    ///
    ///chroniker::sleep(1000);
    ///
    ///let elapsed_sec = timer.get_elapsed(TimeUnit::Second);
    ///println!("Timer: {}", elapsed_sec); //Prints "1"
    ///```
    pub fn get_elapsed(&self, unit: units::TimeUnit) -> u64{
        units::convert(units::TimeUnit::Millisecond, unit, self.elapsed_millis())
    }

    ///Returns the amount of milliseconds since the
    ///timer was created or reset.
    ///# Examples
    ///
    ///```
    ///use chroniker::Timer;
    ///
    /// //Create the timer
    ///let timer = Timer::new();
    ///
    /// //Do some "operations"
    ///chroniker::sleep(1000);
    ///
    ///let elapsed_millis = timer.elapsed_millis();
    ///println!("Timer: {}", elapsed_millis);//Prints 1000
    ///```
    pub fn elapsed_millis(&self) -> u64{
        (self.time.elapsed().as_secs() * 1000) + ((self.time.elapsed().subsec_nanos() / 1_000_000) as u64)
    }

    ///Resets thes timer to 0 and starts
    ///counting up again.
    ///# Examples
    ///
    ///```
    ///use chroniker::Timer;
    ///
    ///let mut timer = Timer::new();
    ///chroniker::sleep(1000);
    ///
    ///let elapsed_millis = timer.elapsed_millis();
    ///println!("Timer: {}", elapsed_millis);//Prints 1000
    ///
    /// //Reset the timer to 0
    ///timer.reset();
    ///println!("Timer: {:?}", timer); //Prints 0
    ///```
    pub fn reset(&mut self){
        self.time = Instant::now();
    }

}

impl fmt::Debug for Timer {

    ///Prints out the time.
    ///# Format
    ///
    ///If the time is 1500 milliseconds (1.5 seconds) it will print out
    ///
    ///```command_line
    ///$ 1.500
    ///```
    ///
    ///If the time is 75699 milliseconds (1 minute, 15 seconds, and 699 milliseconds) it will print out
    ///
    ///```command_line
    ///$ 1:15.699
    ///```
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut seconds = 0;
        let mut millis = self.elapsed_millis();
        let mut minutes = 0;

        while millis >= 1000{
            millis -= 1000;
            seconds += 1;
        }

        while seconds >= 60{
            seconds -= 60;
            minutes += 1;
        }

        if minutes != 0{
            return write!(f, "{}:{}.{}", minutes, seconds, millis);
        }

        write!(f, "{}.{}", seconds, millis)
    }
}

///Sleeps the thread for the supplied amount of time in
/// milliseconds.
///# Examples
///To sleep for one second:
///
///```
///chroniker::sleep(1000);
///```
///
///However to sleep for 5 seconds you can use
///the convert function:
///
///```
///use chroniker::units;
///use chroniker::units::TimeUnit;
///
///chroniker::sleep(units::convert(TimeUnit::Second, TimeUnit::Millisecond, 5));
///```
pub fn sleep(time: u64){
    thread::sleep(Duration::from_millis(time));
}

///Returns the current time in milliseconds.
///# Examples
///
///```
///
///let unix_time = chroniker::current_time_millis();
///```
pub fn current_time_millis() -> u64{
    let start = SystemTime::now();

    let since_the_epoch = start.duration_since(UNIX_EPOCH)
        .expect("Time went backwards");

    since_the_epoch.as_secs() * 1000 +
            since_the_epoch.subsec_nanos() as u64 / 1_000_000
}
<commit_msg>Optimization Updates<commit_after>use std::fmt;
use std::thread;
use std::time::{SystemTime, UNIX_EPOCH, Duration, Instant};

pub mod units;

/// A thin wrapper behind the Instant api from [std::time](https://doc.rust-lang.org/nightly/std/time/).
///The timer is for timing different parts of a program
pub struct Timer{
    /// The actual timer See [std::time::Instant](https://doc.rust-lang.org/nightly/std/time/struct.Instant.html)
    pub time: Instant
}

impl Timer{

    ///Creates and starts the timer.
    ///
    ///# Examples
    ///
    ///```
    ///use chroniker::Timer;
    ///
    ///let timer = Timer::new();
    ///```
    pub fn new() -> Timer{
        Timer{time: Instant::now()}
    }

    ///Similar to elapsed_millis. Gets the elapsed time in the unit passed.
    ///# Examples
    ///
    ///```
    ///use chroniker::Timer;
    ///use chroniker::units::TimeUnit;
    ///
    ///let timer = Timer::new();
    ///
    ///chroniker::sleep(1000);
    ///
    ///let elapsed_sec = timer.get_elapsed(TimeUnit::Second);
    ///println!("Timer: {}", elapsed_sec); //Prints "1"
    ///```
    pub fn get_elapsed(&self, unit: units::TimeUnit) -> u64{
        units::convert(units::TimeUnit::Millisecond, unit, self.elapsed_millis())
    }

    ///Returns the amount of milliseconds since the
    ///timer was created or reset.
    ///# Examples
    ///
    ///```
    ///use chroniker::Timer;
    ///
    /// //Create the timer
    ///let timer = Timer::new();
    ///
    /// //Do some "operations"
    ///chroniker::sleep(1000);
    ///
    ///let elapsed_millis = timer.elapsed_millis();
    ///println!("Timer: {}", elapsed_millis);//Prints 1000
    ///```
    pub fn elapsed_millis(&self) -> u64{
        (self.time.elapsed().as_secs() * 1000) + ((self.time.elapsed().subsec_nanos() / 1_000_000) as u64)
    }

    ///Resets thes timer to 0 and starts
    ///counting up again.
    ///# Examples
    ///
    ///```
    ///use chroniker::Timer;
    ///
    ///let mut timer = Timer::new();
    ///chroniker::sleep(1000);
    ///
    ///let elapsed_millis = timer.elapsed_millis();
    ///println!("Timer: {}", elapsed_millis);//Prints 1000
    ///
    /// //Reset the timer to 0
    ///timer.reset();
    ///println!("Timer: {:?}", timer); //Prints 0
    ///```
    pub fn reset(&mut self){
        self.time = Instant::now();
    }

}

impl fmt::Debug for Timer {

    ///Prints out the time.
    ///# Format
    ///
    ///If the time is 1500 milliseconds (1.5 seconds) it will print out
    ///
    ///```command_line
    ///$ 1.500
    ///```
    ///
    ///If the time is 75699 milliseconds (1 minute, 15 seconds, and 699 milliseconds) it will print out
    ///
    ///```command_line
    ///$ 1:15.699
    ///```
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

        let millis = self.elapsed_millis() % 1000;
        let mut seconds = millis / 1000;
        let mut minutes = seconds / 60;

        while seconds >= 60{
            seconds -= 60;
            minutes += 1;
        }

        if minutes != 0{
            return write!(f, "{}:{}.{}", minutes, seconds, millis);
        }

        write!(f, "{}.{}", seconds, millis)
    }
}

///Sleeps the thread for the supplied amount of time in
/// milliseconds.
///# Examples
///To sleep for one second:
///
///```
///chroniker::sleep(1000);
///```
///
///However to sleep for 5 seconds you can use
///the convert function:
///
///```
///use chroniker::units;
///use chroniker::units::TimeUnit;
///
///chroniker::sleep(units::convert(TimeUnit::Second, TimeUnit::Millisecond, 5));
///```
pub fn sleep(time: u64){
    thread::sleep(Duration::from_millis(time));
}

///Returns the current time in milliseconds.
///# Examples
///
///```
///
///let unix_time = chroniker::current_time_millis();
///```
pub fn current_time_millis() -> u64{
    let start = SystemTime::now();

    let since_the_epoch = start.duration_since(UNIX_EPOCH)
        .expect("Time went backwards");

    since_the_epoch.as_secs() * 1000 +
            since_the_epoch.subsec_nanos() as u64 / 1_000_000
}
<|endoftext|>


<commit_before>pub mod error;
pub mod interface;
pub mod object;
pub mod server;
pub mod target;
<commit_msg>lib: require the 'core' feature<commit_after>#![feature(core)]

pub mod error;
pub mod interface;
pub mod object;
pub mod server;
pub mod target;
<|endoftext|>


<commit_before>//! libc - Raw FFI bindings to platforms' system libraries
//!
//! [Documentation for other platforms][pd].
//!
//! [pd]: https://rust-lang.github.io/libc/#platform-specific-documentation
#![crate_name = "libc"]
#![crate_type = "rlib"]
#![allow(
    renamed_and_removed_lints, // Keep this order.
    unknown_lints, // Keep this order.
    bad_style,
    overflowing_literals,
    improper_ctypes,
    // This lint is renamed but we run CI for old stable rustc so should be here.
    redundant_semicolon,
    redundant_semicolons
)]
#![cfg_attr(libc_deny_warnings, deny(warnings))]
// Attributes needed when building as part of the standard library
#![cfg_attr(
    feature = "rustc-dep-of-std",
    feature(cfg_target_vendor, link_cfg, no_core)
)]
#![cfg_attr(libc_thread_local, feature(thread_local))]
// Enable extra lints:
#![cfg_attr(feature = "extra_traits", deny(missing_debug_implementations))]
#![deny(missing_copy_implementations, safe_packed_borrows)]
#![no_std]
#![cfg_attr(feature = "rustc-dep-of-std", no_core)]
#![cfg_attr(
    any(feature = "rustc-dep-of-std", target_os = "redox"),
    feature(static_nobundle)
)]
#![cfg_attr(libc_const_extern_fn, feature(const_extern_fn))]

#[macro_use]
mod macros;

cfg_if! {
    if #[cfg(feature = "rustc-dep-of-std")] {
        extern crate rustc_std_workspace_core as core;
        #[allow(unused_imports)]
        use core::iter;
        #[allow(unused_imports)]
        use core::ops;
        #[allow(unused_imports)]
        use core::option;
    }
}

cfg_if! {
    if #[cfg(libc_priv_mod_use)] {
        #[cfg(libc_core_cvoid)]
        #[allow(unused_imports)]
        use core::ffi;
        #[allow(unused_imports)]
        use core::fmt;
        #[allow(unused_imports)]
        use core::hash;
        #[allow(unused_imports)]
        use core::num;
        #[allow(unused_imports)]
        use core::mem;
        #[doc(hidden)]
        #[allow(unused_imports)]
        use core::clone::Clone;
        #[doc(hidden)]
        #[allow(unused_imports)]
        use core::marker::Copy;
        #[doc(hidden)]
        #[allow(unused_imports)]
        use core::option::Option;
    } else {
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::fmt;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::hash;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::num;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::mem;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::clone::Clone;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::marker::Copy;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::option::Option;
    }
}

cfg_if! {
    if #[cfg(windows)] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod windows;
        pub use windows::*;
    } else if #[cfg(target_os = "cloudabi")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod cloudabi;
        pub use cloudabi::*;
    } else if #[cfg(target_os = "fuchsia")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod fuchsia;
        pub use fuchsia::*;
    } else if #[cfg(target_os = "switch")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod switch;
        pub use switch::*;
    } else if #[cfg(target_os = "psp")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod psp;
        pub use psp::*;
    } else if #[cfg(target_os = "vxworks")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod vxworks;
        pub use vxworks::*;
    } else if #[cfg(unix)] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod unix;
        pub use unix::*;
    } else if #[cfg(target_os = "hermit")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod hermit;
        pub use hermit::*;
    } else if #[cfg(all(target_env = "sgx", target_vendor = "fortanix"))] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod sgx;
        pub use sgx::*;
    } else if #[cfg(any(target_env = "wasi", target_os = "wasi"))] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod wasi;
        pub use wasi::*;
    } else {
        // non-supported targets: empty...
    }
}
<commit_msg>Auto merge of #2028 - IsaacWoods:master, r=JohnTitor<commit_after>//! libc - Raw FFI bindings to platforms' system libraries
//!
//! [Documentation for other platforms][pd].
//!
//! [pd]: https://rust-lang.github.io/libc/#platform-specific-documentation
#![crate_name = "libc"]
#![crate_type = "rlib"]
#![allow(
    renamed_and_removed_lints, // Keep this order.
    unknown_lints, // Keep this order.
    bad_style,
    overflowing_literals,
    improper_ctypes,
    // This lint is renamed but we run CI for old stable rustc so should be here.
    redundant_semicolon,
    redundant_semicolons
)]
#![cfg_attr(libc_deny_warnings, deny(warnings))]
// Attributes needed when building as part of the standard library
#![cfg_attr(
    feature = "rustc-dep-of-std",
    feature(cfg_target_vendor, link_cfg, no_core)
)]
#![cfg_attr(libc_thread_local, feature(thread_local))]
// Enable extra lints:
#![cfg_attr(feature = "extra_traits", deny(missing_debug_implementations))]
#![deny(missing_copy_implementations, safe_packed_borrows)]
#![cfg_attr(not(feature = "rustc-dep-of-std"), no_std)]
#![cfg_attr(feature = "rustc-dep-of-std", no_core)]
#![cfg_attr(
    any(feature = "rustc-dep-of-std", target_os = "redox"),
    feature(static_nobundle)
)]
#![cfg_attr(libc_const_extern_fn, feature(const_extern_fn))]

#[macro_use]
mod macros;

cfg_if! {
    if #[cfg(feature = "rustc-dep-of-std")] {
        extern crate rustc_std_workspace_core as core;
        #[allow(unused_imports)]
        use core::iter;
        #[allow(unused_imports)]
        use core::ops;
        #[allow(unused_imports)]
        use core::option;
    }
}

cfg_if! {
    if #[cfg(libc_priv_mod_use)] {
        #[cfg(libc_core_cvoid)]
        #[allow(unused_imports)]
        use core::ffi;
        #[allow(unused_imports)]
        use core::fmt;
        #[allow(unused_imports)]
        use core::hash;
        #[allow(unused_imports)]
        use core::num;
        #[allow(unused_imports)]
        use core::mem;
        #[doc(hidden)]
        #[allow(unused_imports)]
        use core::clone::Clone;
        #[doc(hidden)]
        #[allow(unused_imports)]
        use core::marker::Copy;
        #[doc(hidden)]
        #[allow(unused_imports)]
        use core::option::Option;
    } else {
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::fmt;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::hash;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::num;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::mem;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::clone::Clone;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::marker::Copy;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::option::Option;
    }
}

cfg_if! {
    if #[cfg(windows)] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod windows;
        pub use windows::*;
    } else if #[cfg(target_os = "cloudabi")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod cloudabi;
        pub use cloudabi::*;
    } else if #[cfg(target_os = "fuchsia")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod fuchsia;
        pub use fuchsia::*;
    } else if #[cfg(target_os = "switch")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod switch;
        pub use switch::*;
    } else if #[cfg(target_os = "psp")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod psp;
        pub use psp::*;
    } else if #[cfg(target_os = "vxworks")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod vxworks;
        pub use vxworks::*;
    } else if #[cfg(unix)] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod unix;
        pub use unix::*;
    } else if #[cfg(target_os = "hermit")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod hermit;
        pub use hermit::*;
    } else if #[cfg(all(target_env = "sgx", target_vendor = "fortanix"))] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod sgx;
        pub use sgx::*;
    } else if #[cfg(any(target_env = "wasi", target_os = "wasi"))] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod wasi;
        pub use wasi::*;
    } else {
        // non-supported targets: empty...
    }
}
<|endoftext|>


<commit_before>#![feature(associated_types, default_type_params, globs)]

extern crate tcod;

pub mod engine;
pub mod gui;
pub mod util;
<commit_msg>Remove unnecessary feature gates<commit_after>extern crate tcod;

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


<commit_before>// Copyright (c) 2016
// Jeff Nettleton
//
// Licensed under the MIT license (http://opensource.org/licenses/MIT). This
// file may not be copied, modified, or distributed except according to those
// terms

//! # Canteen
//!
//! ## Description
//!
//! A pure Rust clone of [Flask](http://flask.pocoo.org), a simple but powerful Python
//! web framework.
//!
//! ## Example
//!
//! The principle behind Canteen is simple -- handler functions are defined as simple
//! Rust functions that take a `Request` and return a `Response`. Handlers are then attached
//! to one or more routes and HTTP methods/verbs. Routes are specified using a simple
//! syntax that lets you define variables within them; variables that can then be
//! extracted to perform various operations. Currently, the following variable types can
//! be used:
//!
//! - `<str:name>` will match anything inside a path segment, returns a `String`
//! - `<int:name>` will return a signed integer (`i32`) from a path segment
//!   - ex: `cnt.add_route("/api/foo/<int:foo_id>", &[Method::Get], my_handler)` will match
//!   `"/api/foo/123"` but not `"/api/foo/123.34"` or `"/api/foo/bar"`
//! - `<uint:name>` will return an unsigned integer (`u32`)
//! - `<float:name>` does the same thing as the `int` parameter definition, but matches numbers
//! with decimal points and returns an `f32`
//! - `<path:name>` will greedily take all path data contained, returns a `String`
//!   - ex: `cnt.add_route("/static/<path:name>", &[Method::Get], utils::static_file)` will
//!   serve anything in the `/static/` directory as a file
//!
//! ```rust
//! extern crate canteen;
//!
//! use canteen::{Canteen, Request, Response, Method};
//! use canteen::utils;
//!
//! fn hello_handler(req: &Request) -> Response {
//!     let mut res = Response::new();
//!
//!     res.set_code(200);
//!     res.set_content_type("text/plain");
//!     res.append("Hello, world!");
//!
//!     res
//! }
//!
//! fn double_handler(req: &Request) -> Response {
//!     let mut res = Response::new();
//!     let to_dbl: i32 = req.get("to_dbl");
//!
//!     /* simpler response generation syntax */
//!     utils::make_response(format!("{}", to_dbl * 2), "text/plain", 200)
//! }
//!
//! fn main() {
//!     let mut cnt = Canteen::new(("127.0.0.1", 8080));
//!
//!     // set the default route handler to show a 404 message
//!     cnt.set_default(utils::err_404);
//!
//!     // respond to requests to / with "Hello, world!"
//!     cnt.add_route("/", &[Method::Get], hello_handler);
//!
//!     // pull a variable from the path and do something with it
//!     cnt.add_route("/double/<int:to_dbl>", &[Method::Get], double_handler);
//!
//!     // serve raw files from the /static/ directory
//!     cnt.add_route("/static/<path:path>", &[Method::Get], utils::static_file);
//!
//!     /* cnt.run() */;
//! }
//! ```

extern crate mio;
extern crate regex;

pub mod utils;
pub mod route;
pub mod request;
pub mod response;

use std::io::Result;
use std::io::prelude::*;
use std::net::ToSocketAddrs;
use std::collections::HashMap;
use std::collections::HashSet;
use mio::tcp::{TcpListener, TcpStream};
use mio::util::Slab;
use mio::*;

pub use request::*;
pub use response::*;

struct Client {
    sock:   TcpStream,
    token:  Token,
    events: EventSet,
    i_buf:  Vec<u8>,
    o_buf:  Vec<u8>,
}

impl Client {
    fn new(sock: TcpStream, token: Token) -> Client {
        Client {
            sock:   sock,
            token:  token,
            events: EventSet::hup(),
            i_buf:  Vec::with_capacity(2048),
            o_buf:  Vec::with_capacity(2048),
        }
    }

    fn receive(&mut self) -> Result<bool> {
        let mut buf: Vec<u8> = Vec::with_capacity(2048);

        match self.sock.try_read_buf(&mut buf) {
            Ok(size)  => {
                match size {
                    Some(_) => {
                        self.events.remove(EventSet::readable());
                        self.events.insert(EventSet::writable());
                        self.i_buf.extend(buf);
                        return Ok(true);
                    },
                    None    => {
                        return Ok(false);
                    },
                }
            },
            Err(e)  => {
                panic!("failed to read from socket! <token: {:?}> <error: {:?}>", self.token, e);
            },
        }

        Ok(false)
    }

    // write the client's output buffer to the socket.
    //
    // the following return values mean:
    //  - Ok(true):  we can close the connection
    //  - Ok(false): keep listening for writeable event and continue next time
    //  - Err(e):    something dun fucked up
    fn send(&mut self) -> Result<bool> {
        while self.o_buf.len() > 0 {
            match self.sock.write(&self.o_buf.as_slice()) {
                Ok(sz)  => {
                    if sz == self.o_buf.len() {
                        // we did it!
                        self.events.remove(EventSet::writable());
                        break;
                    } else {
                        // keep going
                        self.o_buf = self.o_buf.split_off(sz);
                    }
                },
                Err(e)  => {
                    panic!("failed to write to socket! <token: {:?}> <error: {:?}>", self.token, e);
                }
            }
        }

        Ok(true)
    }

    fn register(&mut self, evl: &mut EventLoop<Canteen>) -> Result<()> {
        self.events.insert(EventSet::readable());

        evl.register(&self.sock, self.token, self.events, PollOpt::edge() | PollOpt::oneshot())
           .or_else(|e| {
               panic!("failed to register client! <token: {:?}> <error: {:?}>", self.token, e);
           })
    }

    fn reregister(&mut self, evl: &mut EventLoop<Canteen>) -> Result<()> {
        evl.reregister(&self.sock, self.token, self.events, PollOpt::edge() | PollOpt::oneshot())
           .or_else(|e| {
               panic!("failed to re-register client! <token: {:?}> <error: {:?}>", self.token, e);
           })
    }
}

/// The primary struct provided by the library. The aim is to have a similar
/// interface to Flask, the Python microframework.
pub struct Canteen {
    routes:  HashMap<route::RouteDef, route::Route>,
    rcache:  HashMap<route::RouteDef, route::RouteDef>,
    server:  TcpListener,
    token:   Token,
    conns:   Slab<Client>,
    default: fn(&Request) -> Response,
}

impl Handler for Canteen {
    type Timeout = ();
    type Message = u32;

    fn ready(&mut self, evl: &mut EventLoop<Canteen>, token: Token, events: EventSet) {
        if events.is_error() || events.is_hup() {
            self.reset_connection(token);
            return;
        }

        if events.is_readable() {
            if self.token == token {
                self.accept(evl);
            } else {
                self.readable(evl, token)
                    .and_then(|_| self.get_client(token)
                                      .reregister(evl))
                    .unwrap_or_else(|e| {
                        panic!("read event failed! <token: {:?}> <error: {:?}>", token, e);
                    });
            }

            return;
        }

        if events.is_writable() {
            match self.get_client(token).send() {
                Ok(true)    => { self.reset_connection(token); },
                Ok(false)   => { let _ = self.get_client(token).reregister(evl); },
                Err(_)      => { panic!("something really bad happened!"); },
            }
        }
    }
}

impl Canteen {
    /// Creates a new Canteen instance.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::Canteen;
    ///
    /// let cnt = Canteen::new(("127.0.0.1", 8081));
    /// ```
    pub fn new<A: ToSocketAddrs>(addr: A) -> Canteen {
        Canteen {
            routes:  HashMap::new(),
            rcache:  HashMap::new(),
            server:  TcpListener::bind(&addr.to_socket_addrs().unwrap().next().unwrap()).unwrap(),
            token:   Token(1),
            conns:   Slab::new_starting_at(Token(2), 2048),
            default: utils::err_404,
        }
    }

    /// Adds a new route definition to be handled by Canteen.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::{Canteen, Request, Response, Method};
    /// use canteen::utils;
    ///
    /// fn handler(_: &Request) -> Response {
    ///     utils::make_response("<b>Hello, world!</b>", "text/html", 200)
    /// }
    ///
    /// fn main() {
    ///     let mut cnt = Canteen::new(("127.0.0.1", 8082));
    ///     cnt.add_route("/hello", &[Method::Get], handler);
    /// }
    /// ```
    pub fn add_route(&mut self, path: &str, mlist: &[Method],
                     handler: fn(&Request) -> Response) -> &mut Canteen {
        let mut methods: HashSet<Method> = HashSet::new();

        // make them unique
        for m in mlist {
            methods.insert(*m);
        }

        for m in methods {
            let rd = route::RouteDef {
                pathdef:    String::from(path),
                method:     m,
            };

            if self.routes.contains_key(&rd) {
                panic!("a route handler for {} has already been defined!", path);
            }

            self.routes.insert(rd, route::Route::new(&path, m, handler));
        }

        self
    }

    /// Defines a default route for undefined paths.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::Canteen;
    /// use canteen::utils;
    ///
    /// let mut cnt = Canteen::new(("127.0.0.1", 8083));
    /// cnt.set_default(utils::err_404);
    /// ```
    pub fn set_default(&mut self, handler: fn(&Request) -> Response) {
        self.default = handler;
    }

    fn get_client<'a>(&'a mut self, token: Token) -> &'a mut Client {
        &mut self.conns[token]
    }

    fn accept(&mut self, evl: &mut EventLoop<Canteen>) {
        let (sock, _) = match self.server.accept() {
            Ok(s)   => {
                match s {
                    Some(sock)  => sock,
                    None        => {
                        panic!("failed to accept new connection!");
                    }
                }
            },
            Err(e)  => {
                panic!("failed to accept new connection! <error: {:?}>", e);
            },
        };

        match self.conns.insert_with(|token| Client::new(sock, token)) {
            Some(token) => {
                match self.get_client(token).register(evl) {
                    Ok(_)   => {},
                    Err(e)  => {
                        panic!("failed to register client! <token: {:?}> <error: {:?}>", token, e);
                    },
                }
            },
            None        => {
                panic!("failed to add client connection!");
            },
        }

        self.reregister(evl);
    }

    fn handle_request(&mut self, req: &mut Request) -> Vec<u8> {
        let resolved = route::RouteDef { pathdef: req.path.clone(), method: req.method };
        let mut handler: fn(&Request) -> Response = self.default;

        if self.rcache.contains_key(&resolved) {
            let ref route = self.routes[&self.rcache[&resolved]];

            handler = route.handler;
            req.params = route.parse(&req.path);
        } else {
            for (path, route) in &self.routes {
                match (route).is_match(req) {
                    true  => {
                        handler = route.handler;
                        req.params = route.parse(&req.path);
                        self.rcache.insert(resolved, (*path).clone());
                        break;
                    },
                    false => continue,
                }
            }
        }

        handler(req).gen_output()
    }

    fn readable(&mut self, evl: &mut EventLoop<Canteen>, token: Token) -> Result<bool> {
        match self.get_client(token).receive() {
            Ok(true)    => {
                let buf = self.get_client(token).i_buf.clone();
                let rqstr = String::from_utf8(buf).unwrap();
                let mut req = Request::from_str(&rqstr);
                let output = self.handle_request(&mut req);

                self.get_client(token).o_buf.extend(output);
            },
            Ok(false)   => {},
            Err(e)      => {
                panic!("message wasn't actually readable! <error: {:?}>", e);
            },
        };

        let _ = self.get_client(token).reregister(evl);

        Ok(true)
    }

    fn reset_connection(&mut self, token: Token) {
        // kill the connection
        self.conns.remove(token);
    }

    fn register(&mut self, evl: &mut EventLoop<Canteen>) -> Result<()> {
        evl.register(&self.server, self.token, EventSet::readable(), PollOpt::edge() | PollOpt::oneshot())
           .or_else(|e| {
               panic!("failed to register server! <token: {:?}> <error: {:?}>", self.token, e);
           })
    }

    fn reregister(&mut self, evl: &mut EventLoop<Canteen>) {
        match evl.reregister(&self.server, self.token,
                             EventSet::readable(),
                             PollOpt::edge() | PollOpt::oneshot()) {
            Ok(_)   => {},
            Err(e)  => {
               panic!("failed to register server! <token: {:?}> <error: {:?}>", self.token, e);
           }
        };
    }

    /// Creates the listener and starts a Canteen server's event loop.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::Canteen;
    ///
    /// let cnt = Canteen::new(("127.0.0.1", 8084));
    /// /* cnt.run(); */
    /// ```
    pub fn run(&mut self) {
        let mut evl = EventLoop::new().unwrap();
        self.register(&mut evl).ok();
        evl.run(self).unwrap();
    }
}
<commit_msg>change the signature of Canteen::handle_request so that it doesn't require a mutable Request instance<commit_after>// Copyright (c) 2016
// Jeff Nettleton
//
// Licensed under the MIT license (http://opensource.org/licenses/MIT). This
// file may not be copied, modified, or distributed except according to those
// terms

//! # Canteen
//!
//! ## Description
//!
//! A pure Rust clone of [Flask](http://flask.pocoo.org), a simple but powerful Python
//! web framework.
//!
//! ## Example
//!
//! The principle behind Canteen is simple -- handler functions are defined as simple
//! Rust functions that take a `Request` and return a `Response`. Handlers are then attached
//! to one or more routes and HTTP methods/verbs. Routes are specified using a simple
//! syntax that lets you define variables within them; variables that can then be
//! extracted to perform various operations. Currently, the following variable types can
//! be used:
//!
//! - `<str:name>` will match anything inside a path segment, returns a `String`
//! - `<int:name>` will return a signed integer (`i32`) from a path segment
//!   - ex: `cnt.add_route("/api/foo/<int:foo_id>", &[Method::Get], my_handler)` will match
//!   `"/api/foo/123"` but not `"/api/foo/123.34"` or `"/api/foo/bar"`
//! - `<uint:name>` will return an unsigned integer (`u32`)
//! - `<float:name>` does the same thing as the `int` parameter definition, but matches numbers
//! with decimal points and returns an `f32`
//! - `<path:name>` will greedily take all path data contained, returns a `String`
//!   - ex: `cnt.add_route("/static/<path:name>", &[Method::Get], utils::static_file)` will
//!   serve anything in the `/static/` directory as a file
//!
//! ```rust
//! extern crate canteen;
//!
//! use canteen::{Canteen, Request, Response, Method};
//! use canteen::utils;
//!
//! fn hello_handler(req: &Request) -> Response {
//!     let mut res = Response::new();
//!
//!     res.set_code(200);
//!     res.set_content_type("text/plain");
//!     res.append("Hello, world!");
//!
//!     res
//! }
//!
//! fn double_handler(req: &Request) -> Response {
//!     let mut res = Response::new();
//!     let to_dbl: i32 = req.get("to_dbl");
//!
//!     /* simpler response generation syntax */
//!     utils::make_response(format!("{}", to_dbl * 2), "text/plain", 200)
//! }
//!
//! fn main() {
//!     let mut cnt = Canteen::new(("127.0.0.1", 8080));
//!
//!     // set the default route handler to show a 404 message
//!     cnt.set_default(utils::err_404);
//!
//!     // respond to requests to / with "Hello, world!"
//!     cnt.add_route("/", &[Method::Get], hello_handler);
//!
//!     // pull a variable from the path and do something with it
//!     cnt.add_route("/double/<int:to_dbl>", &[Method::Get], double_handler);
//!
//!     // serve raw files from the /static/ directory
//!     cnt.add_route("/static/<path:path>", &[Method::Get], utils::static_file);
//!
//!     /* cnt.run() */;
//! }
//! ```

extern crate mio;
extern crate regex;

pub mod utils;
pub mod route;
pub mod request;
pub mod response;

use std::io::Result;
use std::io::prelude::*;
use std::net::ToSocketAddrs;
use std::collections::HashMap;
use std::collections::HashSet;
use mio::tcp::{TcpListener, TcpStream};
use mio::util::Slab;
use mio::*;

pub use request::*;
pub use response::*;

struct Client {
    sock:   TcpStream,
    token:  Token,
    events: EventSet,
    i_buf:  Vec<u8>,
    o_buf:  Vec<u8>,
}

impl Client {
    fn new(sock: TcpStream, token: Token) -> Client {
        Client {
            sock:   sock,
            token:  token,
            events: EventSet::hup(),
            i_buf:  Vec::with_capacity(2048),
            o_buf:  Vec::with_capacity(2048),
        }
    }

    fn receive(&mut self) -> Result<bool> {
        let mut buf: Vec<u8> = Vec::with_capacity(2048);

        match self.sock.try_read_buf(&mut buf) {
            Ok(size)  => {
                match size {
                    Some(_) => {
                        self.events.remove(EventSet::readable());
                        self.events.insert(EventSet::writable());
                        self.i_buf.extend(buf);
                        return Ok(true);
                    },
                    None    => {
                        return Ok(false);
                    },
                }
            },
            Err(e)  => {
                panic!("failed to read from socket! <token: {:?}> <error: {:?}>", self.token, e);
            },
        }

        Ok(false)
    }

    // write the client's output buffer to the socket.
    //
    // the following return values mean:
    //  - Ok(true):  we can close the connection
    //  - Ok(false): keep listening for writeable event and continue next time
    //  - Err(e):    something dun fucked up
    fn send(&mut self) -> Result<bool> {
        while self.o_buf.len() > 0 {
            match self.sock.write(&self.o_buf.as_slice()) {
                Ok(sz)  => {
                    if sz == self.o_buf.len() {
                        // we did it!
                        self.events.remove(EventSet::writable());
                        break;
                    } else {
                        // keep going
                        self.o_buf = self.o_buf.split_off(sz);
                    }
                },
                Err(e)  => {
                    panic!("failed to write to socket! <token: {:?}> <error: {:?}>", self.token, e);
                }
            }
        }

        Ok(true)
    }

    fn register(&mut self, evl: &mut EventLoop<Canteen>) -> Result<()> {
        self.events.insert(EventSet::readable());

        evl.register(&self.sock, self.token, self.events, PollOpt::edge() | PollOpt::oneshot())
           .or_else(|e| {
               panic!("failed to register client! <token: {:?}> <error: {:?}>", self.token, e);
           })
    }

    fn reregister(&mut self, evl: &mut EventLoop<Canteen>) -> Result<()> {
        evl.reregister(&self.sock, self.token, self.events, PollOpt::edge() | PollOpt::oneshot())
           .or_else(|e| {
               panic!("failed to re-register client! <token: {:?}> <error: {:?}>", self.token, e);
           })
    }
}

/// The primary struct provided by the library. The aim is to have a similar
/// interface to Flask, the Python microframework.
pub struct Canteen {
    routes:  HashMap<route::RouteDef, route::Route>,
    rcache:  HashMap<route::RouteDef, route::RouteDef>,
    server:  TcpListener,
    token:   Token,
    conns:   Slab<Client>,
    default: fn(&Request) -> Response,
}

impl Handler for Canteen {
    type Timeout = ();
    type Message = u32;

    fn ready(&mut self, evl: &mut EventLoop<Canteen>, token: Token, events: EventSet) {
        if events.is_error() || events.is_hup() {
            self.reset_connection(token);
            return;
        }

        if events.is_readable() {
            if self.token == token {
                self.accept(evl);
            } else {
                self.readable(evl, token)
                    .and_then(|_| self.get_client(token)
                                      .reregister(evl))
                    .unwrap_or_else(|e| {
                        panic!("read event failed! <token: {:?}> <error: {:?}>", token, e);
                    });
            }

            return;
        }

        if events.is_writable() {
            match self.get_client(token).send() {
                Ok(true)    => { self.reset_connection(token); },
                Ok(false)   => { let _ = self.get_client(token).reregister(evl); },
                Err(_)      => { panic!("something really bad happened!"); },
            }
        }
    }
}

impl Canteen {
    /// Creates a new Canteen instance.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::Canteen;
    ///
    /// let cnt = Canteen::new(("127.0.0.1", 8081));
    /// ```
    pub fn new<A: ToSocketAddrs>(addr: A) -> Canteen {
        Canteen {
            routes:  HashMap::new(),
            rcache:  HashMap::new(),
            server:  TcpListener::bind(&addr.to_socket_addrs().unwrap().next().unwrap()).unwrap(),
            token:   Token(1),
            conns:   Slab::new_starting_at(Token(2), 2048),
            default: utils::err_404,
        }
    }

    /// Adds a new route definition to be handled by Canteen.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::{Canteen, Request, Response, Method};
    /// use canteen::utils;
    ///
    /// fn handler(_: &Request) -> Response {
    ///     utils::make_response("<b>Hello, world!</b>", "text/html", 200)
    /// }
    ///
    /// fn main() {
    ///     let mut cnt = Canteen::new(("127.0.0.1", 8082));
    ///     cnt.add_route("/hello", &[Method::Get], handler);
    /// }
    /// ```
    pub fn add_route(&mut self, path: &str, mlist: &[Method],
                     handler: fn(&Request) -> Response) -> &mut Canteen {
        let mut methods: HashSet<Method> = HashSet::new();

        // make them unique
        for m in mlist {
            methods.insert(*m);
        }

        for m in methods {
            let rd = route::RouteDef {
                pathdef:    String::from(path),
                method:     m,
            };

            if self.routes.contains_key(&rd) {
                panic!("a route handler for {} has already been defined!", path);
            }

            self.routes.insert(rd, route::Route::new(&path, m, handler));
        }

        self
    }

    /// Defines a default route for undefined paths.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::Canteen;
    /// use canteen::utils;
    ///
    /// let mut cnt = Canteen::new(("127.0.0.1", 8083));
    /// cnt.set_default(utils::err_404);
    /// ```
    pub fn set_default(&mut self, handler: fn(&Request) -> Response) {
        self.default = handler;
    }

    fn get_client<'a>(&'a mut self, token: Token) -> &'a mut Client {
        &mut self.conns[token]
    }

    fn accept(&mut self, evl: &mut EventLoop<Canteen>) {
        let (sock, _) = match self.server.accept() {
            Ok(s)   => {
                match s {
                    Some(sock)  => sock,
                    None        => {
                        panic!("failed to accept new connection!");
                    }
                }
            },
            Err(e)  => {
                panic!("failed to accept new connection! <error: {:?}>", e);
            },
        };

        match self.conns.insert_with(|token| Client::new(sock, token)) {
            Some(token) => {
                match self.get_client(token).register(evl) {
                    Ok(_)   => {},
                    Err(e)  => {
                        panic!("failed to register client! <token: {:?}> <error: {:?}>", token, e);
                    },
                }
            },
            None        => {
                panic!("failed to add client connection!");
            },
        }

        self.reregister(evl);
    }

    fn handle_request(&mut self, rqstr: &str) -> Vec<u8> {
        let mut req = Request::from_str(&rqstr);
        let resolved = route::RouteDef { pathdef: req.path.clone(), method: req.method };
        let mut handler: fn(&Request) -> Response = self.default;

        if self.rcache.contains_key(&resolved) {
            let ref route = self.routes[&self.rcache[&resolved]];

            handler = route.handler;
            req.params = route.parse(&req.path);
        } else {
            for (path, route) in &self.routes {
                match (route).is_match(&req) {
                    true  => {
                        handler = route.handler;
                        req.params = route.parse(&req.path);
                        self.rcache.insert(resolved, (*path).clone());
                        break;
                    },
                    false => continue,
                }
            }
        }

        handler(&req).gen_output()
    }

    fn readable(&mut self, evl: &mut EventLoop<Canteen>, token: Token) -> Result<bool> {
        match self.get_client(token).receive() {
            Ok(true)    => {
                let buf = self.get_client(token).i_buf.clone();
                let rqstr = String::from_utf8(buf).unwrap();
                let output = self.handle_request(&rqstr);

                self.get_client(token).o_buf.extend(output);
            },
            Ok(false)   => {},
            Err(e)      => {
                panic!("message wasn't actually readable! <error: {:?}>", e);
            },
        };

        let _ = self.get_client(token).reregister(evl);

        Ok(true)
    }

    fn reset_connection(&mut self, token: Token) {
        // kill the connection
        self.conns.remove(token);
    }

    fn register(&mut self, evl: &mut EventLoop<Canteen>) -> Result<()> {
        evl.register(&self.server, self.token, EventSet::readable(), PollOpt::edge() | PollOpt::oneshot())
           .or_else(|e| {
               panic!("failed to register server! <token: {:?}> <error: {:?}>", self.token, e);
           })
    }

    fn reregister(&mut self, evl: &mut EventLoop<Canteen>) {
        match evl.reregister(&self.server, self.token,
                             EventSet::readable(),
                             PollOpt::edge() | PollOpt::oneshot()) {
            Ok(_)   => {},
            Err(e)  => {
               panic!("failed to register server! <token: {:?}> <error: {:?}>", self.token, e);
           }
        };
    }

    /// Creates the listener and starts a Canteen server's event loop.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::Canteen;
    ///
    /// let cnt = Canteen::new(("127.0.0.1", 8084));
    /// /* cnt.run(); */
    /// ```
    pub fn run(&mut self) {
        let mut evl = EventLoop::new().unwrap();
        self.register(&mut evl).ok();
        evl.run(self).unwrap();
    }
}
<|endoftext|>


<commit_before>extern crate byteorder;

use std::mem;
use std::default::Default;
use std::string::String;
use std::io::{Read, Write, Result};

use byteorder::{ReadBytesExt, WriteBytesExt, LittleEndian};

// this trait defines a "prefered implementation" of ColumnarStack for a type T,
// because multiple types may implement, for example, ColumnarStack<(u64, u64)>.
pub trait Columnar : Sized + 'static {
    type Stack: ColumnarStack<Self>;
}

// this trait defines a push/pop interface backed by easily serialized columnar storage.
pub trait ColumnarStack<T> : Default {
    fn push(&mut self, T);
    fn pop(&mut self) -> Option<T>;

    fn encode<W: Write>(&mut self, &mut W) -> Result<()>;
    fn decode<R: Read>(&mut self, &mut R) -> Result<()>;
}

// implementations defining default implementors of ColumnarStack.
impl Columnar for i64 { type Stack = Vec<i64>; }
impl Columnar for i32 { type Stack = Vec<i32>; }
impl Columnar for i16 { type Stack = Vec<i16>; }

impl Columnar for u64 { type Stack = Vec<u64>; }
impl Columnar for u32 { type Stack = Vec<u32>; }
impl Columnar for u16 { type Stack = Vec<u16>; }
impl Columnar for u8  { type Stack = Vec<u8>;  }

impl Columnar for usize { type Stack = Vec<usize>; }
impl Columnar for isize { type Stack = Vec<isize>; }

impl Columnar for f32 { type Stack = Vec<f32>; }
impl Columnar for f64 { type Stack = Vec<f64>; }

impl Columnar for String { type Stack = (Vec<u64>, Vec<u8>, Vec<Vec<u8>>); }

impl<T1: Columnar, T2: Columnar> Columnar for (T1, T2) {
    type Stack = (T1::Stack, T2::Stack);
}
impl<T1: Columnar, T2: Columnar, T3: Columnar> Columnar for (T1, T2, T3) {
    type Stack = (T1::Stack, T2::Stack, T3::Stack);
}
impl<T1: Columnar, T2: Columnar, T3: Columnar, T4: Columnar> Columnar for (T1, T2, T3, T4) {
    type Stack = (T1::Stack, T2::Stack, T3::Stack, T4::Stack);
}

impl<T: Columnar> Columnar for Option<T> { type Stack = (Vec<u8>, T::Stack); }
impl<T: Columnar+'static> Columnar for Vec<T> { type Stack = (Vec<u64>, T::Stack, Vec<Vec<T>>); }

impl Columnar for () { type Stack = u64; }

impl ColumnarStack<()> for u64 {
    #[inline(always)] fn push(&mut self, _empty: ()) {
        *self += 1;
    }
    #[inline(always)] fn pop(&mut self) -> Option<()> {
        if *self > 0 { *self -= 1; Some(()) }
        else         { None }
    }

    fn encode<W: Write>(&mut self, writer: &mut W) -> Result<()> {
        try!(writer.write_u64::<LittleEndian>(*self));
        Ok(())
    }
    fn decode<R: Read>(&mut self, reader: &mut R) -> Result<()> {
        *self = try!(reader.read_u64::<LittleEndian>());
        Ok(())
    }
}

// implementations of specific ColumnarQueues.
impl<T:Copy+'static> ColumnarStack<T> for Vec<T> {
    #[inline(always)] fn push(&mut self, data: T) { self.push(data); }
    #[inline(always)] fn pop(&mut self) -> Option<T> { self.pop() }

    fn encode<W: Write>(&mut self, writer: &mut W) -> Result<()> {
        try!(writer.write_typed_vec(self));
        self.clear();
        Ok(())
    }
    fn decode<R: Read>(&mut self, reader: &mut R) -> Result<()> {
        self.clear();
        try!(reader.read_typed_vec(self));
        Ok(())
    }
}

impl ColumnarStack<String> for (Vec<u64>, Vec<u8>, Vec<Vec<u8>>) {
    #[inline(always)]
    fn push(&mut self, string: String) {
        let mut vector = string.into_bytes();
        self.0.push(vector.len() as u64);
        while let Some(record) = vector.pop() { self.1.push(record); }
        self.2.push(vector);
    }

    #[inline(always)]
    fn pop(&mut self) -> Option<String> {
        self.0.pop().map(|count| {
            let mut vector = self.2.pop().unwrap_or_default();
            for _ in 0..count { vector.push(self.1.pop().unwrap()); }
            unsafe { String::from_utf8_unchecked(vector) }
        })
    }

    fn encode<W: Write>(&mut self, writer: &mut W) -> Result<()> {
        try!(self.0.encode(writer));
        try!(self.1.encode(writer));
        Ok(())
    }
    fn decode<R: Read>(&mut self, reader: &mut R) -> Result<()> {
        try!(self.0.decode(reader));
        try!(self.1.decode(reader));
        Ok(())
    }
}

impl<T1, T2, R1: ColumnarStack<T1>, R2: ColumnarStack<T2>> ColumnarStack<(T1, T2)> for (R1, R2) {
    #[inline(always)]
    fn push(&mut self, (x, y): (T1, T2)) {
        self.0.push(x);
        self.1.push(y);
    }

    #[inline(always)]
    fn pop(&mut self) -> Option<(T1, T2)> {
        // self.0.pop().map(|x| (x, self.1.pop().unwrap()))
        match (self.0.pop(), self.1.pop()) {
            (Some(x), Some(y)) => Some((x, y)),
            (None, None)       => None,
            _                  => { println!("error in pair de-columnarization"); None },
        }
    }

    fn encode<W: Write>(&mut self, writer: &mut W) -> Result<()> {
        try!(self.0.encode(writer));
        try!(self.1.encode(writer));
        Ok(())
    }
    fn decode<R: Read>(&mut self, reader: &mut R) -> Result<()> {
        try!(self.0.decode(reader));
        try!(self.1.decode(reader));
        Ok(())
    }
}

impl<T1, T2, T3, R1: ColumnarStack<T1>, R2: ColumnarStack<T2>, R3: ColumnarStack<T3>> ColumnarStack<(T1, T2, T3)> for (R1, R2, R3) {
    #[inline(always)]
    fn push(&mut self, (x, y, z): (T1, T2, T3)) {
        self.0.push(x);
        self.1.push(y);
        self.2.push(z);
    }

    #[inline(always)]
    fn pop(&mut self) -> Option<(T1, T2, T3)> {
        self.0.pop().map(|x| (x, self.1.pop().unwrap(), self.2.pop().unwrap()))
    }

    fn encode<W: Write>(&mut self, writer: &mut W) -> Result<()> {
        try!(self.0.encode(writer));
        try!(self.1.encode(writer));
        try!(self.2.encode(writer));
        Ok(())
    }
    fn decode<R: Read>(&mut self, reader: &mut R) -> Result<()> {
        try!(self.0.decode(reader));
        try!(self.1.decode(reader));
        try!(self.2.decode(reader));
        Ok(())
    }
}

impl<T1, T2, T3, T4,
     R1: ColumnarStack<T1>,
     R2: ColumnarStack<T2>,
     R3: ColumnarStack<T3>,
     R4: ColumnarStack<T4>>
 ColumnarStack<(T1, T2, T3, T4)> for (R1, R2, R3, R4) {
    #[inline(always)]
    fn push(&mut self, (x, y, z, w): (T1, T2, T3, T4)) {
        self.0.push(x);
        self.1.push(y);
        self.2.push(z);
        self.3.push(w);
    }

    #[inline(always)]
    fn pop(&mut self) -> Option<(T1, T2, T3, T4)> {
        self.0.pop().map(|x| (x, self.1.pop().unwrap(), self.2.pop().unwrap(), self.3.pop().unwrap()))
    }
    fn encode<W: Write>(&mut self, writer: &mut W) -> Result<()> {
        try!(self.0.encode(writer));
        try!(self.1.encode(writer));
        try!(self.2.encode(writer));
        try!(self.3.encode(writer));
        Ok(())
    }
    fn decode<R: Read>(&mut self, reader: &mut R) -> Result<()> {
        try!(self.0.decode(reader));
        try!(self.1.decode(reader));
        try!(self.2.decode(reader));
        try!(self.3.decode(reader));
        Ok(())
    }
}

impl<T, S: ColumnarStack<T>> ColumnarStack<Option<T>> for (Vec<u8>, S) {
    #[inline(always)]
    fn push(&mut self, option: Option<T>) {
        match option {
            Some(record) => { self.0.push(1); self.1.push(record); },
            None         => { self.0.push(0); },
        }
    }

    #[inline(always)]
    fn pop(&mut self) -> Option<Option<T>> {
        self.0.pop().map(|count| {
            if count > 0 { Some(self.1.pop().unwrap()) }
            else         { None }
        })
    }

    fn encode<W: Write>(&mut self, writer: &mut W) -> Result<()> {
        try!(writer.write_typed_vec(&mut self.0));
        try!(self.1.encode(writer));
        Ok(())
    }
    fn decode<R: Read>(&mut self, reader: &mut R) -> Result<()> {
        try!(reader.read_typed_vec(&mut self.0));
        try!(self.1.decode(reader));
        Ok(())
    }
}

impl<T:'static, R1: ColumnarStack<u64>, R2: ColumnarStack<T>> ColumnarStack<Vec<T>> for (R1, R2, Vec<Vec<T>>) {
    #[inline(always)]
    fn push(&mut self, mut vector: Vec<T>) {
        self.0.push(vector.len() as u64);
        while let Some(record) = vector.pop() { self.1.push(record); }
        self.2.push(vector);
    }

    #[inline(always)]
    fn pop(&mut self) -> Option<Vec<T>> {
        self.0.pop().map(|count| {
            let mut vector = self.2.pop().unwrap_or_default();
            for _ in 0..count { vector.push(self.1.pop().unwrap()); }
            vector
        })
    }

    fn encode<W: Write>(&mut self, writer: &mut W) -> Result<()> {
        try!(self.0.encode(writer));
        try!(self.1.encode(writer));
        Ok(())
    }
    fn decode<R: Read>(&mut self, reader: &mut R) -> Result<()> {
        try!(self.0.decode(reader));
        try!(self.1.decode(reader));
        Ok(())
    }
}

trait ColumnarWriteExt {
    fn write_typed_vec<T: Copy>(&mut self, vector: &mut Vec<T>) -> Result<()>;
}

impl<W: Write> ColumnarWriteExt for W {
    fn write_typed_vec<T: Copy>(&mut self, vector: &mut Vec<T>) -> Result<()> {
        try!(self.write_u64::<LittleEndian>(vector.len() as u64));
        try!(self.write_all(unsafe { typed_as_byte_slice(&mut vector[..]) }));
        Ok(())
    }
}

trait ColumnarReadExt {
    fn read_typed_vec<T: Copy>(&mut self, vector: &mut Vec<T>) -> Result<()>;
}

impl<R: Read> ColumnarReadExt for R {
    fn read_typed_vec<T: Copy>(&mut self, vector: &mut Vec<T>) -> Result<()> {
        vector.clear();

        let len = try!(self.read_u64::<LittleEndian>()) as usize;
        vector.reserve(len);
        unsafe { vector.set_len(len); }

        let slice = unsafe { typed_as_byte_slice(&mut vector[..]) };
        let mut read = 0;
        while read < slice.len() {
            let just_read = try!(self.read(&mut slice[read..]));
            read += just_read;
        }

        Ok(())
    }
}

unsafe fn typed_as_byte_slice<T>(slice: &mut [T]) -> &mut [u8] {
    std::slice::from_raw_parts_mut(slice.as_mut_ptr() as *mut u8, slice.len() * mem::size_of::<T>())
}
<commit_msg>Remove Copy requirement<commit_after>extern crate byteorder;

use std::mem;
use std::default::Default;
use std::string::String;
use std::io::{Read, Write, Result};

use byteorder::{ReadBytesExt, WriteBytesExt, LittleEndian};

// this trait defines a "prefered implementation" of ColumnarStack for a type T,
// because multiple types may implement, for example, ColumnarStack<(u64, u64)>.
pub trait Columnar : Sized + 'static {
    type Stack: ColumnarStack<Self>;
}

// this trait defines a push/pop interface backed by easily serialized columnar storage.
pub trait ColumnarStack<T> : Default {
    fn push(&mut self, T);
    fn pop(&mut self) -> Option<T>;

    fn encode<W: Write>(&mut self, &mut W) -> Result<()>;
    fn decode<R: Read>(&mut self, &mut R) -> Result<()>;
}

// implementations defining default implementors of ColumnarStack.
impl Columnar for i64 { type Stack = Vec<i64>; }
impl Columnar for i32 { type Stack = Vec<i32>; }
impl Columnar for i16 { type Stack = Vec<i16>; }

impl Columnar for u64 { type Stack = Vec<u64>; }
impl Columnar for u32 { type Stack = Vec<u32>; }
impl Columnar for u16 { type Stack = Vec<u16>; }
impl Columnar for u8  { type Stack = Vec<u8>;  }

impl Columnar for usize { type Stack = Vec<usize>; }
impl Columnar for isize { type Stack = Vec<isize>; }

impl Columnar for f32 { type Stack = Vec<f32>; }
impl Columnar for f64 { type Stack = Vec<f64>; }

impl Columnar for String { type Stack = (Vec<u64>, Vec<u8>, Vec<Vec<u8>>); }

impl<T1: Columnar, T2: Columnar> Columnar for (T1, T2) {
    type Stack = (T1::Stack, T2::Stack);
}
impl<T1: Columnar, T2: Columnar, T3: Columnar> Columnar for (T1, T2, T3) {
    type Stack = (T1::Stack, T2::Stack, T3::Stack);
}
impl<T1: Columnar, T2: Columnar, T3: Columnar, T4: Columnar> Columnar for (T1, T2, T3, T4) {
    type Stack = (T1::Stack, T2::Stack, T3::Stack, T4::Stack);
}

impl<T: Columnar> Columnar for Option<T> { type Stack = (Vec<u8>, T::Stack); }
impl<T: Columnar+'static> Columnar for Vec<T> { type Stack = (Vec<u64>, T::Stack, Vec<Vec<T>>); }

impl Columnar for () { type Stack = u64; }

impl ColumnarStack<()> for u64 {
    #[inline(always)] fn push(&mut self, _empty: ()) {
        *self += 1;
    }
    #[inline(always)] fn pop(&mut self) -> Option<()> {
        if *self > 0 { *self -= 1; Some(()) }
        else         { None }
    }

    fn encode<W: Write>(&mut self, writer: &mut W) -> Result<()> {
        try!(writer.write_u64::<LittleEndian>(*self));
        Ok(())
    }
    fn decode<R: Read>(&mut self, reader: &mut R) -> Result<()> {
        *self = try!(reader.read_u64::<LittleEndian>());
        Ok(())
    }
}

// implementations of specific ColumnarQueues.
impl<T> ColumnarStack<T> for Vec<T> {
    #[inline(always)] fn push(&mut self, data: T) { self.push(data); }
    #[inline(always)] fn pop(&mut self) -> Option<T> { self.pop() }

    fn encode<W: Write>(&mut self, writer: &mut W) -> Result<()> {
        try!(writer.write_typed_vec(self));
        self.clear();
        Ok(())
    }
    fn decode<R: Read>(&mut self, reader: &mut R) -> Result<()> {
        self.clear();
        try!(reader.read_typed_vec(self));
        Ok(())
    }
}

impl ColumnarStack<String> for (Vec<u64>, Vec<u8>, Vec<Vec<u8>>) {
    #[inline(always)]
    fn push(&mut self, string: String) {
        let mut vector = string.into_bytes();
        self.0.push(vector.len() as u64);
        while let Some(record) = vector.pop() { self.1.push(record); }
        self.2.push(vector);
    }

    #[inline(always)]
    fn pop(&mut self) -> Option<String> {
        self.0.pop().map(|count| {
            let mut vector = self.2.pop().unwrap_or_default();
            for _ in 0..count { vector.push(self.1.pop().unwrap()); }
            unsafe { String::from_utf8_unchecked(vector) }
        })
    }

    fn encode<W: Write>(&mut self, writer: &mut W) -> Result<()> {
        try!(self.0.encode(writer));
        try!(self.1.encode(writer));
        Ok(())
    }
    fn decode<R: Read>(&mut self, reader: &mut R) -> Result<()> {
        try!(self.0.decode(reader));
        try!(self.1.decode(reader));
        Ok(())
    }
}

impl<T1, T2, R1: ColumnarStack<T1>, R2: ColumnarStack<T2>> ColumnarStack<(T1, T2)> for (R1, R2) {
    #[inline(always)]
    fn push(&mut self, (x, y): (T1, T2)) {
        self.0.push(x);
        self.1.push(y);
    }

    #[inline(always)]
    fn pop(&mut self) -> Option<(T1, T2)> {
        // self.0.pop().map(|x| (x, self.1.pop().unwrap()))
        match (self.0.pop(), self.1.pop()) {
            (Some(x), Some(y)) => Some((x, y)),
            (None, None)       => None,
            _                  => { println!("error in pair de-columnarization"); None },
        }
    }

    fn encode<W: Write>(&mut self, writer: &mut W) -> Result<()> {
        try!(self.0.encode(writer));
        try!(self.1.encode(writer));
        Ok(())
    }
    fn decode<R: Read>(&mut self, reader: &mut R) -> Result<()> {
        try!(self.0.decode(reader));
        try!(self.1.decode(reader));
        Ok(())
    }
}

impl<T1, T2, T3, R1: ColumnarStack<T1>, R2: ColumnarStack<T2>, R3: ColumnarStack<T3>> ColumnarStack<(T1, T2, T3)> for (R1, R2, R3) {
    #[inline(always)]
    fn push(&mut self, (x, y, z): (T1, T2, T3)) {
        self.0.push(x);
        self.1.push(y);
        self.2.push(z);
    }

    #[inline(always)]
    fn pop(&mut self) -> Option<(T1, T2, T3)> {
        self.0.pop().map(|x| (x, self.1.pop().unwrap(), self.2.pop().unwrap()))
    }

    fn encode<W: Write>(&mut self, writer: &mut W) -> Result<()> {
        try!(self.0.encode(writer));
        try!(self.1.encode(writer));
        try!(self.2.encode(writer));
        Ok(())
    }
    fn decode<R: Read>(&mut self, reader: &mut R) -> Result<()> {
        try!(self.0.decode(reader));
        try!(self.1.decode(reader));
        try!(self.2.decode(reader));
        Ok(())
    }
}

impl<T1, T2, T3, T4,
     R1: ColumnarStack<T1>,
     R2: ColumnarStack<T2>,
     R3: ColumnarStack<T3>,
     R4: ColumnarStack<T4>>
 ColumnarStack<(T1, T2, T3, T4)> for (R1, R2, R3, R4) {
    #[inline(always)]
    fn push(&mut self, (x, y, z, w): (T1, T2, T3, T4)) {
        self.0.push(x);
        self.1.push(y);
        self.2.push(z);
        self.3.push(w);
    }

    #[inline(always)]
    fn pop(&mut self) -> Option<(T1, T2, T3, T4)> {
        self.0.pop().map(|x| (x, self.1.pop().unwrap(), self.2.pop().unwrap(), self.3.pop().unwrap()))
    }
    fn encode<W: Write>(&mut self, writer: &mut W) -> Result<()> {
        try!(self.0.encode(writer));
        try!(self.1.encode(writer));
        try!(self.2.encode(writer));
        try!(self.3.encode(writer));
        Ok(())
    }
    fn decode<R: Read>(&mut self, reader: &mut R) -> Result<()> {
        try!(self.0.decode(reader));
        try!(self.1.decode(reader));
        try!(self.2.decode(reader));
        try!(self.3.decode(reader));
        Ok(())
    }
}

impl<T, S: ColumnarStack<T>> ColumnarStack<Option<T>> for (Vec<u8>, S) {
    #[inline(always)]
    fn push(&mut self, option: Option<T>) {
        match option {
            Some(record) => { self.0.push(1); self.1.push(record); },
            None         => { self.0.push(0); },
        }
    }

    #[inline(always)]
    fn pop(&mut self) -> Option<Option<T>> {
        self.0.pop().map(|count| {
            if count > 0 { Some(self.1.pop().unwrap()) }
            else         { None }
        })
    }

    fn encode<W: Write>(&mut self, writer: &mut W) -> Result<()> {
        try!(writer.write_typed_vec(&mut self.0));
        try!(self.1.encode(writer));
        Ok(())
    }
    fn decode<R: Read>(&mut self, reader: &mut R) -> Result<()> {
        try!(reader.read_typed_vec(&mut self.0));
        try!(self.1.decode(reader));
        Ok(())
    }
}

impl<T:'static, R1: ColumnarStack<u64>, R2: ColumnarStack<T>> ColumnarStack<Vec<T>> for (R1, R2, Vec<Vec<T>>) {
    #[inline(always)]
    fn push(&mut self, mut vector: Vec<T>) {
        self.0.push(vector.len() as u64);
        while let Some(record) = vector.pop() { self.1.push(record); }
        self.2.push(vector);
    }

    #[inline(always)]
    fn pop(&mut self) -> Option<Vec<T>> {
        self.0.pop().map(|count| {
            let mut vector = self.2.pop().unwrap_or_default();
            for _ in 0..count { vector.push(self.1.pop().unwrap()); }
            vector
        })
    }

    fn encode<W: Write>(&mut self, writer: &mut W) -> Result<()> {
        try!(self.0.encode(writer));
        try!(self.1.encode(writer));
        Ok(())
    }
    fn decode<R: Read>(&mut self, reader: &mut R) -> Result<()> {
        try!(self.0.decode(reader));
        try!(self.1.decode(reader));
        Ok(())
    }
}

trait ColumnarWriteExt {
    fn write_typed_vec<T>(&mut self, vector: &mut Vec<T>) -> Result<()>;
}

impl<W: Write> ColumnarWriteExt for W {
    fn write_typed_vec<T>(&mut self, vector: &mut Vec<T>) -> Result<()> {
        try!(self.write_u64::<LittleEndian>(vector.len() as u64));
        try!(self.write_all(unsafe { typed_as_byte_slice(&mut vector[..]) }));
        Ok(())
    }
}

trait ColumnarReadExt {
    fn read_typed_vec<T>(&mut self, vector: &mut Vec<T>) -> Result<()>;
}

impl<R: Read> ColumnarReadExt for R {
    fn read_typed_vec<T>(&mut self, vector: &mut Vec<T>) -> Result<()> {
        vector.clear();

        let len = try!(self.read_u64::<LittleEndian>()) as usize;
        vector.reserve(len);
        unsafe { vector.set_len(len); }

        let slice = unsafe { typed_as_byte_slice(&mut vector[..]) };
        let mut read = 0;
        while read < slice.len() {
            let just_read = try!(self.read(&mut slice[read..]));
            read += just_read;
        }

        Ok(())
    }
}

unsafe fn typed_as_byte_slice<T>(slice: &mut [T]) -> &mut [u8] {
    std::slice::from_raw_parts_mut(slice.as_mut_ptr() as *mut u8, slice.len() * mem::size_of::<T>())
}
<|endoftext|>


<commit_before>// Copyright (c) <2015> <lummax>
// Licensed under MIT (http://opensource.org/licenses/MIT)

#![allow(unstable)]
#![feature(link_llvm_intrinsics)]

extern crate libc;
use std::{mem, ptr};

pub use self::gc_object::{GCHeader, GCRTTI, GCObject, GCObjectRef};

mod macros;
mod constants;
mod gc_object;
mod spaces;
mod stack;

pub struct RCImmixCons {
    spaces: spaces::Spaces,
}

impl RCImmixCons {
    pub fn new() -> RCImmixCons {
        return RCImmixCons {
            spaces: spaces::Spaces::new(),
        };
    }

    pub fn allocate(&mut self, rtti: *const GCRTTI) -> Option<GCObjectRef> {
        return self.spaces.allocate(rtti);
    }

    pub fn collect(&mut self, evacuation: bool, cycle_collect: bool) {
        return self.spaces.collect(evacuation, cycle_collect);
    }

    pub fn write_barrier(&mut self, object: GCObjectRef) {
        return self.spaces.write_barrier(object);
    }
}

#[no_mangle]
pub extern fn rcx_create() -> *mut RCImmixCons {
    return unsafe { mem::transmute(Box::new(RCImmixCons::new())) };
}

#[no_mangle]
pub extern fn rcx_allocate(this: *mut RCImmixCons, rtti: *const GCRTTI)
    -> GCObjectRef {
    unsafe { return (*this).allocate(rtti).unwrap_or(ptr::null_mut()); }
}

#[no_mangle]
pub extern fn rcx_collect(this: *mut RCImmixCons, evacuation: bool, cycle_collect: bool) {
    unsafe { (*this).collect(evacuation, cycle_collect) };
}

#[no_mangle]
pub extern fn rcx_write_barrier(this: *mut RCImmixCons, object: GCObjectRef) {
    unsafe { (*this).write_barrier(object) };
}

#[no_mangle]
pub extern fn rcx_destroy(this: *mut RCImmixCons) {
    let _to_be_dropped: Box<RCImmixCons> = unsafe{ mem::transmute(this) };
}
<commit_msg>Update to rustc 1.0.0-nightly (c5961ad06 2015-01-28 21:49:38 +0000)<commit_after>// Copyright (c) <2015> <lummax>
// Licensed under MIT (http://opensource.org/licenses/MIT)

#![feature(libc)]
#![feature(os)]
#![feature(core)]
#![feature(std_misc)]
#![feature(collections)]
#![feature(link_llvm_intrinsics)]

extern crate libc;
use std::{mem, ptr};

pub use self::gc_object::{GCHeader, GCRTTI, GCObject, GCObjectRef};

mod macros;
mod constants;
mod gc_object;
mod spaces;
mod stack;

pub struct RCImmixCons {
    spaces: spaces::Spaces,
}

impl RCImmixCons {
    pub fn new() -> RCImmixCons {
        return RCImmixCons {
            spaces: spaces::Spaces::new(),
        };
    }

    pub fn allocate(&mut self, rtti: *const GCRTTI) -> Option<GCObjectRef> {
        return self.spaces.allocate(rtti);
    }

    pub fn collect(&mut self, evacuation: bool, cycle_collect: bool) {
        return self.spaces.collect(evacuation, cycle_collect);
    }

    pub fn write_barrier(&mut self, object: GCObjectRef) {
        return self.spaces.write_barrier(object);
    }
}

#[no_mangle]
pub extern fn rcx_create() -> *mut RCImmixCons {
    return unsafe { mem::transmute(Box::new(RCImmixCons::new())) };
}

#[no_mangle]
pub extern fn rcx_allocate(this: *mut RCImmixCons, rtti: *const GCRTTI)
    -> GCObjectRef {
    unsafe { return (*this).allocate(rtti).unwrap_or(ptr::null_mut()); }
}

#[no_mangle]
pub extern fn rcx_collect(this: *mut RCImmixCons, evacuation: bool, cycle_collect: bool) {
    unsafe { (*this).collect(evacuation, cycle_collect) };
}

#[no_mangle]
pub extern fn rcx_write_barrier(this: *mut RCImmixCons, object: GCObjectRef) {
    unsafe { (*this).write_barrier(object) };
}

#[no_mangle]
pub extern fn rcx_destroy(this: *mut RCImmixCons) {
    let _to_be_dropped: Box<RCImmixCons> = unsafe{ mem::transmute(this) };
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016-2017 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

//! Type for representing keys and functions for parsing strings into `Key`s.

use std::fmt::{self, Display, Formatter};

use errors::{ParseError, Result};
use errors::ErrorType::Parse;
use position::Pos;

use self::Key::*;

/// Structure to represent which keys were pressed.
struct ConstructorKeys {
    alt: bool,
    control: bool,
    shift: bool,
}

impl ConstructorKeys {
    fn new() -> Self {
        ConstructorKeys {
            alt: false,
            control: false,
            shift: false,
        }
    }
}

/// Enum representing the keys that can be used in a mapping.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub enum Key {
    /// Alt + another key.
    Alt(Box<Key>),
    /// Backspace key.
    Backspace,
    /// A single-character key.
    Char(char),
    /// Control + another key.
    Control(Box<Key>),
    /// Down arrow.
    Down,
    /// Enter key.
    Enter,
    /// Escape key.
    Escape,
    /// Function key 1
    F1,
    /// Function key 2
    F2,
    /// Function key 3
    F3,
    /// Function key 4
    F4,
    /// Function key 5
    F5,
    /// Function key 6
    F6,
    /// Function key 7
    F7,
    /// Function key 8
    F8,
    /// Function key 9
    F9,
    /// Function key 10
    F10,
    /// Function key 11
    F11,
    /// Function key 12
    F12,
    /// Left arrow.
    Left,
    /// Right arrow.
    Right,
    /// Shift + another key.
    Shift(Box<Key>),
    /// Space key.
    Space,
    /// Tab key.
    Tab,
    /// Up arrow.
    Up,
}

/// Convert a `Key` a to `String`.
/// Note that the result does not contain < and >.
fn key_to_string(key: &Key) -> String {
    let string =
        match *key {
            Alt(ref key) => return format!("A-{}", key_to_string(&*key)),
            Backspace => "Backspace",
            Char(character) => return character.to_string(),
            Control(ref key) => return format!("C-{}", key_to_string(&*key)),
            Down => "Down",
            Enter => "Enter",
            Escape => "Esc",
            F1 => "F1",
            F2 => "F2",
            F3 => "F3",
            F4 => "F4",
            F5 => "F5",
            F6 => "F6",
            F7 => "F7",
            F8 => "F8",
            F9 => "F9",
            F10 => "F10",
            F11 => "F11",
            F12 => "F12",
            Left => "Left",
            Right => "Right",
            Shift(ref key) => return format!("S-{}", key_to_string(&*key)),
            Space => "Space",
            Tab => "Tab",
            Up => "Up",
        };
    string.to_string()
}

impl Display for Key {
    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
        let string = key_to_string(self);
        let string =
            if let Char(_) = *self {
                string
            }
            else {
                format!("<{}>", string)
            };
        write!(formatter, "{}", string)
    }
}

fn key_constructor(key: Key, constructor_keys: &ConstructorKeys) -> Key {
    if constructor_keys.control {
        if constructor_keys.shift {
            if constructor_keys.alt {
                Control(Box::new(Alt(Box::new(Shift(Box::new(key))))))
            }
            else {
                Control(Box::new(Shift(Box::new(key))))
            }
        }
        else if constructor_keys.alt {
            Control(Box::new(Alt(Box::new(key))))
        }
        else {
            Control(Box::new(key))
        }
    }
    else if constructor_keys.shift {
        Shift(Box::new(key))
    }
    else if constructor_keys.alt {
        Alt(Box::new(key))
    }
    else {
        key
    }
}

fn parse_key(input: &str, line_num: usize, column_num: usize) -> Result<(Key, usize)> {
    let mut chars = input.chars();
    let result =
        match chars.next() {
            Some('<') => {
                let key: String = chars.take_while(|&character| character != '>').collect();
                if !input.contains('>') {
                    return Err(ParseError::new(
                        Parse,
                        "(none)".to_string(),
                        ">".to_string(),
                        Pos::new(line_num, column_num + input.len())
                    ));

                }
                let mut end = key.clone();
                if end.len() >= 2 && (&end[..2] == "A-" || &end[..2] == "C-" || &end[..2] == "S-") {
                    let mut delta = 0;
                    let mut constructor_keys = ConstructorKeys::new();
                    while end.len() >= 2 && (&end[..2] == "A-" || &end[..2] == "C-" || &end[..2] == "S-") {
                        let new_end = {
                            let (start, new_end) = end.split_at(2);
                            match start {
                                "A-" => constructor_keys.alt = true,
                                "C-" => constructor_keys.control = true,
                                "S-" => constructor_keys.shift = true,
                                _ => unreachable!(),
                            }
                            delta += 2;
                            new_end.to_string()
                        };
                        end = new_end;
                    }

                    let character = end.chars().next().unwrap(); // NOTE: There is at least one character, hence unwrap.
                    let result_special_key = special_key(&end, line_num, column_num + delta, true)
                        .map(|(key, size)| (key_constructor(key, &constructor_keys), size + delta));
                    match result_special_key {
                        Ok(result) => result,
                        Err(error) => {
                            match character {
                                'A' ... 'Z' | 'a' ... 'z' => {
                                    if end.len() == 1 {
                                        (key_constructor(Char(character), &constructor_keys), 5)
                                    }
                                    else {
                                        return Err(ParseError::new(
                                            Parse,
                                            end.to_string(),
                                            "one character".to_string(),
                                            Pos::new(line_num, column_num + 3)
                                        ));
                                    }
                                },
                                _ => return Err(error),
                            }
                        },
                    }
                }
                else {
                    return special_key(&key, line_num, column_num, false);
                }
            },
            Some(character) => {
                let characters = "=+-;!\"#%&()*,./<>?@[\\]^_{|}~çÇéÉàÀèÈ$";
                match character {
                    'A' ... 'Z' | 'a' ... 'z' => (Char(character), 1),
                    _ if characters.contains(character) => (Char(character), 1),
                    _ =>
                        return Err(ParseError::new(
                            Parse,
                            character.to_string(),
                            "key".to_string(),
                            Pos::new(line_num, column_num)
                        ))
                }
            },
            None => unreachable!() ,
        };
    Ok(result)
}

/// Parse a string into a vector of `Key`s.
pub fn parse_keys(mut input: &str, line_num: usize, column_num: usize) -> Result<Vec<Key>> {
    let mut keys = vec![];
    let mut index = 0;
    while !input.is_empty() {
        let (key, size) = parse_key(input, line_num, column_num + index)?;
        keys.push(key);
        input = &input[size..];
        index += size;
    }
    Ok(keys)
}

/// Parse a special key.
fn special_key(key: &str, line_num: usize, column_num: usize, in_special_key: bool) -> Result<(Key, usize)> {
    let expected =
        if in_special_key {
            "A-Z or special key"
        }
        else {
            "special key"
        };
    let result =
        match key {
            "Backspace" => (Backspace, 11),
            "Down" => (Down, 6),
            "Enter" => (Enter, 7),
            "Esc" => (Escape, 5),
            "F1" => (F1, 4),
            "F2" => (F2, 4),
            "F3" => (F3, 4),
            "F4" => (F4, 4),
            "F5" => (F5, 4),
            "F6" => (F6, 4),
            "F7" => (F7, 4),
            "F8" => (F8, 4),
            "F9" => (F9, 4),
            "F10" => (F10, 5),
            "F11" => (F11, 5),
            "F12" => (F12, 5),
            "Left" => (Left, 6),
            "Right" => (Right, 7),
            "Space" => (Space, 7),
            "Tab" => (Tab, 5),
            "Up" => (Up, 4),
            _ => return Err(ParseError::new(
                     Parse,
                     key.to_string(),
                     expected.to_string(),
                     Pos::new(line_num, column_num + 1)
                 )),
        };
    Ok(result)
}
<commit_msg>Add apos to the list of accepted characters in a key<commit_after>/*
 * Copyright (c) 2016-2017 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

//! Type for representing keys and functions for parsing strings into `Key`s.

use std::fmt::{self, Display, Formatter};

use errors::{ParseError, Result};
use errors::ErrorType::Parse;
use position::Pos;

use self::Key::*;

/// Structure to represent which keys were pressed.
struct ConstructorKeys {
    alt: bool,
    control: bool,
    shift: bool,
}

impl ConstructorKeys {
    fn new() -> Self {
        ConstructorKeys {
            alt: false,
            control: false,
            shift: false,
        }
    }
}

/// Enum representing the keys that can be used in a mapping.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub enum Key {
    /// Alt + another key.
    Alt(Box<Key>),
    /// Backspace key.
    Backspace,
    /// A single-character key.
    Char(char),
    /// Control + another key.
    Control(Box<Key>),
    /// Down arrow.
    Down,
    /// Enter key.
    Enter,
    /// Escape key.
    Escape,
    /// Function key 1
    F1,
    /// Function key 2
    F2,
    /// Function key 3
    F3,
    /// Function key 4
    F4,
    /// Function key 5
    F5,
    /// Function key 6
    F6,
    /// Function key 7
    F7,
    /// Function key 8
    F8,
    /// Function key 9
    F9,
    /// Function key 10
    F10,
    /// Function key 11
    F11,
    /// Function key 12
    F12,
    /// Left arrow.
    Left,
    /// Right arrow.
    Right,
    /// Shift + another key.
    Shift(Box<Key>),
    /// Space key.
    Space,
    /// Tab key.
    Tab,
    /// Up arrow.
    Up,
}

/// Convert a `Key` a to `String`.
/// Note that the result does not contain < and >.
fn key_to_string(key: &Key) -> String {
    let string =
        match *key {
            Alt(ref key) => return format!("A-{}", key_to_string(&*key)),
            Backspace => "Backspace",
            Char(character) => return character.to_string(),
            Control(ref key) => return format!("C-{}", key_to_string(&*key)),
            Down => "Down",
            Enter => "Enter",
            Escape => "Esc",
            F1 => "F1",
            F2 => "F2",
            F3 => "F3",
            F4 => "F4",
            F5 => "F5",
            F6 => "F6",
            F7 => "F7",
            F8 => "F8",
            F9 => "F9",
            F10 => "F10",
            F11 => "F11",
            F12 => "F12",
            Left => "Left",
            Right => "Right",
            Shift(ref key) => return format!("S-{}", key_to_string(&*key)),
            Space => "Space",
            Tab => "Tab",
            Up => "Up",
        };
    string.to_string()
}

impl Display for Key {
    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
        let string = key_to_string(self);
        let string =
            if let Char(_) = *self {
                string
            }
            else {
                format!("<{}>", string)
            };
        write!(formatter, "{}", string)
    }
}

fn key_constructor(key: Key, constructor_keys: &ConstructorKeys) -> Key {
    if constructor_keys.control {
        if constructor_keys.shift {
            if constructor_keys.alt {
                Control(Box::new(Alt(Box::new(Shift(Box::new(key))))))
            }
            else {
                Control(Box::new(Shift(Box::new(key))))
            }
        }
        else if constructor_keys.alt {
            Control(Box::new(Alt(Box::new(key))))
        }
        else {
            Control(Box::new(key))
        }
    }
    else if constructor_keys.shift {
        Shift(Box::new(key))
    }
    else if constructor_keys.alt {
        Alt(Box::new(key))
    }
    else {
        key
    }
}

fn parse_key(input: &str, line_num: usize, column_num: usize) -> Result<(Key, usize)> {
    let mut chars = input.chars();
    let result =
        match chars.next() {
            Some('<') => {
                let key: String = chars.take_while(|&character| character != '>').collect();
                if !input.contains('>') {
                    return Err(ParseError::new(
                        Parse,
                        "(none)".to_string(),
                        ">".to_string(),
                        Pos::new(line_num, column_num + input.len())
                    ));

                }
                let mut end = key.clone();
                if end.len() >= 2 && (&end[..2] == "A-" || &end[..2] == "C-" || &end[..2] == "S-") {
                    let mut delta = 0;
                    let mut constructor_keys = ConstructorKeys::new();
                    while end.len() >= 2 && (&end[..2] == "A-" || &end[..2] == "C-" || &end[..2] == "S-") {
                        let new_end = {
                            let (start, new_end) = end.split_at(2);
                            match start {
                                "A-" => constructor_keys.alt = true,
                                "C-" => constructor_keys.control = true,
                                "S-" => constructor_keys.shift = true,
                                _ => unreachable!(),
                            }
                            delta += 2;
                            new_end.to_string()
                        };
                        end = new_end;
                    }

                    let character = end.chars().next().unwrap(); // NOTE: There is at least one character, hence unwrap.
                    let result_special_key = special_key(&end, line_num, column_num + delta, true)
                        .map(|(key, size)| (key_constructor(key, &constructor_keys), size + delta));
                    match result_special_key {
                        Ok(result) => result,
                        Err(error) => {
                            match character {
                                'A' ... 'Z' | 'a' ... 'z' => {
                                    if end.len() == 1 {
                                        (key_constructor(Char(character), &constructor_keys), 5)
                                    }
                                    else {
                                        return Err(ParseError::new(
                                            Parse,
                                            end.to_string(),
                                            "one character".to_string(),
                                            Pos::new(line_num, column_num + 3)
                                        ));
                                    }
                                },
                                _ => return Err(error),
                            }
                        },
                    }
                }
                else {
                    return special_key(&key, line_num, column_num, false);
                }
            },
            Some(character) => {
                let characters = "=+-;!\"'#%&()*,./<>?@[\\]^_{|}~çÇéÉàÀèÈ$";
                match character {
                    'A' ... 'Z' | 'a' ... 'z' => (Char(character), 1),
                    _ if characters.contains(character) => (Char(character), 1),
                    _ =>
                        return Err(ParseError::new(
                            Parse,
                            character.to_string(),
                            "key".to_string(),
                            Pos::new(line_num, column_num)
                        ))
                }
            },
            None => unreachable!() ,
        };
    Ok(result)
}

/// Parse a string into a vector of `Key`s.
pub fn parse_keys(mut input: &str, line_num: usize, column_num: usize) -> Result<Vec<Key>> {
    let mut keys = vec![];
    let mut index = 0;
    while !input.is_empty() {
        let (key, size) = parse_key(input, line_num, column_num + index)?;
        keys.push(key);
        input = &input[size..];
        index += size;
    }
    Ok(keys)
}

/// Parse a special key.
fn special_key(key: &str, line_num: usize, column_num: usize, in_special_key: bool) -> Result<(Key, usize)> {
    let expected =
        if in_special_key {
            "A-Z or special key"
        }
        else {
            "special key"
        };
    let result =
        match key {
            "Backspace" => (Backspace, 11),
            "Down" => (Down, 6),
            "Enter" => (Enter, 7),
            "Esc" => (Escape, 5),
            "F1" => (F1, 4),
            "F2" => (F2, 4),
            "F3" => (F3, 4),
            "F4" => (F4, 4),
            "F5" => (F5, 4),
            "F6" => (F6, 4),
            "F7" => (F7, 4),
            "F8" => (F8, 4),
            "F9" => (F9, 4),
            "F10" => (F10, 5),
            "F11" => (F11, 5),
            "F12" => (F12, 5),
            "Left" => (Left, 6),
            "Right" => (Right, 7),
            "Space" => (Space, 7),
            "Tab" => (Tab, 5),
            "Up" => (Up, 4),
            _ => return Err(ParseError::new(
                     Parse,
                     key.to_string(),
                     expected.to_string(),
                     Pos::new(line_num, column_num + 1)
                 )),
        };
    Ok(result)
}
<|endoftext|>


<commit_before>#![feature(custom_attribute)]
#![feature(plugin)]
#![allow(dead_code)]
#![plugin(quickcheck_macros)]
#![feature(rand)]
#![feature(collections)]
#![feature(convert)]

extern crate rand;
extern crate quickcheck;

use rand::Rng;

use quickcheck::{quickcheck, Arbitrary, Gen};
use quickcheck as qc;

use std::io::Write;
use std::iter::{FromIterator,Peekable};

#[derive(PartialEq, Eq,Debug, Clone)]
enum SexpToken {
  OpenParen,
  CloseParen,
  Str(String)
}

impl qc::Arbitrary for SexpToken {
  fn arbitrary<G: qc::Gen>(g : &mut G) -> SexpToken {
    match u64::arbitrary(g) % 3 {
      0 => SexpToken::OpenParen,
      1 => SexpToken::CloseParen,
      2 => SexpToken::Str(qc::Arbitrary::arbitrary(g)),
      n => panic!("Unexpected value mod 3: {:?}", n)
    }
  }

  fn shrink(&self) -> Box<Iterator<Item=SexpToken>+'static> {
//    writeln!(std::io::stderr(),"shrink: {:?}", self).unwrap();
    match *self {
      SexpToken::OpenParen => qc::empty_shrinker(),
      SexpToken::CloseParen => qc::single_shrinker(SexpToken::OpenParen),
      SexpToken::Str(ref x) => {
	let chained = qc::single_shrinker(SexpToken::CloseParen)
		      .chain(qc::single_shrinker(SexpToken::OpenParen))
		      .chain(x.shrink().map(SexpToken::Str));
	Box::new(chained)
      }
    }
  }
}

struct EncodingIterator<I: Iterator> {
  iter: I
}

fn encode<'a, I>(it : I) -> Vec<u8> where I : Iterator<Item=&'a SexpToken> {
  let mut out = vec![];
  for t in it {
    match t {
      &SexpToken::OpenParen => out.push('(' as u8),
      &SexpToken::CloseParen => out.push(')' as u8),
      &SexpToken::Str(ref s) => {
	let bytes = s.clone().into_bytes();
	out.push_all(format!("{}", bytes.len()).into_bytes().as_slice());
	out.push(':' as u8);
	out.push_all(bytes.as_slice())
      }
    }
  }
  out
}

struct DecodingIterator<I: Iterator> {
  iter: Peekable<I>
}

impl<'a, I> Iterator for DecodingIterator<I> where I : Iterator<Item=&'a u8> {
  type Item = SexpToken;
  fn next(&mut self) -> Option<SexpToken> {
    let current : Option<u8> = self.iter.peek().map(|cp| **cp);
    current.map(|c|
      match c {
	c if c == '(' as u8 => { self.iter.next(); SexpToken::OpenParen }
      , c if c == ')' as u8 => { self.iter.next(); SexpToken::CloseParen }
      , c if '0' as u8 <= c && c <= '9' as u8 => { let s = read_string(&mut self.iter); SexpToken::Str(s) }
      , _ => panic!("Unexpected char in sexp decode: {:?}", c)
      }
    )
  }
}

fn decode<'a, I>(it : I) -> DecodingIterator<I> where I : Iterator<Item=&'a u8> {
  DecodingIterator { iter: it.peekable() }
}

fn read_string<'a, I>(it : &mut Peekable<I>) -> String where I : Iterator<Item=&'a u8> {
//  writeln!(std::io::stderr(),"read_string: {:?}" , it.peek());
  let mut len = 0;
  while let Some(&c) = it.next() {
    if c <= '9' as u8 {
      let digit = c - '0' as u8;
      len = len * 10 + digit as usize;
//      writeln!(std::io::stderr(),"read_string! {:?}; len:{:?}" , c as char, len).unwrap();
    } else if c == ':' as u8 {
//      writeln!(std::io::stderr(),"read_string! Colon!");
      break;
    } else {
//      writeln!(std::io::stderr(),"read_string! wat: {:?}", c);
      panic!("Unexpected char in string: {:?}", c);
    }
  }

//  writeln!(std::io::stderr(),"read_string! len: {:?}", len);
  let bytes : Vec<u8> = it.take(len).map(|c| *c).collect();
  let s = String::from_utf8_lossy(bytes.as_slice());
//  writeln!(std::io::stderr(),"read_string! {:?}; peek:{:?}", s, it.peek());
  s.into_owned()
}

fn vec8_as_str(v :&Vec<u8>) -> String {
  String::from_utf8_lossy(v).into_owned()
}

#[quickcheck]
fn round_trip(toks : Vec<SexpToken>) -> bool {
//   writeln!(std::io::stderr(),"orig: {:?}", toks).unwrap();
  let encd = encode(toks.iter());
//   writeln!(std::io::stderr(),"{:?}", vec8_as_str(&encd)).unwrap();
  let res : Vec<_> = decode(encd.iter()).collect();
//   writeln!(std::io::stderr(),"{:?} -> {:?} -> {:?} => {:?}", toks, vec8_as_str(&encd), res, res == toks).unwrap();
  res == toks
}
<commit_msg>Remove redundant type annotation.<commit_after>#![feature(custom_attribute)]
#![feature(plugin)]
#![allow(dead_code)]
#![plugin(quickcheck_macros)]
#![feature(rand)]
#![feature(collections)]
#![feature(convert)]

extern crate rand;
extern crate quickcheck;

use rand::Rng;

use quickcheck::{quickcheck, Arbitrary, Gen};
use quickcheck as qc;

use std::io::Write;
use std::iter::{FromIterator,Peekable};

#[derive(PartialEq, Eq,Debug, Clone)]
enum SexpToken {
  OpenParen,
  CloseParen,
  Str(String)
}

impl qc::Arbitrary for SexpToken {
  fn arbitrary<G: qc::Gen>(g : &mut G) -> SexpToken {
    match u64::arbitrary(g) % 3 {
      0 => SexpToken::OpenParen,
      1 => SexpToken::CloseParen,
      2 => SexpToken::Str(qc::Arbitrary::arbitrary(g)),
      n => panic!("Unexpected value mod 3: {:?}", n)
    }
  }

  fn shrink(&self) -> Box<Iterator<Item=SexpToken>+'static> {
//    writeln!(std::io::stderr(),"shrink: {:?}", self).unwrap();
    match *self {
      SexpToken::OpenParen => qc::empty_shrinker(),
      SexpToken::CloseParen => qc::single_shrinker(SexpToken::OpenParen),
      SexpToken::Str(ref x) => {
	let chained = qc::single_shrinker(SexpToken::CloseParen)
		      .chain(qc::single_shrinker(SexpToken::OpenParen))
		      .chain(x.shrink().map(SexpToken::Str));
	Box::new(chained)
      }
    }
  }
}

struct EncodingIterator<I: Iterator> {
  iter: I
}

fn encode<'a, I>(it : I) -> Vec<u8> where I : Iterator<Item=&'a SexpToken> {
  let mut out = vec![];
  for t in it {
    match t {
      &SexpToken::OpenParen => out.push('(' as u8),
      &SexpToken::CloseParen => out.push(')' as u8),
      &SexpToken::Str(ref s) => {
	let bytes = s.clone().into_bytes();
	out.push_all(format!("{}", bytes.len()).into_bytes().as_slice());
	out.push(':' as u8);
	out.push_all(bytes.as_slice())
      }
    }
  }
  out
}

struct DecodingIterator<I: Iterator> {
  iter: Peekable<I>
}

impl<'a, I> Iterator for DecodingIterator<I> where I : Iterator<Item=&'a u8> {
  type Item = SexpToken;
  fn next(&mut self) -> Option<SexpToken> {
    let current = self.iter.peek().map(|cp| **cp);
    current.map(|c|
      match c {
	c if c == '(' as u8 => { self.iter.next(); SexpToken::OpenParen }
      , c if c == ')' as u8 => { self.iter.next(); SexpToken::CloseParen }
      , c if '0' as u8 <= c && c <= '9' as u8 => { let s = read_string(&mut self.iter); SexpToken::Str(s) }
      , _ => panic!("Unexpected char in sexp decode: {:?}", c)
      }
    )
  }
}

fn decode<'a, I>(it : I) -> DecodingIterator<I> where I : Iterator<Item=&'a u8> {
  DecodingIterator { iter: it.peekable() }
}

fn read_string<'a, I>(it : &mut Peekable<I>) -> String where I : Iterator<Item=&'a u8> {
//  writeln!(std::io::stderr(),"read_string: {:?}" , it.peek());
  let mut len = 0;
  while let Some(&c) = it.next() {
    if c <= '9' as u8 {
      let digit = c - '0' as u8;
      len = len * 10 + digit as usize;
//      writeln!(std::io::stderr(),"read_string! {:?}; len:{:?}" , c as char, len).unwrap();
    } else if c == ':' as u8 {
//      writeln!(std::io::stderr(),"read_string! Colon!");
      break;
    } else {
//      writeln!(std::io::stderr(),"read_string! wat: {:?}", c);
      panic!("Unexpected char in string: {:?}", c);
    }
  }

//  writeln!(std::io::stderr(),"read_string! len: {:?}", len);
  let bytes : Vec<u8> = it.take(len).map(|c| *c).collect();
  let s = String::from_utf8_lossy(bytes.as_slice());
//  writeln!(std::io::stderr(),"read_string! {:?}; peek:{:?}", s, it.peek());
  s.into_owned()
}

fn vec8_as_str(v :&Vec<u8>) -> String {
  String::from_utf8_lossy(v).into_owned()
}

#[quickcheck]
fn round_trip(toks : Vec<SexpToken>) -> bool {
//   writeln!(std::io::stderr(),"orig: {:?}", toks).unwrap();
  let encd = encode(toks.iter());
//   writeln!(std::io::stderr(),"{:?}", vec8_as_str(&encd)).unwrap();
  let res : Vec<_> = decode(encd.iter()).collect();
//   writeln!(std::io::stderr(),"{:?} -> {:?} -> {:?} => {:?}", toks, vec8_as_str(&encd), res, res == toks).unwrap();
  res == toks
}
<|endoftext|>