<commit_before>//! Crate retry provides functionality for retrying an operation until its return value satisfies a
//! specific condition.
//!
//! # Usage
//!
//! Create a retryable operation by passing two mutable closure references to `Retry::new`. The
//! first argument, `value_fn`, will be executed to produce a value. The second argument,
//! `condition_fn`, takes the value produced by `value_fn` and returns a boolean indicating whether
//! or not some desired condition is true. Call `execute` on the returned `Retry` object to begin
//! executing the operation, ultimately returning a `Result` containing the final value or an
//! error.
//!
//! By default, the operation will be retried an infinite number of times with no delay between
//! tries. To change either of these values, you may call the following two methods on the `Retry`
//! object:
//!
//! 1. `try`: The maximum number of tries to make.  If the operation reaches this number of tries
//!    without passsing the condition, an error will be returned.
//! 2. `wait` The number of milliseconds to wait after each unsuccessful try.
//!
//! # Failures
//!
//! Executing a `Retry` will fail when:
//!
//! 1. The operation reaches the maximum number of tries without success.
//! 2. A value of 0 is supplied to `try`. It must be at least 1.
//!
//! # Examples
//!
//! Imagine an HTTP API with an endpoint that returns 204 No Content while a job is processing, and
//! eventually 200 OK when the job has completed. Retrying until the job is finished would be
//! written:
//!
//! ```
//! # use retry::Retry;
//! # struct Client;
//! # impl Client {
//! #     fn query_job_status(&self) -> Response {
//! #         Response {
//! #             code: 200,
//! #             body: "success",
//! #         }
//! #     }
//! # }
//! # struct Response {
//! #     code: u16,
//! #     body: &'static str,
//! # }
//! # let api_client = Client;
//! match Retry::new(
//!     &mut || api_client.query_job_status(),
//!     &mut |response| response.code == 200
//! ).try(10).wait(500).execute() {
//!     Ok(response) => println!("Job completed with result: {}", response.body),
//!     Err(error) => println!("Job completion could not be verified: {}", error),
//! }
//! ```
//!
//! This retries the API call up to 10 times, waiting 500 milliseconds after each unsuccessful
//! attempt.

use std::error::Error;
use std::fmt::{Display,Formatter};
use std::fmt::Error as FmtError;
use std::thread::sleep_ms;

/// Builder object for a retryable operation.
#[derive(Debug)]
pub struct Retry<'a, F: FnMut() -> R + 'a, G: FnMut(&R) -> bool + 'a, R> {
    condition_fn: &'a mut G,
    tries: Option<u32>,
    value_fn: &'a mut F,
    wait: u32,
}

impl<'a, F: FnMut() -> R, G: FnMut(&R) -> bool, R> Retry<'a, F, G, R> {
    /// Build a new `Retry` object.
    pub fn new(
        value_fn: &'a mut F,
        condition_fn: &'a mut G
    ) -> Retry<'a, F, G, R> where F: FnMut() -> R, G: FnMut(&R) -> bool {
        Retry {
            condition_fn: condition_fn,
            tries: None,
            value_fn: value_fn,
            wait: 0,
        }
    }

    /// Begin executing the retryable operation.
    pub fn execute(self) -> Result<R, RetryError> {
        if self.tries.is_some() && self.tries.unwrap() == 0 {
            return Err(RetryError { message: "tries must be non-zero" });
        }

        let mut try = 0;

        loop {
            if self.tries.is_some() && self.tries.unwrap() == try {
                return Err(RetryError { message: "reached last try without condition match" })
            }

            let value = (self.value_fn)();

            if (self.condition_fn)(&value) {
                return Ok(value);
            }

            sleep_ms(self.wait);
            try += 1;
        }
    }

    /// Set a maximum number of tries to make before failing.
    pub fn try(mut self, tries: u32) -> Retry<'a, F, G, R> {
        self.tries = Some(tries);

        self
    }

    /// Set the number of milliseconds to wait after an unsuccesful try before trying again.
    pub fn wait(mut self, wait: u32) -> Retry<'a, F, G, R> {
        self.wait = wait;

        self
    }
}

/// An error indicating that a retry call failed.
#[derive(Debug)]
pub struct RetryError {
    message: &'static str
}

impl Display for RetryError {
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), FmtError> {
        write!(formatter, "{}", self.message)
    }
}

impl Error for RetryError {
    fn description(&self) -> &str {
        self.message
    }
}

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

    #[test]
    fn succeeds_without_try_count() {
        let mut collection = vec![1, 2, 3, 4, 5].into_iter();

        let value = Retry::new(
            &mut || collection.next().unwrap(),
            &mut |value| *value == 5
        ).execute().unwrap();

        assert_eq!(value, 5);
    }

    #[test]
    fn succeeds_on_first_try() {
        let value = Retry::new(&mut || 1, &mut |value| *value == 1).try(1).execute().ok().unwrap();

        assert_eq!(value, 1);
    }

    #[test]
    fn requires_non_zero_tries() {
        let error = Retry::new(&mut || 1, &mut |value| *value == 1).try(0).execute().err().unwrap();

        assert_eq!(error.message, "tries must be non-zero");
    }

    #[test]
    fn succeeds_on_subsequent_try() {
        let mut collection = vec![1, 2].into_iter();

        let value = Retry::new(
            &mut || collection.next().unwrap(),
            &mut |value| *value == 2
        ).try(2).execute().ok().unwrap();

        assert_eq!(value, 2);
    }

    #[test]
    fn fails_after_last_try() {
        let mut collection = vec![1].into_iter();

        let error = Retry::new(
            &mut || collection.next().unwrap(),
            &mut |value| *value == 2
        ).try(1).execute().err().unwrap();

        assert_eq!(error.message, "reached last try without condition match");
    }

    #[test]
    fn sets_custom_wait_time() {
        let mut collection = vec![1, 2].into_iter();

        let value = Retry::new(
            &mut || collection.next().unwrap(),
            &mut |value| *value == 2
        ).try(2).wait(1).execute().ok().unwrap();

        assert_eq!(value, 2);
    }
}
<commit_msg>Remove unecessary try count from wait test.<commit_after>//! Crate retry provides functionality for retrying an operation until its return value satisfies a
//! specific condition.
//!
//! # Usage
//!
//! Create a retryable operation by passing two mutable closure references to `Retry::new`. The
//! first argument, `value_fn`, will be executed to produce a value. The second argument,
//! `condition_fn`, takes the value produced by `value_fn` and returns a boolean indicating whether
//! or not some desired condition is true. Call `execute` on the returned `Retry` object to begin
//! executing the operation, ultimately returning a `Result` containing the final value or an
//! error.
//!
//! By default, the operation will be retried an infinite number of times with no delay between
//! tries. To change either of these values, you may call the following two methods on the `Retry`
//! object:
//!
//! 1. `try`: The maximum number of tries to make.  If the operation reaches this number of tries
//!    without passsing the condition, an error will be returned.
//! 2. `wait` The number of milliseconds to wait after each unsuccessful try.
//!
//! # Failures
//!
//! Executing a `Retry` will fail when:
//!
//! 1. The operation reaches the maximum number of tries without success.
//! 2. A value of 0 is supplied to `try`. It must be at least 1.
//!
//! # Examples
//!
//! Imagine an HTTP API with an endpoint that returns 204 No Content while a job is processing, and
//! eventually 200 OK when the job has completed. Retrying until the job is finished would be
//! written:
//!
//! ```
//! # use retry::Retry;
//! # struct Client;
//! # impl Client {
//! #     fn query_job_status(&self) -> Response {
//! #         Response {
//! #             code: 200,
//! #             body: "success",
//! #         }
//! #     }
//! # }
//! # struct Response {
//! #     code: u16,
//! #     body: &'static str,
//! # }
//! # let api_client = Client;
//! match Retry::new(
//!     &mut || api_client.query_job_status(),
//!     &mut |response| response.code == 200
//! ).try(10).wait(500).execute() {
//!     Ok(response) => println!("Job completed with result: {}", response.body),
//!     Err(error) => println!("Job completion could not be verified: {}", error),
//! }
//! ```
//!
//! This retries the API call up to 10 times, waiting 500 milliseconds after each unsuccessful
//! attempt.

use std::error::Error;
use std::fmt::{Display,Formatter};
use std::fmt::Error as FmtError;
use std::thread::sleep_ms;

/// Builder object for a retryable operation.
#[derive(Debug)]
pub struct Retry<'a, F: FnMut() -> R + 'a, G: FnMut(&R) -> bool + 'a, R> {
    condition_fn: &'a mut G,
    tries: Option<u32>,
    value_fn: &'a mut F,
    wait: u32,
}

impl<'a, F: FnMut() -> R, G: FnMut(&R) -> bool, R> Retry<'a, F, G, R> {
    /// Build a new `Retry` object.
    pub fn new(
        value_fn: &'a mut F,
        condition_fn: &'a mut G
    ) -> Retry<'a, F, G, R> where F: FnMut() -> R, G: FnMut(&R) -> bool {
        Retry {
            condition_fn: condition_fn,
            tries: None,
            value_fn: value_fn,
            wait: 0,
        }
    }

    /// Begin executing the retryable operation.
    pub fn execute(self) -> Result<R, RetryError> {
        if self.tries.is_some() && self.tries.unwrap() == 0 {
            return Err(RetryError { message: "tries must be non-zero" });
        }

        let mut try = 0;

        loop {
            if self.tries.is_some() && self.tries.unwrap() == try {
                return Err(RetryError { message: "reached last try without condition match" })
            }

            let value = (self.value_fn)();

            if (self.condition_fn)(&value) {
                return Ok(value);
            }

            sleep_ms(self.wait);
            try += 1;
        }
    }

    /// Set a maximum number of tries to make before failing.
    pub fn try(mut self, tries: u32) -> Retry<'a, F, G, R> {
        self.tries = Some(tries);

        self
    }

    /// Set the number of milliseconds to wait after an unsuccesful try before trying again.
    pub fn wait(mut self, wait: u32) -> Retry<'a, F, G, R> {
        self.wait = wait;

        self
    }
}

/// An error indicating that a retry call failed.
#[derive(Debug)]
pub struct RetryError {
    message: &'static str
}

impl Display for RetryError {
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), FmtError> {
        write!(formatter, "{}", self.message)
    }
}

impl Error for RetryError {
    fn description(&self) -> &str {
        self.message
    }
}

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

    #[test]
    fn succeeds_without_try_count() {
        let mut collection = vec![1, 2, 3, 4, 5].into_iter();

        let value = Retry::new(
            &mut || collection.next().unwrap(),
            &mut |value| *value == 5
        ).execute().unwrap();

        assert_eq!(value, 5);
    }

    #[test]
    fn succeeds_on_first_try() {
        let value = Retry::new(&mut || 1, &mut |value| *value == 1).try(1).execute().ok().unwrap();

        assert_eq!(value, 1);
    }

    #[test]
    fn requires_non_zero_tries() {
        let error = Retry::new(&mut || 1, &mut |value| *value == 1).try(0).execute().err().unwrap();

        assert_eq!(error.message, "tries must be non-zero");
    }

    #[test]
    fn succeeds_on_subsequent_try() {
        let mut collection = vec![1, 2].into_iter();

        let value = Retry::new(
            &mut || collection.next().unwrap(),
            &mut |value| *value == 2
        ).try(2).execute().ok().unwrap();

        assert_eq!(value, 2);
    }

    #[test]
    fn fails_after_last_try() {
        let mut collection = vec![1].into_iter();

        let error = Retry::new(
            &mut || collection.next().unwrap(),
            &mut |value| *value == 2
        ).try(1).execute().err().unwrap();

        assert_eq!(error.message, "reached last try without condition match");
    }

    #[test]
    fn sets_custom_wait_time() {
        let mut collection = vec![1, 2].into_iter();

        let value = Retry::new(
            &mut || collection.next().unwrap(),
            &mut |value| *value == 2
        ).wait(1).execute().ok().unwrap();

        assert_eq!(value, 2);
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

#[macro_use]
extern crate pest;

extern crate rand;

mod parse;

use pest::*;
use parse::*;

pub fn roll_dice(r: &str) -> i32 {
    let mut parser = Rdp::new(StringInput::new(r));
    parser.expression();

    parser.compute()
}

#[derive(Debug)]
pub struct Roller<'a> {
    roll: &'a str,
    total: i32,
}

impl<'a> Roller<'a> {
     fn new(roll: &str) -> Roller {
         Roller{
             roll: roll,
             total: roll_dice(roll)
         }
     }

     fn reroll(&mut self) -> i32 {
         self.total = roll_dice(self.roll);

         self.total
     }

     fn total(&self) -> i32 {
         self.total
     }
}<commit_msg>Roller impl methods should be pub<commit_after>#[macro_use]
extern crate pest;
extern crate rand;

mod parse;

use pest::*;
use parse::*;

pub fn roll_dice(r: &str) -> i32 {
    let mut parser = Rdp::new(StringInput::new(r));
    parser.expression();

    parser.compute()
}

#[derive(Debug)]
pub struct Roller<'a> {
    roll: &'a str,
    total: i32,
}

impl<'a> Roller<'a> {
     pub fn new(roll: &str) -> Roller {
         Roller{
             roll: roll,
             total: roll_dice(roll)
         }
     }

     pub fn reroll(&mut self) -> i32 {
         self.total = roll_dice(self.roll);

         self.total
     }

     pub fn total(&self) -> i32 {
         self.total
     }
}<|endoftext|>


<commit_before>//! `Future`-powered I/O at the core of Tokio
//!
//! This crate uses the `futures` crate to provide an event loop ("reactor
//! core") which can be used to drive I/O like TCP and UDP, spawned future
//! tasks, and other events like channels/timeouts. All asynchronous I/O is
//! powered by the `mio` crate.
//!
//! The concrete types provided in this crate are relatively bare bones but are
//! intended to be the essential foundation for further projects needing an
//! event loop. In this crate you'll find:
//!
//! * TCP, both streams and listeners
//! * UDP sockets
//! * Timeouts
//! * An event loop to run futures
//!
//! More functionality is likely to be added over time, but otherwise the crate
//! is intended to be flexible, with the `PollEvented` type accepting any
//! type that implements `mio::Evented`. For example, the `tokio-uds` crate
//! uses `PollEvented` to provide support for Unix domain sockets.
//!
//! Some other important tasks covered by this crate are:
//!
//! * The ability to spawn futures into an event loop. The `Handle` and `Remote`
//!   types have a `spawn` method which allows executing a future on an event
//!   loop. The `Handle::spawn` method crucially does not require the future
//!   itself to be `Send`.
//!
//! * The `Io` trait serves as an abstraction for future crates to build on top
//!   of. This packages up `Read` and `Write` functionality as well as the
//!   ability to poll for readiness on both ends.
//!
//! * All I/O is futures-aware. If any action in this crate returns "not ready"
//!   or "would block", then the current future task is scheduled to receive a
//!   notification when it would otherwise make progress.
//!
//! You can find more extensive documentation in terms of tutorials at
//! [https://tokio.rs](https://tokio.rs).
//!
//! # Examples
//!
//! A simple TCP echo server:
//!
//! ```no_run
//! extern crate futures;
//! extern crate tokio_core;
//!
//! use futures::{Future, Stream};
//! use tokio_core::io::{copy, Io};
//! use tokio_core::net::TcpListener;
//! use tokio_core::reactor::Core;
//!
//! fn main() {
//!     // Create the event loop that will drive this server
//!     let mut core = Core::new().unwrap();
//!     let handle = core.handle();
//!
//!     // Bind the server's socket
//!     let addr = "127.0.0.1:12345".parse().unwrap();
//!     let listener = TcpListener::bind(&addr, &handle).unwrap();
//!
//!     // Pull out a stream of sockets for incoming connections
//!     let server = listener.incoming().for_each(|(sock, _)| {
//!         // Split up the reading and writing parts of the
//!         // socket
//!         let (reader, writer) = sock.split();
//!
//!         // A future that echos the data and returns how
//!         // many bytes were copied...
//!         let bytes_copied = copy(reader, writer);
//!
//!         // ... after which we'll print what happened
//!         let handle_conn = bytes_copied.map(|amt| {
//!             println!("wrote {} bytes", amt)
//!         }).map_err(|err| {
//!             println!("IO error {:?}", err)
//!         });
//!
//!         // Spawn the future as a concurrent task
//!         handle.spawn(handle_conn);
//!
//!         Ok(())
//!     });
//!
//!     // Spin up the server on the event loop
//!     core.run(server).unwrap();
//! }
//! ```

#![doc(html_root_url = "https://docs.rs/tokio-core/0.1")]
#![deny(missing_docs)]

extern crate bytes;
#[macro_use]
extern crate futures;
extern crate iovec;
extern crate mio;
extern crate slab;
extern crate tokio_io;

#[macro_use]
extern crate scoped_tls;

#[macro_use]
extern crate log;

#[macro_use]
#[doc(hidden)]
pub mod io;

mod heap;
#[doc(hidden)]
pub mod channel;
pub mod net;
pub mod reactor;

use std::io as sio;

fn would_block() -> sio::Error {
    sio::Error::new(sio::ErrorKind::WouldBlock, "would block")
}
<commit_msg>update example in doc comment<commit_after>//! `Future`-powered I/O at the core of Tokio
//!
//! This crate uses the `futures` crate to provide an event loop ("reactor
//! core") which can be used to drive I/O like TCP and UDP, spawned future
//! tasks, and other events like channels/timeouts. All asynchronous I/O is
//! powered by the `mio` crate.
//!
//! The concrete types provided in this crate are relatively bare bones but are
//! intended to be the essential foundation for further projects needing an
//! event loop. In this crate you'll find:
//!
//! * TCP, both streams and listeners
//! * UDP sockets
//! * Timeouts
//! * An event loop to run futures
//!
//! More functionality is likely to be added over time, but otherwise the crate
//! is intended to be flexible, with the `PollEvented` type accepting any
//! type that implements `mio::Evented`. For example, the `tokio-uds` crate
//! uses `PollEvented` to provide support for Unix domain sockets.
//!
//! Some other important tasks covered by this crate are:
//!
//! * The ability to spawn futures into an event loop. The `Handle` and `Remote`
//!   types have a `spawn` method which allows executing a future on an event
//!   loop. The `Handle::spawn` method crucially does not require the future
//!   itself to be `Send`.
//!
//! * The `Io` trait serves as an abstraction for future crates to build on top
//!   of. This packages up `Read` and `Write` functionality as well as the
//!   ability to poll for readiness on both ends.
//!
//! * All I/O is futures-aware. If any action in this crate returns "not ready"
//!   or "would block", then the current future task is scheduled to receive a
//!   notification when it would otherwise make progress.
//!
//! You can find more extensive documentation in terms of tutorials at
//! [https://tokio.rs](https://tokio.rs).
//!
//! # Examples
//!
//! A simple TCP echo server:
//!
//! ```no_run
//! extern crate futures;
//! extern crate tokio_core;
//! extern crate tokio_io;
//!
//! use futures::{Future, Stream};
//! use tokio_io::AsyncRead;
//! use tokio_io::io::copy;
//! use tokio_core::net::TcpListener;
//! use tokio_core::reactor::Core;
//!
//! fn main() {
//!     // Create the event loop that will drive this server
//!     let mut core = Core::new().unwrap();
//!     let handle = core.handle();
//!
//!     // Bind the server's socket
//!     let addr = "127.0.0.1:12345".parse().unwrap();
//!     let listener = TcpListener::bind(&addr, &handle).unwrap();
//!
//!     // Pull out a stream of sockets for incoming connections
//!     let server = listener.incoming().for_each(|(sock, _)| {
//!         // Split up the reading and writing parts of the
//!         // socket
//!         let (reader, writer) = sock.split();
//!
//!         // A future that echos the data and returns how
//!         // many bytes were copied...
//!         let bytes_copied = copy(reader, writer);
//!
//!         // ... after which we'll print what happened
//!         let handle_conn = bytes_copied.map(|amt| {
//!             println!("wrote {:?} bytes", amt)
//!         }).map_err(|err| {
//!             println!("IO error {:?}", err)
//!         });
//!
//!         // Spawn the future as a concurrent task
//!         handle.spawn(handle_conn);
//!
//!         Ok(())
//!     });
//!
//!     // Spin up the server on the event loop
//!     core.run(server).unwrap();
//! }
//! ```

#![doc(html_root_url = "https://docs.rs/tokio-core/0.1")]
#![deny(missing_docs)]

extern crate bytes;
#[macro_use]
extern crate futures;
extern crate iovec;
extern crate mio;
extern crate slab;
extern crate tokio_io;

#[macro_use]
extern crate scoped_tls;

#[macro_use]
extern crate log;

#[macro_use]
#[doc(hidden)]
pub mod io;

mod heap;
#[doc(hidden)]
pub mod channel;
pub mod net;
pub mod reactor;

use std::io as sio;

fn would_block() -> sio::Error {
    sio::Error::new(sio::ErrorKind::WouldBlock, "would block")
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;
extern crate serde_yaml;

use std::fs;
use std::io::Read;
use std::path::Path;

mod schema;
pub use schema::Spec;

pub mod errors {
    error_chain!{
        foreign_links {
            Io(::std::io::Error);
            Yaml(::serde_yaml::Error);
            Serialize(::serde_json::Error);
        }
    }
}

/// deserialize an open api spec from a path
pub fn from_path<P>(path: P) -> errors::Result<Spec>
where
    P: AsRef<Path>,
{
    from_reader(fs::File::open(path)?)
}

/// deserialize an open api spec from type which implements Read
pub fn from_reader<R>(read: R) -> errors::Result<Spec>
where
    R: Read,
{
    Ok(serde_yaml::from_reader::<R, Spec>(read)?)
}

/// serialize to a yaml string
pub fn to_yaml(spec: &Spec) -> errors::Result<String> {
    Ok(serde_yaml::to_string(spec)?)
}

/// serialize to a json string
pub fn to_json(spec: &Spec) -> errors::Result<String> {
    Ok(serde_json::to_string_pretty(spec)?)
}

#[cfg(test)]
mod tests {
    use super::*;
    // Just tests if the deserialization does not blow up. But does not test correctness
    #[test]
    fn can_deserialize() {
        for entry in fs::read_dir("data/").unwrap() {
            let entry = entry.unwrap();
            let path = entry.path();
            // cargo test -- --nocapture to see this message
            println!("Testing if {:?} is deserializable", path);
            from_path(path).unwrap();
        }
    }
}
<commit_msg>expose other types publicly<commit_after>#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;
extern crate serde_yaml;

use std::fs;
use std::io::Read;
use std::path::Path;

mod schema;
pub use schema::*;

pub mod errors {
    error_chain!{
        foreign_links {
            Io(::std::io::Error);
            Yaml(::serde_yaml::Error);
            Serialize(::serde_json::Error);
        }
    }
}

/// deserialize an open api spec from a path
pub fn from_path<P>(path: P) -> errors::Result<Spec>
where
    P: AsRef<Path>,
{
    from_reader(fs::File::open(path)?)
}

/// deserialize an open api spec from type which implements Read
pub fn from_reader<R>(read: R) -> errors::Result<Spec>
where
    R: Read,
{
    Ok(serde_yaml::from_reader::<R, Spec>(read)?)
}

/// serialize to a yaml string
pub fn to_yaml(spec: &Spec) -> errors::Result<String> {
    Ok(serde_yaml::to_string(spec)?)
}

/// serialize to a json string
pub fn to_json(spec: &Spec) -> errors::Result<String> {
    Ok(serde_json::to_string_pretty(spec)?)
}

#[cfg(test)]
mod tests {
    use super::*;
    // Just tests if the deserialization does not blow up. But does not test correctness
    #[test]
    fn can_deserialize() {
        for entry in fs::read_dir("data/").unwrap() {
            let entry = entry.unwrap();
            let path = entry.path();
            // cargo test -- --nocapture to see this message
            println!("Testing if {:?} is deserializable", path);
            from_path(path).unwrap();
        }
    }
}
<|endoftext|>


<commit_before>extern crate "boxdraw-rs" as boxdraw;

use boxdraw::{Undraw, Script};
use boxdraw::grid::Grid;

pub struct SimpleSearch;

impl Undraw for SimpleSearch {
    fn undraw(&self, picture: &str) -> Script {
        let mut grid = Grid::from_str(picture).unwrap();
        let w = grid.width();
        let h = grid.height();

        let mut s = Script::new(w, h);

        for x in range(0, w) {
            for y in range(0, h) {
                // Found a left-corner; find the extent of the box.
                println!("inspecting ({},{})", x, y);
                println!("char at: ({},{}): '{}'", x, y, grid.get(x, y));
                if grid.get(x, y) == '+' {
                    let mut box_w = 1;
                    for i in range(x+1, w) {
                        let c = grid.get(i, y);
                        println!("scanning across, c: '{}'", c);
                        if c == '-' {
                            continue;
                        }
                        if c == '+' {
                            box_w = i - x + 1;
                            break;
                        }
                    }

                    let mut box_h = 1;
                    for j in range(y+1, h) {
                        assert!(j < h);
                        let left = grid.get(x, j);
                        assert!(j < h);
                        let right = grid.get(x + box_w - 1, j);
                        println!("scanning down, left: '{}' right: '{}'",
                                 left, right);
                        if left == '|' && right == '|' {
                            continue
                        }
                        if left == '+' && right == '+' {
                            box_h = j - y + 1;
                            break;
                        }
                    }

                    assert!(y+1 < h);
                    let fill = grid.get(x+1, y+1);
                    let cmd = boxdraw::rect(x, y, box_w, box_h, fill);
                    s.add_end_command(cmd);

                    // Now, clear the matched area.
                    println!("clearing matched area ({},{}) of w:{} h:{}",
                             x, y, box_w, box_h);
                    for i in range(x, x+box_w) {
                        for j in range(y, y+box_h) {
                            grid.set(i, j, '?');
                        }
                    }
                }
            }
        }

        s
    }
}

#[test]
fn check_simple() {
    boxdraw::check_undraw("...\n", &SimpleSearch).unwrap();

    boxdraw::check_undraw(".....\n\
                           .+-+.\n\
                           .|b|.\n\
                           .+-+.\n\
                          ",
                          &SimpleSearch).unwrap();

    boxdraw::check_undraw(".............\n\
                           .......+--+..\n\
                           .+-+...|cc|..\n\
                           .|b|...|cc|..\n\
                           .+-+...+--+..\n\
                           .............\n\
                          ",
                          &SimpleSearch).unwrap();

    boxdraw::check_undraw(".........\n\
                           .........\n\
                           .+-+.....\n\
                           .|b|.....\n\
                           .+-+.....\n\
                           .+--+....\n\
                           .|cc|....\n\
                           .|cc|....\n\
                           .+--+....\n\
                           .........\n\
                          ",
                          &SimpleSearch).unwrap();
}
<commit_msg>added example of a failing case so that no one is confused about limits here.<commit_after>extern crate "boxdraw-rs" as boxdraw;

use boxdraw::{Undraw, Script};
use boxdraw::grid::Grid;

pub struct SimpleSearch;

impl Undraw for SimpleSearch {
    fn undraw(&self, picture: &str) -> Script {
        let mut grid = Grid::from_str(picture).unwrap();
        let w = grid.width();
        let h = grid.height();

        let mut s = Script::new(w, h);

        for x in range(0, w) {
            for y in range(0, h) {
                // Found a left-corner; find the extent of the box.
                println!("inspecting ({},{})", x, y);
                println!("char at: ({},{}): '{}'", x, y, grid.get(x, y));
                if grid.get(x, y) == '+' {
                    let mut box_w = 1;
                    for i in range(x+1, w) {
                        let c = grid.get(i, y);
                        println!("scanning across, c: '{}'", c);
                        if c == '-' {
                            continue;
                        }
                        if c == '+' {
                            box_w = i - x + 1;
                            break;
                        }
                    }

                    let mut box_h = 1;
                    for j in range(y+1, h) {
                        assert!(j < h);
                        let left = grid.get(x, j);
                        assert!(j < h);
                        let right = grid.get(x + box_w - 1, j);
                        println!("scanning down, left: '{}' right: '{}'",
                                 left, right);
                        if left == '|' && right == '|' {
                            continue
                        }
                        if left == '+' && right == '+' {
                            box_h = j - y + 1;
                            break;
                        }
                    }

                    assert!(y+1 < h);
                    let fill = grid.get(x+1, y+1);
                    let cmd = boxdraw::rect(x, y, box_w, box_h, fill);
                    s.add_end_command(cmd);

                    // Now, clear the matched area.
                    println!("clearing matched area ({},{}) of w:{} h:{}",
                             x, y, box_w, box_h);
                    for i in range(x, x+box_w) {
                        for j in range(y, y+box_h) {
                            grid.set(i, j, '?');
                        }
                    }
                }
            }
        }

        s
    }
}

#[test]
fn check_simple() {
    boxdraw::check_undraw("...\n", &SimpleSearch).unwrap();

    boxdraw::check_undraw(".....\n\
                           .+-+.\n\
                           .|b|.\n\
                           .+-+.\n\
                          ",
                          &SimpleSearch).unwrap();

    boxdraw::check_undraw(".............\n\
                           .......+--+..\n\
                           .+-+...|cc|..\n\
                           .|b|...|cc|..\n\
                           .+-+...+--+..\n\
                           .............\n\
                          ",
                          &SimpleSearch).unwrap();

    boxdraw::check_undraw(".........\n\
                           .........\n\
                           .+-+.....\n\
                           .|b|.....\n\
                           .+-+.....\n\
                           .+--+....\n\
                           .|cc|....\n\
                           .|cc|....\n\
                           .+--+....\n\
                           .........\n\
                          ",
                          &SimpleSearch).unwrap();
}

#[test]
#[should_fail]
fn too_naive_to_pass_this_yet() {
    boxdraw::check_undraw(".............\n\
                           ....+---+....\n\
                           ....|bbb|....\n\
                           ....|bb+--+..\n\
                           ....|bb|cc|..\n\
                           ....+--|cc|..\n\
                           .......+--+..\n\
                           .............\n\
                          ",
                          &SimpleSearch).unwrap();

}
<|endoftext|>


<commit_before>extern crate antidote;
extern crate chrono;
extern crate config;
extern crate data_encoding;
#![deny(unused_features)]
#![deny(deprecated)]
#![warn(unused_variables)]
#![warn(unused_imports)]
#![warn(dead_code)]
#![warn(missing_copy_implementations)]

#[macro_use]
extern crate failure;
extern crate fern;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[cfg(test)]
extern crate rand;
extern crate reqwest;
extern crate serde;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate serde_json;
#[cfg(test)]
extern crate spectral;
#[cfg(test)]
extern crate test_server;

mod ctapi;
mod http;
mod logging;
mod settings;

use crate::ctapi::close::close;
use crate::ctapi::data::data;
use crate::ctapi::init::init;
use crate::ctapi::status::Status;
use crate::settings::Settings;
use antidote::RwLock;
use std::panic;

lazy_static! {
    pub(crate) static ref CONFIG: RwLock<Settings> =
        RwLock::new(Settings::init().expect("Failed to init configuration!"));
}

#[no_mangle]
pub extern "system" fn CT_init(ctn: u16, pn: u16) -> i8 {
    logging::init();

    debug!("CT_init(ctn: {}, pn: {})", ctn, pn);
    let status: i8 = match init(ctn, pn) {
        Ok(status) => status.value(),
        Err(why) => {
            error!("Failure during CT_init!");
            debug!("{}", why);
            Status::ERR_HTSI.value()
        }
    };

    debug!("Returning {}", status);
    status
}

#[no_mangle]
pub extern "system" fn CT_data(
    ctn: u16,
    dad: *mut u8,
    sad: *mut u8,
    lenc: u16,
    command: *const u8,
    lenr: *mut u16,
    response: *mut u8,
) -> i8 {
    logging::init();

    if dad.is_null() {
        error!("Null pointer passed into CT_data() as dad");
        return Status::ERR_HTSI.value();
    }

    if sad.is_null() {
        error!("Null pointer passed into CT_data() as sad");
        return Status::ERR_HTSI.value();
    }

    if lenr.is_null() {
        error!("Null pointer passed into CT_data() as lenr");
        return Status::ERR_HTSI.value();
    }

    if response.is_null() {
        error!("Null pointer passed into CT_data() as response");
        return Status::ERR_HTSI.value();
    }

    debug!("CT_data(ctn: {})", ctn);
    let status: i8 =
        match panic::catch_unwind(|| data(ctn, dad, sad, lenc, command, lenr, response)) {
            Ok(result) => match result {
                Ok(status) => status.value(),
                Err(why) => {
                    error!("Failure during CT_data!");
                    debug!("{}", why);
                    Status::ERR_HTSI.value()
                }
            },
            Err(_) => {
                error!("Caught panic!");
                Status::ERR_HTSI.value()
            }
        };

    debug!("Returning {}", status);
    status
}

#[no_mangle]
pub extern "system" fn CT_close(ctn: u16) -> i8 {
    logging::init();

    debug!("CT_close(ctn: {})", ctn);
    let status = match close(ctn) {
        Ok(status) => status.value(),
        Err(why) => {
            error!("Failure during CT_close!");
            debug!("{}", why);
            Status::ERR_HTSI.value()
        }
    };

    debug!("Returning {}", status);
    status
}
<commit_msg>remove extern crates<commit_after>#![deny(unused_features)]
#![deny(deprecated)]
#![warn(unused_variables)]
#![warn(unused_imports)]
#![warn(dead_code)]
#![warn(missing_copy_implementations)]

#[macro_use]
extern crate failure;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate serde_json;

mod ctapi;
mod http;
mod logging;
mod settings;

use crate::ctapi::close::close;
use crate::ctapi::data::data;
use crate::ctapi::init::init;
use crate::ctapi::status::Status;
use crate::settings::Settings;
use antidote::RwLock;
use std::panic;

lazy_static! {
    pub(crate) static ref CONFIG: RwLock<Settings> =
        RwLock::new(Settings::init().expect("Failed to init configuration!"));
}

#[no_mangle]
pub extern "system" fn CT_init(ctn: u16, pn: u16) -> i8 {
    logging::init();

    debug!("CT_init(ctn: {}, pn: {})", ctn, pn);
    let status: i8 = match init(ctn, pn) {
        Ok(status) => status.value(),
        Err(why) => {
            error!("Failure during CT_init!");
            debug!("{}", why);
            Status::ERR_HTSI.value()
        }
    };

    debug!("Returning {}", status);
    status
}

#[no_mangle]
pub extern "system" fn CT_data(
    ctn: u16,
    dad: *mut u8,
    sad: *mut u8,
    lenc: u16,
    command: *const u8,
    lenr: *mut u16,
    response: *mut u8,
) -> i8 {
    logging::init();

    if dad.is_null() {
        error!("Null pointer passed into CT_data() as dad");
        return Status::ERR_HTSI.value();
    }

    if sad.is_null() {
        error!("Null pointer passed into CT_data() as sad");
        return Status::ERR_HTSI.value();
    }

    if lenr.is_null() {
        error!("Null pointer passed into CT_data() as lenr");
        return Status::ERR_HTSI.value();
    }

    if response.is_null() {
        error!("Null pointer passed into CT_data() as response");
        return Status::ERR_HTSI.value();
    }

    debug!("CT_data(ctn: {})", ctn);
    let status: i8 =
        match panic::catch_unwind(|| data(ctn, dad, sad, lenc, command, lenr, response)) {
            Ok(result) => match result {
                Ok(status) => status.value(),
                Err(why) => {
                    error!("Failure during CT_data!");
                    debug!("{}", why);
                    Status::ERR_HTSI.value()
                }
            },
            Err(_) => {
                error!("Caught panic!");
                Status::ERR_HTSI.value()
            }
        };

    debug!("Returning {}", status);
    status
}

#[no_mangle]
pub extern "system" fn CT_close(ctn: u16) -> i8 {
    logging::init();

    debug!("CT_close(ctn: {})", ctn);
    let status = match close(ctn) {
        Ok(status) => status.value(),
        Err(why) => {
            error!("Failure during CT_close!");
            debug!("{}", why);
            Status::ERR_HTSI.value()
        }
    };

    debug!("Returning {}", status);
    status
}
<|endoftext|>


<commit_before>//! Manipulations and data types that represent 2d matrix.

#![warn(bad_style, missing_docs,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results, unused_typecasts)]

#![feature(macro_rules)]

extern crate num;

use num::{One, Zero};

/// 2D matrix.
#[deriving(PartialEq, Eq, Clone, Show)]
pub struct Matrix<T> {
    row: uint,
    column: uint,
    data: Vec<T>
}

impl<T> Matrix<T> {
    /// Creates a new `Matrix`.
    #[inline]
    pub fn from_fn(row: uint, column: uint, f: |uint, uint| -> T) -> Matrix<T> {
        Matrix {
            row: row,
            column: column,
            data: range(0, row * column).map(|i| f(i / column, i % column)).collect()
        }
    }

    /// Creates a new `Matrix` from vector.
    #[inline]
    pub fn from_vec(row: uint, column: uint, data: Vec<T>) -> Matrix<T> {
        assert_eq!(row * column, data.len());
        Matrix { row: row, column: column, data: data }
    }

    /// Returns the matrix's row and column.
    #[inline]
    pub fn size(&self) -> (uint, uint) { (self.row(), self.column()) }
    /// Returns the matrix's row.
    #[inline]
    pub fn row(&self) -> uint { self.row }
    /// Returns the matrix's column.
    #[inline]
    pub fn column(&self) -> uint { self.column }
}

impl<T: Zero> Matrix<T> {
    /// Creates a matrix whose elements are all zero.
    #[inline]
    pub fn zero(row: uint, column: uint) -> Matrix<T> {
        Matrix::from_fn(row, column, |_, _| Zero::zero())
    }
}

impl<T: One + Zero> Matrix<T> {
    /// Creates a identity matrix.
    #[inline]
    pub fn one(row: uint, column: uint) -> Matrix<T> {
        Matrix::from_fn(row, column, |i, j| {
            if i == j {
                One::one()
            } else {
                Zero::zero()
            }
        })
    }
}

impl<T: Clone> Matrix<T> {
    #[inline]
    /// Returns transpose of the matrix.
    pub fn trans(&self) -> Matrix<T> {
        Matrix::from_fn(self.column(), self.row(), |i, j| self[(j, i)].clone())
    }
}

impl<T> Index<(uint, uint), T> for Matrix<T> {
    #[inline]
    fn index(&self, &(i, j): &(uint, uint)) -> &T {
        assert!(i < self.row() && j < self.column());
        &self.data[i * self.column() + j]
    }
}

macro_rules! forward_val_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<Lhs, Rhs, Result> $imp<Matrix<Rhs>, Matrix<Result>> for Matrix<Lhs>
            where Lhs: $imp<Rhs, Result> + Clone, Rhs: Clone {
            #[inline]
            fn $method(self, other: Matrix<Rhs>) -> Matrix<Result> {
                (&self).$method(&other)
            }
        }
    }
}

macro_rules! forward_ref_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs, Result> $imp<Matrix<Rhs>, Matrix<Result>> for &'a Matrix<Lhs>
            where Lhs: $imp<Rhs, Result> + Clone, Rhs: Clone {
            #[inline]
            fn $method(self, other: Matrix<Rhs>) -> Matrix<Result> {
                self.$method(&other)
            }
        }
    }
}

macro_rules! forward_val_ref_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs, Result> $imp<&'a Matrix<Rhs>, Matrix<Result>> for Matrix<Lhs>
            where Lhs: $imp<Rhs, Result> + Clone, Rhs: Clone {
            #[inline]
            fn $method(self, other: &Matrix<Rhs>) -> Matrix<Result> {
                (&self).$method(other)
            }
        }
    }
}

macro_rules! forward_all_binop {
    (impl $imp:ident, $method:ident) => {
        forward_val_val_binop!(impl $imp, $method);
        forward_ref_val_binop!(impl $imp, $method);
        forward_val_ref_binop!(impl $imp, $method);
    };
}

forward_all_binop!(impl Add, add);

impl<'a, 'b, Lhs, Rhs, Result> Add<&'b Matrix<Rhs>, Matrix<Result>> for &'a Matrix<Lhs>
    where Lhs: Add<Rhs, Result> + Clone, Rhs: Clone {
    #[inline]
    fn add(self, other: &Matrix<Rhs>) -> Matrix<Result> {
        assert_eq!(self.size(), other.size());
        Matrix::from_fn(self.row(), self.column(), |i, j| self[(i, j)].clone() + other[(i, j)].clone())
    }
}

forward_all_binop!(impl Sub, sub);

impl<'a, 'b, Lhs, Rhs, Result> Sub<&'b Matrix<Rhs>, Matrix<Result>> for &'a Matrix<Lhs>
    where Lhs: Sub<Rhs, Result> + Clone, Rhs: Clone {
    #[inline]
    fn sub(self, other: &Matrix<Rhs>) -> Matrix<Result> {
        assert_eq!(self.size(), other.size());
        Matrix::from_fn(self.row(), self.column(), |i, j| self[(i, j)].clone() - other[(i, j)].clone())
    }
}

impl<Lhs, Rhs, Result> Mul<Matrix<Rhs>, Matrix<Result>> for Matrix<Lhs>
    where Lhs: Mul<Rhs, Result> + Clone, Rhs: Clone, Result: Add<Result, Result> {
    #[inline]
    fn mul(self, other: Matrix<Rhs>) -> Matrix<Result> { (&self).mul(&other) }
}

impl<'a, Lhs, Rhs, Result> Mul<Matrix<Rhs>, Matrix<Result>> for &'a Matrix<Lhs>
    where Lhs: Mul<Rhs, Result> + Clone, Rhs: Clone, Result: Add<Result, Result> {
    #[inline]
    fn mul(self, other: Matrix<Rhs>) -> Matrix<Result> { self.mul(&other) }
}

impl<'a, Lhs, Rhs, Result> Mul<&'a Matrix<Rhs>, Matrix<Result>> for Matrix<Lhs>
    where Lhs: Mul<Rhs, Result> + Clone, Rhs: Clone, Result: Add<Result, Result> {
    #[inline]
    fn mul(self, other: &Matrix<Rhs>) -> Matrix<Result> { self.mul(other) }
}

impl<'a, 'b, Lhs, Rhs, Result> Mul<&'b Matrix<Rhs>, Matrix<Result>> for &'a Matrix<Lhs>
    where Lhs: Mul<Rhs, Result> + Clone, Rhs: Clone, Result: Add<Result, Result> {
    #[inline]
    fn mul(self, other: &Matrix<Rhs>) -> Matrix<Result> {
        assert_eq!(self.column(), other.row());
        Matrix::from_fn(self.row(), other.column(), |i, j| {
            let mut sum = self[(i, 0)].clone() * other[(0, j)].clone();
            for k in range(1, self.column()) {
                sum = sum + self[(i, k)].clone() * other[(k, j)].clone();
            }
            sum
        })
    }
}

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

    #[test]
    fn from_vec() {
        let mat = Matrix::from_vec(2, 3, vec![(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)]);
        for i in range(0, mat.row()) {
            for j in range(0, mat.column()) {
                assert_eq!((i, j), mat[(i, j)]);
            }
        }
    }

    #[test]
    fn index() {
        let mat = Matrix::from_fn(3, 5, |i, j| (i, j));
        for i in range(0, mat.row()) {
            for j in range(0, mat.column()) {
                assert_eq!((i, j), mat[(i, j)]);
            }
        }
    }

    #[test]
    fn mul() {
        let m1 = Matrix::from_vec(1, 3, vec![1.0f64, 2.0, 3.0]);
        let m2 = Matrix::from_vec(3, 1, vec![1.0, 2.0, 3.0]);
        assert_eq!(Matrix::from_vec(1, 1, vec![14.0]), m1 * m2);
        assert_eq!(Matrix::from_vec(3, 1, vec![1.0f64, 4.0, 7.0]),
                   Matrix::from_vec(3, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]) *
                   Matrix::from_vec(3, 1, vec![1.0, 0.0, 0.0]));
        assert_eq!(Matrix::from_vec(3, 2, vec![1.0f64, 3.0, 4.0, 6.0, 7.0, 9.0]),
                   Matrix::from_vec(3, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]) *
                   Matrix::from_vec(3, 2, vec![1.0, 0.0, 0.0, 0.0, 0.0, 1.0]));
    }
}

<commit_msg>update to rust master<commit_after>//! Manipulations and data types that represent 2d matrix.

#![warn(bad_style, missing_docs,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results, unused_typecasts)]

#![feature(associated_types, default_type_params, macro_rules)]

extern crate num;

use std::ops::{Add, Index, Mul, Sub};
use num::{One, Zero};

/// 2D matrix.
#[deriving(PartialEq, Eq, Clone, Show)]
pub struct Matrix<T> {
    row: uint,
    column: uint,
    data: Vec<T>
}

impl<T> Matrix<T> {
    /// Creates a new `Matrix`.
    #[inline]
    pub fn from_fn(row: uint, column: uint, f: |uint, uint| -> T) -> Matrix<T> {
        Matrix {
            row: row,
            column: column,
            data: range(0, row * column).map(|i| f(i / column, i % column)).collect()
        }
    }

    /// Creates a new `Matrix` from vector.
    #[inline]
    pub fn from_vec(row: uint, column: uint, data: Vec<T>) -> Matrix<T> {
        assert_eq!(row * column, data.len());
        Matrix { row: row, column: column, data: data }
    }

    /// Returns the matrix's row and column.
    #[inline]
    pub fn size(&self) -> (uint, uint) { (self.row(), self.column()) }
    /// Returns the matrix's row.
    #[inline]
    pub fn row(&self) -> uint { self.row }
    /// Returns the matrix's column.
    #[inline]
    pub fn column(&self) -> uint { self.column }
}

impl<T: Zero> Matrix<T> {
    /// Creates a matrix whose elements are all zero.
    #[inline]
    pub fn zero(row: uint, column: uint) -> Matrix<T> {
        Matrix::from_fn(row, column, |_, _| Zero::zero())
    }
}

impl<T: One + Zero> Matrix<T> {
    /// Creates a identity matrix.
    #[inline]
    pub fn one(row: uint, column: uint) -> Matrix<T> {
        Matrix::from_fn(row, column, |i, j| {
            if i == j {
                One::one()
            } else {
                Zero::zero()
            }
        })
    }
}

impl<T: Clone> Matrix<T> {
    #[inline]
    /// Returns transpose of the matrix.
    pub fn trans(&self) -> Matrix<T> {
        Matrix::from_fn(self.column(), self.row(), |i, j| self[(j, i)].clone())
    }
}

impl<T> Index<(uint, uint)> for Matrix<T> {
    type Output = T;

    #[inline]
    fn index(&self, &(i, j): &(uint, uint)) -> &T {
        assert!(i < self.row() && j < self.column());
        &self.data[i * self.column() + j]
    }
}

macro_rules! forward_val_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<Lhs, Rhs> $imp<Matrix<Rhs>> for Matrix<Lhs>
            where Lhs: $imp<Rhs> + Clone, Rhs: Clone
        {
            type Output = Matrix<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: Matrix<Rhs>) -> Matrix<<Lhs as $imp<Rhs>>::Output> {
                (&self).$method(&other)
            }
        }
    }
}

macro_rules! forward_ref_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs> $imp<Matrix<Rhs>> for &'a Matrix<Lhs>
            where Lhs: $imp<Rhs> + Clone, Rhs: Clone
        {
            type Output = Matrix<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: Matrix<Rhs>) -> Matrix<<Lhs as $imp<Rhs>>::Output> {
                self.$method(&other)
            }
        }
    }
}

macro_rules! forward_val_ref_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs> $imp<&'a Matrix<Rhs>> for Matrix<Lhs>
            where Lhs: $imp<Rhs> + Clone, Rhs: Clone
        {
            type Output = Matrix<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as $imp<Rhs>>::Output> {
                (&self).$method(other)
            }
        }
    }
}

macro_rules! forward_all_binop {
    (impl $imp:ident, $method:ident) => {
        forward_val_val_binop!(impl $imp, $method);
        forward_ref_val_binop!(impl $imp, $method);
        forward_val_ref_binop!(impl $imp, $method);
    };
}

forward_all_binop!(impl Add, add);

impl<'a, 'b, Lhs, Rhs> Add<&'b Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Add<Rhs> + Clone, Rhs: Clone
{
    type Output = Matrix<<Lhs as Add<Rhs>>::Output>;

    #[inline]
    fn add(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Add<Rhs>>::Output> {
        assert_eq!(self.size(), other.size());
        Matrix::from_fn(self.row(), self.column(), |i, j| self[(i, j)].clone() + other[(i, j)].clone())
    }
}

forward_all_binop!(impl Sub, sub);

impl<'a, 'b, Lhs, Rhs> Sub<&'b Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Sub<Rhs> + Clone, Rhs: Clone
{
    type Output = Matrix<<Lhs as Sub<Rhs>>::Output>;

    #[inline]
    fn sub(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Sub<Rhs>>::Output> {
        assert_eq!(self.size(), other.size());
        Matrix::from_fn(self.row(), self.column(), |i, j| self[(i, j)].clone() - other[(i, j)].clone())
    }
}

impl<Lhs, Rhs> Mul<Matrix<Rhs>> for Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: Matrix<Rhs>) -> Matrix<<Lhs as Mul<Rhs>>::Output> {
        (&self).mul(&other)
    }
}

impl<'a, Lhs, Rhs> Mul<Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: Matrix<Rhs>) ->  Matrix<<Lhs as Mul<Rhs>>::Output> {
        self.mul(&other)
    }
}

impl<'a, Lhs, Rhs> Mul<&'a Matrix<Rhs>> for Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Mul<Rhs>>::Output> {
        self.mul(other)
    }
}

impl<'a, 'b, Lhs, Rhs> Mul<&'b Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Mul<Rhs>>::Output> {
        assert_eq!(self.column(), other.row());
        Matrix::from_fn(self.row(), other.column(), |i, j| {
            let mut sum = self[(i, 0)].clone() * other[(0, j)].clone();
            for k in range(1, self.column()) {
                sum = sum + self[(i, k)].clone() * other[(k, j)].clone();
            }
            sum
        })
    }
}

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

    #[test]
    fn from_vec() {
        let mat = Matrix::from_vec(2, 3, vec![(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)]);
        for i in range(0, mat.row()) {
            for j in range(0, mat.column()) {
                assert_eq!((i, j), mat[(i, j)]);
            }
        }
    }

    #[test]
    fn index() {
        let mat = Matrix::from_fn(3, 5, |i, j| (i, j));
        for i in range(0, mat.row()) {
            for j in range(0, mat.column()) {
                assert_eq!((i, j), mat[(i, j)]);
            }
        }
    }

    #[test]
    fn mul() {
        let m1 = Matrix::from_vec(1, 3, vec![1.0f64, 2.0, 3.0]);
        let m2 = Matrix::from_vec(3, 1, vec![1.0, 2.0, 3.0]);
        assert_eq!(Matrix::from_vec(1, 1, vec![14.0]), m1 * m2);
        assert_eq!(Matrix::from_vec(3, 1, vec![1.0f64, 4.0, 7.0]),
                   Matrix::from_vec(3, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]) *
                   Matrix::from_vec(3, 1, vec![1.0, 0.0, 0.0]));
        assert_eq!(Matrix::from_vec(3, 2, vec![1.0f64, 3.0, 4.0, 6.0, 7.0, 9.0]),
                   Matrix::from_vec(3, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]) *
                   Matrix::from_vec(3, 2, vec![1.0, 0.0, 0.0, 0.0, 0.0, 1.0]));
    }
}

<|endoftext|>


<commit_before>//! rdb - Parse, analyze and dump RDB files
//!
//! A RDB file is a binary representation of the in-memory data of Redis.
//! This binary file is sufficient to completely restore Redis’ state.
//!
//! This library provides the methods to parse and analyze a RDB file
//! and to reformat and dump it in another format such as JSON or
//! RESP, the Redis Serialization.
//!
//! You can depend on this library via Cargo:
//!
//! ```ini
//! [dependencies]
//! rdb = "0.5.0"
//! ```
//!
//! # Basic operation
//!
//! rdb-rs exposes just one important method: `parse`.
//! This methods takes care of reading the RDB from a stream,
//! parsing the containted data and calling the provided formatter with already-parsed values.
//!
//! ```rust,no_run
//! # #![allow(unstable)]
//! # use std::io::{BufferedReader, File};
//! let file = File::open(&Path::new("dump.rdb"));
//! let reader = BufferedReader::new(file);
//! rdb::parse(reader, rdb::formatter::JSON::new(), rdb::filter::Simple::new());
//! ```
//!
//! # Formatter
//!
//! rdb-rs brings 4 pre-defined formatters, which can be used:
//!
//! * `PlainFormatter`: Just plain output for testing
//! * `JSONFormatter`: JSON-encoded output
//! * `NilFormatter`: Surpresses all output
//! * `ProtocolFormatter`: Formats the data in [RESP](http://redis.io/topics/protocol),
//! the Redis Serialization Protocol
//!
//! These formatters adhere to the `RdbParseFormatter` trait
//! and supply a method for each possible datatype or opcode.
//! Its up to the formatter to correctly handle all provided data such as
//! lists, sets, hashes, expires and metadata.
//!
//! # Command-line
//!
//! rdb-rs brings a Command Line application as well.
//!
//! This application will take a RDB file as input and format it in the specified format (JSON by
//! default).
//!
//! Example:
//!
//! ```shell,no_compile
//! $ rdb --format json dump.rdb
//! [{"key":"value"}]
//! $ rdb --format protocol dump.rdb
//! *2
//! $6
//! SELECT
//! $1
//! 0
//! *3
//! $3
//! SET
//! $3
//! key
//! $5
//! value
//! ```

#![feature(slicing_syntax)]
#![feature(io)]
#![feature(core)]

extern crate lzf;
extern crate "rustc-serialize" as serialize;
extern crate regex;
extern crate byteorder;

use std::io::Read;

#[doc(hidden)]
pub use types::{
    ZiplistEntry,
    Type,

    /* error and result types */
    RdbError,
    RdbResult,
    RdbOk,
};

pub use parser::RdbParser;

use formatter::Formatter;
use filter::Filter;

mod macros;
mod constants;
mod helper;

pub mod types;
pub mod parser;
pub mod formatter;
pub mod filter;

pub fn parse<R: Read, F: Formatter, T: Filter>(input: R, formatter: F, filter: T) -> RdbOk {
    let mut parser = RdbParser::new(input, formatter, filter);
    parser.parse()
}
<commit_msg>Remove unnecessary features<commit_after>//! rdb - Parse, analyze and dump RDB files
//!
//! A RDB file is a binary representation of the in-memory data of Redis.
//! This binary file is sufficient to completely restore Redis’ state.
//!
//! This library provides the methods to parse and analyze a RDB file
//! and to reformat and dump it in another format such as JSON or
//! RESP, the Redis Serialization.
//!
//! You can depend on this library via Cargo:
//!
//! ```ini
//! [dependencies]
//! rdb = "0.5.0"
//! ```
//!
//! # Basic operation
//!
//! rdb-rs exposes just one important method: `parse`.
//! This methods takes care of reading the RDB from a stream,
//! parsing the containted data and calling the provided formatter with already-parsed values.
//!
//! ```rust,no_run
//! # #![allow(unstable)]
//! # use std::io::{BufferedReader, File};
//! let file = File::open(&Path::new("dump.rdb"));
//! let reader = BufferedReader::new(file);
//! rdb::parse(reader, rdb::formatter::JSON::new(), rdb::filter::Simple::new());
//! ```
//!
//! # Formatter
//!
//! rdb-rs brings 4 pre-defined formatters, which can be used:
//!
//! * `PlainFormatter`: Just plain output for testing
//! * `JSONFormatter`: JSON-encoded output
//! * `NilFormatter`: Surpresses all output
//! * `ProtocolFormatter`: Formats the data in [RESP](http://redis.io/topics/protocol),
//! the Redis Serialization Protocol
//!
//! These formatters adhere to the `RdbParseFormatter` trait
//! and supply a method for each possible datatype or opcode.
//! Its up to the formatter to correctly handle all provided data such as
//! lists, sets, hashes, expires and metadata.
//!
//! # Command-line
//!
//! rdb-rs brings a Command Line application as well.
//!
//! This application will take a RDB file as input and format it in the specified format (JSON by
//! default).
//!
//! Example:
//!
//! ```shell,no_compile
//! $ rdb --format json dump.rdb
//! [{"key":"value"}]
//! $ rdb --format protocol dump.rdb
//! *2
//! $6
//! SELECT
//! $1
//! 0
//! *3
//! $3
//! SET
//! $3
//! key
//! $5
//! value
//! ```

#![feature(io)]
#![feature(core)]

extern crate lzf;
extern crate "rustc-serialize" as serialize;
extern crate regex;
extern crate byteorder;

use std::io::Read;

#[doc(hidden)]
pub use types::{
    ZiplistEntry,
    Type,

    /* error and result types */
    RdbError,
    RdbResult,
    RdbOk,
};

pub use parser::RdbParser;

use formatter::Formatter;
use filter::Filter;

mod macros;
mod constants;
mod helper;

pub mod types;
pub mod parser;
pub mod formatter;
pub mod filter;

pub fn parse<R: Read, F: Formatter, T: Filter>(input: R, formatter: F, filter: T) -> RdbOk {
    let mut parser = RdbParser::new(input, formatter, filter);
    parser.parse()
}
<|endoftext|>


<commit_before>#![feature(associated_consts)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(question_mark)]
//#![feature(plugin)]

//#![plugin(clippy)]

extern crate jsrs_common;

#[macro_use] extern crate matches;

pub mod alloc;
mod scope;
mod test_utils;

use std::cell::RefCell;
use std::collections::hash_map::HashMap;
use std::rc::Rc;

use jsrs_common::ast::Exp;
use jsrs_common::backend::Backend;
use jsrs_common::types::js_var::{JsPtrEnum, JsVar};
use jsrs_common::types::binding::{Binding, UniqueBinding};

use alloc::AllocBox;
use jsrs_common::gc_error::{GcError, Result};
use scope::{LookupError, Scope, ScopeTag};

pub struct ScopeManager {
    scopes: Vec<Scope>,
    closures: HashMap<UniqueBinding, Scope>,
    pub alloc_box: Rc<RefCell<AllocBox>>,
}

impl ScopeManager {
    fn new(alloc_box: Rc<RefCell<AllocBox>>) -> ScopeManager {
        ScopeManager {
            scopes: vec![Scope::new(ScopeTag::Call, &alloc_box)],
            closures: HashMap::new(),
            alloc_box: alloc_box,
        }
    }

    #[allow(dead_code)]
    #[inline]
    fn curr_scope(&self) -> &Scope {
        self.scopes.last().expect("Tried to access current scope, but none existed")
    }

    #[inline]
    fn curr_scope_mut(&mut self) -> &mut Scope {
        self.scopes.last_mut().expect("Tried to access current scope, but none existed")
    }

    #[inline]
    fn global_scope(&self) -> &Scope {
        self.scopes.get(0).expect("Tried to access global scope, but none existed")
    }

    #[inline]
    fn global_scope_mut(&mut self) -> &mut Scope {
        self.scopes.get_mut(0).expect("Tried to access global scope, but none existed")
    }

    pub fn push_closure_scope(&mut self, closure: &UniqueBinding) -> Result<()> {
        let closure_scope = self.closures.remove(closure).ok_or(GcError::Scope)?;
        self.scopes.push(closure_scope);
        Ok(())
    }

    pub fn push_scope(&mut self, exp: &Exp) {
        let tag = match *exp {
            Exp::Call(..) => ScopeTag::Call,
            _ => ScopeTag::Block,
        };
        self.scopes.push(Scope::new(tag, &self.alloc_box));
    }

    pub fn pop_scope(&mut self, returning_closure: Option<UniqueBinding>, gc_yield: bool) -> Result<()> {
        if let Some(mut scope) = self.scopes.pop() {
            // Clean up the dying scope's stack and take ownership of its heap-allocated data for
            // later collection
            if self.scopes.is_empty() {
                // The global scope was popped and the program is ending.
                scope.trigger_gc();
                return Err(GcError::Scope);
            }
            if let Some(unique) = returning_closure {
                let mut closure_scope = Scope::new(ScopeTag::Closure(unique.clone()), &self.alloc_box);
                scope.transfer_stack(&mut closure_scope, true)?;
                self.closures.insert(unique, closure_scope);
            } else {
                if !matches!(scope.tag, ScopeTag::Closure(_)) {
                    scope.transfer_stack(self.curr_scope_mut(), false)?
                }
            }
            // Potentially trigger the garbage collector
            if gc_yield {
                self.curr_scope_mut().trigger_gc();
            }
            if let ScopeTag::Closure(unique) = scope.tag.clone() {
                self.closures.insert(unique.clone(), scope);
            }
            Ok(())
        } else {
            Err(GcError::Scope)
        }
    }

    pub fn rename_closure(&mut self, old: &UniqueBinding, new: &UniqueBinding) -> bool {
        if self.closures.contains_key(old) {
            let mut scope = self.closures.remove(old).unwrap();
            scope.tag = ScopeTag::Closure(new.clone());
            self.closures.insert(new.clone(), scope);
            true
        } else {
            false
        }
    }
}

impl Backend for ScopeManager {
    fn alloc(&mut self, var: JsVar, ptr: Option<JsPtrEnum>) -> Result<Binding> {
        let binding = var.binding.clone();
        let is_allocated = self.alloc_box.borrow().is_allocated(&var.unique);

        // If the ptr is already allocated in the heap, just push it onto the stack
        if is_allocated && ptr.is_some() {
            self.curr_scope_mut().bind_var(var);
        } else {
            self.curr_scope_mut().push_var(var, ptr)?;
        }
        Ok(binding)
    }

    /// Try to load the variable behind a binding
    fn load(&self, bnd: &Binding) -> Result<(JsVar, Option<JsPtrEnum>)> {
        let lookup = || {
            for scope in self.scopes.iter().rev() {
                match scope.get_var_copy(bnd) {
                    Ok(v) => { return Ok(v); },
                    Err(LookupError::FnBoundary) => {
                        return Err(GcError::Load(bnd.clone()));
                    },
                    Err(LookupError::CheckParent) => {},
                    Err(LookupError::Unreachable) => unreachable!(),
                }
            }
            Err(GcError::Load(bnd.clone()))
        };
        match lookup() {
            Ok(v) => Ok(v),
            Err(GcError::Load(bnd)) =>
                self.global_scope().get_var_copy(&bnd)
                .map_err(|_| GcError::Load(bnd.clone())),
            _ => unreachable!(),
        }
    }

    fn store(&mut self, var: JsVar, ptr: Option<JsPtrEnum>) -> Result<()> {
        let res = self.curr_scope_mut().update_var(var, ptr);
        if let Err(GcError::Store(var, ptr)) = res {
            self.global_scope_mut().update_var(var, ptr)
        } else {
            res
        }
    }
}

pub fn init_gc() -> ScopeManager {
    let alloc_box = Rc::new(RefCell::new(AllocBox::new()));
    ScopeManager::new(alloc_box)
}

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

    use jsrs_common::ast::Exp;
    use jsrs_common::backend::Backend;
    use jsrs_common::types::js_var::{JsKey, JsPtrEnum, JsType, JsVar};
    use jsrs_common::types::binding::Binding;

    use jsrs_common::gc_error::GcError;
    use test_utils;

    #[test]
    fn test_push_closure_scope() {
        let alloc_box = test_utils::make_alloc_box();
        let mut mgr = ScopeManager::new(alloc_box);
        mgr.push_scope(&Exp::Undefined);
        let (fn_var, fn_ptr) = test_utils::make_fn(&None, &Vec::new());
        let unique = fn_var.unique.clone();
        mgr.alloc(fn_var, Some(fn_ptr)).unwrap();
        mgr.pop_scope(Some(unique.clone()), false).unwrap();
        assert_eq!(mgr.closures.len(), 1);
        mgr.push_closure_scope(&unique).unwrap();
        assert_eq!(mgr.closures.len(), 0);
        mgr.pop_scope(None, false).unwrap();
        assert_eq!(mgr.closures.len(), 1);
    }

    #[test]
    fn test_pop_scope() {
        let alloc_box = test_utils::make_alloc_box();
        let mut mgr = ScopeManager::new(alloc_box);
        mgr.push_scope(&Exp::Undefined);
        assert_eq!(mgr.scopes.len(), 2);
        mgr.pop_scope(None, false).unwrap();
        assert_eq!(mgr.scopes.len(), 1);
    }

    #[test]
    fn test_pop_scope_fail() {
        let alloc_box = test_utils::make_alloc_box();
        let mut mgr = ScopeManager::new(alloc_box);
        let res = mgr.pop_scope(None, false);
        assert!(res.is_err());
        assert!(matches!(res, Err(GcError::Scope)));
    }

    #[test]
    fn test_alloc() {
        let alloc_box = test_utils::make_alloc_box();
        let mut mgr = ScopeManager::new(alloc_box);
        mgr.alloc(test_utils::make_num(1.), None).unwrap();
        mgr.push_scope(&Exp::Undefined);
        mgr.alloc(test_utils::make_num(2.), None).unwrap();
        assert!(mgr.alloc_box.borrow().is_empty());
    }

    #[test]
    fn test_load() {
        let alloc_box = test_utils::make_alloc_box();
        let mut mgr = ScopeManager::new(alloc_box);
        let x = test_utils::make_num(1.);
        let x_bnd = mgr.alloc(x, None).unwrap();
        let load = mgr.load(&x_bnd);
        assert!(load.is_ok());
        let load = load.unwrap();
        match load.0.t {
            JsType::JsNum(n) => assert!(f64::abs(n - 1.) < 0.0001),
            _ => unreachable!(),
        }
        assert!(load.1.is_none());
    }

    #[test]
    fn test_load_fail() {
        let alloc_box = test_utils::make_alloc_box();
        let mgr = ScopeManager::new(alloc_box);
        let bnd = Binding::new("".to_owned());
        let res = mgr.load(&bnd);
        assert!(res.is_err());
        assert!(matches!(res, Err(GcError::Load(_))));
        if let Err(GcError::Load(res_bnd)) = res {
            assert_eq!(bnd, res_bnd);
        }
    }

    #[test]
    fn test_store() {
        let alloc_box = test_utils::make_alloc_box();
        let mut mgr = ScopeManager::new(alloc_box,);
        mgr.push_scope(&Exp::Undefined);

        let x = test_utils::make_num(1.);
        let x_bnd = mgr.alloc(x, None).unwrap();

        let (mut var, _) = mgr.load(&x_bnd).unwrap();
        var.t = JsType::JsNum(2.);

        assert!(mgr.store(var, None).is_ok());
    }

    #[test]
    fn test_store_fail() {
        let alloc_box = test_utils::make_alloc_box();
        let mut mgr = ScopeManager::new(alloc_box);
        let x = test_utils::make_num(1.);
        assert!(mgr.store(x, None).is_err());
    }

    #[test]
    fn test_load_from_parent_scope_across_fn_boundary() {
        let heap = test_utils::make_alloc_box();
        let mut mgr = ScopeManager::new(heap);

        // Avoids having just the global scope available
        mgr.push_scope(&Exp::Call(box Exp::Undefined, vec![]));
        let (x, x_ptr) = test_utils::make_str("x");
        let x_bnd = mgr.alloc(x, Some(x_ptr)).unwrap();

        mgr.push_scope(&Exp::Call(box Exp::Undefined, vec![]));
        let copy = mgr.load(&x_bnd);

        assert!(copy.is_err());
        assert!(matches!(copy, Err(GcError::Load(_))));
    }

    #[test]
    fn test_load_from_parent_scope_no_fn_call() {
        let heap = test_utils::make_alloc_box();
        let mut mgr = ScopeManager::new(heap);

        // Avoids having just the global scope available
        mgr.push_scope(&Exp::Call(box Exp::Undefined, vec![]));
        let (x, x_ptr) = test_utils::make_str("x");
        let x_bnd = mgr.alloc(x, Some(x_ptr)).unwrap();

        mgr.push_scope(&Exp::Undefined);
        let copy = mgr.load(&x_bnd);

        assert!(copy.is_ok());
        let (var_copy, ptr_copy) = copy.unwrap();
        assert!(matches!(var_copy, JsVar { t: JsType::JsPtr(_), .. }));
        assert!(ptr_copy.is_some());
    }

    #[test]
    fn test_transfer_stack_with_yield() {
        let heap = test_utils::make_alloc_box();
        let mut mgr = ScopeManager::new(heap);
        // Make some scopes
        mgr.push_scope(&Exp::Undefined);
        {
            // Push a child scope
            mgr.push_scope(&Exp::Undefined);
            // Allocate some non-root variables (numbers)
            mgr.alloc(test_utils::make_num(0.), None).unwrap();
            mgr.alloc(test_utils::make_num(1.), None).unwrap();
            mgr.alloc(test_utils::make_num(2.), None).unwrap();

            // Make a string to put into an object
            // (so it's heap-allocated and we can lose its ref from the object)
            let (var, ptr) = test_utils::make_str("test");

            // Create an obj of { true: 1.0, false: heap("test") }
            let kvs = vec![(JsKey::JsSym("true".to_string()),
                            test_utils::make_num(1.), None),
                           (JsKey::JsSym("false".to_string()),
                            var, Some(ptr))];
            let (var, ptr) = test_utils::make_obj(kvs, mgr.alloc_box.clone());

            // Push the obj into the current scope
            let bnd = mgr.alloc(var, Some(ptr)).unwrap();
            // The heap should now have 2 things in it: an object and a string
            assert_eq!(mgr.alloc_box.borrow().len(), 2);

            // Replace the string in the object with something else so it's no longer live
            let copy = mgr.load(&bnd);
            let (var_cp, mut ptr_cp) = copy.unwrap();
            let key = JsKey::JsSym("false".to_string());
            match *&mut ptr_cp {
                Some(JsPtrEnum::JsObj(ref mut obj)) => {
                    obj.add_key(key, test_utils::make_num(-1.), None, &mut *(mgr.alloc_box.borrow_mut()));
                },
                _ => unreachable!()
            }
            mgr.store(var_cp, ptr_cp).unwrap();
            // The heap should still have 2 things in it: an object and a string
            assert_eq!(mgr.alloc_box.borrow().len(), 2);

            // Kill the current scope & give its refs to the parent,
            // allowing the GC to kick in beforehand.
            mgr.pop_scope(None, true).unwrap();
        }
        // The object we created above should still exist
        assert_eq!(mgr.curr_scope().len(), 1);
        // But the string it had allocated shouldn't, since we leaked it into the void
        assert_eq!(mgr.alloc_box.borrow().len(), 1);
    }
}
<commit_msg>Update load to take &mut self (used in caching, just doing this for convenience)<commit_after>#![feature(associated_consts)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(question_mark)]
//#![feature(plugin)]

//#![plugin(clippy)]

extern crate jsrs_common;

#[macro_use] extern crate matches;

pub mod alloc;
mod scope;
mod test_utils;

use std::cell::RefCell;
use std::collections::hash_map::HashMap;
use std::rc::Rc;

use jsrs_common::ast::Exp;
use jsrs_common::backend::Backend;
use jsrs_common::types::js_var::{JsPtrEnum, JsVar};
use jsrs_common::types::binding::{Binding, UniqueBinding};

use alloc::AllocBox;
use jsrs_common::gc_error::{GcError, Result};
use scope::{LookupError, Scope, ScopeTag};

pub struct ScopeManager {
    scopes: Vec<Scope>,
    closures: HashMap<UniqueBinding, Scope>,
    pub alloc_box: Rc<RefCell<AllocBox>>,
}

impl ScopeManager {
    fn new(alloc_box: Rc<RefCell<AllocBox>>) -> ScopeManager {
        ScopeManager {
            scopes: vec![Scope::new(ScopeTag::Call, &alloc_box)],
            closures: HashMap::new(),
            alloc_box: alloc_box,
        }
    }

    #[allow(dead_code)]
    #[inline]
    fn curr_scope(&self) -> &Scope {
        self.scopes.last().expect("Tried to access current scope, but none existed")
    }

    #[inline]
    fn curr_scope_mut(&mut self) -> &mut Scope {
        self.scopes.last_mut().expect("Tried to access current scope, but none existed")
    }

    #[inline]
    fn global_scope(&self) -> &Scope {
        self.scopes.get(0).expect("Tried to access global scope, but none existed")
    }

    #[inline]
    fn global_scope_mut(&mut self) -> &mut Scope {
        self.scopes.get_mut(0).expect("Tried to access global scope, but none existed")
    }

    pub fn push_closure_scope(&mut self, closure: &UniqueBinding) -> Result<()> {
        let closure_scope = self.closures.remove(closure).ok_or(GcError::Scope)?;
        self.scopes.push(closure_scope);
        Ok(())
    }

    pub fn push_scope(&mut self, exp: &Exp) {
        let tag = match *exp {
            Exp::Call(..) => ScopeTag::Call,
            _ => ScopeTag::Block,
        };
        self.scopes.push(Scope::new(tag, &self.alloc_box));
    }

    pub fn pop_scope(&mut self, returning_closure: Option<UniqueBinding>, gc_yield: bool) -> Result<()> {
        if let Some(mut scope) = self.scopes.pop() {
            // Clean up the dying scope's stack and take ownership of its heap-allocated data for
            // later collection
            if self.scopes.is_empty() {
                // The global scope was popped and the program is ending.
                scope.trigger_gc();
                return Err(GcError::Scope);
            }
            if let Some(unique) = returning_closure {
                let mut closure_scope = Scope::new(ScopeTag::Closure(unique.clone()), &self.alloc_box);
                scope.transfer_stack(&mut closure_scope, true)?;
                self.closures.insert(unique, closure_scope);
            } else {
                if !matches!(scope.tag, ScopeTag::Closure(_)) {
                    scope.transfer_stack(self.curr_scope_mut(), false)?
                }
            }
            // Potentially trigger the garbage collector
            if gc_yield {
                self.curr_scope_mut().trigger_gc();
            }
            if let ScopeTag::Closure(unique) = scope.tag.clone() {
                self.closures.insert(unique.clone(), scope);
            }
            Ok(())
        } else {
            Err(GcError::Scope)
        }
    }

    pub fn rename_closure(&mut self, old: &UniqueBinding, new: &UniqueBinding) -> bool {
        if self.closures.contains_key(old) {
            let mut scope = self.closures.remove(old).unwrap();
            scope.tag = ScopeTag::Closure(new.clone());
            self.closures.insert(new.clone(), scope);
            true
        } else {
            false
        }
    }
}

impl Backend for ScopeManager {
    fn alloc(&mut self, var: JsVar, ptr: Option<JsPtrEnum>) -> Result<Binding> {
        let binding = var.binding.clone();
        let is_allocated = self.alloc_box.borrow().is_allocated(&var.unique);

        // If the ptr is already allocated in the heap, just push it onto the stack
        if is_allocated && ptr.is_some() {
            self.curr_scope_mut().bind_var(var);
        } else {
            self.curr_scope_mut().push_var(var, ptr)?;
        }
        Ok(binding)
    }

    /// Try to load the variable behind a binding
    fn load(&mut self, bnd: &Binding) -> Result<(JsVar, Option<JsPtrEnum>)> {
        let lookup = || {
            for scope in self.scopes.iter().rev() {
                match scope.get_var_copy(bnd) {
                    Ok(v) => { return Ok(v); },
                    Err(LookupError::FnBoundary) => {
                        return Err(GcError::Load(bnd.clone()));
                    },
                    Err(LookupError::CheckParent) => {},
                    Err(LookupError::Unreachable) => unreachable!(),
                }
            }
            Err(GcError::Load(bnd.clone()))
        };
        match lookup() {
            Ok(v) => Ok(v),
            Err(GcError::Load(bnd)) =>
                self.global_scope().get_var_copy(&bnd)
                .map_err(|_| GcError::Load(bnd.clone())),
            _ => unreachable!(),
        }
    }

    fn store(&mut self, var: JsVar, ptr: Option<JsPtrEnum>) -> Result<()> {
        let res = self.curr_scope_mut().update_var(var, ptr);
        if let Err(GcError::Store(var, ptr)) = res {
            self.global_scope_mut().update_var(var, ptr)
        } else {
            res
        }
    }
}

pub fn init_gc() -> ScopeManager {
    let alloc_box = Rc::new(RefCell::new(AllocBox::new()));
    ScopeManager::new(alloc_box)
}

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

    use jsrs_common::ast::Exp;
    use jsrs_common::backend::Backend;
    use jsrs_common::types::js_var::{JsKey, JsPtrEnum, JsType, JsVar};
    use jsrs_common::types::binding::Binding;

    use jsrs_common::gc_error::GcError;
    use test_utils;

    #[test]
    fn test_push_closure_scope() {
        let alloc_box = test_utils::make_alloc_box();
        let mut mgr = ScopeManager::new(alloc_box);
        mgr.push_scope(&Exp::Undefined);
        let (fn_var, fn_ptr) = test_utils::make_fn(&None, &Vec::new());
        let unique = fn_var.unique.clone();
        mgr.alloc(fn_var, Some(fn_ptr)).unwrap();
        mgr.pop_scope(Some(unique.clone()), false).unwrap();
        assert_eq!(mgr.closures.len(), 1);
        mgr.push_closure_scope(&unique).unwrap();
        assert_eq!(mgr.closures.len(), 0);
        mgr.pop_scope(None, false).unwrap();
        assert_eq!(mgr.closures.len(), 1);
    }

    #[test]
    fn test_pop_scope() {
        let alloc_box = test_utils::make_alloc_box();
        let mut mgr = ScopeManager::new(alloc_box);
        mgr.push_scope(&Exp::Undefined);
        assert_eq!(mgr.scopes.len(), 2);
        mgr.pop_scope(None, false).unwrap();
        assert_eq!(mgr.scopes.len(), 1);
    }

    #[test]
    fn test_pop_scope_fail() {
        let alloc_box = test_utils::make_alloc_box();
        let mut mgr = ScopeManager::new(alloc_box);
        let res = mgr.pop_scope(None, false);
        assert!(res.is_err());
        assert!(matches!(res, Err(GcError::Scope)));
    }

    #[test]
    fn test_alloc() {
        let alloc_box = test_utils::make_alloc_box();
        let mut mgr = ScopeManager::new(alloc_box);
        mgr.alloc(test_utils::make_num(1.), None).unwrap();
        mgr.push_scope(&Exp::Undefined);
        mgr.alloc(test_utils::make_num(2.), None).unwrap();
        assert!(mgr.alloc_box.borrow().is_empty());
    }

    #[test]
    fn test_load() {
        let alloc_box = test_utils::make_alloc_box();
        let mut mgr = ScopeManager::new(alloc_box);
        let x = test_utils::make_num(1.);
        let x_bnd = mgr.alloc(x, None).unwrap();
        let load = mgr.load(&x_bnd);
        assert!(load.is_ok());
        let load = load.unwrap();
        match load.0.t {
            JsType::JsNum(n) => assert!(f64::abs(n - 1.) < 0.0001),
            _ => unreachable!(),
        }
        assert!(load.1.is_none());
    }

    #[test]
    fn test_load_fail() {
        let alloc_box = test_utils::make_alloc_box();
        let mut mgr = ScopeManager::new(alloc_box);
        let bnd = Binding::new("".to_owned());
        let res = mgr.load(&bnd);
        assert!(res.is_err());
        assert!(matches!(res, Err(GcError::Load(_))));
        if let Err(GcError::Load(res_bnd)) = res {
            assert_eq!(bnd, res_bnd);
        }
    }

    #[test]
    fn test_store() {
        let alloc_box = test_utils::make_alloc_box();
        let mut mgr = ScopeManager::new(alloc_box,);
        mgr.push_scope(&Exp::Undefined);

        let x = test_utils::make_num(1.);
        let x_bnd = mgr.alloc(x, None).unwrap();

        let (mut var, _) = mgr.load(&x_bnd).unwrap();
        var.t = JsType::JsNum(2.);

        assert!(mgr.store(var, None).is_ok());
    }

    #[test]
    fn test_store_fail() {
        let alloc_box = test_utils::make_alloc_box();
        let mut mgr = ScopeManager::new(alloc_box);
        let x = test_utils::make_num(1.);
        assert!(mgr.store(x, None).is_err());
    }

    #[test]
    fn test_load_from_parent_scope_across_fn_boundary() {
        let heap = test_utils::make_alloc_box();
        let mut mgr = ScopeManager::new(heap);

        // Avoids having just the global scope available
        mgr.push_scope(&Exp::Call(box Exp::Undefined, vec![]));
        let (x, x_ptr) = test_utils::make_str("x");
        let x_bnd = mgr.alloc(x, Some(x_ptr)).unwrap();

        mgr.push_scope(&Exp::Call(box Exp::Undefined, vec![]));
        let copy = mgr.load(&x_bnd);

        assert!(copy.is_err());
        assert!(matches!(copy, Err(GcError::Load(_))));
    }

    #[test]
    fn test_load_from_parent_scope_no_fn_call() {
        let heap = test_utils::make_alloc_box();
        let mut mgr = ScopeManager::new(heap);

        // Avoids having just the global scope available
        mgr.push_scope(&Exp::Call(box Exp::Undefined, vec![]));
        let (x, x_ptr) = test_utils::make_str("x");
        let x_bnd = mgr.alloc(x, Some(x_ptr)).unwrap();

        mgr.push_scope(&Exp::Undefined);
        let copy = mgr.load(&x_bnd);

        assert!(copy.is_ok());
        let (var_copy, ptr_copy) = copy.unwrap();
        assert!(matches!(var_copy, JsVar { t: JsType::JsPtr(_), .. }));
        assert!(ptr_copy.is_some());
    }

    #[test]
    fn test_transfer_stack_with_yield() {
        let heap = test_utils::make_alloc_box();
        let mut mgr = ScopeManager::new(heap);
        // Make some scopes
        mgr.push_scope(&Exp::Undefined);
        {
            // Push a child scope
            mgr.push_scope(&Exp::Undefined);
            // Allocate some non-root variables (numbers)
            mgr.alloc(test_utils::make_num(0.), None).unwrap();
            mgr.alloc(test_utils::make_num(1.), None).unwrap();
            mgr.alloc(test_utils::make_num(2.), None).unwrap();

            // Make a string to put into an object
            // (so it's heap-allocated and we can lose its ref from the object)
            let (var, ptr) = test_utils::make_str("test");

            // Create an obj of { true: 1.0, false: heap("test") }
            let kvs = vec![(JsKey::JsSym("true".to_string()),
                            test_utils::make_num(1.), None),
                           (JsKey::JsSym("false".to_string()),
                            var, Some(ptr))];
            let (var, ptr) = test_utils::make_obj(kvs, mgr.alloc_box.clone());

            // Push the obj into the current scope
            let bnd = mgr.alloc(var, Some(ptr)).unwrap();
            // The heap should now have 2 things in it: an object and a string
            assert_eq!(mgr.alloc_box.borrow().len(), 2);

            // Replace the string in the object with something else so it's no longer live
            let copy = mgr.load(&bnd);
            let (var_cp, mut ptr_cp) = copy.unwrap();
            let key = JsKey::JsSym("false".to_string());
            match *&mut ptr_cp {
                Some(JsPtrEnum::JsObj(ref mut obj)) => {
                    obj.add_key(key, test_utils::make_num(-1.), None, &mut *(mgr.alloc_box.borrow_mut()));
                },
                _ => unreachable!()
            }
            mgr.store(var_cp, ptr_cp).unwrap();
            // The heap should still have 2 things in it: an object and a string
            assert_eq!(mgr.alloc_box.borrow().len(), 2);

            // Kill the current scope & give its refs to the parent,
            // allowing the GC to kick in beforehand.
            mgr.pop_scope(None, true).unwrap();
        }
        // The object we created above should still exist
        assert_eq!(mgr.curr_scope().len(), 1);
        // But the string it had allocated shouldn't, since we leaked it into the void
        assert_eq!(mgr.alloc_box.borrow().len(), 1);
    }
}
<|endoftext|>


<commit_before><commit_msg>Implement the `peek` method for the `PeekableReader`<commit_after>use std::io::IoResult;

pub struct PeekableReader<R> {
    inner: R,
    peeked_result: Option<IoResult<u8>>,
}

impl<R: Reader> PeekableReader<R> {
    /// Initializes a new `PeekableReader` which wraps the given underlying
    /// reader.
    pub fn new(reader: R) -> PeekableReader<R> {
        PeekableReader {
            inner: reader,
            peeked_result: None,
        }
    }

    pub fn peek(&mut self) -> IoResult<u8> {
        // Return either the currently cached peeked byte or obtain a new one
        // from the underlying reader.
        match self.peeked_result {
            Some(ref old_res) => old_res.clone(),
            None => {
                // First get the result of the read from the underlying reader
                self.peeked_result = Some(self.inner.read_byte());

                // Now just return that
                self.peeked_result.clone().unwrap()
            }
        }
    }
}

mod tests {
    use super::PeekableReader;
    use std::io::{MemReader, IoError, IoErrorKind, IoResult};

    /// Helper function which checks whether the given result indicated EOF.
    fn is_eof<T>(res: IoResult<T>) -> bool {
        match res {
            Err(IoError {
                kind: IoErrorKind::EndOfFile,
                ..
            }) => true,
            _ => false,
        }
    }

    /// Tests that it is possible to invoke the `peek` method multiple times
    /// with the same effect, when there are no intermediate reads.
    #[test]
    fn multiple_peeks_idempotent() {
        let b = 1;
        let mut reader = PeekableReader::new(MemReader::new(vec!(b, b + 1)));

        // The first peek is correct?
        assert_eq!(b, reader.peek().unwrap());
        // The second peek (with no reads in between) still returns the same
        // byte?
        assert_eq!(b, reader.peek().unwrap());
    }

    #[test]
    fn single_byte_reader_peek() {
        let b = 5u8;
        let mut reader = PeekableReader::new(MemReader::new(vec!(b)));

        // When we peek, we get the correct byte back?
        assert_eq!(b, reader.peek().unwrap());
    }

    #[test]
    fn empty_underlying_reader() {
        let mut reader = PeekableReader::new(MemReader::new(vec!()));

        // Must return EOF since the underlying reader is empty
        assert!(is_eof(reader.peek()));
    }
}
<|endoftext|>


<commit_before>//! Crate **ruma_identifiers** contains types for [Matrix](https://matrix.org/) identifiers
//! for events, rooms, room aliases, room versions, and users.

#![deny(
    missing_copy_implementations,
    missing_debug_implementations,
    missing_docs,
    warnings
)]
#![warn(
    clippy::empty_line_after_outer_attr,
    clippy::expl_impl_clone_on_copy,
    clippy::if_not_else,
    clippy::items_after_statements,
    clippy::match_same_arms,
    clippy::mem_forget,
    clippy::missing_docs_in_private_items,
    clippy::multiple_inherent_impl,
    clippy::mut_mut,
    clippy::needless_borrow,
    clippy::needless_continue,
    clippy::single_match_else,
    clippy::unicode_not_nfc,
    clippy::use_self,
    clippy::used_underscore_binding,
    clippy::wrong_pub_self_convention,
    clippy::wrong_self_convention
)]

#[cfg(feature = "diesel")]
#[cfg_attr(feature = "diesel", macro_use)]
extern crate diesel;

use std::fmt::{Formatter, Result as FmtResult};

use rand::{distributions::Alphanumeric, thread_rng, Rng};
use url::Url;

pub use url::Host;

#[doc(inline)]
pub use crate::device_id::DeviceId;
pub use crate::{
    error::Error, event_id::EventId, room_alias_id::RoomAliasId, room_id::RoomId,
    room_id_or_room_alias_id::RoomIdOrAliasId, room_version_id::RoomVersionId, user_id::UserId,
};

pub mod device_id;
#[cfg(feature = "diesel")]
mod diesel_integration;
mod error;
mod event_id;
mod room_alias_id;
mod room_id;
mod room_id_or_room_alias_id;
mod room_version_id;
mod user_id;

/// All identifiers must be 255 bytes or less.
const MAX_BYTES: usize = 255;
/// The minimum number of characters an ID can be.
///
/// This is an optimization and not required by the spec. The shortest possible valid ID is a sigil
/// + a single character local ID + a colon + a single character hostname.
const MIN_CHARS: usize = 4;
/// The number of bytes in a valid sigil.
const SIGIL_BYTES: usize = 1;

/// `Display` implementation shared by identifier types.
fn display(
    f: &mut Formatter<'_>,
    sigil: char,
    localpart: &str,
    hostname: &Host,
    port: u16,
) -> FmtResult {
    if port == 443 {
        write!(f, "{}{}:{}", sigil, localpart, hostname)
    } else {
        write!(f, "{}{}:{}:{}", sigil, localpart, hostname, port)
    }
}

/// Generates a random identifier localpart.
fn generate_localpart(length: usize) -> String {
    thread_rng()
        .sample_iter(&Alphanumeric)
        .take(length)
        .collect()
}

/// Checks if an identifier is within the acceptable byte lengths.
fn validate_id(id: &str) -> Result<(), Error> {
    if id.len() > MAX_BYTES {
        return Err(Error::MaximumLengthExceeded);
    }

    if id.len() < MIN_CHARS {
        return Err(Error::MinimumLengthNotSatisfied);
    }

    Ok(())
}

/// Parses the localpart, host, and port from a string identifier.
fn parse_id(required_sigil: char, id: &str) -> Result<(&str, Host, u16), Error> {
    validate_id(id)?;

    if !id.starts_with(required_sigil) {
        return Err(Error::MissingSigil);
    }

    let delimiter_index = match id.find(':') {
        Some(index) => index,
        None => return Err(Error::MissingDelimiter),
    };

    let localpart = &id[1..delimiter_index];
    let raw_host = &id[delimiter_index + SIGIL_BYTES..];
    let url_string = format!("https://{}", raw_host);
    let url = Url::parse(&url_string)?;

    let host = match url.host() {
        Some(host) => host.to_owned(),
        None => return Err(Error::InvalidHost),
    };

    let port = url.port().unwrap_or(443);

    Ok((localpart, host, port))
}
<commit_msg>Allow clippy::use_self<commit_after>//! Crate **ruma_identifiers** contains types for [Matrix](https://matrix.org/) identifiers
//! for events, rooms, room aliases, room versions, and users.

#![deny(
    missing_copy_implementations,
    missing_debug_implementations,
    missing_docs,
    warnings
)]
#![warn(
    clippy::empty_line_after_outer_attr,
    clippy::expl_impl_clone_on_copy,
    clippy::if_not_else,
    clippy::items_after_statements,
    clippy::match_same_arms,
    clippy::mem_forget,
    clippy::missing_docs_in_private_items,
    clippy::multiple_inherent_impl,
    clippy::mut_mut,
    clippy::needless_borrow,
    clippy::needless_continue,
    clippy::single_match_else,
    clippy::unicode_not_nfc,
    clippy::use_self,
    clippy::used_underscore_binding,
    clippy::wrong_pub_self_convention,
    clippy::wrong_self_convention
)]
// Since we support Rust 1.34.2, we can't apply this suggestion yet
#![allow(clippy::use_self)]

#[cfg(feature = "diesel")]
#[cfg_attr(feature = "diesel", macro_use)]
extern crate diesel;

use std::fmt::{Formatter, Result as FmtResult};

use rand::{distributions::Alphanumeric, thread_rng, Rng};
use url::Url;

pub use url::Host;

#[doc(inline)]
pub use crate::device_id::DeviceId;
pub use crate::{
    error::Error, event_id::EventId, room_alias_id::RoomAliasId, room_id::RoomId,
    room_id_or_room_alias_id::RoomIdOrAliasId, room_version_id::RoomVersionId, user_id::UserId,
};

pub mod device_id;
#[cfg(feature = "diesel")]
mod diesel_integration;
mod error;
mod event_id;
mod room_alias_id;
mod room_id;
mod room_id_or_room_alias_id;
mod room_version_id;
mod user_id;

/// All identifiers must be 255 bytes or less.
const MAX_BYTES: usize = 255;
/// The minimum number of characters an ID can be.
///
/// This is an optimization and not required by the spec. The shortest possible valid ID is a sigil
/// + a single character local ID + a colon + a single character hostname.
const MIN_CHARS: usize = 4;
/// The number of bytes in a valid sigil.
const SIGIL_BYTES: usize = 1;

/// `Display` implementation shared by identifier types.
fn display(
    f: &mut Formatter<'_>,
    sigil: char,
    localpart: &str,
    hostname: &Host,
    port: u16,
) -> FmtResult {
    if port == 443 {
        write!(f, "{}{}:{}", sigil, localpart, hostname)
    } else {
        write!(f, "{}{}:{}:{}", sigil, localpart, hostname, port)
    }
}

/// Generates a random identifier localpart.
fn generate_localpart(length: usize) -> String {
    thread_rng()
        .sample_iter(&Alphanumeric)
        .take(length)
        .collect()
}

/// Checks if an identifier is within the acceptable byte lengths.
fn validate_id(id: &str) -> Result<(), Error> {
    if id.len() > MAX_BYTES {
        return Err(Error::MaximumLengthExceeded);
    }

    if id.len() < MIN_CHARS {
        return Err(Error::MinimumLengthNotSatisfied);
    }

    Ok(())
}

/// Parses the localpart, host, and port from a string identifier.
fn parse_id(required_sigil: char, id: &str) -> Result<(&str, Host, u16), Error> {
    validate_id(id)?;

    if !id.starts_with(required_sigil) {
        return Err(Error::MissingSigil);
    }

    let delimiter_index = match id.find(':') {
        Some(index) => index,
        None => return Err(Error::MissingDelimiter),
    };

    let localpart = &id[1..delimiter_index];
    let raw_host = &id[delimiter_index + SIGIL_BYTES..];
    let url_string = format!("https://{}", raw_host);
    let url = Url::parse(&url_string)?;

    let host = match url.host() {
        Some(host) => host.to_owned(),
        None => return Err(Error::InvalidHost),
    };

    let port = url.port().unwrap_or(443);

    Ok((localpart, host, port))
}
<|endoftext|>