<commit_before>//! # A CHIP-8 cpu simulator and instruction coding/decoding library.
//!
//! `chip8` provides tools to enable working with
//! [CHIP-8 virtual machine](https://en.wikipedia.org/wiki/CHIP-8)
//! instructions, and a CHIP-8 virtual machine simulator. No GUI is provided,
//! it is intended to be used by another crate. For example, this crate could:
//!  - encode abstract instructions into CHIP-8 codewords for a CHIP-8 assembler
//!  - decode CHIP-8 binary machine codes into abstract instruction objects for a CHIP-8 disassembler
//!  - decode instructions and execute them in a CHIP-8 virtual machine as the core of a GUI CHIP-8 emulator
//!
//! ```rust
//! use chip8::{Simulator, Simulate};
//! use chip8::instruction::Src::Register;
//! let mut chip8 = Simulator::default();
//! //A simple program: LD v6, 25  /  LD v7, 17  /  ADD v6, v7
//! chip8.load_program( &[0x66, 0x19, 0x67, 0x11, 0x86, 0x74] ).unwrap();
//! chip8.step_n(3).unwrap();
//! let result = chip8.load(Register(6)).unwrap();
//! assert_eq!( result, 25+17 );
//! ```
//!
//!
//!
//!
//! ## Configuration
//! A `Config` stores the configuration of a CHIP-8 system. It contains the A `Config` is
//! used when instantiating machine state or an instruction set.
//!
//! ## Instructions
//! A set of `Operation`s are supported by this library. These operations correspond
//! with instructions from the CHIP-8 instruction set, but are typically more flexible to allow
//! re-use.
//!
//! A `Pattern` defines how the operands required by an `Operation` will be defined by the
//! codeword.
//!
//! An `instruction::Definition` is a combination of an `Operation` and a `Pattern`.
//! These `Definition`s can be combined into an `instruction::Set` that is able to *decode* codewords
//! and return `instruction::Instruction`s and *encode* `instruction::Instruction`s into codewords.
//!
//! `Definition`s and `Instruction`s are very similar, but a key difference sets them apart - a
//! `Definition` only stores the *kind* of operands that will be used and the `Instruction` stores
//! the specific operands that will be used. When a codeword is decoded, information about the
//! operands is extracted based on the pattern in the definition. For example, a generic 'Register'
//! operand in a `Definition` could be specified as 'the v6 register' when the Instruction is
//! created.
//!
//! ## Simulation
//! The state of a CHIP-8 system, including CPU and peripherals, is represented by a `Chip8`.
//! It is able to execute instructions by providing an implementation of the `Execute` trait.
//!
//! A `Simulator` contains a `Chip8` and an `instruction::Set`, which allows it to simulate
//! a CHIP-8 machine fetching codewords from memory, decoding the codewords, and executing the
//! resulting instructions. The `Simulator` provides a mechanism for thread-safe control
//! of the machine and access to state information.

#![feature(inclusive_range_syntax, fnbox, plugin)]
#![feature(question_mark)]
#![plugin(drawbytes)]

// enable errors for some additional lints
#![deny(trivial_casts, trivial_numeric_casts, unsafe_code,
        unused_qualifications)]

#![cfg_attr(feature = "lints", warn(missing_docs))]
#![cfg_attr(feature = "lints", plugin(clippy))]
#![cfg_attr(feature = "lints", deny(clippy))]
#![cfg_attr(feature = "lints", deny(if_not_else, invalid_upcast_comparisons, items_after_statements,
                                    mem_forget, mut_mut, mutex_integer, non_ascii_literal,
                                    nonminimal_bool, shadow_reuse, shadow_same, shadow_unrelated,
                                    similar_names, single_match_else, string_add, string_add_assign,
                                    unicode_not_nfc, wrong_pub_self_convention ))]
#![cfg_attr(feature = "lints", warn(option_unwrap_used, result_unwrap_used, missing_debug_implementations,
                                    unused_import_braces,missing_copy_implementations))]
#![cfg_attr(feature = "lints", allow(doc_markdown))]

//#![cfg_attr(feature = "lints", cast_possible_truncation, cast_possible_wrap, cast_sign_loss))]

#![allow(unused_imports, unused_variables, unused_mut)]

extern crate rand;
extern crate strfmt;

pub mod config;
pub mod fonts;
pub mod instruction;
mod simulator;
mod state;
mod types;

pub use config::Config;
pub use types::*;
pub use state::Chip8;
pub use simulator::{Simulator, Simulate};

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

/*    #[test]
    fn test_chip8_system() {
        let conf = config::presets::COSMAC_VIP_STOCK;
        let chip8 = Chip8::new(&conf, None);
        let mut isa = instruction::Set::new(&conf);
        let d = instruction::Decoder::new(&conf, &isa);
        let e = instruction::Encoder::new(&conf, &isa);

        assert!(true)
    }*/
}
<commit_msg>Format the introductory doctest a bit<commit_after>//! # A CHIP-8 cpu simulator and instruction coding/decoding library.
//!
//! `chip8` provides tools to enable working with
//! [CHIP-8 virtual machine](https://en.wikipedia.org/wiki/CHIP-8)
//! instructions, and a CHIP-8 virtual machine simulator. No GUI is provided,
//! it is intended to be used by another crate. For example, this crate could:
//!  - encode abstract instructions into CHIP-8 codewords for a CHIP-8 assembler
//!  - decode CHIP-8 binary machine codes into abstract instruction objects for a CHIP-8 disassembler
//!  - decode instructions and execute them in a CHIP-8 virtual machine as the core of a GUI CHIP-8 emulator
//!
//! ```rust
//! use chip8::{Simulator, Simulate};
//! use chip8::instruction::Src::Register;
//! let mut chip8 = Simulator::default();
//! // A simple program: LD v6, 25  /  LD v7, 17  /  ADD v6, v7
//! chip8.load_program( &[0x66, 0x19, 0x67, 0x11, 0x86, 0x74] ).unwrap();
//! // Execute three instructions.
//! chip8.step_n(3).unwrap();
//! // Fetch the contents of register v6.
//! let result = chip8.load(Register(6)).unwrap();
//! assert_eq!( result, 25+17 );
//! ```
//!
//!
//!
//!
//! ## Configuration
//! A `Config` stores the configuration of a CHIP-8 system. It contains the A `Config` is
//! used when instantiating machine state or an instruction set.
//!
//! ## Instructions
//! A set of `Operation`s are supported by this library. These operations correspond
//! with instructions from the CHIP-8 instruction set, but are typically more flexible to allow
//! re-use.
//!
//! A `Pattern` defines how the operands required by an `Operation` will be defined by the
//! codeword.
//!
//! An `instruction::Definition` is a combination of an `Operation` and a `Pattern`.
//! These `Definition`s can be combined into an `instruction::Set` that is able to *decode* codewords
//! and return `instruction::Instruction`s and *encode* `instruction::Instruction`s into codewords.
//!
//! `Definition`s and `Instruction`s are very similar, but a key difference sets them apart - a
//! `Definition` only stores the *kind* of operands that will be used and the `Instruction` stores
//! the specific operands that will be used. When a codeword is decoded, information about the
//! operands is extracted based on the pattern in the definition. For example, a generic 'Register'
//! operand in a `Definition` could be specified as 'the v6 register' when the Instruction is
//! created.
//!
//! ## Simulation
//! The state of a CHIP-8 system, including CPU and peripherals, is represented by a `Chip8`.
//! It is able to execute instructions by providing an implementation of the `Execute` trait.
//!
//! A `Simulator` contains a `Chip8` and an `instruction::Set`, which allows it to simulate
//! a CHIP-8 machine fetching codewords from memory, decoding the codewords, and executing the
//! resulting instructions. The `Simulator` provides a mechanism for thread-safe control
//! of the machine and access to state information.

#![feature(inclusive_range_syntax, fnbox, plugin)]
#![feature(question_mark)]
#![plugin(drawbytes)]

// enable errors for some additional lints
#![deny(trivial_casts, trivial_numeric_casts, unsafe_code,
        unused_qualifications)]

#![cfg_attr(feature = "lints", warn(missing_docs))]
#![cfg_attr(feature = "lints", plugin(clippy))]
#![cfg_attr(feature = "lints", deny(clippy))]
#![cfg_attr(feature = "lints", deny(if_not_else, invalid_upcast_comparisons, items_after_statements,
                                    mem_forget, mut_mut, mutex_integer, non_ascii_literal,
                                    nonminimal_bool, shadow_reuse, shadow_same, shadow_unrelated,
                                    similar_names, single_match_else, string_add, string_add_assign,
                                    unicode_not_nfc, wrong_pub_self_convention ))]
#![cfg_attr(feature = "lints", warn(option_unwrap_used, result_unwrap_used, missing_debug_implementations,
                                    unused_import_braces,missing_copy_implementations))]
#![cfg_attr(feature = "lints", allow(doc_markdown))]

//#![cfg_attr(feature = "lints", cast_possible_truncation, cast_possible_wrap, cast_sign_loss))]

#![allow(unused_imports, unused_variables, unused_mut)]

extern crate rand;
extern crate strfmt;

pub mod config;
pub mod fonts;
pub mod instruction;
mod simulator;
mod state;
mod types;

pub use config::Config;
pub use types::*;
pub use state::Chip8;
pub use simulator::{Simulator, Simulate};

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

/*    #[test]
    fn test_chip8_system() {
        let conf = config::presets::COSMAC_VIP_STOCK;
        let chip8 = Chip8::new(&conf, None);
        let mut isa = instruction::Set::new(&conf);
        let d = instruction::Decoder::new(&conf, &isa);
        let e = instruction::Encoder::new(&conf, &isa);

        assert!(true)
    }*/
}
<|endoftext|>


<commit_before>//! [(Link to repository page.)](https://github.com/C4K3/Ozelot)
//!
//! This is a library made for interacting with the Minecraft protocl
//! (MCMODERN only, not MCPE.)
//!
//! It is mostly a low-level library, its goals are to
//! handle everything network related, but nothing beyond that. For example
//! this library does not support any types beyond ones found in standard Rust,
//! this results in certain packets that contain compound datatypes not having
//! their complex fields serialized by this library, but instead handing the
//! raw binary data to consumers of this library to parse however they wish.
//! One example of this is packets that contain NBT data, the packets are read
//! but the NBT data is not in any way parsed by this library. You'll probably
//! want to see what the meanings of each of the packets are, which is
//! documented on [wiki.vg](http://wiki.vg/Main_Page). The [protocol
//! documentation](http://wiki.vg/Protocol) in particular is likely to be a
//! necessary companion to using this library.
//!
//! Currently the library is entirely synchronous, requiring consumers to handle
//! concurrency however they wish. It would be cool to add an asynchronous API
//! though, maybe using mio.
//!
//! The library nominally supports every packet used in MCMODERN, but the goal
//! is still to add lots more helper functions and other useful things. There
//! are still many errors and inconvenient things in the library, where changes
//! or helper functions would be good to add. If you find any errors or
//! suggestions for improvement, no matter how trivial, then post it on the
//! bugtracker.
//!
//! The library does not yet have any stable releases, not because it may
//! contain bugs (which it certainly does,) but because the API may be
//! significantly restructured without warning.
//!
//! # Examples
//!
//! Connecting to a remote server as an authenticated user, printing all chat
//! messages, and then echoing back messages that appear not to be written by us
//! (else we'd get into an infinite loop echoing our own messages.)
//!
//! (See the *textclient* example for a comprehensive version.)
//!
//! ```rust,no_run
//! use ozelot::{mojang, Client, serverbound, utils};
//! use ozelot::clientbound::ClientboundPacket;
//!
//! let auth = mojang::Authenticate::new("my_email@example.com".to_string(),
//!                                      "my_password".to_string())
//!     .perform().unwrap();
//!
//!
//! /* By using connect_authenticated, auto_handle will be true and thus ozelot
//!  * will respond to keepalives automatically */
//! let mut client = Client::connect_authenticated("minecraft.example.com",
//!                                                25565, &auth).unwrap();
//!
//! let username = auth.selectedProfile.name;
//!
//! 'main: loop {
//!     let packets = client.read().unwrap();
//!     for packet in packets {
//!         match packet {
//!         ClientboundPacket::PlayDisconnect(ref p) => {
//!             println!("Disconnected, reason: {}",
//!                      utils::chat_to_str(p.get_reason()).unwrap());
//!             break 'main;
//!         },
//!         ClientboundPacket::ChatMessage(ref p) => {
//!             let msg = utils::chat_to_str(p.get_chat()).unwrap();
//!             println!("{}", msg);
//!             if !msg.contains(&username) {
//!                 /* Since we don't want an infinite loop, we don't echo back
//!                  * our own messages. We say that a received message wasn't
//!                  * written by us if it doesn't contain our username
//!                  *
//!                  * Note that this echoes back the raw chat message, that is
//!                  * playername and everything, and also non-chat messages. */
//!                 let response = serverbound::ChatMessage::new(msg);
//!                 let _: usize = client.send(response).unwrap();
//!             }
//!         },
//!         /* We throw away all other packets */
//!         _ => (),
//!         }
//!     }
//! }
//! ```
extern crate byteorder;
extern crate curl;
extern crate flate2;
extern crate netbuf;
extern crate openssl;
extern crate serde;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate serde_json;
#[macro_use]
extern crate error_chain;

mod client;
mod connection;
#[allow(non_snake_case)]
mod json;
mod server;
pub mod clientbound;
pub mod errors;
#[allow(non_snake_case)]
pub mod mojang;
pub mod read;
pub mod serverbound;
pub mod utils;
pub mod write;
#[cfg(test)]
mod tests;

pub use client::Client;
pub use server::Server;

use std::fmt;

/// The protocol version supported by this version of ozelot
pub const PROTOCOL_VERSION: i32 = 340;

/// FIXME temporary struct until u128 lands in stable rust, used for uuids
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[allow(non_camel_case_types)]
pub struct u128(pub u64, pub u64);

/// This tracks which state of play the client is in. The value of this changes
/// the meaning of the different packet ids.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ClientState {
    Handshake,
    Status,
    Login,
    Play,
}
impl fmt::Display for ClientState {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", match self {
            &ClientState::Handshake => "Handshake",
            &ClientState::Status => "Status",
            &ClientState::Login => "Login",
            &ClientState::Play => "Play",
        })
    }
}
<commit_msg>sleep in the example<commit_after>//! [(Link to repository page.)](https://github.com/C4K3/Ozelot)
//!
//! This is a library made for interacting with the Minecraft protocl
//! (MCMODERN only, not MCPE.)
//!
//! It is mostly a low-level library, its goals are to
//! handle everything network related, but nothing beyond that. For example
//! this library does not support any types beyond ones found in standard Rust,
//! this results in certain packets that contain compound datatypes not having
//! their complex fields serialized by this library, but instead handing the
//! raw binary data to consumers of this library to parse however they wish.
//! One example of this is packets that contain NBT data, the packets are read
//! but the NBT data is not in any way parsed by this library. You'll probably
//! want to see what the meanings of each of the packets are, which is
//! documented on [wiki.vg](http://wiki.vg/Main_Page). The [protocol
//! documentation](http://wiki.vg/Protocol) in particular is likely to be a
//! necessary companion to using this library.
//!
//! Currently the library is entirely synchronous, requiring consumers to handle
//! concurrency however they wish. It would be cool to add an asynchronous API
//! though, maybe using mio.
//!
//! The library nominally supports every packet used in MCMODERN, but the goal
//! is still to add lots more helper functions and other useful things. There
//! are still many errors and inconvenient things in the library, where changes
//! or helper functions would be good to add. If you find any errors or
//! suggestions for improvement, no matter how trivial, then post it on the
//! bugtracker.
//!
//! The library does not yet have any stable releases, not because it may
//! contain bugs (which it certainly does,) but because the API may be
//! significantly restructured without warning.
//!
//! # Examples
//!
//! Connecting to a remote server as an authenticated user, printing all chat
//! messages, and then echoing back messages that appear not to be written by us
//! (else we'd get into an infinite loop echoing our own messages.)
//!
//! (See the *textclient* example for a comprehensive version.)
//!
//! ```rust,no_run
//! use std::thread;
//! use std::time::Duration;
//! use ozelot::{mojang, Client, serverbound, utils};
//! use ozelot::clientbound::ClientboundPacket;
//!
//! let auth = mojang::Authenticate::new("my_email@example.com".to_string(),
//!                                      "my_password".to_string())
//!     .perform().unwrap();
//!
//!
//! /* By using connect_authenticated, auto_handle will be true and thus ozelot
//!  * will respond to keepalives automatically */
//! let mut client = Client::connect_authenticated("minecraft.example.com",
//!                                                25565, &auth).unwrap();
//!
//! let username = auth.selectedProfile.name;
//!
//! 'main: loop {
//!     let packets = client.read().unwrap();
//!     for packet in packets {
//!         match packet {
//!         ClientboundPacket::PlayDisconnect(ref p) => {
//!             println!("Disconnected, reason: {}",
//!                      utils::chat_to_str(p.get_reason()).unwrap());
//!             break 'main;
//!         },
//!         ClientboundPacket::ChatMessage(ref p) => {
//!             let msg = utils::chat_to_str(p.get_chat()).unwrap();
//!             println!("{}", msg);
//!             if !msg.contains(&username) {
//!                 /* Since we don't want an infinite loop, we don't echo back
//!                  * our own messages. We say that a received message wasn't
//!                  * written by us if it doesn't contain our username
//!                  *
//!                  * Note that this echoes back the raw chat message, that is
//!                  * playername and everything, and also non-chat messages. */
//!                 let response = serverbound::ChatMessage::new(msg);
//!                 let _: usize = client.send(response).unwrap();
//!             }
//!         },
//!         /* We throw away all other packets */
//!         _ => (),
//!         }
//!     }
//!     /* Make sure we don't consume the entire CPU trying to check if new packets have arrived */
//!     thread::sleep(Duration::from_millis(50));
//! }
//! ```
extern crate byteorder;
extern crate curl;
extern crate flate2;
extern crate netbuf;
extern crate openssl;
extern crate serde;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate serde_json;
#[macro_use]
extern crate error_chain;

mod client;
mod connection;
#[allow(non_snake_case)]
mod json;
mod server;
pub mod clientbound;
pub mod errors;
#[allow(non_snake_case)]
pub mod mojang;
pub mod read;
pub mod serverbound;
pub mod utils;
pub mod write;
#[cfg(test)]
mod tests;

pub use client::Client;
pub use server::Server;

use std::fmt;

/// The protocol version supported by this version of ozelot
pub const PROTOCOL_VERSION: i32 = 340;

/// FIXME temporary struct until u128 lands in stable rust, used for uuids
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[allow(non_camel_case_types)]
pub struct u128(pub u64, pub u64);

/// This tracks which state of play the client is in. The value of this changes
/// the meaning of the different packet ids.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ClientState {
    Handshake,
    Status,
    Login,
    Play,
}
impl fmt::Display for ClientState {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", match self {
            &ClientState::Handshake => "Handshake",
            &ClientState::Status => "Status",
            &ClientState::Login => "Login",
            &ClientState::Play => "Play",
        })
    }
}
<|endoftext|>


<commit_before>//! **mprovision** is a tool that helps iOS developers to manage mobileprovision
//! files. Main purpose of this crate is to contain functions and types
//! for **mprovision**.

#[cfg(test)]
#[macro_use(expect)]
extern crate expectest;
#[cfg(test)]
extern crate tempdir;
extern crate plist;
extern crate chrono;
extern crate crossbeam;
extern crate num_cpus;

use std::fs::{self, DirEntry, File};
use std::path::{Path, PathBuf};
use std::env;
use std::io::{self, Read};
use plist::PlistEvent::*;

use std::thread;
use std::thread::JoinHandle;
use std::sync::mpsc::channel;
use std::sync::mpsc::Receiver;

use crossbeam::sync::chase_lev;
use crossbeam::sync::chase_lev::*;

pub use error::Error;
pub use profile::Profile;

mod error;
mod profile;

fn execute<F, I, J>(iter: I, number_of_threads: usize, f: F) -> JobIter<J::Output>
    where F: Fn(I::Item) -> J,
          J: Job + Send + 'static,
          J::Output: Send + 'static,
          I: Iterator
{
    let (mut worker, stealer) = chase_lev::deque();
    let (tx, rx) = channel();

    for item in iter {
        let job = (f)(item);
        worker.push(job);
    }

    let mut handles = Vec::new();
    for thread_id in 0..number_of_threads {
        let stealer = stealer.clone();
        let tx = tx.clone();

        let handle = thread::spawn(move || {
            loop {
                match stealer.steal() {
                    Steal::Data(job) => {
                        tx.send(Event::Data(thread_id, job.execute())).unwrap_or(())
                    }
                    Steal::Empty => break,
                    _ => (),
                }
            }

            tx.send(Event::Finish(thread_id)).unwrap_or(());
        });

        handles.push((thread_id, handle));
    }

    JobIter {
        handles: handles,
        receiver: rx,
    }
}

trait Job {
    type Output;
    fn execute(self) -> Self::Output;
}

struct ReadProfileJob(DirEntry);

impl Job for ReadProfileJob {
    type Output = Result<Profile>;
    fn execute(self) -> Self::Output {
        profile_from_file(self.0.path().as_path())
    }
}

struct JobIter<T> {
    handles: Vec<(usize, JoinHandle<()>)>,
    receiver: Receiver<Event<T>>,
}

impl<T> Iterator for JobIter<T> {
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        loop {
            match self.receiver.recv() {
                Ok(event) => {
                    match event {
                        Event::Finish(thread_index) => {
                            let mut index = None;
                            for (i, &(id, _)) in self.handles.iter().enumerate() {
                                if thread_index == id {
                                    index = Some(i);
                                    break;
                                }
                            }
                            if let Some(i) = index {
                                let handle = self.handles.swap_remove(i);
                                match handle.1.join() {
                                    Err(error) => println!("Error: {:?}", error),
                                    Ok(_) => (),
                                }
                            }
                        }
                        Event::Data(_, data) => {
                            return Some(data);
                        }
                    }
                }
                Err(_) => {
                    break;
                }
            }
        }
        None
    }
}

enum Event<T> {
    Finish(usize),
    Data(usize, T),
}

/// A Result type for this crate.
pub type Result<T> = std::result::Result<T, Error>;

/// Returns an iterator over the `*.mobileprovision` entries within a given
/// directory.
///
/// # Errors
/// This function will return an error in the following cases:
///
/// - the user lacks the requisite permissions
/// - there is no entry in the filesystem at the provided path
/// - the provided path is not a directory
pub fn files(path: &Path) -> Result<Box<Iterator<Item = DirEntry>>> {
    let entries = try!(fs::read_dir(path));
    let filtered = entries.filter_map(|entry| entry.ok())
                          .filter_map(|entry| {
                              if let Some(ext) = entry.path().extension() {
                                  if ext == "mobileprovision" {
                                      return Some(entry);
                                  }
                              }
                              None
                          });
    Ok(Box::new(filtered))
}

/// Returns the path to the directory that contains installed mobile
/// provisioning profiles.
///
/// Should return `~/Library/MobileDevice/Provisioning Profiles` directory.
///
/// # Errors
/// This function will return an error if 'HOME' environment variable is not set
/// or equal to the empty string.
pub fn directory() -> Result<PathBuf> {
    env::home_dir()
        .map(|path| path.join("Library/MobileDevice/Provisioning Profiles"))
        .ok_or(Error::Own("'HOME' environment variable is not set or equal to the empty string."
                              .to_owned()))
}

pub fn with_path<F, T>(path: Option<&Path>, f: F) -> Result<T>
    where F: FnOnce(&Path) -> Result<T>
{
    if let Some(path) = path {
        f(&path)
    } else {
        let path = try!(directory());
        f(&path)
    }
}

pub fn profiles(path: &Path) -> Result<Box<Iterator<Item = Result<Profile>>>> {
    let files = try!(files(path));
    let iter = execute(files, num_cpus::get(), |entry| ReadProfileJob(entry));
    Ok(Box::new(iter))
}

pub fn valid_profiles(path: &Path) -> Result<Box<Iterator<Item = Profile>>> {
    Ok(Box::new(try!(profiles(path)).filter(Result::is_ok).map(|r| r.unwrap())))
}

pub struct SearchInfo {
    pub total: usize,
    pub profiles: Vec<Profile>,
}

pub fn search(path: &Path, s: &str) -> Result<SearchInfo> {
    let mut total = 0;
    let profiles = try!(valid_profiles(path))
                       .filter(|profile| {
                           total += 1;
                           profile.contains(s)
                       })
                       .collect();

    Ok(SearchInfo {
        total: total,
        profiles: profiles,
    })
}

pub fn remove(path: &Path, uuid: &str) -> Result<()> {
    for profile in try!(valid_profiles(path)).into_iter() {
        if profile.uuid == uuid {
            try!(std::fs::remove_file(&profile.path));
            return Ok(());
        }
    }
    return Err(Error::Own(format!("Profile '{}' is not found.", uuid)));
}

pub fn xml(path: &Path, uuid: &str) -> Result<String> {
    for profile in try!(valid_profiles(path)).into_iter() {
        if profile.uuid == uuid {
            let mut file = try!(File::open(&profile.path));
            let mut buf = Vec::new();
            try!(file.read_to_end(&mut buf));
            let data = try!(find_plist(&buf).ok_or(Error::Own("Couldn't parse file.".into())));
            return Ok(try!(String::from_utf8(data.to_owned())));
        }
    }
    return Err(Error::Own(format!("Profile '{}' is not found.", uuid)));
}

/// Returns instance of the `Profile` parsed from a file.
pub fn profile_from_file(path: &Path) -> Result<Profile> {
    let mut file = try!(File::open(path));
    let mut buf = Vec::new();
    try!(file.read_to_end(&mut buf));
    profile_from_data(&buf)
        .map(|mut p| {
            p.path = path.to_owned();
            p
        })
        .ok_or(Error::Own("Couldn't parse file.".into()))
}

/// Returns instance of the `Profile` parsed from a `data`.
pub fn profile_from_data(data: &[u8]) -> Option<Profile> {
    if let Some(data) = find_plist(data) {
        let mut profile = Profile::empty();
        let mut iter = plist::xml::EventReader::new(io::Cursor::new(data)).into_iter();
        while let Some(item) = iter.next() {
            if let Ok(StringValue(key)) = item {
                if key == "UUID" {
                    if let Some(Ok(StringValue(value))) = iter.next() {
                        profile.uuid = value;
                    }
                }
                if key == "Name" {
                    if let Some(Ok(StringValue(value))) = iter.next() {
                        profile.name = value;
                    }
                }
                if key == "application-identifier" {
                    if let Some(Ok(StringValue(value))) = iter.next() {
                        profile.app_identifier = value;
                    }
                }
                if key == "CreationDate" {
                    if let Some(Ok(DateValue(value))) = iter.next() {
                        profile.creation_date = value;
                    }
                }
                if key == "ExpirationDate" {
                    if let Some(Ok(DateValue(value))) = iter.next() {
                        profile.expiration_date = value;
                    }
                }
            }
        }
        Some(profile)
    } else {
        None
    }
}

/// Returns an index where the `needle` starts in the `data`.
fn find(data: &[u8], needle: &[u8]) -> Option<usize> {
    let needle_len = needle.len();
    for (i, _) in data.iter().enumerate() {
        if i + needle_len > data.len() {
            return None;
        }
        if &data[i..i + needle_len] == needle {
            return Some(i);
        }
    }
    None
}

/// Returns a plist content in a `data`.
fn find_plist(data: &[u8]) -> Option<&[u8]> {
    let prefix = b"<?xml version=";
    let suffix = b"</plist>";

    let start_i = find(data, prefix);
    let end_i = find(data, suffix).map(|i| i + suffix.len());

    if let (Some(start_i), Some(end_i)) = (start_i, end_i) {
        if end_i < data.len() {
            return Some(&data[start_i..end_i]);
        }
    }

    None
}

    #[cfg(test)]
mod tests {
    use expectest::prelude::*;
    use tempdir::TempDir;
    use std::fs::File;
    use super::files;

    #[test]
    fn filter_mobileprovision_files() {
        let temp_dir = TempDir::new("test").unwrap();
        let result = files(temp_dir.path()).map(|iter| iter.count());
        expect!(result).to(be_ok().value(0));

        File::create(temp_dir.path().join("1.mobileprovision")).unwrap();
        File::create(temp_dir.path().join("2.mobileprovision")).unwrap();
        File::create(temp_dir.path().join("3.txt")).unwrap();
        let result = files(temp_dir.path()).map(|iter| iter.count());
        expect!(result).to(be_ok().value(2));
    }
}
<commit_msg>Add tests for find_plist function.<commit_after>//! **mprovision** is a tool that helps iOS developers to manage mobileprovision
//! files. Main purpose of this crate is to contain functions and types
//! for **mprovision**.

#[cfg(test)]
#[macro_use(expect)]
extern crate expectest;
#[cfg(test)]
extern crate tempdir;
extern crate plist;
extern crate chrono;
extern crate crossbeam;
extern crate num_cpus;

use std::fs::{self, DirEntry, File};
use std::path::{Path, PathBuf};
use std::env;
use std::io::{self, Read};
use plist::PlistEvent::*;

use std::thread;
use std::thread::JoinHandle;
use std::sync::mpsc::channel;
use std::sync::mpsc::Receiver;

use crossbeam::sync::chase_lev;
use crossbeam::sync::chase_lev::*;

pub use error::Error;
pub use profile::Profile;

mod error;
mod profile;

fn execute<F, I, J>(iter: I, number_of_threads: usize, f: F) -> JobIter<J::Output>
    where F: Fn(I::Item) -> J,
          J: Job + Send + 'static,
          J::Output: Send + 'static,
          I: Iterator
{
    let (mut worker, stealer) = chase_lev::deque();
    let (tx, rx) = channel();

    for item in iter {
        let job = (f)(item);
        worker.push(job);
    }

    let mut handles = Vec::new();
    for thread_id in 0..number_of_threads {
        let stealer = stealer.clone();
        let tx = tx.clone();

        let handle = thread::spawn(move || {
            loop {
                match stealer.steal() {
                    Steal::Data(job) => {
                        tx.send(Event::Data(thread_id, job.execute())).unwrap_or(())
                    }
                    Steal::Empty => break,
                    _ => (),
                }
            }

            tx.send(Event::Finish(thread_id)).unwrap_or(());
        });

        handles.push((thread_id, handle));
    }

    JobIter {
        handles: handles,
        receiver: rx,
    }
}

trait Job {
    type Output;
    fn execute(self) -> Self::Output;
}

struct ReadProfileJob(DirEntry);

impl Job for ReadProfileJob {
    type Output = Result<Profile>;
    fn execute(self) -> Self::Output {
        profile_from_file(self.0.path().as_path())
    }
}

struct JobIter<T> {
    handles: Vec<(usize, JoinHandle<()>)>,
    receiver: Receiver<Event<T>>,
}

impl<T> Iterator for JobIter<T> {
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        loop {
            match self.receiver.recv() {
                Ok(event) => {
                    match event {
                        Event::Finish(thread_index) => {
                            let mut index = None;
                            for (i, &(id, _)) in self.handles.iter().enumerate() {
                                if thread_index == id {
                                    index = Some(i);
                                    break;
                                }
                            }
                            if let Some(i) = index {
                                let handle = self.handles.swap_remove(i);
                                match handle.1.join() {
                                    Err(error) => println!("Error: {:?}", error),
                                    Ok(_) => (),
                                }
                            }
                        }
                        Event::Data(_, data) => {
                            return Some(data);
                        }
                    }
                }
                Err(_) => {
                    break;
                }
            }
        }
        None
    }
}

enum Event<T> {
    Finish(usize),
    Data(usize, T),
}

/// A Result type for this crate.
pub type Result<T> = std::result::Result<T, Error>;

/// Returns an iterator over the `*.mobileprovision` entries within a given
/// directory.
///
/// # Errors
/// This function will return an error in the following cases:
///
/// - the user lacks the requisite permissions
/// - there is no entry in the filesystem at the provided path
/// - the provided path is not a directory
pub fn files(path: &Path) -> Result<Box<Iterator<Item = DirEntry>>> {
    let entries = try!(fs::read_dir(path));
    let filtered = entries.filter_map(|entry| entry.ok())
                          .filter_map(|entry| {
                              if let Some(ext) = entry.path().extension() {
                                  if ext == "mobileprovision" {
                                      return Some(entry);
                                  }
                              }
                              None
                          });
    Ok(Box::new(filtered))
}

/// Returns the path to the directory that contains installed mobile
/// provisioning profiles.
///
/// Should return `~/Library/MobileDevice/Provisioning Profiles` directory.
///
/// # Errors
/// This function will return an error if 'HOME' environment variable is not set
/// or equal to the empty string.
pub fn directory() -> Result<PathBuf> {
    env::home_dir()
        .map(|path| path.join("Library/MobileDevice/Provisioning Profiles"))
        .ok_or(Error::Own("'HOME' environment variable is not set or equal to the empty string."
                              .to_owned()))
}

pub fn with_path<F, T>(path: Option<&Path>, f: F) -> Result<T>
    where F: FnOnce(&Path) -> Result<T>
{
    if let Some(path) = path {
        f(&path)
    } else {
        let path = try!(directory());
        f(&path)
    }
}

pub fn profiles(path: &Path) -> Result<Box<Iterator<Item = Result<Profile>>>> {
    let files = try!(files(path));
    let iter = execute(files, num_cpus::get(), |entry| ReadProfileJob(entry));
    Ok(Box::new(iter))
}

pub fn valid_profiles(path: &Path) -> Result<Box<Iterator<Item = Profile>>> {
    Ok(Box::new(try!(profiles(path)).filter(Result::is_ok).map(|r| r.unwrap())))
}

pub struct SearchInfo {
    pub total: usize,
    pub profiles: Vec<Profile>,
}

pub fn search(path: &Path, s: &str) -> Result<SearchInfo> {
    let mut total = 0;
    let profiles = try!(valid_profiles(path))
                       .filter(|profile| {
                           total += 1;
                           profile.contains(s)
                       })
                       .collect();

    Ok(SearchInfo {
        total: total,
        profiles: profiles,
    })
}

pub fn remove(path: &Path, uuid: &str) -> Result<()> {
    for profile in try!(valid_profiles(path)).into_iter() {
        if profile.uuid == uuid {
            try!(std::fs::remove_file(&profile.path));
            return Ok(());
        }
    }
    return Err(Error::Own(format!("Profile '{}' is not found.", uuid)));
}

pub fn xml(path: &Path, uuid: &str) -> Result<String> {
    for profile in try!(valid_profiles(path)).into_iter() {
        if profile.uuid == uuid {
            let mut file = try!(File::open(&profile.path));
            let mut buf = Vec::new();
            try!(file.read_to_end(&mut buf));
            let data = try!(find_plist(&buf).ok_or(Error::Own("Couldn't parse file.".into())));
            return Ok(try!(String::from_utf8(data.to_owned())));
        }
    }
    return Err(Error::Own(format!("Profile '{}' is not found.", uuid)));
}

/// Returns instance of the `Profile` parsed from a file.
pub fn profile_from_file(path: &Path) -> Result<Profile> {
    let mut file = try!(File::open(path));
    let mut buf = Vec::new();
    try!(file.read_to_end(&mut buf));
    profile_from_data(&buf)
        .map(|mut p| {
            p.path = path.to_owned();
            p
        })
        .ok_or(Error::Own("Couldn't parse file.".into()))
}

/// Returns instance of the `Profile` parsed from a `data`.
pub fn profile_from_data(data: &[u8]) -> Option<Profile> {
    if let Some(data) = find_plist(data) {
        let mut profile = Profile::empty();
        let mut iter = plist::xml::EventReader::new(io::Cursor::new(data)).into_iter();
        while let Some(item) = iter.next() {
            if let Ok(StringValue(key)) = item {
                if key == "UUID" {
                    if let Some(Ok(StringValue(value))) = iter.next() {
                        profile.uuid = value;
                    }
                }
                if key == "Name" {
                    if let Some(Ok(StringValue(value))) = iter.next() {
                        profile.name = value;
                    }
                }
                if key == "application-identifier" {
                    if let Some(Ok(StringValue(value))) = iter.next() {
                        profile.app_identifier = value;
                    }
                }
                if key == "CreationDate" {
                    if let Some(Ok(DateValue(value))) = iter.next() {
                        profile.creation_date = value;
                    }
                }
                if key == "ExpirationDate" {
                    if let Some(Ok(DateValue(value))) = iter.next() {
                        profile.expiration_date = value;
                    }
                }
            }
        }
        Some(profile)
    } else {
        None
    }
}

/// Returns an index where the `needle` starts in the `data`.
fn find(data: &[u8], needle: &[u8]) -> Option<usize> {
    let needle_len = needle.len();
    for (i, _) in data.iter().enumerate() {
        if i + needle_len > data.len() {
            return None;
        }
        if &data[i..i + needle_len] == needle {
            return Some(i);
        }
    }
    None
}

/// Returns a plist content in a `data`.
fn find_plist(data: &[u8]) -> Option<&[u8]> {
    let prefix = b"<?xml version=";
    let suffix = b"</plist>";

    let start_i = find(data, prefix);
    let end_i = find(data, suffix).map(|i| i + suffix.len());

    if let (Some(start_i), Some(end_i)) = (start_i, end_i) {
        if end_i <= data.len() {
            return Some(&data[start_i..end_i]);
        }
    }

    None
}

    #[cfg(test)]
mod tests {
    use expectest::prelude::*;
    use tempdir::TempDir;
    use std::fs::File;
    use super::files;
    use super::find_plist;

    #[test]
    fn filter_mobileprovision_files() {
        let temp_dir = TempDir::new("test").unwrap();
        let result = files(temp_dir.path()).map(|iter| iter.count());
        expect!(result).to(be_ok().value(0));

        File::create(temp_dir.path().join("1.mobileprovision")).unwrap();
        File::create(temp_dir.path().join("2.mobileprovision")).unwrap();
        File::create(temp_dir.path().join("3.txt")).unwrap();
        let result = files(temp_dir.path()).map(|iter| iter.count());
        expect!(result).to(be_ok().value(2));
    }

    #[test]
    fn test_find_plist() {
        let data: &[u8] = b"<?xml version=</plist>";
        expect!(find_plist(&data)).to(be_some().value(data));

        let data: &[u8] = b"   <?xml version=</plist>   ";
        expect!(find_plist(&data)).to(be_some().value(b"<?xml version=</plist>"));
    }
}
<|endoftext|>


<commit_before>/*!
Rust bindings to the [sodium library](https://github.com/jedisct1/libsodium).

Sodium is a portable implementation of Dan Bernsteins [NaCl: Networking and
Cryptography library](http://nacl.cr.yp.to)

For most users, if you want public-key (asymmetric) cryptography you should use
the functions in `crypto::asymmetricbox` for encryption/decryption.

If you want secret-key (symmetric) cryptography you should be using the
functions in `crypto::secretbox` for encryption/decryption.

For public-key signatures you should use the functions in `crypto::sign` for
signature creation and verification.

Unless you know what you're doing you most certainly don't want to use the
functions in `crypto::scalarmult`, `crypto::stream`, `crypto::auth` and
`crypto::onetimeauth`.

## Thread Safety
All functions in this library are thread-safe provided that the `init()`
function has been called during program execution.

If `init()` hasn't been called then all functions except the random-number
generation functions and the key-generation functions are thread-safe.

# Public-key cryptography
 `crypto::asymmetricbox`

 `crypto::sign`

# Secret-key cryptography
 `crypto::secretbox`

 `crypto::stream`

 `crypto::auth`

 `crypto::onetimeauth`

# Low-level functions
 `crypto::hash`

 `crypto::verify`

 `crypto::shorthash`
 */
#![crate_name = "sodiumoxide"]
#![crate_type = "lib"]
#![warn(missing_docs)]
#![warn(non_upper_case_globals)]
#![warn(non_camel_case_types)]
#![warn(unused_qualifications)]
#![feature(macro_rules)]

extern crate "libsodium-sys" as ffi;
extern crate libc;

/**
 * `init()` initializes the sodium library and chooses faster versions of
 * the primitives if possible. `init()` also makes the random number generation
 * functions (`gen_key`, `gen_keypair`, `gen_nonce`, `randombytes`, `randombytes_into`)
 * thread-safe
 */
pub fn init() -> bool {
    unsafe {
        ffi::sodium_init() == 0
    }
}

mod utils;

pub mod randombytes;

/**
 * Cryptographic functions
 */
pub mod crypto {
    pub mod asymmetricbox;
    pub mod sign;
    pub mod scalarmult;
    pub mod auth;
    pub mod hash;
    pub mod secretbox;
    pub mod onetimeauth;
    pub mod stream;
    pub mod shorthash;
    pub mod verify;
}

<commit_msg>removed #![feature(macro_rules)]<commit_after>/*!
Rust bindings to the [sodium library](https://github.com/jedisct1/libsodium).

Sodium is a portable implementation of Dan Bernsteins [NaCl: Networking and
Cryptography library](http://nacl.cr.yp.to)

For most users, if you want public-key (asymmetric) cryptography you should use
the functions in `crypto::asymmetricbox` for encryption/decryption.

If you want secret-key (symmetric) cryptography you should be using the
functions in `crypto::secretbox` for encryption/decryption.

For public-key signatures you should use the functions in `crypto::sign` for
signature creation and verification.

Unless you know what you're doing you most certainly don't want to use the
functions in `crypto::scalarmult`, `crypto::stream`, `crypto::auth` and
`crypto::onetimeauth`.

## Thread Safety
All functions in this library are thread-safe provided that the `init()`
function has been called during program execution.

If `init()` hasn't been called then all functions except the random-number
generation functions and the key-generation functions are thread-safe.

# Public-key cryptography
 `crypto::asymmetricbox`

 `crypto::sign`

# Secret-key cryptography
 `crypto::secretbox`

 `crypto::stream`

 `crypto::auth`

 `crypto::onetimeauth`

# Low-level functions
 `crypto::hash`

 `crypto::verify`

 `crypto::shorthash`
 */
#![crate_name = "sodiumoxide"]
#![crate_type = "lib"]
#![warn(missing_docs)]
#![warn(non_upper_case_globals)]
#![warn(non_camel_case_types)]
#![warn(unused_qualifications)]

extern crate "libsodium-sys" as ffi;
extern crate libc;

/**
 * `init()` initializes the sodium library and chooses faster versions of
 * the primitives if possible. `init()` also makes the random number generation
 * functions (`gen_key`, `gen_keypair`, `gen_nonce`, `randombytes`, `randombytes_into`)
 * thread-safe
 */
pub fn init() -> bool {
    unsafe {
        ffi::sodium_init() == 0
    }
}

mod utils;

pub mod randombytes;

/**
 * Cryptographic functions
 */
pub mod crypto {
    pub mod asymmetricbox;
    pub mod sign;
    pub mod scalarmult;
    pub mod auth;
    pub mod hash;
    pub mod secretbox;
    pub mod onetimeauth;
    pub mod stream;
    pub mod shorthash;
    pub mod verify;
}

<|endoftext|>


<commit_before>#![allow(unstable)]

extern crate "libforestdb-sys" as ffi;

#[macro_use] extern crate log;

use std::default::Default;
use std::error;
use std::ffi::{CString, c_str_to_bytes};
use std::mem;
use std::ptr;

#[derive(Copy)]
pub struct Error {code: i32}

impl Error {
    pub fn from_code(code: i32) -> Error {
        Error {code: code}
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        "ForestDB error"
    }

    fn detail(&self) -> Option<String> {
        unsafe { String::from_utf8(c_str_to_bytes(&ffi::fdb_error_msg(self.code)).to_vec()).ok() }
    }
}

impl std::fmt::Show for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        f.write_str(&format!("fdb error: {:?}", (self as &error::Error).detail())[])
    }
}

pub type FdbResult<T> = Result<T, Error>;

macro_rules! lift_error {
    ($e: expr) => (lift_error!($e, ()));
    ($e: expr, $r: expr) => ({
        let t = $e;
        match t {
            ffi::FDB_RESULT_SUCCESS => Ok($r),
            _ => return Err(Error::from_code(t))
        }
    })
}

macro_rules! try_fdb {
    ($e: expr) => ({
        let t = $e;
        match t {
            ffi::FDB_RESULT_SUCCESS => (),
            _ => return Err(Error::from_code(t))
        }
    })
}

#[derive(Copy)]
pub struct Config {
    raw: ffi::fdb_config
}

impl Config {
}

impl Default for Config {
    fn default() -> Config {
        Config {
            raw: unsafe { ffi::fdb_get_default_config() }
        }
    }
}

pub fn init(config: Config) -> Result<(), Error> {
    lift_error!(unsafe {ffi::fdb_init(mem::transmute(&config.raw))})
}

pub fn shutdown() -> Result<(), Error> {
    lift_error!(unsafe {ffi::fdb_shutdown()})
}

pub struct FileHandle {
    path: Path,
    config: Config,
    raw: *mut ffi::fdb_file_handle,
}

impl FileHandle {
    fn from_raw(handle: *mut ffi::fdb_file_handle, path: &Path, config: Config) -> FileHandle {
        FileHandle {
            raw: handle,
            path: path.clone(),
            config: config
        }
    }

    pub fn open(path: &Path, config: Config) -> FdbResult<FileHandle> {
        let mut handle: *mut ffi::fdb_file_handle = ptr::null_mut();
        let c_path = CString::from_slice(path.as_vec());

        try_fdb!(unsafe { ffi::fdb_open(mem::transmute(&mut handle),
                                        c_path.as_ptr(),
                                        mem::transmute(&config.raw)) });
        let res = FileHandle::from_raw(handle, path, config);
        Ok(res)
    }
}

unsafe impl Send for FileHandle {}

// FIXME: do not use trait, implement clone as method
// which returns result? Otherwise it is impossible
// to handle cloning right
impl Clone for FileHandle {
    fn clone(&self) -> FileHandle {
        match FileHandle::open(&self.path, self.config) {
            Ok(res) => res,
            Err(_) => panic!("failed to clone")
        }
    }
}

impl Drop for FileHandle {
    fn drop(&mut self) {
        debug!("Dropping");
        unsafe { ffi::fdb_close(self.raw); }
    }
}

impl std::fmt::Show for FileHandle {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        f.write_str(&format!("FdbFileHandle {{path: {:?}}}", self.path)[])
    }
}

#[cfg(test)]
mod tests {
    use super::{FileHandle, Error};

    use std::default::Default;
    use std::error;
    use std::thread::Thread;

    use ffi;

    #[test]
    fn test_error_msg(){
        let err = Error::from_code(ffi::FDB_RESULT_OPEN_FAIL);
        assert_eq!("error opening file", (&err as &error::Error).detail().unwrap().as_slice());
    }

    #[test]
    fn test_init() {
        assert!(super::init(Default::default()).is_ok());
    }

    #[test]
    fn test_open_file() {
        assert!(super::init(Default::default()).is_ok());
        assert!(FileHandle::open(&Path::new("test1"), Default::default()).is_ok());
    }

    #[test]
    fn test_clone() {
        let fh1 = FileHandle::open(&Path::new("test2"), Default::default()).unwrap();
        let fh2 = fh1.clone();

        Thread::scoped(move || {
            let fh_cloned = fh2;
            // FIXME: test something useful
        }).join();
    }
}
<commit_msg>Initial stores<commit_after>#![allow(unstable)]

extern crate "libforestdb-sys" as ffi;

#[macro_use] extern crate log;

use std::default::Default;
use std::error;
use std::ffi::{CString, c_str_to_bytes};
use std::mem;
use std::ptr;

#[derive(Copy)]
pub struct Error {code: i32}

impl Error {
    pub fn from_code(code: i32) -> Error {
        Error {code: code}
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        "ForestDB error"
    }

    fn detail(&self) -> Option<String> {
        unsafe { String::from_utf8(c_str_to_bytes(&ffi::fdb_error_msg(self.code)).to_vec()).ok() }
    }
}

impl std::fmt::Show for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        f.write_str(&format!("fdb error: {:?}", (self as &error::Error).detail())[])
    }
}

pub type FdbResult<T> = Result<T, Error>;

macro_rules! lift_error {
    ($e: expr) => (lift_error!($e, ()));
    ($e: expr, $r: expr) => ({
        let t = $e;
        match t {
            ffi::FDB_RESULT_SUCCESS => Ok($r),
            _ => return Err(Error::from_code(t))
        }
    })
}

macro_rules! try_fdb {
    ($e: expr) => ({
        let t = $e;
        match t {
            ffi::FDB_RESULT_SUCCESS => (),
            _ => return Err(Error::from_code(t))
        }
    })
}

#[derive(Copy)]
pub struct Config {
    raw: ffi::fdb_config
}

impl Config {
}

impl Default for Config {
    fn default() -> Config {
        Config {
            raw: unsafe { ffi::fdb_get_default_config() }
        }
    }
}

pub fn init(config: Config) -> Result<(), Error> {
    lift_error!(unsafe {ffi::fdb_init(mem::transmute(&config.raw))})
}

pub fn shutdown() -> Result<(), Error> {
    lift_error!(unsafe {ffi::fdb_shutdown()})
}

pub struct FileHandle {
    path: Path,
    config: Config,
    raw: *mut ffi::fdb_file_handle,
}

impl FileHandle {
    fn from_raw(handle: *mut ffi::fdb_file_handle, path: &Path, config: Config) -> FileHandle {
        FileHandle {
            raw: handle,
            path: path.clone(),
            config: config
        }
    }

    pub fn open(path: &Path, config: Config) -> FdbResult<FileHandle> {
        let mut handle: *mut ffi::fdb_file_handle = ptr::null_mut();
        let c_path = CString::from_slice(path.as_vec());

        try_fdb!(unsafe { ffi::fdb_open(mem::transmute(&mut handle),
                                        c_path.as_ptr(),
                                        mem::transmute(&config.raw)) });
        let res = FileHandle::from_raw(handle, path, config);
        Ok(res)
    }

    pub fn get_default_store(&self, config: StoreConfig) -> FdbResult<Store> {
        self._get_store(None, config)
    }

    pub fn get_store(&self, name: &str, config: StoreConfig) -> FdbResult<Store> {
        let c_name = CString::from_slice(name.as_bytes());
        self._get_store(Some(c_name), config)
    }

    fn _get_store(&self, name: Option<CString>, config: StoreConfig) -> FdbResult<Store> {
        let mut handle: *mut ffi::fdb_kvs_handle = ptr::null_mut();
        try_fdb!(unsafe { ffi::fdb_kvs_open(self.raw,
                                            mem::transmute(&mut handle),
                                            if name.is_some() {name.unwrap().as_ptr()} else {ptr::null()},
                                            mem::transmute(&config.raw)
                                            )});
        Ok(Store::from_raw(handle, config))
    }
}

unsafe impl Send for FileHandle {}

// FIXME: do not use trait, implement clone as method
// which returns result? Otherwise it is impossible
// to handle cloning right
impl Clone for FileHandle {
    fn clone(&self) -> FileHandle {
        match FileHandle::open(&self.path, self.config) {
            Ok(res) => res,
            Err(_) => panic!("failed to clone")
        }
    }
}

impl Drop for FileHandle {
    fn drop(&mut self) {
        debug!("Dropping");
        unsafe { ffi::fdb_close(self.raw); }
    }
}

impl std::fmt::Show for FileHandle {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        f.write_str(&format!("FdbFileHandle {{path: {:?}}}", self.path)[])
    }
}

#[derive(Copy)]
pub struct StoreConfig {
    raw: ffi::fdb_kvs_config
}

impl Default for StoreConfig {
    fn default() -> StoreConfig {
        StoreConfig {
            raw: unsafe {ffi::fdb_get_default_kvs_config()}
        }
    }
}

pub struct Store {
    raw: *mut ffi::fdb_kvs_handle,
    config: StoreConfig
}

impl Store {
    fn from_raw(raw: *mut ffi::fdb_kvs_handle, config: StoreConfig) -> Store {
        Store {
            raw: raw,
            config: config
        }
    }
}

impl Drop for Store {
    fn drop(&mut self) {
        unsafe {ffi::fdb_kvs_close(self.raw); }
    }
}

#[cfg(test)]
mod tests {
    use super::{FileHandle, Error};

    use std::default::Default;
    use std::error;
    use std::thread::Thread;

    use ffi;

    #[test]
    fn test_error_msg(){
        let err = Error::from_code(ffi::FDB_RESULT_OPEN_FAIL);
        assert_eq!("error opening file", (&err as &error::Error).detail().unwrap().as_slice());
    }

    #[test]
    fn test_init() {
        assert!(super::init(Default::default()).is_ok());
    }

    #[test]
    fn test_open_file() {
        assert!(super::init(Default::default()).is_ok());
        assert!(FileHandle::open(&Path::new("test1"), Default::default()).is_ok());
    }

    #[test]
    fn test_clone() {
        let fh1 = FileHandle::open(&Path::new("test2"), Default::default()).unwrap();
        let fh2 = fh1.clone();

        Thread::scoped(move || {
            let fh_cloned = fh2;
            // FIXME: test something useful
        }).join();
    }

    #[test]
    fn test_open_store() {
        let db = FileHandle::open(&Path::new("test3"), Default::default()).unwrap();
        assert!(db.get_default_store(Default::default()).is_ok());
        assert!(db.get_store("hello", Default::default()).is_ok())
    }
}
<|endoftext|>


<commit_before>#![feature(collections)]

#[derive(Copy)]
pub enum Case {
    Upper,
    Lower
}

pub trait ChangeCase {
    fn to_uppercase<'a>(&'a self) -> String;
    fn to_lowercase<'a>(&'a self) -> String;
    fn to_capitalized<'a>(&'a self) -> String;
    fn to_invertedcase<'a>(&'a self) -> String;
    fn to_altcase<'a>(&'a self, start_with: Case) -> String;
}

impl<'a> ChangeCase for String {
    fn to_uppercase(&self) -> String {
        if self.is_empty() {
            return String::new();
        }

        let mut result = String::with_capacity(self.len());

        {
            for c in self.chars() {
                let upper = c.to_uppercase().next().unwrap();
                result.push(upper);
            }
        }

        result
    }

    fn to_lowercase(&self) -> String {
        if self.is_empty() {
            return String::new();
        }

        let mut result = String::with_capacity(self.len());

        {
            for c in self.chars() {
                let lower = c.to_lowercase().next().unwrap();
                result.push(lower);
            }
        }

        result
    }

    fn to_capitalized(&self) -> String {
        if self.is_empty() {
            return String::new();
        }

        let mut result = String::with_capacity(self.len());

        {
            let mut chars = self.chars();
            let first = chars.next().unwrap().to_uppercase().next().unwrap();
            result.push(first);

            for c in chars {
                let lower = c.to_lowercase().next().unwrap();
                result.push(lower);
            }
        }

        result
    }

    fn to_invertedcase(&self) -> String {
        if self.is_empty() {
            return String::new();
        }

        let mut result = String::with_capacity(self.len());

        {

            for c in self.chars() {
                if c.is_uppercase() {
                    let lower = c.to_lowercase().next().unwrap();
                    result.push(lower);
                } else if c.is_lowercase() {
                    let upper = c.to_uppercase().next().unwrap();
                    result.push(upper);
                } else {
                    result.push(c);
                }
            }
        }

        result
    }

    fn to_altcase(&self, start_with: Case) -> String {
        if self.is_empty() {
            return String::new();
        }

        let mut result = String::with_capacity(self.len());

        {
            let mut current_case = start_with;

            for c in self.chars() {
                if c.is_uppercase() || c.is_lowercase() {
                    match current_case {
                        Case::Upper => {
                            let upper = c.to_uppercase().next().unwrap();
                            result.push(upper);
                            current_case = Case::Lower;
                        },
                        Case::Lower => {
                            let lower = c.to_lowercase().next().unwrap();
                            result.push(lower);
                            current_case = Case::Upper;
                        }
                    };
                } else {
                    result.push(c);
                }
            }
        }

        result
    }
}

impl<'a> ChangeCase for &'a str {
    fn to_uppercase(&self) -> String {
        String::from_str(self).to_uppercase()
    }
    fn to_lowercase(&self) -> String {
        String::from_str(self).to_lowercase()
    }
    fn to_capitalized(&self) -> String {
        String::from_str(self).to_capitalized()
    }
    fn to_invertedcase(&self) -> String {
        String::from_str(self).to_invertedcase()
    }
    fn to_altcase(&self, start_with: Case) -> String {
        String::from_str(self).to_altcase(start_with)
    }
}

#[test]
fn upper() {
    assert_eq!(String::from_str("Something").to_uppercase(), "SOMETHING");
    assert_eq!(String::from_str("sOmEtHiNg").to_uppercase(), "SOMETHING");
    assert_eq!(String::from_str("word word2").to_uppercase(), "WORD WORD2");
}

#[test]
fn lower() {
    assert_eq!(String::from_str("SOMETHING").to_lowercase(), "something");
    assert_eq!(String::from_str("sOmEtHiNg").to_lowercase(), "something");
    assert_eq!(String::from_str("Word WORD2").to_lowercase(), "word word2");
}

#[test]
fn capitalize() {
    assert_eq!(String::from_str("SOMETHING").to_capitalized(), "Something");
    assert_eq!(String::from_str("sOmEtHiNg").to_capitalized(), "Something");
    assert_eq!(String::from_str("Word WORD2").to_capitalized(), "Word word2");
}

#[test]
fn swapped() {
    assert_eq!(String::from_str("SOMETHING").to_invertedcase(), "something");
    assert_eq!(String::from_str("SoMeThInG").to_invertedcase(), "sOmEtHiNg");
    assert_eq!(String::from_str("Some WorD2").to_invertedcase(), "sOME wORd2");
}

#[test]
fn alternating() {
    assert_eq!(String::from_str("SOMETHING").to_altcase(Case::Lower), "sOmEtHiNg");
    assert_eq!(String::from_str("SOMETHING").to_altcase(Case::Upper), "SoMeThInG");
    assert_eq!(String::from_str("som3thing").to_altcase(Case::Lower), "sOm3ThInG");
    assert_eq!(String::from_str("som3thing").to_altcase(Case::Upper), "SoM3tHiNg");
    assert_eq!(String::from_str("some word").to_altcase(Case::Lower), "sOmE wOrD");
}

#[test]
fn str_lower() {
    assert_eq!("SOMETHING".to_lowercase(), "something");
    assert_eq!("sOmEtHiNg".to_lowercase(), "something");
    assert_eq!("Word WORD2".to_lowercase(), "word word2");
}

#[test]
fn str_capitalize() {
    assert_eq!("SOMETHING".to_capitalized(), "Something");
    assert_eq!("sOmEtHiNg".to_capitalized(), "Something");
    assert_eq!("Word WORD2".to_capitalized(), "Word word2");
}

#[test]
fn str_swapped() {
    assert_eq!("SOMETHING".to_invertedcase(), "something");
    assert_eq!("SoMeThInG".to_invertedcase(), "sOmEtHiNg");
    assert_eq!("Some WorD2".to_invertedcase(), "sOME wORd2");
}

#[test]
fn str_alternating() {
    assert_eq!("SOMETHING".to_altcase(Case::Lower), "sOmEtHiNg");
    assert_eq!("SOMETHING".to_altcase(Case::Upper), "SoMeThInG");
    assert_eq!("som3thing".to_altcase(Case::Lower), "sOm3ThInG");
    assert_eq!("som3thing".to_altcase(Case::Upper), "SoM3tHiNg");
    assert_eq!("some word".to_altcase(Case::Lower), "sOmE wOrD");
}
<commit_msg>Derive Clone trait for Case<commit_after>#![feature(collections)]

#[derive(Copy, Clone)]
pub enum Case {
    Upper,
    Lower
}

pub trait ChangeCase {
    fn to_uppercase<'a>(&'a self) -> String;
    fn to_lowercase<'a>(&'a self) -> String;
    fn to_capitalized<'a>(&'a self) -> String;
    fn to_invertedcase<'a>(&'a self) -> String;
    fn to_altcase<'a>(&'a self, start_with: Case) -> String;
}

impl<'a> ChangeCase for String {
    fn to_uppercase(&self) -> String {
        if self.is_empty() {
            return String::new();
        }

        let mut result = String::with_capacity(self.len());

        {
            for c in self.chars() {
                let upper = c.to_uppercase().next().unwrap();
                result.push(upper);
            }
        }

        result
    }

    fn to_lowercase(&self) -> String {
        if self.is_empty() {
            return String::new();
        }

        let mut result = String::with_capacity(self.len());

        {
            for c in self.chars() {
                let lower = c.to_lowercase().next().unwrap();
                result.push(lower);
            }
        }

        result
    }

    fn to_capitalized(&self) -> String {
        if self.is_empty() {
            return String::new();
        }

        let mut result = String::with_capacity(self.len());

        {
            let mut chars = self.chars();
            let first = chars.next().unwrap().to_uppercase().next().unwrap();
            result.push(first);

            for c in chars {
                let lower = c.to_lowercase().next().unwrap();
                result.push(lower);
            }
        }

        result
    }

    fn to_invertedcase(&self) -> String {
        if self.is_empty() {
            return String::new();
        }

        let mut result = String::with_capacity(self.len());

        {

            for c in self.chars() {
                if c.is_uppercase() {
                    let lower = c.to_lowercase().next().unwrap();
                    result.push(lower);
                } else if c.is_lowercase() {
                    let upper = c.to_uppercase().next().unwrap();
                    result.push(upper);
                } else {
                    result.push(c);
                }
            }
        }

        result
    }

    fn to_altcase(&self, start_with: Case) -> String {
        if self.is_empty() {
            return String::new();
        }

        let mut result = String::with_capacity(self.len());

        {
            let mut current_case = start_with;

            for c in self.chars() {
                if c.is_uppercase() || c.is_lowercase() {
                    match current_case {
                        Case::Upper => {
                            let upper = c.to_uppercase().next().unwrap();
                            result.push(upper);
                            current_case = Case::Lower;
                        },
                        Case::Lower => {
                            let lower = c.to_lowercase().next().unwrap();
                            result.push(lower);
                            current_case = Case::Upper;
                        }
                    };
                } else {
                    result.push(c);
                }
            }
        }

        result
    }
}

impl<'a> ChangeCase for &'a str {
    fn to_uppercase(&self) -> String {
        String::from_str(self).to_uppercase()
    }
    fn to_lowercase(&self) -> String {
        String::from_str(self).to_lowercase()
    }
    fn to_capitalized(&self) -> String {
        String::from_str(self).to_capitalized()
    }
    fn to_invertedcase(&self) -> String {
        String::from_str(self).to_invertedcase()
    }
    fn to_altcase(&self, start_with: Case) -> String {
        String::from_str(self).to_altcase(start_with)
    }
}

#[test]
fn upper() {
    assert_eq!(String::from_str("Something").to_uppercase(), "SOMETHING");
    assert_eq!(String::from_str("sOmEtHiNg").to_uppercase(), "SOMETHING");
    assert_eq!(String::from_str("word word2").to_uppercase(), "WORD WORD2");
}

#[test]
fn lower() {
    assert_eq!(String::from_str("SOMETHING").to_lowercase(), "something");
    assert_eq!(String::from_str("sOmEtHiNg").to_lowercase(), "something");
    assert_eq!(String::from_str("Word WORD2").to_lowercase(), "word word2");
}

#[test]
fn capitalize() {
    assert_eq!(String::from_str("SOMETHING").to_capitalized(), "Something");
    assert_eq!(String::from_str("sOmEtHiNg").to_capitalized(), "Something");
    assert_eq!(String::from_str("Word WORD2").to_capitalized(), "Word word2");
}

#[test]
fn swapped() {
    assert_eq!(String::from_str("SOMETHING").to_invertedcase(), "something");
    assert_eq!(String::from_str("SoMeThInG").to_invertedcase(), "sOmEtHiNg");
    assert_eq!(String::from_str("Some WorD2").to_invertedcase(), "sOME wORd2");
}

#[test]
fn alternating() {
    assert_eq!(String::from_str("SOMETHING").to_altcase(Case::Lower), "sOmEtHiNg");
    assert_eq!(String::from_str("SOMETHING").to_altcase(Case::Upper), "SoMeThInG");
    assert_eq!(String::from_str("som3thing").to_altcase(Case::Lower), "sOm3ThInG");
    assert_eq!(String::from_str("som3thing").to_altcase(Case::Upper), "SoM3tHiNg");
    assert_eq!(String::from_str("some word").to_altcase(Case::Lower), "sOmE wOrD");
}

#[test]
fn str_lower() {
    assert_eq!("SOMETHING".to_lowercase(), "something");
    assert_eq!("sOmEtHiNg".to_lowercase(), "something");
    assert_eq!("Word WORD2".to_lowercase(), "word word2");
}

#[test]
fn str_capitalize() {
    assert_eq!("SOMETHING".to_capitalized(), "Something");
    assert_eq!("sOmEtHiNg".to_capitalized(), "Something");
    assert_eq!("Word WORD2".to_capitalized(), "Word word2");
}

#[test]
fn str_swapped() {
    assert_eq!("SOMETHING".to_invertedcase(), "something");
    assert_eq!("SoMeThInG".to_invertedcase(), "sOmEtHiNg");
    assert_eq!("Some WorD2".to_invertedcase(), "sOME wORd2");
}

#[test]
fn str_alternating() {
    assert_eq!("SOMETHING".to_altcase(Case::Lower), "sOmEtHiNg");
    assert_eq!("SOMETHING".to_altcase(Case::Upper), "SoMeThInG");
    assert_eq!("som3thing".to_altcase(Case::Lower), "sOm3ThInG");
    assert_eq!("som3thing".to_altcase(Case::Upper), "SoM3tHiNg");
    assert_eq!("some word".to_altcase(Case::Lower), "sOmE wOrD");
}
<|endoftext|>


<commit_before>#![feature(conservative_impl_trait)]

use std::fmt;

macro_rules! assert_that {
    ( $actual: expr, $matcher: expr ) => {
        match $matcher.check(&$actual) {
            MatchResult::Match => { },
            MatchResult::FailWithReason{matcher, reason} => {
                panic!("\nFailed assertion of matcher: {}\n  {}\n", matcher, reason)
            },
            MatchResult::FailWithComparison{matcher, expected, actual} => {
                panic!("\nFailed assertion of matcher {}\n  Expected: {}\n  Got: {}\n", matcher, expected, actual);
            }
        }
    }
}

pub trait Matcher<T> {
    fn check(&mut self, actual: &T) -> MatchResult;
}

impl<T, F> Matcher<T> for F
where F: FnMut(&T) -> MatchResult {
    fn check(&mut self, actual: &T) -> MatchResult {
        self(actual)
    }
}

pub enum MatchResult {
    Matched {
        name: String
    },
    Failed {
        name: String,
        reason: String
    }
}

pub fn format_fail_reason(reason: &str) -> String {
    format!("  Because: {}", reason)
}

pub fn format_fail_comparison<T>(actual: T, expected: T) -> String
where T: fmt::Debug {
    format!("  Expected: {:?}\n  Got: {:?}", expected, actual)
}

pub mod matchers;
<commit_msg>fix expansion of assert_that! matcher check add assert_that!(..., panics) to assert panic behaviour add assert_that!(..., does not panic) to assert non-panicking behaviour<commit_after>#![feature(conservative_impl_trait)]

use std::fmt;

#[macro_export]
macro_rules! assert_that {
    ( $actual: expr, panics ) => {
        let result = std::panic::catch_unwind(|| { $actual; });
        if result.is_ok() {
            panic!("\nFailed assertion; expected expression to panic")
        }
    };
    ( $actual: expr, does not panic ) => {
        let result = std::panic::catch_unwind(|| { $actual; });
        if result.is_err() {
            panic!("\nFailed assertion; expected expression to panic")
        }
    };
    ( $actual: expr, $matcher: expr ) => {
        match $matcher.check(&$actual) {
            MatchResult::Matched { .. } => { },
            MatchResult::Failed { name, reason } => {
                panic!("\nFailed assertion of matcher: {}\n{}", name, reason)
            }
        }
    };
}

pub trait Matcher<T> {
    fn check(&mut self, actual: &T) -> MatchResult;
}

impl<T, F> Matcher<T> for F
where F: FnMut(&T) -> MatchResult {
    fn check(&mut self, actual: &T) -> MatchResult {
        self(actual)
    }
}

pub enum MatchResult {
    Matched {
        name: String
    },
    Failed {
        name: String,
        reason: String
    }
}

pub fn format_fail_reason(reason: &str) -> String {
    format!("  Because: {}", reason)
}

pub fn format_fail_comparison<T>(actual: T, expected: T) -> String
where T: fmt::Debug {
    format!("  Expected: {:?}\n  Got: {:?}", expected, actual)
}

pub mod matchers;
<|endoftext|>


<commit_before>//! # Example
//!
//! ```rust
//! # extern crate env_logger;
//! # extern crate embed_lang;
//!
//! use embed_lang::{new_vm, run_expr};
//!
//! # fn main() {
//! # let _ = ::env_logger::init();
//!
//! let text = r#"
//! // `type` is used to declare a new type.
//! // In this case we declare `Eq` to be a record with a single field (`==`) which is a function
//! // which takes two arguments of the same type and returns a boolean
//! type Eq a = { (==) : a -> a -> Bool }
//! in
//! // `let` declares new variables.
//! let id x = x
//! and factorial n =
//!         if n < 2
//!         then 1
//!         else n * factorial (n - 1)
//! in
//! let list_module =
//!         // Declare a new type which only exists in the current scope
//!         type List a = | Cons a (List a) | Nil
//!         in
//!         let map f xs =
//!                 case xs of
//!                     | Cons y ys -> Cons (f y) (map f ys)
//!                     | Nil -> Nil
//!         in
//!         let eq eq_a: Eq a -> Eq (List a) =
//!                 let { (==) } = eq_a in
//!                 let (===) l r =
//!                         case l of
//!                             | Cons la lxs ->
//!                                 (case r of
//!                                     | Cons ra rxs -> la == ra && lxs === rxs
//!                                     | Nil -> False)
//!                             | Nil ->
//!                                 (case r of
//!                                     | Cons _ _ -> False
//!                                     | Nil -> True)
//!                 in { (==) = (===) }
//!         in {
//!             // Since `List` is local we export it so its constructors can be used
//!             // outside the current scope
//!             List,
//!             eq,
//!             map
//!         }
//! in
//! // Bring the `List` type and its constructors into scope
//! let { List, eq = list_Eq } = list_module
//! // Create `==` for `List Int`
//! and { (==) }: Eq (List Int) = list_Eq { (==) }
//! in
//! if Cons 1 Nil == Nil then
//!     error "This branch is not executed"
//! else
//!     io.print "Hello world!"
//! "#;
//!
//! let vm = new_vm();
//! match run_expr(&vm, "example", text) {
//!     Ok(value) => {
//!         println!("{:?}", value);
//!     }
//!     Err(err) => {
//!         panic!("{}", err);
//!     }
//! }
//! return;
//!
//! # }
//! ```

#[macro_use]
extern crate log;
extern crate env_logger;
#[macro_use]
extern crate quick_error;
#[macro_use]
extern crate vm as vm_mod;

mod io;
mod crates {
    extern crate base;
    extern crate parser;
    extern crate check;
}

pub use crates::base;
pub use crates::parser;
pub use crates::check;
pub use vm_mod as vm;

pub mod import;

pub use vm::vm::VM;

use base::ast;
use base::types::TcType;
use base::symbol::{Name, NameBuf, Symbol};
use std::result::Result as StdResult;
use std::string::String as StdString;
use std::error::Error as StdError;
use vm::vm::{ClosureDataDef, RootedValue};
use vm::compiler::CompiledFunction;

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        Parse(err: ::parser::Error) {
            description(err.description())
            display("{}", err)
            from()
        }
        Typecheck(err: ::base::error::InFile<::check::typecheck::TypeError<StdString>>) {
            description(err.description())
            display("{}", err)
            from()
        }
        IO(err: ::std::io::Error) {
            description(err.description())
            display("{}", err)
            from()
        }
        VM(err: ::vm::vm::Error) {
            description(err.description())
            display("{}", err)
            from()
        }
        Macro(err: ::base::error::Errors<::base::macros::Error>) {
            description(err.description())
            display("{}", err)
            from()
        }
    }
}

pub type Result<T> = StdResult<T, Error>;

fn include_implicit_prelude(vm: &VM, name: &str, expr: &mut ast::LExpr<ast::TcIdent<Symbol>>) {
    use std::mem;
    if name == "std.prelude" {
        return;
    }

    let prelude_import = r#"
let __implicit_prelude = import "std/prelude.hs"
and { Num, Eq, Ord, Show, Functor, Monad, Option, Result, not } = __implicit_prelude
in
let { (+), (-), (*), (/) } = __implicit_prelude.num_Int
and { (==) } = __implicit_prelude.eq_Int
and { (<), (<=), (=>), (>) } = __implicit_prelude.make_Ord __implicit_prelude.ord_Int
in
let { (+), (-), (*), (/) } = __implicit_prelude.num_Float
and { (==) } = __implicit_prelude.eq_Float
and { (<), (<=), (=>), (>) } = __implicit_prelude.make_Ord __implicit_prelude.ord_Float
in 0
"#;
    let prelude_expr = parse_expr(vm, "", prelude_import).unwrap();
    let original_expr = mem::replace(expr, prelude_expr);
    fn assign_last_body(l: &mut ast::LExpr<ast::TcIdent<Symbol>>,
                        original_expr: ast::LExpr<ast::TcIdent<Symbol>>) {
        match l.value {
            ast::Expr::Let(_, ref mut e) => {
                assign_last_body(e, original_expr);
            }
            _ => *l = original_expr,
        }
    }
    assign_last_body(expr, original_expr);
}

fn compile_script(vm: &VM,
                  filename: &str,
                  expr: &ast::LExpr<ast::TcIdent<Symbol>>)
                  -> CompiledFunction {
    use base::symbol::SymbolModule;
    use vm::compiler::Compiler;
    debug!("Compile `{}`", filename);
    let mut function = {
        let env = vm.env();
        let mut interner = vm.interner.borrow_mut();
        let mut gc = vm.gc.borrow_mut();
        let mut symbols = vm.get_mut_symbols();
        let name = Name::new(filename);
        let name = NameBuf::from(name.module());
        let symbols = SymbolModule::new(StdString::from(name.as_ref()), &mut symbols);
        let mut compiler = Compiler::new(&env, &mut interner, &mut gc, symbols);
        compiler.compile_expr(&expr)
    };
    function.id = vm.symbol(filename);
    function
}

/// Compiles `input` and if it is successful runs the resulting code and stores the resulting value
/// in the global variable named by running `filename_to_module` on `filename`.
///
/// If at any point the function fails the resulting error is returned and nothing is added to the
/// VM.
pub fn load_script(vm: &VM, filename: &str, input: &str) -> Result<()> {
    load_script2(vm, filename, input, true)
}

pub fn load_script2(vm: &VM, filename: &str, input: &str, implicit_prelude: bool) -> Result<()> {
    let (expr, typ) = try!(typecheck_expr(vm, filename, input, implicit_prelude));
    let function = compile_script(vm, filename, &expr);
    let function = vm.new_function(function);
    let closure = {
        let stack = vm.current_frame();
        vm.alloc(&stack.stack, ClosureDataDef(function, &[]))
    };
    let value = try!(vm.call_module(&typ, closure));
    try!(vm.set_global(function.name, typ, value));
    Ok(())
}

pub fn filename_to_module(filename: &str) -> StdString {
    use std::path::Path;
    let path = Path::new(filename);
    let name = path.extension()
                   .map(|ext| {
                       ext.to_str()
                          .map(|ext| &filename[..filename.len() - ext.len() - 1])
                          .unwrap_or(filename)
                   })
                   .expect("filename");

    name.replace("/", ".")
}

/// Loads `filename` and compiles and runs its input by calling `load_script`
pub fn load_file(vm: &VM, filename: &str) -> Result<()> {
    use std::fs::File;
    use std::io::Read;
    let mut file = try!(File::open(filename));
    let mut buffer = ::std::string::String::new();
    try!(file.read_to_string(&mut buffer));
    drop(file);
    let name = filename_to_module(filename);
    load_script(vm, &name, &buffer)
}

pub fn parse_expr(vm: &VM,
                  file: &str,
                  input: &str)
                  -> StdResult<ast::LExpr<ast::TcIdent<Symbol>>, ::parser::Error> {
    use base::symbol::SymbolModule;
    let mut symbols = vm.get_mut_symbols();
    Ok(try!(::parser::parse_tc(&mut SymbolModule::new(file.into(), &mut symbols), input)))
}

pub fn typecheck_expr<'a>(vm: &VM<'a>,
                          file: &str,
                          expr_str: &str,
                          implicit_prelude: bool)
                          -> Result<(ast::LExpr<ast::TcIdent<Symbol>>, TcType)> {
    use check::typecheck::Typecheck;
    use base::error;
    let mut expr = try!(parse_expr(vm, file, expr_str));
    if implicit_prelude {
        include_implicit_prelude(vm, file, &mut expr);
    }
    try!(vm.get_macros().run(vm, &mut expr));
    let env = vm.env();
    let mut symbols = vm.get_mut_symbols();
    let mut tc = Typecheck::new(file.into(), &mut symbols, &env);
    let typ = try!(tc.typecheck_expr(&mut expr)
                     .map_err(|err| error::InFile::new(StdString::from(file), expr_str, err)));
    Ok((expr, typ))
}

/// Compiles and runs the expression in `expr_str`. If successful the value from running the
/// expression is returned
pub fn run_expr<'a, 'vm>(vm: &'vm VM<'a>,
                         name: &str,
                         expr_str: &str)
                         -> Result<RootedValue<'a, 'vm>> {
    run_expr2(vm, name, expr_str, true)
}

pub fn run_expr2<'a, 'vm>(vm: &'vm VM<'a>,
                      name: &str,
                      expr_str: &str,
                      implicit_prelude: bool)
                      -> Result<RootedValue<'a, 'vm>> {
    let (expr, typ) = try!(typecheck_expr(vm, name, expr_str, implicit_prelude));
    let mut function = compile_script(vm, name, &expr);
    function.id = vm.symbol(name);
    let function = vm.new_function(function);
    let closure = {
        let stack = vm.current_frame();
        vm.alloc(&stack.stack, ClosureDataDef(function, &[]))
    };
    let value = try!(vm.call_module(&typ, closure));
    Ok(vm.root_value(value))
}

pub fn new_vm<'a>() -> VM<'a> {
    let vm = VM::new();
    vm.get_macros().insert(vm.symbol("import"), ::import::Import::new());
    ::vm::primitives::load(&vm).expect("Loaded primitives library");
    ::io::load(&vm).expect("Loaded IO library");
    vm
}
<commit_msg>docs: Add a doc comment to new_vm<commit_after>//! # Example
//!
//! ```rust
//! # extern crate env_logger;
//! # extern crate embed_lang;
//!
//! use embed_lang::{new_vm, run_expr};
//!
//! # fn main() {
//! # let _ = ::env_logger::init();
//!
//! let text = r#"
//! // `type` is used to declare a new type.
//! // In this case we declare `Eq` to be a record with a single field (`==`) which is a function
//! // which takes two arguments of the same type and returns a boolean
//! type Eq a = { (==) : a -> a -> Bool }
//! in
//! // `let` declares new variables.
//! let id x = x
//! and factorial n =
//!         if n < 2
//!         then 1
//!         else n * factorial (n - 1)
//! in
//! let list_module =
//!         // Declare a new type which only exists in the current scope
//!         type List a = | Cons a (List a) | Nil
//!         in
//!         let map f xs =
//!                 case xs of
//!                     | Cons y ys -> Cons (f y) (map f ys)
//!                     | Nil -> Nil
//!         in
//!         let eq eq_a: Eq a -> Eq (List a) =
//!                 let { (==) } = eq_a in
//!                 let (===) l r =
//!                         case l of
//!                             | Cons la lxs ->
//!                                 (case r of
//!                                     | Cons ra rxs -> la == ra && lxs === rxs
//!                                     | Nil -> False)
//!                             | Nil ->
//!                                 (case r of
//!                                     | Cons _ _ -> False
//!                                     | Nil -> True)
//!                 in { (==) = (===) }
//!         in {
//!             // Since `List` is local we export it so its constructors can be used
//!             // outside the current scope
//!             List,
//!             eq,
//!             map
//!         }
//! in
//! // Bring the `List` type and its constructors into scope
//! let { List, eq = list_Eq } = list_module
//! // Create `==` for `List Int`
//! and { (==) }: Eq (List Int) = list_Eq { (==) }
//! in
//! if Cons 1 Nil == Nil then
//!     error "This branch is not executed"
//! else
//!     io.print "Hello world!"
//! "#;
//!
//! let vm = new_vm();
//! match run_expr(&vm, "example", text) {
//!     Ok(value) => {
//!         println!("{:?}", value);
//!     }
//!     Err(err) => {
//!         panic!("{}", err);
//!     }
//! }
//! return;
//!
//! # }
//! ```

#[macro_use]
extern crate log;
extern crate env_logger;
#[macro_use]
extern crate quick_error;
#[macro_use]
extern crate vm as vm_mod;

mod io;
mod crates {
    extern crate base;
    extern crate parser;
    extern crate check;
}

pub use crates::base;
pub use crates::parser;
pub use crates::check;
pub use vm_mod as vm;

pub mod import;

pub use vm::vm::VM;

use base::ast;
use base::types::TcType;
use base::symbol::{Name, NameBuf, Symbol};
use std::result::Result as StdResult;
use std::string::String as StdString;
use std::error::Error as StdError;
use vm::vm::{ClosureDataDef, RootedValue};
use vm::compiler::CompiledFunction;

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        Parse(err: ::parser::Error) {
            description(err.description())
            display("{}", err)
            from()
        }
        Typecheck(err: ::base::error::InFile<::check::typecheck::TypeError<StdString>>) {
            description(err.description())
            display("{}", err)
            from()
        }
        IO(err: ::std::io::Error) {
            description(err.description())
            display("{}", err)
            from()
        }
        VM(err: ::vm::vm::Error) {
            description(err.description())
            display("{}", err)
            from()
        }
        Macro(err: ::base::error::Errors<::base::macros::Error>) {
            description(err.description())
            display("{}", err)
            from()
        }
    }
}

pub type Result<T> = StdResult<T, Error>;

fn include_implicit_prelude(vm: &VM, name: &str, expr: &mut ast::LExpr<ast::TcIdent<Symbol>>) {
    use std::mem;
    if name == "std.prelude" {
        return;
    }

    let prelude_import = r#"
let __implicit_prelude = import "std/prelude.hs"
and { Num, Eq, Ord, Show, Functor, Monad, Option, Result, not } = __implicit_prelude
in
let { (+), (-), (*), (/) } = __implicit_prelude.num_Int
and { (==) } = __implicit_prelude.eq_Int
and { (<), (<=), (=>), (>) } = __implicit_prelude.make_Ord __implicit_prelude.ord_Int
in
let { (+), (-), (*), (/) } = __implicit_prelude.num_Float
and { (==) } = __implicit_prelude.eq_Float
and { (<), (<=), (=>), (>) } = __implicit_prelude.make_Ord __implicit_prelude.ord_Float
in 0
"#;
    let prelude_expr = parse_expr(vm, "", prelude_import).unwrap();
    let original_expr = mem::replace(expr, prelude_expr);
    fn assign_last_body(l: &mut ast::LExpr<ast::TcIdent<Symbol>>,
                        original_expr: ast::LExpr<ast::TcIdent<Symbol>>) {
        match l.value {
            ast::Expr::Let(_, ref mut e) => {
                assign_last_body(e, original_expr);
            }
            _ => *l = original_expr,
        }
    }
    assign_last_body(expr, original_expr);
}

fn compile_script(vm: &VM,
                  filename: &str,
                  expr: &ast::LExpr<ast::TcIdent<Symbol>>)
                  -> CompiledFunction {
    use base::symbol::SymbolModule;
    use vm::compiler::Compiler;
    debug!("Compile `{}`", filename);
    let mut function = {
        let env = vm.env();
        let mut interner = vm.interner.borrow_mut();
        let mut gc = vm.gc.borrow_mut();
        let mut symbols = vm.get_mut_symbols();
        let name = Name::new(filename);
        let name = NameBuf::from(name.module());
        let symbols = SymbolModule::new(StdString::from(name.as_ref()), &mut symbols);
        let mut compiler = Compiler::new(&env, &mut interner, &mut gc, symbols);
        compiler.compile_expr(&expr)
    };
    function.id = vm.symbol(filename);
    function
}

/// Compiles `input` and if it is successful runs the resulting code and stores the resulting value
/// in the global variable named by running `filename_to_module` on `filename`.
///
/// If at any point the function fails the resulting error is returned and nothing is added to the
/// VM.
pub fn load_script(vm: &VM, filename: &str, input: &str) -> Result<()> {
    load_script2(vm, filename, input, true)
}

pub fn load_script2(vm: &VM, filename: &str, input: &str, implicit_prelude: bool) -> Result<()> {
    let (expr, typ) = try!(typecheck_expr(vm, filename, input, implicit_prelude));
    let function = compile_script(vm, filename, &expr);
    let function = vm.new_function(function);
    let closure = {
        let stack = vm.current_frame();
        vm.alloc(&stack.stack, ClosureDataDef(function, &[]))
    };
    let value = try!(vm.call_module(&typ, closure));
    try!(vm.set_global(function.name, typ, value));
    Ok(())
}

pub fn filename_to_module(filename: &str) -> StdString {
    use std::path::Path;
    let path = Path::new(filename);
    let name = path.extension()
                   .map(|ext| {
                       ext.to_str()
                          .map(|ext| &filename[..filename.len() - ext.len() - 1])
                          .unwrap_or(filename)
                   })
                   .expect("filename");

    name.replace("/", ".")
}

/// Loads `filename` and compiles and runs its input by calling `load_script`
pub fn load_file(vm: &VM, filename: &str) -> Result<()> {
    use std::fs::File;
    use std::io::Read;
    let mut file = try!(File::open(filename));
    let mut buffer = ::std::string::String::new();
    try!(file.read_to_string(&mut buffer));
    drop(file);
    let name = filename_to_module(filename);
    load_script(vm, &name, &buffer)
}

pub fn parse_expr(vm: &VM,
                  file: &str,
                  input: &str)
                  -> StdResult<ast::LExpr<ast::TcIdent<Symbol>>, ::parser::Error> {
    use base::symbol::SymbolModule;
    let mut symbols = vm.get_mut_symbols();
    Ok(try!(::parser::parse_tc(&mut SymbolModule::new(file.into(), &mut symbols), input)))
}

pub fn typecheck_expr<'a>(vm: &VM<'a>,
                          file: &str,
                          expr_str: &str,
                          implicit_prelude: bool)
                          -> Result<(ast::LExpr<ast::TcIdent<Symbol>>, TcType)> {
    use check::typecheck::Typecheck;
    use base::error;
    let mut expr = try!(parse_expr(vm, file, expr_str));
    if implicit_prelude {
        include_implicit_prelude(vm, file, &mut expr);
    }
    try!(vm.get_macros().run(vm, &mut expr));
    let env = vm.env();
    let mut symbols = vm.get_mut_symbols();
    let mut tc = Typecheck::new(file.into(), &mut symbols, &env);
    let typ = try!(tc.typecheck_expr(&mut expr)
                     .map_err(|err| error::InFile::new(StdString::from(file), expr_str, err)));
    Ok((expr, typ))
}

/// Compiles and runs the expression in `expr_str`. If successful the value from running the
/// expression is returned
pub fn run_expr<'a, 'vm>(vm: &'vm VM<'a>,
                         name: &str,
                         expr_str: &str)
                         -> Result<RootedValue<'a, 'vm>> {
    run_expr2(vm, name, expr_str, true)
}

pub fn run_expr2<'a, 'vm>(vm: &'vm VM<'a>,
                      name: &str,
                      expr_str: &str,
                      implicit_prelude: bool)
                      -> Result<RootedValue<'a, 'vm>> {
    let (expr, typ) = try!(typecheck_expr(vm, name, expr_str, implicit_prelude));
    let mut function = compile_script(vm, name, &expr);
    function.id = vm.symbol(name);
    let function = vm.new_function(function);
    let closure = {
        let stack = vm.current_frame();
        vm.alloc(&stack.stack, ClosureDataDef(function, &[]))
    };
    let value = try!(vm.call_module(&typ, closure));
    Ok(vm.root_value(value))
}

/// Creates a new virtual machine with support for importing other modules and with all primitives
/// loaded.
pub fn new_vm<'a>() -> VM<'a> {
    let vm = VM::new();
    vm.get_macros().insert(vm.symbol("import"), ::import::Import::new());
    ::vm::primitives::load(&vm).expect("Loaded primitives library");
    ::io::load(&vm).expect("Loaded IO library");
    vm
}
<|endoftext|>


<commit_before>
pub fn puzzle(input: &str) -> u32 {
    let mut num_triangles = 0;

    // Deciding to stream rather than collect and use slice chunk
    let mut lines = input.lines().peekable();

    while lines.peek().is_some() {
        // Kinda... not great
        let chunk = [
            lines.next().expect("No first line"),
            lines.next().expect("No second line"),
            lines.next().expect("No third line"),
        ];

        let chunk: Vec<Vec<u32>> = chunk.iter().map(|line| {
            line.split_whitespace().map(|dim| {
                dim.parse::<u32>().expect("Could not parse!")
            }).collect()
        }).collect();

        for i in 0..2 {
            let dims: Vec<u32> = chunk.iter().map(|v| v[i] ).collect();
            println!("dimensions are: {}, {}, {}", dims[0], dims[1], dims[2]);

            if is_a_triangle(dims[0], dims[1], dims[2]) {
                num_triangles += 1;
            }
        }
    }

    num_triangles
}

pub fn is_a_triangle(a: u32, b: u32, c: u32) -> bool {
    a + b > c && b + c > a && c + a > b
}

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

    #[test]
    fn equilateral_triangle() {
        assert!(is_a_triangle(3, 3, 3));
    }

    #[test]
    fn isoceles_triangle() {
        assert!(is_a_triangle(13, 13, 3));
    }

    #[test]
    fn acute_triangle() { // so cute
        assert!(is_a_triangle(208, 203, 145));
    }

    #[test]
    fn obtuse_triangle() {
        assert!(is_a_triangle(244, 360, 159));
    }

    #[test]
    fn not_a_triangle() {
        assert!( ! is_a_triangle(5, 10, 25) );
        assert!( ! is_a_triangle(5, 25, 10) );
        assert!( ! is_a_triangle(10, 5, 25) );
        assert!( ! is_a_triangle(10, 25, 5) );
        assert!( ! is_a_triangle(25, 5, 10) );
        assert!( ! is_a_triangle(25, 10, 5) );
    }

    #[test]
    fn whole_puzzle() {
        let input = "\
  785  516  744
  272  511  358
    1  791  600
";
        assert_eq!(puzzle(input), 2);
    }
}
<commit_msg>Fix the off by one error<commit_after>
pub fn puzzle(input: &str) -> u32 {
    let mut num_triangles = 0;

    // Deciding to stream rather than collect and use slice chunk
    let mut lines = input.lines().peekable();

    while lines.peek().is_some() {
        // Kinda... not great
        let chunk = [
            lines.next().expect("No first line"),
            lines.next().expect("No second line"),
            lines.next().expect("No third line"),
        ];

        let chunk: Vec<Vec<u32>> = chunk.iter().map(|line| {
            line.split_whitespace().map(|dim| {
                dim.parse::<u32>().expect("Could not parse!")
            }).collect()
        }).collect();

        for i in 0..3 {
            let dims: Vec<u32> = chunk.iter().map(|v| v[i] ).collect();
            println!("dimensions are: {}, {}, {}", dims[0], dims[1], dims[2]);

            if is_a_triangle(dims[0], dims[1], dims[2]) {
                num_triangles += 1;
            }
        }
    }

    num_triangles
}

pub fn is_a_triangle(a: u32, b: u32, c: u32) -> bool {
    a + b > c && b + c > a && c + a > b
}

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

    #[test]
    fn equilateral_triangle() {
        assert!(is_a_triangle(3, 3, 3));
    }

    #[test]
    fn isoceles_triangle() {
        assert!(is_a_triangle(13, 13, 3));
    }

    #[test]
    fn acute_triangle() { // so cute
        assert!(is_a_triangle(208, 203, 145));
    }

    #[test]
    fn obtuse_triangle() {
        assert!(is_a_triangle(244, 360, 159));
    }

    #[test]
    fn not_a_triangle() {
        assert!( ! is_a_triangle(5, 10, 25) );
        assert!( ! is_a_triangle(5, 25, 10) );
        assert!( ! is_a_triangle(10, 5, 25) );
        assert!( ! is_a_triangle(10, 25, 5) );
        assert!( ! is_a_triangle(25, 5, 10) );
        assert!( ! is_a_triangle(25, 10, 5) );
    }

    #[test]
    fn whole_puzzle() {
        let input = "\
  785  516  744
  272  511  358
    1  791  600
";
        assert_eq!(puzzle(input), 2);
    }
}
<|endoftext|>