<commit_before>#[macro_use]
extern crate lazy_static;
extern crate regex;

use std::collections::HashMap;
use std::io::Read;
use std::fs::File;

use regex::Regex;

lazy_static! {
    static ref WORDS: HashMap<String, usize> = {
        let mut f = File::open("data/big.txt").unwrap();
        let mut s = String::new();
        f.read_to_string(&mut s).unwrap();

        // Count occurrences of words found in `big.txt`
        let mut words = HashMap::new();

        for word in Regex::new(r"\W+").unwrap().split(&s) {
            let count = words.entry(word.to_lowercase()).or_insert(0);
            *count += 1;
        }

        return words;
    };
}

/// Most probable spelling correction for `word`.
pub fn correction(word: &str) -> String {
    if word == "" {
        return String::from("");
    }

    let mut best_match = String::from(word);
    let mut best_score = 0;

    for candidate in candidates(word) {
        if let Some(score) = WORDS.get(&candidate) {
            if *score > best_score {
                best_score = *score;
                best_match = candidate;
            }
        }
    }

    best_match
}

/// Generate possible spelling corrections for `word`.
fn candidates(word: &str) -> Vec<String> {
    let mut word_set = Vec::new();
    word_set.push(String::from(word));

    if WORDS.contains_key(word) {
        word_set
    } else if let Some(single_edits) = known(edits(word)) {
        single_edits
    } else if let Some(double_edits) = known(double_edits(word)) {
        double_edits
    } else {
        word_set
    }
}

/// The subset of `words` that appear in the dictionary of WORDS
fn known(words: Vec<String>) -> Option<Vec<String>> {
    let mut known_words = Vec::new();

    for word in words {
        if WORDS.contains_key(&word) {
            known_words.push(word);
        }
    }

    if known_words.is_empty() {
        None
    } else {
        Some(known_words)
    }
}

/// All edits that are one edit away from `word`.
fn edits(word: &str) -> Vec<String> {
    // String containing lowercase letters in alphabetical order
    let letters = String::from_utf8((97..123).collect()).unwrap();

    // Construct vector of split variants of `word`
    // cat -> [("", "cat"), ("c", "at"), ("ca", "t")]
    let splits: Vec<_> = (0..word.len()).map(|i| (&word[..i], &word[i..])).collect();

    // Iterate through different edit permutations (at most 54n + 25)
    let mut all_edits = Vec::with_capacity(word.len() * 54 + 25);

    for (left, right) in splits {
        // Deletions
        let deletion = String::from(left);
        all_edits.push(deletion + &right[1..]);

        // Transpositions
        if right.len() > 1 {
            let transposition = String::from(left);
            let middle: &String = &right[..2].chars().rev().collect();
            all_edits.push(transposition + middle + &right[2..]);
        }

        for letter in letters.chars() {
            // Replacements
            let mut replacement = String::from(left);
            replacement.push(letter);
            all_edits.push(replacement + &right[1..]);

            // Insertions
            let mut insertion = String::from(left);
            insertion.push(letter);
            all_edits.push(insertion + right);
        }
    }

    // End-of-word insertions (appends?)
    for letter in letters.chars() {
        let mut insertion = String::from(word);
        insertion.push(letter);
        all_edits.push(insertion);
    }

    all_edits
}

/// All edits that are two edits away from `word`
fn double_edits(word: &str) -> Vec<String> {
    let mut all_edits = Vec::new();

    for single_edit in edits(word) {
        for double_edit in edits(&single_edit) {
            all_edits.push(double_edit);
        }
    }

    all_edits
}

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

    #[test]
    fn edit_count() {
        // Words of length n > 1 will have:
        // - n deletions
        // - n-1 transpositions
        // - 26n replacements
        // - 26(n+1) insertions
        // = 54n + 25 total edits

        // Use a punctuation-based test word to ensure unique edits
        let test_word = "!@#$%^&*()";

        for i in 1..(test_word.len() + 1) {
            assert_eq!(edits(&test_word[..i]).len(), 54*i + 25);
        }
    }

    #[test]
    fn possible_candidates() {
        let candidates = candidates("ther");

        for word in vec!["there", "the", "their", "her"] {
            assert!(candidates.contains(&String::from(word)));
        }
    }
}
<commit_msg>Use more iterator methods<commit_after>#[macro_use]
extern crate lazy_static;
extern crate regex;

use std::collections::HashMap;
use std::io::Read;
use std::fs::File;

use regex::Regex;

lazy_static! {
    static ref WORDS: HashMap<String, usize> = {
        let mut f = File::open("data/big.txt").unwrap();
        let mut s = String::new();
        f.read_to_string(&mut s).unwrap();

        // Count occurrences of words found in `big.txt`
        let mut words = HashMap::new();

        for word in Regex::new(r"\W+").unwrap().split(&s) {
            let count = words.entry(word.to_lowercase()).or_insert(0);
            *count += 1;
        }

        return words;
    };
}

/// Most probable spelling correction for `word`.
pub fn correction(word: &str) -> String {
    if word == "" {
        return String::from("");
    }

    let mut best_match = String::from(word);
    let mut best_score = 0;

    for candidate in candidates(word) {
        if let Some(score) = WORDS.get(&candidate) {
            if *score > best_score {
                best_score = *score;
                best_match = candidate;
            }
        }
    }

    best_match
}

/// Generate possible spelling corrections for `word`.
fn candidates(word: &str) -> Vec<String> {
    let mut word_set = Vec::new();
    word_set.push(String::from(word));

    if WORDS.contains_key(word) {
        word_set
    } else if let Some(single_edits) = known(edits(word)) {
        single_edits
    } else if let Some(double_edits) = known(double_edits(word)) {
        double_edits
    } else {
        word_set
    }
}

/// The subset of `words` that appear in the dictionary of WORDS
fn known(words: Vec<String>) -> Option<Vec<String>> {
    let known_words: Vec<_> = words.iter().filter(|&w| WORDS.contains_key(w)).cloned().collect();

    if known_words.is_empty() {
        None
    } else {
        Some(known_words)
    }
}

/// All edits that are one edit away from `word`.
fn edits(word: &str) -> Vec<String> {
    // String containing lowercase letters in alphabetical order
    let letters = String::from_utf8((97..123).collect()).unwrap();

    // Construct vector of split variants of `word`
    // cat -> [("", "cat"), ("c", "at"), ("ca", "t")]
    let splits: Vec<_> = (0..word.len()).map(|i| word.split_at(i)).collect();

    // Iterate through different edit permutations (at most 54n + 25)
    let mut all_edits = Vec::with_capacity(54 * word.len() + 25);

    for (left, right) in splits {
        // Deletions
        let deletion = String::from(left);
        all_edits.push(deletion + &right[1..]);

        // Transpositions
        if right.len() > 1 {
            let transposition = String::from(left);
            let middle: &String = &right[..2].chars().rev().collect();
            all_edits.push(transposition + middle + &right[2..]);
        }

        for letter in letters.chars() {
            // Replacements
            let mut replacement = String::from(left);
            replacement.push(letter);
            all_edits.push(replacement + &right[1..]);

            // Insertions
            let mut insertion = String::from(left);
            insertion.push(letter);
            all_edits.push(insertion + right);
        }
    }

    // End-of-word insertions (appends?)
    for letter in letters.chars() {
        let mut insertion = String::from(word);
        insertion.push(letter);
        all_edits.push(insertion);
    }

    all_edits
}

/// All edits that are two edits away from `word`
fn double_edits(word: &str) -> Vec<String> {
    edits(word).iter().flat_map(|e| edits(e)).collect()
}

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

    #[test]
    fn edit_count() {
        // Words of length n > 1 will have:
        // - n deletions
        // - n-1 transpositions
        // - 26n replacements
        // - 26(n+1) insertions
        // = 54n + 25 total edits

        // Use a punctuation-based test word to ensure unique edits
        let test_word = "!@#$%^&*()";

        for i in 1..(test_word.len() + 1) {
            assert_eq!(edits(&test_word[..i]).len(), 54*i + 25);
        }
    }

    #[test]
    fn possible_candidates() {
        let candidates = candidates("ther");

        for word in vec!["there", "the", "their", "her"] {
            assert!(candidates.contains(&String::from(word)));
        }
    }
}
<|endoftext|>


<commit_before>//! # libgit2 bindings for Rust
//!
//! This library contains bindings to the [libgit2][1] C library which is used
//! to manage git repositories. The library itself is a work in progress and is
//! likely lacking some bindings here and there, so be warned.
//!
//! [1]: https://libgit2.github.com/
//!
//! The git2-rs library strives to be as close to libgit2 as possible, but also
//! strives to make using libgit2 as safe as possible. All resource management
//! is automatic as well as adding strong types to all interfaces (including
//! `Result`)
//!
//! ## Creating a `Repository`
//!
//! The `Repository` is the source from which almost all other objects in git-rs
//! are spawned. A repository can be created through opening, initializing, or
//! cloning.
//!
//! ### Initializing a new repository
//!
//! The `init` method will create a new repository, assuming one does not
//! already exist.
//!
//! ```no_run
//! use git2::Repository;
//!
//! let path = Path::new("/path/to/a/repo");
//! let repo = match Repository::init(&path) {
//!     Ok(repo) => repo,
//!     Err(e) => panic!("failed to init `{}`: {}", path.display(), e),
//! };
//! ```
//!
//! ### Opening an existing repository
//!
//! ```no_run
//! use git2::Repository;
//!
//! let path = Path::new("/path/to/a/repo");
//! let repo = match Repository::open(&path) {
//!     Ok(repo) => repo,
//!     Err(e) => panic!("failed to open `{}`: {}", path.display(), e),
//! };
//! ```
//!
//! ### Cloning an existing repository
//!
//! ```no_run
//! use git2::Repository;
//!
//! let url = "https://github.com/alexcrichton/git2-rs";
//! let path = Path::new("/path/to/a/repo");
//! let repo = match Repository::clone(url, &path) {
//!     Ok(repo) => repo,
//!     Err(e) => panic!("failed to clone `{}`: {}", path.display(), e),
//! };
//! ```
//!
//! ## Working with a `Repository`
//!
//! All deriviative objects, references, etc are attached to the lifetime of the
//! source `Repository`, to ensure that they do not outlive the repository
//! itself.

#![feature(macro_rules, unsafe_destructor)]
#![deny(missing_docs)]
#![cfg_attr(test, deny(warnings))]

extern crate libc;
extern crate time;
extern crate url;
extern crate "libgit2-sys" as raw;

use std::c_str::CString;
use std::fmt;
use std::mem;
use std::rt;
use std::str;
use std::sync::{Once, ONCE_INIT};

pub use blob::Blob;
pub use branch::{Branch, Branches};
pub use buf::Buf;
pub use commit::{Commit, Parents};
pub use config::{Config, ConfigEntry, ConfigEntries};
pub use cred::{Cred, CredentialHelper};
pub use diff::{DiffDelta, DiffFile};
pub use error::Error;
pub use index::{Index, IndexEntry, IndexEntries, IndexMatchedPath};
pub use note::{Note, Notes};
pub use object::Object;
pub use oid::Oid;
pub use push::{Push, PushStatus};
pub use reference::{Reference, References, ReferenceNames};
pub use refspec::Refspec;
pub use remote::{Remote, Refspecs};
pub use remote_callbacks::{RemoteCallbacks, Credentials, TransferProgress};
pub use remote_callbacks::{TransportMessage, Progress};
pub use repo::{Repository, RepositoryInitOptions};
pub use revspec::Revspec;
pub use revwalk::Revwalk;
pub use signature::Signature;
pub use status::{StatusOptions, Statuses, StatusIter, StatusEntry, StatusShow};
pub use string_array::{StringArray, StringArrayItems, StringArrayBytes};
pub use submodule::Submodule;
pub use tag::Tag;
pub use tree::{Tree, TreeEntry};

/// An enumeration of possible errors that can happen when working with a git
/// repository.
#[deriving(PartialEq, Eq, Clone, Show, Copy)]
pub enum ErrorCode {
    /// Generic error
    GenericError,
    /// Requested object could not be found
    NotFound,
    /// Object exists preventing operation
    Exists,
    /// More than one object matches
    Ambiguous,
    /// Output buffer too short to hold data
    BufSize,
    /// Operation not allowed on bare repository
    User,
    /// Operation not allowed on bare repository
    BareRepo,
    /// HEAD refers to branch with no commits
    UnbornBranch,
    /// Merge in progress prevented operation
    Unmerged,
    /// Reference was not fast-forwardable
    NotFastForward,
    /// Name/ref spec was not in a valid format
    InvalidSpec,
    /// Merge conflicts prevented operation
    MergeConflict,
    /// Lock file prevented operation
    Locked,
    /// Reference value does not match expected
    Modified,
}

/// A listing of the possible states that a repository can be in.
#[deriving(PartialEq, Eq, Clone, Show, Copy)]
#[allow(missing_docs)]
pub enum RepositoryState {
    Clean,
    Merge,
    Revert,
    CherryPick,
    Bisect,
    Rebase,
    RebaseInteractive,
    RebaseMerge,
    ApplyMailbox,
    ApplyMailboxOrRebase,
}

/// An enumeration of the possible directions for a remote.
#[deriving(Copy)]
pub enum Direction {
    /// Data will be fetched (read) from this remote.
    Fetch,
    /// Data will be pushed (written) to this remote.
    Push,
}

/// An enumeration of the operations that can be performed for the `reset`
/// method on a `Repository`.
#[deriving(Copy)]
pub enum ResetType {
    /// Move the head to the given commit.
    Soft,
    /// Soft plus reset the index to the commit.
    Mixed,
    /// Mixed plus changes in the working tree are discarded.
    Hard,
}

/// An enumeration all possible kinds objects may have.
#[deriving(PartialEq, Eq, Copy)]
pub enum ObjectType {
    /// An object which corresponds to a any git object
    Any,
    /// An object which corresponds to a git commit
    Commit,
    /// An object which corresponds to a git tree
    Tree,
    /// An object which corresponds to a git blob
    Blob,
    /// An object which corresponds to a git tag
    Tag,
}

/// An enumeration for the possible types of branches
#[deriving(PartialEq, Eq, Show, Copy)]
pub enum BranchType {
    /// A local branch not on a remote.
    Local,
    /// A branch for a remote.
    Remote,
}

/// An enumeration of the possible priority levels of a config file.
///
/// The levels corresponding to the escalation logic (higher to lower) when
/// searching for config entries.
#[deriving(PartialEq, Eq, Show, Copy)]
pub enum ConfigLevel {
    /// System-wide configuration file, e.g. /etc/gitconfig
    System,
    /// XDG-compatible configuration file, e.g. ~/.config/git/config
    XDG,
    /// User-specific configuration, e.g. ~/.gitconfig
    Global,
    /// Reopsitory specific config, e.g. $PWD/.git/config
    Local,
    /// Application specific configuration file
    App,
    /// Highest level available
    Highest,
}

bitflags! {
    #[doc = "
Orderings that may be specified for Revwalk iteration.
"]
    flags Sort: uint {
        const SORT_NONE = raw::GIT_SORT_NONE as uint,
        const SORT_TOPOLOGICAL = raw::GIT_SORT_TOPOLOGICAL as uint,
        const SORT_TIME = raw::GIT_SORT_TIME as uint,
        const SORT_REVERSE = raw::GIT_SORT_REVERSE as uint,
    }
}

bitflags! {
    #[doc = "
Types of credentials that can be requested by a credential callback.
"]
    flags CredentialType: uint {
        const USER_PASS_PLAINTEXT = raw::GIT_CREDTYPE_USERPASS_PLAINTEXT as uint,
        const SSH_KEY = raw::GIT_CREDTYPE_SSH_KEY as uint,
        const SSH_CUSTOM = raw::GIT_CREDTYPE_SSH_CUSTOM as uint,
        const DEFAULT = raw::GIT_CREDTYPE_DEFAULT as uint,
        const SSH_INTERACTIVE = raw::GIT_CREDTYPE_SSH_INTERACTIVE as uint,
    }
}

bitflags! {
    #[doc = "
Flags for APIs that add files matching pathspec
"]
    flags IndexAddOption: u32 {
        const ADD_DEFAULT = raw::GIT_INDEX_ADD_DEFAULT as u32,
        const ADD_FORCE = raw::GIT_INDEX_ADD_FORCE as u32,
        const ADD_DISABLE_PATHSPEC_MATCH =
                raw::GIT_INDEX_ADD_DISABLE_PATHSPEC_MATCH as u32,
        const ADD_CHECK_PATHSPEC = raw::GIT_INDEX_ADD_CHECK_PATHSPEC as u32,
    }
}

mod call;

pub mod build;

mod blob;
mod branch;
mod buf;
mod commit;
mod config;
mod cred;
mod diff;
mod error;
mod index;
mod note;
mod object;
mod oid;
mod push;
mod reference;
mod refspec;
mod remote;
mod remote_callbacks;
mod repo;
mod revspec;
mod revwalk;
mod signature;
mod status;
mod string_array;
mod submodule;
mod tag;
mod tree;

#[cfg(test)] mod test;

fn init() {
    static INIT: Once = ONCE_INIT;
    INIT.doit(|| unsafe {
        raw::openssl_init();
        let r = raw::git_libgit2_init();
        assert!(r >= 0,
                "couldn't initialize the libgit2 library: {}", r);
        rt::at_exit(|| {
            raw::git_libgit2_shutdown();
        });
    });
}

unsafe fn opt_bytes<'a, T>(_: &'a T,
                           c: *const libc::c_char) -> Option<&'a [u8]> {
    if c.is_null() {
        None
    } else {
        let s = CString::new(c, false);
        Some(mem::transmute(s.as_bytes_no_nul()))
    }
}

impl ObjectType {
    /// Convert an object type to its string representation.
    pub fn str(&self) -> &'static str {
        unsafe {
            let ptr = call!(raw::git_object_type2string(*self));
            mem::transmute::<&str, &'static str>(str::from_c_str(ptr))
        }
    }

    /// Determine if the given git_otype is a valid loose object type.
    pub fn is_loose(&self) -> bool {
        unsafe { (call!(raw::git_object_typeisloose(*self)) == 1) }
    }

    /// Convert a raw git_otype to an ObjectType
    pub fn from_raw(raw: raw::git_otype) -> Option<ObjectType> {
        match raw {
            raw::GIT_OBJ_ANY => Some(ObjectType::Any),
            raw::GIT_OBJ_BAD => None,
            raw::GIT_OBJ__EXT1 => None,
            raw::GIT_OBJ_COMMIT => Some(ObjectType::Commit),
            raw::GIT_OBJ_TREE => Some(ObjectType::Tree),
            raw::GIT_OBJ_BLOB => Some(ObjectType::Blob),
            raw::GIT_OBJ_TAG => Some(ObjectType::Tag),
            raw::GIT_OBJ__EXT2 => None,
            raw::GIT_OBJ_OFS_DELTA => None,
            raw::GIT_OBJ_REF_DELTA => None,
        }
    }

    /// Convert this kind into its raw representation
    pub fn raw(&self) -> raw::git_otype {
        call::convert(self)
    }

    /// Convert a string object type representation to its object type.
    pub fn from_str(s: &str) -> Option<ObjectType> {
        let raw = unsafe { call!(raw::git_object_string2type(s.to_c_str())) };
        ObjectType::from_raw(raw)
    }
}

impl fmt::Show for ObjectType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.str().fmt(f)
    }
}

impl ConfigLevel {
    /// Converts a raw configuration level to a ConfigLevel
    pub fn from_raw(raw: raw::git_config_level_t) -> ConfigLevel {
        match raw {
            raw::GIT_CONFIG_LEVEL_SYSTEM => ConfigLevel::System,
            raw::GIT_CONFIG_LEVEL_XDG => ConfigLevel::XDG,
            raw::GIT_CONFIG_LEVEL_GLOBAL => ConfigLevel::Global,
            raw::GIT_CONFIG_LEVEL_LOCAL => ConfigLevel::Local,
            raw::GIT_CONFIG_LEVEL_APP => ConfigLevel::App,
            raw::GIT_CONFIG_HIGHEST_LEVEL => ConfigLevel::Highest,
        }
    }
}

bitflags! {
    #[doc = "
Flags for repository status
"]
    flags Status: u32 {
        const STATUS_INDEX_NEW = raw::GIT_STATUS_INDEX_NEW as u32,
        const STATUS_INDEX_MODIFIED = raw::GIT_STATUS_INDEX_MODIFIED as u32,
        const STATUS_INDEX_DELETED = raw::GIT_STATUS_INDEX_DELETED as u32,
        const STATUS_INDEX_RENAMED = raw::GIT_STATUS_INDEX_RENAMED as u32,
        const STATUS_INDEX_TYPECHANGE = raw::GIT_STATUS_INDEX_TYPECHANGE as u32,

        const STATUS_WT_NEW = raw::GIT_STATUS_WT_NEW as u32,
        const STATUS_WT_MODIFIED = raw::GIT_STATUS_WT_MODIFIED as u32,
        const STATUS_WT_DELETED = raw::GIT_STATUS_WT_DELETED as u32,
        const STATUS_WT_TYPECHANGE = raw::GIT_STATUS_WT_TYPECHANGE as u32,
        const STATUS_WT_RENAMED = raw::GIT_STATUS_WT_RENAMED as u32,

        const STATUS_IGNORED = raw::GIT_STATUS_IGNORED as u32,
    }
}

/// What type of change is described by a `DiffDelta`?
#[deriving(Copy)]
pub enum Delta {
    /// No changes
    Unmodified,
    /// Entry does not exist in old version
    Added,
    /// Entry does not exist in new version
    Deleted,
    /// Entry content changed between old and new
    Modified,
    /// Entry was renamed wbetween old and new
    Renamed,
    /// Entry was copied from another old entry
    Copied,
    /// Entry is ignored item in workdir
    Ignored,
    /// Entry is untracked item in workdir
    Untracked,
    /// Type of entry changed between old and new
    Typechange,
    /// Entry is unreadable
    Unreadable,
}

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

    #[test]
    fn convert() {
        assert_eq!(ObjectType::Blob.str(), "blob");
        assert_eq!(ObjectType::from_str("blob"), Some(ObjectType::Blob));
        assert!(ObjectType::Blob.is_loose());
    }

}
<commit_msg>Make sure that the argument of str::from_c_str is always of the right type.<commit_after>//! # libgit2 bindings for Rust
//!
//! This library contains bindings to the [libgit2][1] C library which is used
//! to manage git repositories. The library itself is a work in progress and is
//! likely lacking some bindings here and there, so be warned.
//!
//! [1]: https://libgit2.github.com/
//!
//! The git2-rs library strives to be as close to libgit2 as possible, but also
//! strives to make using libgit2 as safe as possible. All resource management
//! is automatic as well as adding strong types to all interfaces (including
//! `Result`)
//!
//! ## Creating a `Repository`
//!
//! The `Repository` is the source from which almost all other objects in git-rs
//! are spawned. A repository can be created through opening, initializing, or
//! cloning.
//!
//! ### Initializing a new repository
//!
//! The `init` method will create a new repository, assuming one does not
//! already exist.
//!
//! ```no_run
//! use git2::Repository;
//!
//! let path = Path::new("/path/to/a/repo");
//! let repo = match Repository::init(&path) {
//!     Ok(repo) => repo,
//!     Err(e) => panic!("failed to init `{}`: {}", path.display(), e),
//! };
//! ```
//!
//! ### Opening an existing repository
//!
//! ```no_run
//! use git2::Repository;
//!
//! let path = Path::new("/path/to/a/repo");
//! let repo = match Repository::open(&path) {
//!     Ok(repo) => repo,
//!     Err(e) => panic!("failed to open `{}`: {}", path.display(), e),
//! };
//! ```
//!
//! ### Cloning an existing repository
//!
//! ```no_run
//! use git2::Repository;
//!
//! let url = "https://github.com/alexcrichton/git2-rs";
//! let path = Path::new("/path/to/a/repo");
//! let repo = match Repository::clone(url, &path) {
//!     Ok(repo) => repo,
//!     Err(e) => panic!("failed to clone `{}`: {}", path.display(), e),
//! };
//! ```
//!
//! ## Working with a `Repository`
//!
//! All deriviative objects, references, etc are attached to the lifetime of the
//! source `Repository`, to ensure that they do not outlive the repository
//! itself.

#![feature(macro_rules, unsafe_destructor)]
#![deny(missing_docs)]
#![cfg_attr(test, deny(warnings))]

extern crate libc;
extern crate time;
extern crate url;
extern crate "libgit2-sys" as raw;

use std::c_str::CString;
use std::fmt;
use std::mem;
use std::rt;
use std::str;
use std::sync::{Once, ONCE_INIT};

pub use blob::Blob;
pub use branch::{Branch, Branches};
pub use buf::Buf;
pub use commit::{Commit, Parents};
pub use config::{Config, ConfigEntry, ConfigEntries};
pub use cred::{Cred, CredentialHelper};
pub use diff::{DiffDelta, DiffFile};
pub use error::Error;
pub use index::{Index, IndexEntry, IndexEntries, IndexMatchedPath};
pub use note::{Note, Notes};
pub use object::Object;
pub use oid::Oid;
pub use push::{Push, PushStatus};
pub use reference::{Reference, References, ReferenceNames};
pub use refspec::Refspec;
pub use remote::{Remote, Refspecs};
pub use remote_callbacks::{RemoteCallbacks, Credentials, TransferProgress};
pub use remote_callbacks::{TransportMessage, Progress};
pub use repo::{Repository, RepositoryInitOptions};
pub use revspec::Revspec;
pub use revwalk::Revwalk;
pub use signature::Signature;
pub use status::{StatusOptions, Statuses, StatusIter, StatusEntry, StatusShow};
pub use string_array::{StringArray, StringArrayItems, StringArrayBytes};
pub use submodule::Submodule;
pub use tag::Tag;
pub use tree::{Tree, TreeEntry};

/// An enumeration of possible errors that can happen when working with a git
/// repository.
#[deriving(PartialEq, Eq, Clone, Show, Copy)]
pub enum ErrorCode {
    /// Generic error
    GenericError,
    /// Requested object could not be found
    NotFound,
    /// Object exists preventing operation
    Exists,
    /// More than one object matches
    Ambiguous,
    /// Output buffer too short to hold data
    BufSize,
    /// Operation not allowed on bare repository
    User,
    /// Operation not allowed on bare repository
    BareRepo,
    /// HEAD refers to branch with no commits
    UnbornBranch,
    /// Merge in progress prevented operation
    Unmerged,
    /// Reference was not fast-forwardable
    NotFastForward,
    /// Name/ref spec was not in a valid format
    InvalidSpec,
    /// Merge conflicts prevented operation
    MergeConflict,
    /// Lock file prevented operation
    Locked,
    /// Reference value does not match expected
    Modified,
}

/// A listing of the possible states that a repository can be in.
#[deriving(PartialEq, Eq, Clone, Show, Copy)]
#[allow(missing_docs)]
pub enum RepositoryState {
    Clean,
    Merge,
    Revert,
    CherryPick,
    Bisect,
    Rebase,
    RebaseInteractive,
    RebaseMerge,
    ApplyMailbox,
    ApplyMailboxOrRebase,
}

/// An enumeration of the possible directions for a remote.
#[deriving(Copy)]
pub enum Direction {
    /// Data will be fetched (read) from this remote.
    Fetch,
    /// Data will be pushed (written) to this remote.
    Push,
}

/// An enumeration of the operations that can be performed for the `reset`
/// method on a `Repository`.
#[deriving(Copy)]
pub enum ResetType {
    /// Move the head to the given commit.
    Soft,
    /// Soft plus reset the index to the commit.
    Mixed,
    /// Mixed plus changes in the working tree are discarded.
    Hard,
}

/// An enumeration all possible kinds objects may have.
#[deriving(PartialEq, Eq, Copy)]
pub enum ObjectType {
    /// An object which corresponds to a any git object
    Any,
    /// An object which corresponds to a git commit
    Commit,
    /// An object which corresponds to a git tree
    Tree,
    /// An object which corresponds to a git blob
    Blob,
    /// An object which corresponds to a git tag
    Tag,
}

/// An enumeration for the possible types of branches
#[deriving(PartialEq, Eq, Show, Copy)]
pub enum BranchType {
    /// A local branch not on a remote.
    Local,
    /// A branch for a remote.
    Remote,
}

/// An enumeration of the possible priority levels of a config file.
///
/// The levels corresponding to the escalation logic (higher to lower) when
/// searching for config entries.
#[deriving(PartialEq, Eq, Show, Copy)]
pub enum ConfigLevel {
    /// System-wide configuration file, e.g. /etc/gitconfig
    System,
    /// XDG-compatible configuration file, e.g. ~/.config/git/config
    XDG,
    /// User-specific configuration, e.g. ~/.gitconfig
    Global,
    /// Reopsitory specific config, e.g. $PWD/.git/config
    Local,
    /// Application specific configuration file
    App,
    /// Highest level available
    Highest,
}

bitflags! {
    #[doc = "
Orderings that may be specified for Revwalk iteration.
"]
    flags Sort: uint {
        const SORT_NONE = raw::GIT_SORT_NONE as uint,
        const SORT_TOPOLOGICAL = raw::GIT_SORT_TOPOLOGICAL as uint,
        const SORT_TIME = raw::GIT_SORT_TIME as uint,
        const SORT_REVERSE = raw::GIT_SORT_REVERSE as uint,
    }
}

bitflags! {
    #[doc = "
Types of credentials that can be requested by a credential callback.
"]
    flags CredentialType: uint {
        const USER_PASS_PLAINTEXT = raw::GIT_CREDTYPE_USERPASS_PLAINTEXT as uint,
        const SSH_KEY = raw::GIT_CREDTYPE_SSH_KEY as uint,
        const SSH_CUSTOM = raw::GIT_CREDTYPE_SSH_CUSTOM as uint,
        const DEFAULT = raw::GIT_CREDTYPE_DEFAULT as uint,
        const SSH_INTERACTIVE = raw::GIT_CREDTYPE_SSH_INTERACTIVE as uint,
    }
}

bitflags! {
    #[doc = "
Flags for APIs that add files matching pathspec
"]
    flags IndexAddOption: u32 {
        const ADD_DEFAULT = raw::GIT_INDEX_ADD_DEFAULT as u32,
        const ADD_FORCE = raw::GIT_INDEX_ADD_FORCE as u32,
        const ADD_DISABLE_PATHSPEC_MATCH =
                raw::GIT_INDEX_ADD_DISABLE_PATHSPEC_MATCH as u32,
        const ADD_CHECK_PATHSPEC = raw::GIT_INDEX_ADD_CHECK_PATHSPEC as u32,
    }
}

mod call;

pub mod build;

mod blob;
mod branch;
mod buf;
mod commit;
mod config;
mod cred;
mod diff;
mod error;
mod index;
mod note;
mod object;
mod oid;
mod push;
mod reference;
mod refspec;
mod remote;
mod remote_callbacks;
mod repo;
mod revspec;
mod revwalk;
mod signature;
mod status;
mod string_array;
mod submodule;
mod tag;
mod tree;

#[cfg(test)] mod test;

fn init() {
    static INIT: Once = ONCE_INIT;
    INIT.doit(|| unsafe {
        raw::openssl_init();
        let r = raw::git_libgit2_init();
        assert!(r >= 0,
                "couldn't initialize the libgit2 library: {}", r);
        rt::at_exit(|| {
            raw::git_libgit2_shutdown();
        });
    });
}

unsafe fn opt_bytes<'a, T>(_: &'a T,
                           c: *const libc::c_char) -> Option<&'a [u8]> {
    if c.is_null() {
        None
    } else {
        let s = CString::new(c, false);
        Some(mem::transmute(s.as_bytes_no_nul()))
    }
}

impl ObjectType {
    /// Convert an object type to its string representation.
    pub fn str(&self) -> &'static str {
        unsafe {
            let ptr = call!(raw::git_object_type2string(*self));
            mem::transmute::<&str, &'static str>(str::from_c_str(ptr as *const _))
        }
    }

    /// Determine if the given git_otype is a valid loose object type.
    pub fn is_loose(&self) -> bool {
        unsafe { (call!(raw::git_object_typeisloose(*self)) == 1) }
    }

    /// Convert a raw git_otype to an ObjectType
    pub fn from_raw(raw: raw::git_otype) -> Option<ObjectType> {
        match raw {
            raw::GIT_OBJ_ANY => Some(ObjectType::Any),
            raw::GIT_OBJ_BAD => None,
            raw::GIT_OBJ__EXT1 => None,
            raw::GIT_OBJ_COMMIT => Some(ObjectType::Commit),
            raw::GIT_OBJ_TREE => Some(ObjectType::Tree),
            raw::GIT_OBJ_BLOB => Some(ObjectType::Blob),
            raw::GIT_OBJ_TAG => Some(ObjectType::Tag),
            raw::GIT_OBJ__EXT2 => None,
            raw::GIT_OBJ_OFS_DELTA => None,
            raw::GIT_OBJ_REF_DELTA => None,
        }
    }

    /// Convert this kind into its raw representation
    pub fn raw(&self) -> raw::git_otype {
        call::convert(self)
    }

    /// Convert a string object type representation to its object type.
    pub fn from_str(s: &str) -> Option<ObjectType> {
        let raw = unsafe { call!(raw::git_object_string2type(s.to_c_str())) };
        ObjectType::from_raw(raw)
    }
}

impl fmt::Show for ObjectType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.str().fmt(f)
    }
}

impl ConfigLevel {
    /// Converts a raw configuration level to a ConfigLevel
    pub fn from_raw(raw: raw::git_config_level_t) -> ConfigLevel {
        match raw {
            raw::GIT_CONFIG_LEVEL_SYSTEM => ConfigLevel::System,
            raw::GIT_CONFIG_LEVEL_XDG => ConfigLevel::XDG,
            raw::GIT_CONFIG_LEVEL_GLOBAL => ConfigLevel::Global,
            raw::GIT_CONFIG_LEVEL_LOCAL => ConfigLevel::Local,
            raw::GIT_CONFIG_LEVEL_APP => ConfigLevel::App,
            raw::GIT_CONFIG_HIGHEST_LEVEL => ConfigLevel::Highest,
        }
    }
}

bitflags! {
    #[doc = "
Flags for repository status
"]
    flags Status: u32 {
        const STATUS_INDEX_NEW = raw::GIT_STATUS_INDEX_NEW as u32,
        const STATUS_INDEX_MODIFIED = raw::GIT_STATUS_INDEX_MODIFIED as u32,
        const STATUS_INDEX_DELETED = raw::GIT_STATUS_INDEX_DELETED as u32,
        const STATUS_INDEX_RENAMED = raw::GIT_STATUS_INDEX_RENAMED as u32,
        const STATUS_INDEX_TYPECHANGE = raw::GIT_STATUS_INDEX_TYPECHANGE as u32,

        const STATUS_WT_NEW = raw::GIT_STATUS_WT_NEW as u32,
        const STATUS_WT_MODIFIED = raw::GIT_STATUS_WT_MODIFIED as u32,
        const STATUS_WT_DELETED = raw::GIT_STATUS_WT_DELETED as u32,
        const STATUS_WT_TYPECHANGE = raw::GIT_STATUS_WT_TYPECHANGE as u32,
        const STATUS_WT_RENAMED = raw::GIT_STATUS_WT_RENAMED as u32,

        const STATUS_IGNORED = raw::GIT_STATUS_IGNORED as u32,
    }
}

/// What type of change is described by a `DiffDelta`?
#[deriving(Copy)]
pub enum Delta {
    /// No changes
    Unmodified,
    /// Entry does not exist in old version
    Added,
    /// Entry does not exist in new version
    Deleted,
    /// Entry content changed between old and new
    Modified,
    /// Entry was renamed wbetween old and new
    Renamed,
    /// Entry was copied from another old entry
    Copied,
    /// Entry is ignored item in workdir
    Ignored,
    /// Entry is untracked item in workdir
    Untracked,
    /// Type of entry changed between old and new
    Typechange,
    /// Entry is unreadable
    Unreadable,
}

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

    #[test]
    fn convert() {
        assert_eq!(ObjectType::Blob.str(), "blob");
        assert_eq!(ObjectType::from_str("blob"), Some(ObjectType::Blob));
        assert!(ObjectType::Blob.is_loose());
    }

}
<|endoftext|>


<commit_before>// lib.rs
// Copyright 2016 Alexander Altman
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::ops::Index;
use std::marker::PhantomData;
use std::fmt;

#[derive(Clone,Copy,PartialEq,Eq,Debug,Hash)]
pub enum Position {
  White,
  Black,
  Empty,
}

impl Position {
  pub fn is_occupied(&self) -> bool { self != &Position::Empty }

  pub fn is_empty(&self) -> bool { self == &Position::Empty }

  pub fn is_white(&self) -> bool { self == &Position::White }

  pub fn is_black(&self) -> bool { self == &Position::Black }
}

#[derive(Clone,Copy,PartialEq,Eq,Debug,Hash)]
pub struct Papamu {
  board: [[Position; 10]; 10],
}

impl Default for Papamu {
  fn default() -> Papamu {
    let mut board = [[Position::White; 10]; 10];
    for (_, pos) in board.iter_mut().enumerate().flat_map(|(x, part)| {
      part.iter_mut().enumerate().filter(move |&(y, _)| (x + y) % 2 == 0)
    }) {
      *pos = Position::Black;
    }
    Papamu { board: board }
  }
}

#[derive(Clone,Copy,PartialEq,Eq,Debug,Hash)]
pub struct Ix {
  x: u8,
  y: u8,
}

impl Ix {
  pub fn mk(x: u8, y: u8) -> Option<Ix> { if x <= 9 && y <= 9 { Some(Ix { x: x, y: y }) } else { None } }

  pub fn x(&self) -> u8 { self.x }

  pub fn set_x(&mut self, new_x: u8) -> bool {
    if new_x <= 9 {
      self.x = new_x;
      true
    } else {
      false
    }
  }

  pub fn y(&self) -> u8 { self.y }

  pub fn set_y(&mut self, new_y: u8) -> bool {
    if new_y <= 9 {
      self.y = new_y;
      true
    } else {
      false
    }
  }
}

impl From<Ix> for (u8, u8) {
  fn from(ix: Ix) -> (u8, u8) { (ix.x, ix.y) }
}

impl Index<Ix> for Papamu {
  type Output = Position;

  fn index(&self, ix: Ix) -> &Position { &self.board[usize::from(ix.x)][usize::from(ix.y)] }
}

pub mod turn {
  pub enum Black {}

  pub enum White {}

  pub trait Turn {
    type Next: Turn;

    fn piece_type() -> super::Position;
  }

  impl Turn for Black {
    type Next = White;

    fn piece_type() -> super::Position { super::Position::Black }
  }

  impl Turn for White {
    type Next = Black;

    fn piece_type() -> super::Position { super::Position::White }
  }
}

pub struct Game<Tn: turn::Turn> {
  papamu: Papamu,
  phantom_turn: PhantomData<Tn>,
}

impl<Tn: turn::Turn> fmt::Debug for Game<Tn> {
  fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
    fmtr.debug_struct("Game").field("papamu", &self.papamu).field("phantom_turn", &self.phantom_turn).finish()
  }
}

impl<Tn: turn::Turn> Default for Game<Tn> {
  fn default() -> Game<Tn> {
    Game {
      papamu: Papamu::default(),
      phantom_turn: PhantomData,
    }
  }
}

#[allow(unknown_lints, expl_impl_clone_on_copy)]
impl<Tn: turn::Turn> Clone for Game<Tn> {
  fn clone(&self) -> Game<Tn> { *self }
}

impl<Tn: turn::Turn> Copy for Game<Tn> {}

impl<Tn: turn::Turn> Index<Ix> for Game<Tn> {
  type Output = Position;

  fn index(&self, ix: Ix) -> &Position { &self.papamu[ix] }
}
<commit_msg>`papamu` method<commit_after>// lib.rs
// Copyright 2016 Alexander Altman
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::ops::Index;
use std::marker::PhantomData;
use std::fmt;

#[derive(Clone,Copy,PartialEq,Eq,Debug,Hash)]
pub enum Position {
  White,
  Black,
  Empty,
}

impl Position {
  pub fn is_occupied(&self) -> bool { self != &Position::Empty }

  pub fn is_empty(&self) -> bool { self == &Position::Empty }

  pub fn is_white(&self) -> bool { self == &Position::White }

  pub fn is_black(&self) -> bool { self == &Position::Black }
}

#[derive(Clone,Copy,PartialEq,Eq,Debug,Hash)]
pub struct Papamu {
  board: [[Position; 10]; 10],
}

impl Default for Papamu {
  fn default() -> Papamu {
    let mut board = [[Position::White; 10]; 10];
    for (_, pos) in board.iter_mut().enumerate().flat_map(|(x, part)| {
      part.iter_mut().enumerate().filter(move |&(y, _)| (x + y) % 2 == 0)
    }) {
      *pos = Position::Black;
    }
    Papamu { board: board }
  }
}

#[derive(Clone,Copy,PartialEq,Eq,Debug,Hash)]
pub struct Ix {
  x: u8,
  y: u8,
}

impl Ix {
  pub fn mk(x: u8, y: u8) -> Option<Ix> { if x <= 9 && y <= 9 { Some(Ix { x: x, y: y }) } else { None } }

  pub fn x(&self) -> u8 { self.x }

  pub fn set_x(&mut self, new_x: u8) -> bool {
    if new_x <= 9 {
      self.x = new_x;
      true
    } else {
      false
    }
  }

  pub fn y(&self) -> u8 { self.y }

  pub fn set_y(&mut self, new_y: u8) -> bool {
    if new_y <= 9 {
      self.y = new_y;
      true
    } else {
      false
    }
  }
}

impl From<Ix> for (u8, u8) {
  fn from(ix: Ix) -> (u8, u8) { (ix.x, ix.y) }
}

impl Index<Ix> for Papamu {
  type Output = Position;

  fn index(&self, ix: Ix) -> &Position { &self.board[usize::from(ix.x)][usize::from(ix.y)] }
}

pub mod turn {
  pub enum Black {}

  pub enum White {}

  pub trait Turn {
    type Next: Turn;

    fn piece_type() -> super::Position;
  }

  impl Turn for Black {
    type Next = White;

    fn piece_type() -> super::Position { super::Position::Black }
  }

  impl Turn for White {
    type Next = Black;

    fn piece_type() -> super::Position { super::Position::White }
  }
}

pub struct Game<Tn: turn::Turn> {
  papamu: Papamu,
  phantom_turn: PhantomData<Tn>,
}

impl<Tn: turn::Turn> fmt::Debug for Game<Tn> {
  fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
    fmtr.debug_struct("Game").field("papamu", &self.papamu).field("phantom_turn", &self.phantom_turn).finish()
  }
}

impl<Tn: turn::Turn> Default for Game<Tn> {
  fn default() -> Game<Tn> {
    Game {
      papamu: Papamu::default(),
      phantom_turn: PhantomData,
    }
  }
}

#[allow(unknown_lints, expl_impl_clone_on_copy)]
impl<Tn: turn::Turn> Clone for Game<Tn> {
  fn clone(&self) -> Game<Tn> { *self }
}

impl<Tn: turn::Turn> Copy for Game<Tn> {}

impl<Tn: turn::Turn> Index<Ix> for Game<Tn> {
  type Output = Position;

  fn index(&self, ix: Ix) -> &Position { &self.papamu[ix] }
}

impl<Tn: turn::Turn> Game<Tn> {
  pub fn papamu(&self) -> Papamu {
    self.papamu
  }
}
<|endoftext|>


<commit_before>extern crate rand;

pub mod macaroni {
    use rand;
    use std::collections::HashMap;
    use std::io;
    use std::rc::Rc;

    const DIGITS: &'static [u8] = b"0123456789";
    const EPSILON: f64 = 0.000001;
    const PRECISION: i32 = 10;

    #[derive(Clone)]
    pub enum Val {
        Num(f64),
        Arr(Vec<Val>)
    }

    use std::fmt;
    impl fmt::Debug for Val {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            match self {
                &Val::Num(n) => write!(f, "{}", n),
                &Val::Arr(ref a) => write!(f, "{:?}", a)
            }
        }
    }

    #[derive(Clone)]
    struct Variable {
        val: Val,
        var: Option<String>
    }

    impl Variable {
        fn by_name(name: String) -> Variable {
            Variable { val: Val::Num(0f64), var: Some(name) }
        }
        fn new_num(n: f64) -> Variable {
            Variable { val: Val::Num(n), var: None }
        }
        fn new_arr(a: Vec<Val>) -> Variable {
            Variable { val: Val::Arr(a), var: None }
        }
    }

    #[derive(Clone)]
    enum Token {
        Var(Variable),
        Op { func: Rc<Fn(&[Variable]) -> Option<Variable>>, arity: usize },
        Label(String),
        Goto(String),
        Set(String)
    }

    pub struct Macaroni {
        vars: HashMap<String, Val>
    }

    impl Macaroni {
        pub fn new() -> Macaroni {
            Macaroni { vars: HashMap::<String, Val>::new() }
        }

        pub fn run(&mut self, code: String) -> Option<Val> {
            let tokens = self.tokenize(code);
            self.run_tokens(&tokens)
        }

        fn tokenize(&self, code: String) -> Vec<Token> {
            let mut tokens = Vec::<String>::new();
            let mut token = String::new();
            for ch in code.chars() {
                if token.starts_with("\"") {
                    token.push(ch);
                    if ch == '"' {
                        tokens.push(token);
                        token = String::new();
                    }
                } else { match ch {
                    'a'...'z' | 'A'...'Z' | '0'...'9' | '_' | '-' => {
                        token.push(ch);
                    },
                    ' ' | '\n' | '\t' => {
                        if !token.is_empty() {
                            tokens.push(token);
                            token = String::new();
                        }
                    },
                    '"' | '/' | '\\' | ':' => {
                        if token.is_empty() {
                            token.push(ch);
                        } else {
                            panic!("unexpected {}", token);
                        }
                    },
                    _ => { panic!("unrecognized char {}", ch); }
                } }
            }
            if !token.is_empty() { tokens.push(token); }
            tokens.iter().map(|t|
                if t.chars().all(|ch| ch.is_digit(10) || ch == '-') {
                    Token::Var(Variable::new_num(t.parse::<f64>().unwrap()))
                } else { match t.chars().next().unwrap() {
                    '"' => {
                        Token::Var(Variable::new_arr(Macaroni::string_to_arr(
                            &t[1..t.len() - 1].to_string())))
                    },
                    '/' => {
                        Token::Label(t[1..t.len()].to_string())
                    },
                    '\\' => {
                        Token::Goto(t[1..t.len()].to_string())
                    },
                    ':' => {
                        Token::Set(t[1..t.len()].to_string())
                    },
                    _ => { match &t[..] {
                        "add" => Token::Op {
                            func: Rc::new(Macaroni::add), arity: 2
                        },
                        "multiply" => Token::Op {
                            func: Rc::new(Macaroni::multiply), arity: 2
                        },
                        "floor" => Token::Op {
                            func: Rc::new(Macaroni::floor), arity: 1
                        },
                        "pow" => Token::Op {
                            func: Rc::new(Macaroni::pow), arity: 2
                        },
                        "tobase" => Token::Op {
                            func: Rc::new(Macaroni::tobase), arity: 2
                        },
                        "concat" => Token::Op {
                            func: Rc::new(Macaroni::concat), arity: 2
                        },
                        "length" => Token::Op {
                            func: Rc::new(Macaroni::length), arity: 1
                        },
                        "slice" => Token::Op {
                            func: Rc::new(Macaroni::slice), arity: 4
                        },
                        "wrap" => Token::Op {
                            func: Rc::new(Macaroni::wrap), arity: 1
                        },
                        "print" => Token::Op {
                            func: Rc::new(Macaroni::print), arity: 1
                        },
                        "read" => Token::Op {
                            func: Rc::new(Macaroni::read), arity: 0
                        },
                        "rand" => Token::Op {
                            func: Rc::new(Macaroni::rand), arity: 0
                        },
                        _ => Token::Var(Variable::by_name(t.clone()))
                    } }
                } }).collect::<Vec<Token>>()
        }

        fn run_tokens(&mut self, program: &[Token]) -> Option<Val> {
            let mut label_addrs: HashMap<String, usize> = HashMap::new();
            let mut i: usize = 0;
            let mut to_set: Option<String> = None;
            let mut last_val: Option<Val> = None;
            while let Some(t) = program.get(i) {
                match t {
                    &Token::Set(ref var_name) => {
                        to_set = Some(var_name.clone());
                        i += 1;
                        continue;
                    },
                    &Token::Op { .. } => {
                        last_val = self.execute_op(&program, &mut i)
                            .map(|x| x.val);
                    },
                    &Token::Label(ref label) => {
                        label_addrs.entry(label.clone()).or_insert(i);
                        i += 1;
                    },
                    &Token::Goto(ref label) => {
                        i = label_addrs.entry(label.clone())
                            .or_insert_with(||
                                self.find_label(program, label, i)
                                    .expect(&format!("{:#08x}: is a GOTO to \
                                                     label {:?}, which does \
                                                     not exist", i, label)[..])
                            ).clone();
                    },
                    &Token::Var(ref v) => {
                        last_val = Some(self.uv(v).val.clone());
                        i += 1;
                    }
                }
                if let Some(ref var_name) = to_set {
                    self.vars.insert(var_name.clone(), last_val.expect(
                        &format!("{:08x}: cannot set to null", i)));
                    last_val = None;
                }
                to_set = None;
            }
            last_val
        }

        fn execute_op(&self, program: &[Token], i: &mut usize) -> Option<Variable> {
            let (func, arity) = match program.get(i.clone()) {
                Some(&Token::Op { ref func, arity }) => (func, arity),
                Some(_) => panic!("Macaroni::execute_op() called on {:#08x}, \
                                  but instruction is not OP", i),
                None => panic!("Macaroni::execute_op() called on out-of-bounds \
                               index {:#08x}", i)
            };
            *i += 1;
            let mut args: Vec<Variable> = Vec::with_capacity(arity);
            while args.len() < arity {
                match program.get(i.clone()) {
                    Some(&Token::Var(ref v)) => {
                        args.push(self.uv(v));
                        *i += 1;
                    },
                    Some(&Token::Op { .. }) => {
                        match self.execute_op(program, i) {
                            Some(v) => args.push(v),
                            None => panic!("nested OP ending before {:#08x} \
                                           returned nothing", i)
                        }
                    }
                    Some(_) => panic!("{:#08x} is not valid as an OP argument; \
                                      it should be a VAR or an OP", i),
                    None => panic!("{:#08x}: expected OP argument (VAR or OP); \
                                   found end of program", i)
                }
            }
            func(&args[..])
        }

        /// Updates the `val` part of a variable, when `var` is Some().
        fn uv(&self, v: &Variable) -> Variable {
            if let Some(ref var_name) = v.var {
                Variable {
                    val: self.vars.get(var_name)
                        .map_or(Val::Num(0f64), |x| x.clone()),
                    var: v.var.clone()
                }
            } else { v.clone() }
        }

        /// Searches the program for the specified label. Returns the position
        /// of the label in the program, or `None` if it was not found.
        ///
        /// `index` merely specifies a starting point. The entire `program`
        /// is always searched, starting at `index` and wrapping around
        /// if necessary.
        ///
        /// # Examples
        ///
        /// ```
        /// use Token::*;
        ///
        /// let print_func = Box::new(|s| println!("{}", s));
        /// let program = vec![
        ///     Label(String::from("loop")),
        ///     Op({ func: print, arity: 1 }),
        ///     Variable(String::from("Hello, world!")),
        ///     Goto(String::from("loop"))
        /// ];
        /// assert_eq!(find_label(program, String::from("loop"), 0), Some(0));
        /// assert_eq!(find_label(program, String::from("cleanup"), 0), None);
        /// ```
        fn find_label(&self, program: &[Token], desired_label: &str,
                index: usize) -> Option<usize> {
            let enumerated = program.iter().enumerate();
            for (i, token) in enumerated.clone()
                                        .skip(index)
                                        .chain(enumerated.take(index)) {
                if let Token::Label(ref label) = *token {
                    if label == desired_label {
                        return Some(i);
                    }
                }
            }
            None
        }

        fn add(args: &[Variable]) -> Option<Variable> {
            Some(Variable::new_num(match args[0].val {
                Val::Num(n) => n,
                Val::Arr(_) => panic!("add called with Arr")
            } + match args[1].val {
                Val::Num(n) => n,
                Val::Arr(_) => panic!("add called with Arr")
            }))
        }

        fn multiply(args: &[Variable]) -> Option<Variable> {
            Some(Variable::new_num(match args[0].val {
                Val::Num(n) => n,
                Val::Arr(_) => panic!("multiply called with Arr")
            } * match args[1].val {
                Val::Num(n) => n,
                Val::Arr(_) => panic!("multiply called with Arr")
            }))
        }

        fn floor(args: &[Variable]) -> Option<Variable> {
            Some(Variable::new_num(match args[0].val {
                Val::Num(n) => n,
                Val::Arr(_) => panic!("floor called with Arr")
            }.floor()))
        }

        fn pow(args: &[Variable]) -> Option<Variable> {
            Some(Variable::new_num(match args[0].val {
                Val::Num(n) => n,
                Val::Arr(_) => panic!("pow called with Arr")
            }.powf(match args[1].val {
                Val::Num(n) => n,
                Val::Arr(_) => panic!("pow called with Arr")
            })))
        }

        fn tobase(args: &[Variable]) -> Option<Variable> {
            match args[0].val { Val::Num(n) => {
                match args[1].val { Val::Num(m) => {
                    let (base, mut ipart, mut fpart) =
                        (m as i64, n.floor() as i64, n - n.floor());
                    let neg = ipart < 0;

                    // convert integer part
                    let mut nb = String::new();
                    while ipart != 0 {
                        nb.insert(0, DIGITS[(ipart % base) as usize] as char);
                        ipart /= base;
                    }

                    // handle negatives and zero (we must do this
                    // before converting float part)
                    if neg { nb.insert(0, '-'); }
                    if nb.is_empty() { nb.push('0'); }

                    // convert float part
                    if fpart > EPSILON {
                        nb.push('.');
                        for _ in 0..PRECISION {
                            if fpart <= EPSILON { break; }
                            fpart *= base as f64;
                            let digit = fpart.floor();
                            nb.push(DIGITS[digit as usize] as char);
                            fpart -= digit;
                        }
                    }

                    Some(Variable::new_arr(Macaroni::string_to_arr(&nb)))
                }, Val::Arr(_) => panic!("tobase called with Arr") }
            }, Val::Arr(_) => panic!("tobase called with Arr") }
        }

        fn concat(args: &[Variable]) -> Option<Variable> {
            let mut arr = match args[0].val {
                Val::Arr(ref a) => a,
                Val::Num(_) => panic!("concat called with Num")
            }.clone();
            arr.extend(match args[1].val {
                Val::Arr(ref a) => a,
                Val::Num(_) => panic!("concat called with Num")
            }.clone().into_iter());
            Some(Variable::new_arr(arr))
        }

        fn slice(args: &[Variable]) -> Option<Variable> {
            Some(Variable::new_arr(match args[0].val {
                Val::Arr(ref a) => {
                    let step = match args[3].val {
                        Val::Num(n) => n,
                        Val::Arr(_) => panic!("slice called with Arr")
                    };
                    let (mut idx, to) = (
                        match args[if step > 0f64 { 1 } else { 2 }].val {
                            Val::Num(n) => n,
                            Val::Arr(_) => panic!("slice called with Arr")
                        },
                        match args[if step > 0f64 { 2 } else { 1 }].val {
                            Val::Num(n) => n,
                            Val::Arr(_) => panic!("slice called with Arr")
                        }
                    );
                    let mut new_arr = Vec::<Val>::new();
                    while if step > 0f64 { idx < to } else { idx > to } {
                        new_arr.push(a[idx as usize].clone());
                        idx += step;
                    }
                    new_arr
                }
                Val::Num(_) => panic!("slice called with Num")
            }))
        }

        fn length(args: &[Variable]) -> Option<Variable> {
            Some(Variable::new_num(match args[0].val {
                Val::Arr(ref a) => a.len() as f64,
                Val::Num(_) => panic!("length called with Num")
            }))
        }

        fn wrap(args: &[Variable]) -> Option<Variable> {
            let ref x = args[0];
            Some(Variable::new_arr(vec![x.val.clone()]))
        }

        fn print(args: &[Variable]) -> Option<Variable> {
            let ref x = args[0];
            print!("{}", match x.val {
                Val::Arr(ref s) => Macaroni::arr_to_string(s),
                Val::Num(_) => panic!("print called with Num")
            });
            None
        }

        fn read(_: &[Variable]) -> Option<Variable> {
            let mut line = String::new();
            io::stdin().read_line(&mut line).unwrap();
            Some(Variable::new_arr(Macaroni::string_to_arr(&line)))
        }

        fn rand(_: &[Variable]) -> Option<Variable> {
            Some(Variable::new_num(rand::random()))
        }

        fn arr_to_string(arr: &Vec<Val>) -> String {
            arr.iter().map(|x| match x {
                &Val::Num(n) => n,
                &Val::Arr(_) => panic!("arr_to_string called with non-string")
            } as u8 as char).collect::<String>()
        }

        fn string_to_arr(str: &String) -> Vec<Val> {
            str.chars().map(|c| Val::Num(c as u8 as f64)).collect()
        }
    }
}
<commit_msg>fix bug in slice<commit_after>extern crate rand;

pub mod macaroni {
    use rand;
    use std::collections::HashMap;
    use std::io;
    use std::rc::Rc;

    const DIGITS: &'static [u8] = b"0123456789";
    const EPSILON: f64 = 0.000001;
    const PRECISION: i32 = 10;

    #[derive(Clone)]
    pub enum Val {
        Num(f64),
        Arr(Vec<Val>)
    }

    use std::fmt;
    impl fmt::Debug for Val {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            match self {
                &Val::Num(n) => write!(f, "{}", n),
                &Val::Arr(ref a) => write!(f, "{:?}", a)
            }
        }
    }

    #[derive(Clone)]
    struct Variable {
        val: Val,
        var: Option<String>
    }

    impl Variable {
        fn by_name(name: String) -> Variable {
            Variable { val: Val::Num(0f64), var: Some(name) }
        }
        fn new_num(n: f64) -> Variable {
            Variable { val: Val::Num(n), var: None }
        }
        fn new_arr(a: Vec<Val>) -> Variable {
            Variable { val: Val::Arr(a), var: None }
        }
    }

    #[derive(Clone)]
    enum Token {
        Var(Variable),
        Op { func: Rc<Fn(&[Variable]) -> Option<Variable>>, arity: usize },
        Label(String),
        Goto(String),
        Set(String)
    }

    pub struct Macaroni {
        vars: HashMap<String, Val>
    }

    impl Macaroni {
        pub fn new() -> Macaroni {
            Macaroni { vars: HashMap::<String, Val>::new() }
        }

        pub fn run(&mut self, code: String) -> Option<Val> {
            let tokens = self.tokenize(code);
            self.run_tokens(&tokens)
        }

        fn tokenize(&self, code: String) -> Vec<Token> {
            let mut tokens = Vec::<String>::new();
            let mut token = String::new();
            for ch in code.chars() {
                if token.starts_with("\"") {
                    token.push(ch);
                    if ch == '"' {
                        tokens.push(token);
                        token = String::new();
                    }
                } else { match ch {
                    'a'...'z' | 'A'...'Z' | '0'...'9' | '_' | '-' => {
                        token.push(ch);
                    },
                    ' ' | '\n' | '\t' => {
                        if !token.is_empty() {
                            tokens.push(token);
                            token = String::new();
                        }
                    },
                    '"' | '/' | '\\' | ':' => {
                        if token.is_empty() {
                            token.push(ch);
                        } else {
                            panic!("unexpected {}", token);
                        }
                    },
                    _ => { panic!("unrecognized char {}", ch); }
                } }
            }
            if !token.is_empty() { tokens.push(token); }
            tokens.iter().map(|t|
                if t.chars().all(|ch| ch.is_digit(10) || ch == '-') {
                    Token::Var(Variable::new_num(t.parse::<f64>().unwrap()))
                } else { match t.chars().next().unwrap() {
                    '"' => {
                        Token::Var(Variable::new_arr(Macaroni::string_to_arr(
                            &t[1..t.len() - 1].to_string())))
                    },
                    '/' => {
                        Token::Label(t[1..t.len()].to_string())
                    },
                    '\\' => {
                        Token::Goto(t[1..t.len()].to_string())
                    },
                    ':' => {
                        Token::Set(t[1..t.len()].to_string())
                    },
                    _ => { match &t[..] {
                        "add" => Token::Op {
                            func: Rc::new(Macaroni::add), arity: 2
                        },
                        "multiply" => Token::Op {
                            func: Rc::new(Macaroni::multiply), arity: 2
                        },
                        "floor" => Token::Op {
                            func: Rc::new(Macaroni::floor), arity: 1
                        },
                        "pow" => Token::Op {
                            func: Rc::new(Macaroni::pow), arity: 2
                        },
                        "tobase" => Token::Op {
                            func: Rc::new(Macaroni::tobase), arity: 2
                        },
                        "concat" => Token::Op {
                            func: Rc::new(Macaroni::concat), arity: 2
                        },
                        "length" => Token::Op {
                            func: Rc::new(Macaroni::length), arity: 1
                        },
                        "slice" => Token::Op {
                            func: Rc::new(Macaroni::slice), arity: 4
                        },
                        "wrap" => Token::Op {
                            func: Rc::new(Macaroni::wrap), arity: 1
                        },
                        "print" => Token::Op {
                            func: Rc::new(Macaroni::print), arity: 1
                        },
                        "read" => Token::Op {
                            func: Rc::new(Macaroni::read), arity: 0
                        },
                        "rand" => Token::Op {
                            func: Rc::new(Macaroni::rand), arity: 0
                        },
                        _ => Token::Var(Variable::by_name(t.clone()))
                    } }
                } }).collect::<Vec<Token>>()
        }

        fn run_tokens(&mut self, program: &[Token]) -> Option<Val> {
            let mut label_addrs: HashMap<String, usize> = HashMap::new();
            let mut i: usize = 0;
            let mut to_set: Option<String> = None;
            let mut last_val: Option<Val> = None;
            while let Some(t) = program.get(i) {
                match t {
                    &Token::Set(ref var_name) => {
                        to_set = Some(var_name.clone());
                        i += 1;
                        continue;
                    },
                    &Token::Op { .. } => {
                        last_val = self.execute_op(&program, &mut i)
                            .map(|x| x.val);
                    },
                    &Token::Label(ref label) => {
                        label_addrs.entry(label.clone()).or_insert(i);
                        i += 1;
                    },
                    &Token::Goto(ref label) => {
                        i = label_addrs.entry(label.clone())
                            .or_insert_with(||
                                self.find_label(program, label, i)
                                    .expect(&format!("{:#08x}: is a GOTO to \
                                                     label {:?}, which does \
                                                     not exist", i, label)[..])
                            ).clone();
                    },
                    &Token::Var(ref v) => {
                        last_val = Some(self.uv(v).val.clone());
                        i += 1;
                    }
                }
                if let Some(ref var_name) = to_set {
                    self.vars.insert(var_name.clone(), last_val.expect(
                        &format!("{:08x}: cannot set to null", i)));
                    last_val = None;
                }
                to_set = None;
            }
            last_val
        }

        fn execute_op(&self, program: &[Token], i: &mut usize) -> Option<Variable> {
            let (func, arity) = match program.get(i.clone()) {
                Some(&Token::Op { ref func, arity }) => (func, arity),
                Some(_) => panic!("Macaroni::execute_op() called on {:#08x}, \
                                  but instruction is not OP", i),
                None => panic!("Macaroni::execute_op() called on out-of-bounds \
                               index {:#08x}", i)
            };
            *i += 1;
            let mut args: Vec<Variable> = Vec::with_capacity(arity);
            while args.len() < arity {
                match program.get(i.clone()) {
                    Some(&Token::Var(ref v)) => {
                        args.push(self.uv(v));
                        *i += 1;
                    },
                    Some(&Token::Op { .. }) => {
                        match self.execute_op(program, i) {
                            Some(v) => args.push(v),
                            None => panic!("nested OP ending before {:#08x} \
                                           returned nothing", i)
                        }
                    }
                    Some(_) => panic!("{:#08x} is not valid as an OP argument; \
                                      it should be a VAR or an OP", i),
                    None => panic!("{:#08x}: expected OP argument (VAR or OP); \
                                   found end of program", i)
                }
            }
            func(&args[..])
        }

        /// Updates the `val` part of a variable, when `var` is Some().
        fn uv(&self, v: &Variable) -> Variable {
            if let Some(ref var_name) = v.var {
                Variable {
                    val: self.vars.get(var_name)
                        .map_or(Val::Num(0f64), |x| x.clone()),
                    var: v.var.clone()
                }
            } else { v.clone() }
        }

        /// Searches the program for the specified label. Returns the position
        /// of the label in the program, or `None` if it was not found.
        ///
        /// `index` merely specifies a starting point. The entire `program`
        /// is always searched, starting at `index` and wrapping around
        /// if necessary.
        ///
        /// # Examples
        ///
        /// ```
        /// use Token::*;
        ///
        /// let print_func = Box::new(|s| println!("{}", s));
        /// let program = vec![
        ///     Label(String::from("loop")),
        ///     Op({ func: print, arity: 1 }),
        ///     Variable(String::from("Hello, world!")),
        ///     Goto(String::from("loop"))
        /// ];
        /// assert_eq!(find_label(program, String::from("loop"), 0), Some(0));
        /// assert_eq!(find_label(program, String::from("cleanup"), 0), None);
        /// ```
        fn find_label(&self, program: &[Token], desired_label: &str,
                index: usize) -> Option<usize> {
            let enumerated = program.iter().enumerate();
            for (i, token) in enumerated.clone()
                                        .skip(index)
                                        .chain(enumerated.take(index)) {
                if let Token::Label(ref label) = *token {
                    if label == desired_label {
                        return Some(i);
                    }
                }
            }
            None
        }

        fn add(args: &[Variable]) -> Option<Variable> {
            Some(Variable::new_num(match args[0].val {
                Val::Num(n) => n,
                Val::Arr(_) => panic!("add called with Arr")
            } + match args[1].val {
                Val::Num(n) => n,
                Val::Arr(_) => panic!("add called with Arr")
            }))
        }

        fn multiply(args: &[Variable]) -> Option<Variable> {
            Some(Variable::new_num(match args[0].val {
                Val::Num(n) => n,
                Val::Arr(_) => panic!("multiply called with Arr")
            } * match args[1].val {
                Val::Num(n) => n,
                Val::Arr(_) => panic!("multiply called with Arr")
            }))
        }

        fn floor(args: &[Variable]) -> Option<Variable> {
            Some(Variable::new_num(match args[0].val {
                Val::Num(n) => n,
                Val::Arr(_) => panic!("floor called with Arr")
            }.floor()))
        }

        fn pow(args: &[Variable]) -> Option<Variable> {
            Some(Variable::new_num(match args[0].val {
                Val::Num(n) => n,
                Val::Arr(_) => panic!("pow called with Arr")
            }.powf(match args[1].val {
                Val::Num(n) => n,
                Val::Arr(_) => panic!("pow called with Arr")
            })))
        }

        fn tobase(args: &[Variable]) -> Option<Variable> {
            match args[0].val { Val::Num(n) => {
                match args[1].val { Val::Num(m) => {
                    let (base, mut ipart, mut fpart) =
                        (m as i64, n.floor() as i64, n - n.floor());
                    let neg = ipart < 0;

                    // convert integer part
                    let mut nb = String::new();
                    while ipart != 0 {
                        nb.insert(0, DIGITS[(ipart % base) as usize] as char);
                        ipart /= base;
                    }

                    // handle negatives and zero (we must do this
                    // before converting float part)
                    if neg { nb.insert(0, '-'); }
                    if nb.is_empty() { nb.push('0'); }

                    // convert float part
                    if fpart > EPSILON {
                        nb.push('.');
                        for _ in 0..PRECISION {
                            if fpart <= EPSILON { break; }
                            fpart *= base as f64;
                            let digit = fpart.floor();
                            nb.push(DIGITS[digit as usize] as char);
                            fpart -= digit;
                        }
                    }

                    Some(Variable::new_arr(Macaroni::string_to_arr(&nb)))
                }, Val::Arr(_) => panic!("tobase called with Arr") }
            }, Val::Arr(_) => panic!("tobase called with Arr") }
        }

        fn concat(args: &[Variable]) -> Option<Variable> {
            let mut arr = match args[0].val {
                Val::Arr(ref a) => a,
                Val::Num(_) => panic!("concat called with Num")
            }.clone();
            arr.extend(match args[1].val {
                Val::Arr(ref a) => a,
                Val::Num(_) => panic!("concat called with Num")
            }.clone().into_iter());
            Some(Variable::new_arr(arr))
        }

        fn slice(args: &[Variable]) -> Option<Variable> {
            Some(Variable::new_arr(match args[0].val {
                Val::Arr(ref a) => {
                    let step = match args[3].val {
                        Val::Num(n) => n,
                        Val::Arr(_) => panic!("slice called with Arr")
                    };
                    let (mut idx, to) = (
                        match args[if step > 0f64 { 1 } else { 2 }].val {
                            Val::Num(n) => n,
                            Val::Arr(_) => panic!("slice called with Arr")
                        },
                        match args[if step > 0f64 { 2 } else { 1 }].val {
                            Val::Num(n) => n,
                            Val::Arr(_) => panic!("slice called with Arr")
                        }
                    );
                    if step < 0f64 { idx -= 1f64; }
                    let mut new_arr = Vec::<Val>::new();
                    while if step > 0f64 { idx < to } else { idx >= to } {
                        new_arr.push(a[idx as usize].clone());
                        idx += step;
                    }
                    new_arr
                }
                Val::Num(_) => panic!("slice called with Num")
            }))
        }

        fn length(args: &[Variable]) -> Option<Variable> {
            Some(Variable::new_num(match args[0].val {
                Val::Arr(ref a) => a.len() as f64,
                Val::Num(_) => panic!("length called with Num")
            }))
        }

        fn wrap(args: &[Variable]) -> Option<Variable> {
            let ref x = args[0];
            Some(Variable::new_arr(vec![x.val.clone()]))
        }

        fn print(args: &[Variable]) -> Option<Variable> {
            let ref x = args[0];
            print!("{}", match x.val {
                Val::Arr(ref s) => Macaroni::arr_to_string(s),
                Val::Num(_) => panic!("print called with Num")
            });
            None
        }

        fn read(_: &[Variable]) -> Option<Variable> {
            let mut line = String::new();
            io::stdin().read_line(&mut line).unwrap();
            Some(Variable::new_arr(Macaroni::string_to_arr(&line)))
        }

        fn rand(_: &[Variable]) -> Option<Variable> {
            Some(Variable::new_num(rand::random()))
        }

        fn arr_to_string(arr: &Vec<Val>) -> String {
            arr.iter().map(|x| match x {
                &Val::Num(n) => n,
                &Val::Arr(_) => panic!("arr_to_string called with non-string")
            } as u8 as char).collect::<String>()
        }

        fn string_to_arr(str: &String) -> Vec<Val> {
            str.chars().map(|c| Val::Num(c as u8 as f64)).collect()
        }
    }
}
<|endoftext|>


<commit_before>//! Space API definitions and serialization.
//!
//! This crate contains all data-related definitions that are present in the Space API
//! (http://spaceapi.net/). It also handles serializing that data to JSON by implementing the
//! [`ToJson`](http://doc.rust-lang.org/rustc-serialize/rustc_serialize/json/trait.ToJson.html)
//! trait for all structs.
//!
//! The currently supported Space API version is 0.13. It is not yet fully implemented.
//!
//! # Examples
//!
//! You can create a new ``Status`` instance by using the ``new()`` constructor method. To serialize
//! this to [``Json``](http://doc.rust-lang.org/rustc-serialize/rustc_serialize/json/enum.Json.html), use
//! the [`ToJson`](http://doc.rust-lang.org/rustc-serialize/rustc_serialize/json/trait.ToJson.html)
//! trait implementation. You can then create a string from the resulting object.
//!
//!     # extern crate rustc_serialize;
//!     # extern crate spaceapi;
//!     # use spaceapi::{Status, Location, Contact};
//!     # use spaceapi::optional::Optional;
//!     use rustc_serialize::json::ToJson;
//!
//!     # fn main() {
//!     let status = Status::new(
//!         "coredump".to_string(),
//!         "https://www.coredump.ch/logo.png".to_string(),
//!         "https://www.coredump.ch/".to_string(),
//!         Location {
//!             address: Optional::Value("Spinnereistrasse 2, 8640 Rapperswil, Switzerland".to_string()),
//!             lat: 47.22936,
//!             lon: 8.82949,
//!         },
//!         Contact {
//!             irc: Optional::Value("irc://freenode.net/#coredump".to_string()),
//!             twitter: Optional::Value("@coredump_ch".to_string()),
//!             foursquare: Optional::Value("525c20e5498e875d8231b1e5".to_string()),
//!             email: Optional::Value("danilo@coredump.ch".to_string()),
//!         },
//!         vec![
//!             "email".to_string(),
//!             "twitter".to_string(),
//!         ],
//!     );
//!
//!     let jsonstatus = status.to_json();
//!     let stringstatus = jsonstatus.to_string();
//!     # }

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

pub mod optional;
pub mod sensors;
mod status;
pub use status::*;
<commit_msg>Remove unneeded to_string() from example<commit_after>//! Space API definitions and serialization.
//!
//! This crate contains all data-related definitions that are present in the Space API
//! (http://spaceapi.net/). It also handles serializing that data to JSON by implementing the
//! [`ToJson`](http://doc.rust-lang.org/rustc-serialize/rustc_serialize/json/trait.ToJson.html)
//! trait for all structs.
//!
//! The currently supported Space API version is 0.13. It is not yet fully implemented.
//!
//! # Examples
//!
//! You can create a new ``Status`` instance by using the ``new()`` constructor method. To serialize
//! this to [``Json``](http://doc.rust-lang.org/rustc-serialize/rustc_serialize/json/enum.Json.html), use
//! the [`ToJson`](http://doc.rust-lang.org/rustc-serialize/rustc_serialize/json/trait.ToJson.html)
//! trait implementation. You can then create a string from the resulting object.
//!
//!     # extern crate rustc_serialize;
//!     # extern crate spaceapi;
//!     # use spaceapi::{Status, Location, Contact};
//!     # use spaceapi::optional::Optional;
//!     use rustc_serialize::json::ToJson;
//!
//!     # fn main() {
//!     let status = Status::new(
//!         "coredump",
//!         "https://www.coredump.ch/logo.png",
//!         "https://www.coredump.ch/",
//!         Location {
//!             address: Optional::Value("Spinnereistrasse 2, 8640 Rapperswil, Switzerland".to_string()),
//!             lat: 47.22936,
//!             lon: 8.82949,
//!         },
//!         Contact {
//!             irc: Optional::Value("irc://freenode.net/#coredump".to_string()),
//!             twitter: Optional::Value("@coredump_ch".to_string()),
//!             foursquare: Optional::Value("525c20e5498e875d8231b1e5".to_string()),
//!             email: Optional::Value("danilo@coredump.ch".to_string()),
//!         },
//!         vec![
//!             "email".to_string(),
//!             "twitter".to_string(),
//!         ],
//!     );
//!
//!     let jsonstatus = status.to_json();
//!     let stringstatus = jsonstatus.to_string();
//!     # }

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

pub mod optional;
pub mod sensors;
mod status;
pub use status::*;
<|endoftext|>


<commit_before>//! Demoscene framework.
//!
//! # Foreword
//!
//! This framework is intented to be used to build up [demos](https://en.wikipedia.org/wiki/Demoscene)
//! as a primary purpose. Everything was designed to quickly write demoscene effects and edit them
//! into an audiovisual executable. However, because a lot was added – especially for debugging
//! purposes, it *should* be possible to use this framework for other purposes as well – among
//! *simulations*, *animations* and *video games*.
//!
//! # Design
//!
//! This framework was designed to be *simple* and *flexible*. Following that path, it’s not
//! impossible that some of its features get moved out of the framework to become a set of
//! dependencies – so that people who don’t want those features can just preclude them from the
//! compilation chain.
//!
//! Up to now, the framework provides you with several modules:
//!
//! - **audio**: this module gives you the ability to play a soundtrack (no streaming implemented
//!   yet though; the whole soundtrack is loaded into memory) and interact with basic yet useful
//!   information about playback (play, pause, toggle, track length, track cursor, etc.)
//! - **bootstrapping**: this module abstracts over the underlying technologies and provides several
//!   simple types that can be used to interact with the demo, such as initialization, default
//!   event handling, and so on
//! - **camera**: provides some camera features for both release and debugging purposes
//! - **color**: color types
//! - **edit**: everything you need to edit your demo – it provides types and functions to reason
//!   about timelines, tracks, cuts and clips, hence easing the overall making of a demo
//! - **gui**: this module provides some GUI code that you can use to build nice debugging
//!   interfaces – up to now, it’s not designed for release code, but it might be at some time
//! - **linear**: linear algebra
//! - **model**: this module provides all the code required to abstract other meshes and add them
//!   the concept of *materials*
//! - **object**: linked to **models**, this module adds the concept of *space properties* to
//!   *models* – so that you can actually have them in your scenes
//! - **overlay**: this module provides 2D primitives and rendering functions
//! - **projection**: projection trait and functions
//! - **shader**: provides
//! - **extra**: some extra (but not mandatory) other modules

#![feature(associated_consts)]
#![feature(conservative_impl_trait)]
#![feature(const_fn)]

extern crate alto;
extern crate any_cache;
extern crate gl;
pub extern crate glfw;
extern crate image;
pub extern crate luminance;
extern crate nalgebra;
#[cfg(feature = "hot-resource")]
extern crate notify;
extern crate num;
extern crate rusttype;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
#[cfg(feature = "hot-resource")]
extern crate time;
extern crate vorbis;
extern crate wavefront_obj;

#[macro_use]
pub mod report;

#[macro_use]
pub mod resource;
#[macro_use]
pub mod scene;

pub mod audio;
pub mod bootstrap;
pub mod camera;
pub mod compositing;
pub mod color;
pub mod edit;
pub mod extra;
pub mod framebuffer_pool;
pub mod gui;
pub mod linear;
pub mod model;
pub mod object;
pub mod overlay;
pub mod projection;
pub mod shader;
pub mod spline;
pub mod text;
pub mod texture;
pub mod transform;

pub use audio::Audio;
pub use bootstrap::{Device, WindowDim};
pub use camera::{Camera, Freefly};
pub use color::{Color, ColorAlpha};
pub use linear::{Matrix4};
pub use model::{Model, ModelError, Part};
pub use object::Object;
pub use projection::{Projectable, perspective};
pub use resource::{Load, LoadError, Reload};
pub use shader::{Program, ShaderError, new_program};
pub use scene::Scene;
pub use spline::{Interpolate, Interpolation, Key, Spline, SplineIterator, Time};
pub use texture::{Texture, TextureImage, load_rgba_texture, save_rgba_texture};
pub use transform::{Axis, Orientation, Position, Translation, Transformable, X_AXIS, Y_AXIS, Z_AXIS,
                   Scale, translation_matrix};
<commit_msg>Removed framebuffer_pool in lib.rs.<commit_after>//! Demoscene framework.
//!
//! # Foreword
//!
//! This framework is intented to be used to build up [demos](https://en.wikipedia.org/wiki/Demoscene)
//! as a primary purpose. Everything was designed to quickly write demoscene effects and edit them
//! into an audiovisual executable. However, because a lot was added – especially for debugging
//! purposes, it *should* be possible to use this framework for other purposes as well – among
//! *simulations*, *animations* and *video games*.
//!
//! # Design
//!
//! This framework was designed to be *simple* and *flexible*. Following that path, it’s not
//! impossible that some of its features get moved out of the framework to become a set of
//! dependencies – so that people who don’t want those features can just preclude them from the
//! compilation chain.
//!
//! Up to now, the framework provides you with several modules:
//!
//! - **audio**: this module gives you the ability to play a soundtrack (no streaming implemented
//!   yet though; the whole soundtrack is loaded into memory) and interact with basic yet useful
//!   information about playback (play, pause, toggle, track length, track cursor, etc.)
//! - **bootstrapping**: this module abstracts over the underlying technologies and provides several
//!   simple types that can be used to interact with the demo, such as initialization, default
//!   event handling, and so on
//! - **camera**: provides some camera features for both release and debugging purposes
//! - **color**: color types
//! - **edit**: everything you need to edit your demo – it provides types and functions to reason
//!   about timelines, tracks, cuts and clips, hence easing the overall making of a demo
//! - **gui**: this module provides some GUI code that you can use to build nice debugging
//!   interfaces – up to now, it’s not designed for release code, but it might be at some time
//! - **linear**: linear algebra
//! - **model**: this module provides all the code required to abstract other meshes and add them
//!   the concept of *materials*
//! - **object**: linked to **models**, this module adds the concept of *space properties* to
//!   *models* – so that you can actually have them in your scenes
//! - **overlay**: this module provides 2D primitives and rendering functions
//! - **projection**: projection trait and functions
//! - **shader**: provides
//! - **extra**: some extra (but not mandatory) other modules

#![feature(associated_consts)]
#![feature(conservative_impl_trait)]
#![feature(const_fn)]

extern crate alto;
extern crate any_cache;
extern crate gl;
pub extern crate glfw;
extern crate image;
pub extern crate luminance;
extern crate nalgebra;
#[cfg(feature = "hot-resource")]
extern crate notify;
extern crate num;
extern crate rusttype;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
#[cfg(feature = "hot-resource")]
extern crate time;
extern crate vorbis;
extern crate wavefront_obj;

#[macro_use]
pub mod report;

#[macro_use]
pub mod resource;
#[macro_use]
pub mod scene;

pub mod audio;
pub mod bootstrap;
pub mod camera;
pub mod compositing;
pub mod color;
pub mod edit;
pub mod extra;
pub mod gui;
pub mod linear;
pub mod model;
pub mod object;
pub mod overlay;
pub mod projection;
pub mod shader;
pub mod spline;
pub mod text;
pub mod texture;
pub mod transform;

pub use audio::Audio;
pub use bootstrap::{Device, WindowDim};
pub use camera::{Camera, Freefly};
pub use color::{Color, ColorAlpha};
pub use linear::{Matrix4};
pub use model::{Model, ModelError, Part};
pub use object::Object;
pub use projection::{Projectable, perspective};
pub use resource::{Load, LoadError, Reload};
pub use shader::{Program, ShaderError, new_program};
pub use scene::Scene;
pub use spline::{Interpolate, Interpolation, Key, Spline, SplineIterator, Time};
pub use texture::{Texture, TextureImage, load_rgba_texture, save_rgba_texture};
pub use transform::{Axis, Orientation, Position, Translation, Transformable, X_AXIS, Y_AXIS, Z_AXIS,
                   Scale, translation_matrix};
<|endoftext|>