<commit_before>//! This crate is a Rust library for using the [Serde] serialization framework
//! with data in [YAML] file format.
//!
//! This library does not reimplement a YAML parser; it uses [yaml-rust] which
//! is a pure Rust YAML 1.2 implementation.
//!
//! [Serde]: https://github.com/serde-rs/serde
//! [YAML]: http://yaml.org
//! [yaml-rust]: https://github.com/chyh1990/yaml-rust
//!
//! # Examples
//!
//! ```
//! use std::collections::BTreeMap;
//!
//! fn main() -> Result<(), serde_yaml::Error> {
//!     // You have some type.
//!     let mut map = BTreeMap::new();
//!     map.insert("x".to_string(), 1.0);
//!     map.insert("y".to_string(), 2.0);
//!
//!     // Serialize it to a YAML string.
//!     let s = serde_yaml::to_string(&map)?;
//!     assert_eq!(s, "---\nx: 1.0\ny: 2.0");
//!
//!     // Deserialize it back to a Rust type.
//!     let deserialized_map: BTreeMap<String, f64> = serde_yaml::from_str(&s)?;
//!     assert_eq!(map, deserialized_map);
//!     Ok(())
//! }
//! ```
//!
//! ## Using Serde derive
//!
//! It can also be used with Serde's serialization code generator `serde_derive` to
//! handle structs and enums defined in your own program.
//!
//! ```
//! # use serde_derive::{Serialize, Deserialize};
//! use serde::{Serialize, Deserialize};
//!
//! #[derive(Debug, PartialEq, Serialize, Deserialize)]
//! struct Point {
//!     x: f64,
//!     y: f64,
//! }
//!
//! fn main() -> Result<(), serde_yaml::Error> {
//!     let point = Point { x: 1.0, y: 2.0 };
//!
//!     let s = serde_yaml::to_string(&point)?;
//!     assert_eq!(s, "---\nx: 1.0\ny: 2.0");
//!
//!     let deserialized_point: Point = serde_yaml::from_str(&s)?;
//!     assert_eq!(point, deserialized_point);
//!     Ok(())
//! }
//! ```

#![doc(html_root_url = "https://docs.rs/serde_yaml/0.8.11")]
#![deny(missing_docs)]
#![allow(unknown_lints, bare_trait_objects)]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints
#![cfg_attr(feature = "cargo-clippy", allow(redundant_field_names))]
// Whitelisted clippy_pedantic lints
#![cfg_attr(feature = "cargo-clippy", allow(
    // private Deserializer::next
    should_implement_trait,
    // things are often more readable this way
    cast_lossless,
    module_name_repetitions,
    single_match_else,
    use_self,
    // code is acceptable
    cast_possible_wrap,
    cast_precision_loss,
    cast_sign_loss,
    // not practical
    indexing_slicing,
    missing_docs_in_private_items,
    // not stable
    checked_conversions,
    empty_enum,
    // meh, some things won't fail
    result_unwrap_used,
))]

pub use crate::de::{from_reader, from_slice, from_str};
pub use crate::error::{Error, Location, Result};
pub use crate::mapping::Mapping;
pub use crate::ser::{to_string, to_vec, to_writer};
pub use crate::value::{from_value, to_value, Index, Number, Sequence, Value};

/// Entry points for deserializing with pre-existing state.
///
/// These functions are only exposed this way because we don't yet expose a
/// Deserializer type. Data formats that have a public Deserializer should not
/// copy these signatures.
pub mod seed {
    pub use super::de::{from_reader_seed, from_slice_seed, from_str_seed};
}

mod de;
mod error;
mod mapping;
mod number;
mod path;
mod ser;
mod value;
<commit_msg>Ignore must_use_candidate pedantic lint<commit_after>//! This crate is a Rust library for using the [Serde] serialization framework
//! with data in [YAML] file format.
//!
//! This library does not reimplement a YAML parser; it uses [yaml-rust] which
//! is a pure Rust YAML 1.2 implementation.
//!
//! [Serde]: https://github.com/serde-rs/serde
//! [YAML]: http://yaml.org
//! [yaml-rust]: https://github.com/chyh1990/yaml-rust
//!
//! # Examples
//!
//! ```
//! use std::collections::BTreeMap;
//!
//! fn main() -> Result<(), serde_yaml::Error> {
//!     // You have some type.
//!     let mut map = BTreeMap::new();
//!     map.insert("x".to_string(), 1.0);
//!     map.insert("y".to_string(), 2.0);
//!
//!     // Serialize it to a YAML string.
//!     let s = serde_yaml::to_string(&map)?;
//!     assert_eq!(s, "---\nx: 1.0\ny: 2.0");
//!
//!     // Deserialize it back to a Rust type.
//!     let deserialized_map: BTreeMap<String, f64> = serde_yaml::from_str(&s)?;
//!     assert_eq!(map, deserialized_map);
//!     Ok(())
//! }
//! ```
//!
//! ## Using Serde derive
//!
//! It can also be used with Serde's serialization code generator `serde_derive` to
//! handle structs and enums defined in your own program.
//!
//! ```
//! # use serde_derive::{Serialize, Deserialize};
//! use serde::{Serialize, Deserialize};
//!
//! #[derive(Debug, PartialEq, Serialize, Deserialize)]
//! struct Point {
//!     x: f64,
//!     y: f64,
//! }
//!
//! fn main() -> Result<(), serde_yaml::Error> {
//!     let point = Point { x: 1.0, y: 2.0 };
//!
//!     let s = serde_yaml::to_string(&point)?;
//!     assert_eq!(s, "---\nx: 1.0\ny: 2.0");
//!
//!     let deserialized_point: Point = serde_yaml::from_str(&s)?;
//!     assert_eq!(point, deserialized_point);
//!     Ok(())
//! }
//! ```

#![doc(html_root_url = "https://docs.rs/serde_yaml/0.8.11")]
#![deny(missing_docs)]
#![allow(unknown_lints, bare_trait_objects)]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints
#![cfg_attr(feature = "cargo-clippy", allow(redundant_field_names))]
// Whitelisted clippy_pedantic lints
#![cfg_attr(feature = "cargo-clippy", allow(
    // private Deserializer::next
    should_implement_trait,
    // things are often more readable this way
    cast_lossless,
    module_name_repetitions,
    single_match_else,
    use_self,
    // code is acceptable
    cast_possible_wrap,
    cast_precision_loss,
    cast_sign_loss,
    // not practical
    indexing_slicing,
    missing_docs_in_private_items,
    // not stable
    checked_conversions,
    empty_enum,
    // meh, some things won't fail
    result_unwrap_used,
    // noisy
    must_use_candidate,
))]

pub use crate::de::{from_reader, from_slice, from_str};
pub use crate::error::{Error, Location, Result};
pub use crate::mapping::Mapping;
pub use crate::ser::{to_string, to_vec, to_writer};
pub use crate::value::{from_value, to_value, Index, Number, Sequence, Value};

/// Entry points for deserializing with pre-existing state.
///
/// These functions are only exposed this way because we don't yet expose a
/// Deserializer type. Data formats that have a public Deserializer should not
/// copy these signatures.
pub mod seed {
    pub use super::de::{from_reader_seed, from_slice_seed, from_str_seed};
}

mod de;
mod error;
mod mapping;
mod number;
mod path;
mod ser;
mod value;
<|endoftext|>


<commit_before>//! This package contains just two macros, for the taking of array
//! references to slices of anything that can be sliced.
//!
//! # Examples
//!
//! Here is a simple example of slicing and dicing a slice into array
//! references with these macros.
//!
//! I would give a real example here, but I can't figure out how to
//! make my doctest actually load the macros...
//!
//! let mut foobar = [0; 512];
//! let bar = array_ref!(foobar, 0, u16, 8); // first 8 elements
//!

#![deny(warnings)]

#[cfg(test)]
extern crate quickcheck;

/// You can use `array_ref` to generate an array reference to a subset
/// of a sliceable bit of data (which could be an array, or a slice,
/// or a Vec).  The arguments are a bit clumsy
#[macro_export]
macro_rules! array_ref {
    ($arr:expr, $offset:expr, $t:ty, $len:expr) => {{
        {
            let sl = &$arr[$offset .. $offset + $len];
            let arrref: &[$t; $len] = unsafe {
                ::std::mem::transmute(sl.as_ptr())
            };
            arrref
        }
    }}
}

/// You can use `array_mut_ref` to generate a mutable array reference
/// to a subset of a sliceable bit of data (which could be an array,
/// or a slice, or a Vec).
#[macro_export]
macro_rules! array_mut_ref {
    ($arr:expr, $offset:expr, $t:ty, $len:expr) => {{
        {
            let sl = &mut $arr[$offset .. $offset + $len];
            let arrref: &mut [$t; $len] = unsafe {
                ::std::mem::transmute(sl.as_ptr())
            };
            arrref
        }
    }}
}

#[test]
#[should_panic]
fn checks_bounds() {
    let foo: [u8; 11] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    let bar = array_ref!(foo, 1, u8, 11);
    println!("{}", bar[0]);
}

#[test]
fn simple_case_works() {
    let mut foo: [u8; 11] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    let bar = array_ref!(foo, 2, u8, 3);
    println!("{}", bar.len());
    fn pr3(x: &[u8; 3]) {
        println!("[{} {} {}]", x[0], x[1], x[2]);
    }
    pr3(bar);
    pr3(array_ref!(foo, 0, u8, 3));
    fn zero2(x: &mut [u8; 2]) {
        x[0] = 0;
        x[1] = 0;
    }
    zero2(array_mut_ref!(foo, 8, u8, 2));
    pr3(array_ref!(foo, 8, u8, 3));
}

#[test]
fn check_array_ref_5() {
    fn f(data: Vec<u8>, offset: usize) -> quickcheck::TestResult {
        if data.len() < offset + 5 {
            return quickcheck::TestResult::discard();
        }
        let out = array_ref!(data, offset, u8, 5);
        quickcheck::TestResult::from_bool(out.len() == 5)
    }
    quickcheck::quickcheck(f as fn(Vec<u8>, usize) -> quickcheck::TestResult);
}

#[test]
fn check_array_ref_out_of_bounds_5() {
    fn f(data: Vec<u8>, offset: usize) -> quickcheck::TestResult {
        if data.len() >= offset + 5 {
            return quickcheck::TestResult::discard();
        }
        quickcheck::TestResult::must_fail(move || {
            array_ref!(data, offset, u8, 5);
        })
    }
    quickcheck::quickcheck(f as fn(Vec<u8>, usize) -> quickcheck::TestResult);
}

#[test]
fn check_array_mut_ref_7() {
    fn f(mut data: Vec<u8>, offset: usize) -> quickcheck::TestResult {
        if data.len() < offset + 7 {
            return quickcheck::TestResult::discard();
        }
        let out = array_mut_ref!(data, offset, u8, 7);
        out[6] = 3;
        quickcheck::TestResult::from_bool(out.len() == 7)
    }
    quickcheck::quickcheck(f as fn(Vec<u8>, usize) -> quickcheck::TestResult);
}

#[test]
fn check_array_mut_ref_out_of_bounds_32() {
    fn f(mut data: Vec<u8>, offset: usize) -> quickcheck::TestResult {
        if data.len() >= offset + 32 {
            return quickcheck::TestResult::discard();
        }
        quickcheck::TestResult::must_fail(move || {
            array_mut_ref!(data, offset, u8, 32);
        })
    }
    quickcheck::quickcheck(f as fn(Vec<u8>, usize) -> quickcheck::TestResult);
}
<commit_msg>changes as suggested by bluss (but not reordering arguments)<commit_after>//! This package contains just two macros, for the taking of array
//! references to slices of anything that can be sliced.
//!
//! # Examples
//!
//! Here is a simple example of slicing and dicing a slice into array
//! references with these macros.
//!
//! I would give a real example here, but I can't figure out how to
//! make my doctest actually load the macros...
//!
//! let mut foobar = [0; 512];
//! let bar = array_ref!(foobar, 0, u16, 8); // first 8 elements
//!

#![deny(warnings)]

#[cfg(test)]
extern crate quickcheck;

/// You can use `array_ref` to generate an array reference to a subset
/// of a sliceable bit of data (which could be an array, or a slice,
/// or a Vec).  The arguments are a bit clumsy
#[macro_export]
macro_rules! array_ref {
    ($arr:expr, $offset:expr, $elemty:ty, $len:expr) => {{
        {
            #[inline]
            unsafe fn as_array(slice: &[$elemty]) -> &[$elemty; $len] {
                &*(slice.as_ptr() as *const [_; $len])
            }
            let a: usize = $offset;
            let l: usize = $len;
            unsafe {
                as_array(&$arr[a..a.saturating_add(l)])
            }
        }
    }}
}

/// You can use `array_mut_ref` to generate a mutable array reference
/// to a subset of a sliceable bit of data (which could be an array,
/// or a slice, or a Vec).
#[macro_export]
macro_rules! array_mut_ref {
    ($arr:expr, $offset:expr, $elemty:ty, $len:expr) => {{
        {
            #[inline]
            unsafe fn as_array(slice: &mut[$elemty]) -> &mut[$elemty; $len] {
                &mut *(slice.as_mut_ptr() as *mut [_; $len])
            }
            let a: usize = $offset;
            let l: usize = $len;
            unsafe {
                as_array(&mut $arr[a..a.saturating_add(l)])
            }
        }
    }}
}

#[test]
#[should_panic]
fn checks_bounds() {
    let foo: [u8; 11] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    let bar = array_ref!(foo, 1, u8, 11);
    println!("{}", bar[0]);
}

#[test]
fn simple_case_works() {
    let mut foo: [u8; 11] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    fn pr3(x: &[u8; 3]) {
        println!("[{} {} {}]", x[0], x[1], x[2]);
    }
    {
        let bar = array_ref!(foo, 2, u8, 3);
        println!("{}", bar.len());
        pr3(bar);
    }
    pr3(array_ref!(foo, 0, u8, 3));
    fn zero2(x: &mut [u8; 2]) {
        x[0] = 0;
        x[1] = 0;
    }
    zero2(array_mut_ref!(foo, 8, u8, 2));
    pr3(array_ref!(foo, 8, u8, 3));
}

#[test]
fn check_array_ref_5() {
    fn f(data: Vec<u8>, offset: usize) -> quickcheck::TestResult {
        if data.len() < offset + 5 {
            return quickcheck::TestResult::discard();
        }
        let out = array_ref!(data, offset, u8, 5);
        quickcheck::TestResult::from_bool(out.len() == 5)
    }
    quickcheck::quickcheck(f as fn(Vec<u8>, usize) -> quickcheck::TestResult);
}

#[test]
fn check_array_ref_out_of_bounds_5() {
    fn f(data: Vec<u8>, offset: usize) -> quickcheck::TestResult {
        if data.len() >= offset + 5 {
            return quickcheck::TestResult::discard();
        }
        quickcheck::TestResult::must_fail(move || {
            array_ref!(data, offset, u8, 5);
        })
    }
    quickcheck::quickcheck(f as fn(Vec<u8>, usize) -> quickcheck::TestResult);
}

#[test]
fn check_array_mut_ref_7() {
    fn f(mut data: Vec<u8>, offset: usize) -> quickcheck::TestResult {
        if data.len() < offset + 7 {
            return quickcheck::TestResult::discard();
        }
        let out = array_mut_ref!(data, offset, u8, 7);
        out[6] = 3;
        quickcheck::TestResult::from_bool(out.len() == 7)
    }
    quickcheck::quickcheck(f as fn(Vec<u8>, usize) -> quickcheck::TestResult);
}

#[test]
fn check_array_mut_ref_out_of_bounds_32() {
    fn f(mut data: Vec<u8>, offset: usize) -> quickcheck::TestResult {
        if data.len() >= offset + 32 {
            return quickcheck::TestResult::discard();
        }
        quickcheck::TestResult::must_fail(move || {
            array_mut_ref!(data, offset, u8, 32);
        })
    }
    quickcheck::quickcheck(f as fn(Vec<u8>, usize) -> quickcheck::TestResult);
}
<|endoftext|>


<commit_before>// #![deny(missing_docs,
//         missing_debug_implementations, missing_copy_implementations,
//         trivial_casts, trivial_numeric_casts,
//         unsafe_code,
//         unstable_features,
//         unused_import_braces, unused_qualifications)]
extern crate rustc_serialize;
extern crate csv;

pub mod pokemon {
    use std::io::prelude::*;
    use std::fs::File;
    use std::path::Path;
    // use rustc_serialize::json;
    use csv;

    pub struct Row { }

    #[derive(RustcDecodable, RustcEncodable, Debug)]
    pub struct Pokemon {
        species: i32,
        language: i32,
        name: String,
        genus: Option<String>,
    }

    impl Clone for Pokemon {
        fn clone(&self) -> Pokemon { *self }
    }

    #[allow(dead_code, unused_variables, unused_mut)]
    pub fn get_pokemon() -> Vec<Pokemon> {

        fn search<P: AsRef<Path>>(file_path: P) -> Vec<Pokemon> {
            let mut found:Vec<Pokemon> = vec![];
            let file = File::open(file_path).unwrap();
            let mut rdr = csv::Reader::from_reader(file).has_headers(true);

            let rows:Vec<Pokemon> = rdr.decode().collect::<csv::Result<Vec<Pokemon>>>().unwrap();

            rows
        }

        search("data/en.csv")
    }

    #[allow(dead_code)]
    pub fn get_all() {

    }

    #[allow(dead_code)]
    pub fn get_random() {
        // let pokes = get_pokemon();
        // pokes.0
    }

    #[allow(dead_code, unused_variables)]
    pub fn get_name(id: i32) -> Pokemon {
        let mut poke = &get_pokemon().clone();
        poke[0]
    }

}
<commit_msg>write get_pokemon() function<commit_after>// #![deny(missing_docs,
//         missing_debug_implementations, missing_copy_implementations,
//         trivial_casts, trivial_numeric_casts,
//         unsafe_code,
//         unstable_features,
//         unused_import_braces, unused_qualifications)]
extern crate rustc_serialize;
extern crate csv;

pub mod pokemon {
    use std::io::prelude::*;
    use std::fs::File;
    use std::path::Path;
    // use rustc_serialize::json;
    use csv;

    pub struct Row { }

    #[derive(RustcDecodable, RustcEncodable, Clone, Debug)]
    pub struct Pokemon {
        species: i32,
        language: i32,
        name: String,
        genus: Option<String>,
    }

    #[allow(dead_code, unused_variables, unused_mut)]
    pub fn get_pokemon() -> Vec<Pokemon> {

        fn search<P: AsRef<Path>>(file_path: P) -> Vec<Pokemon> {
            let mut found:Vec<Pokemon> = vec![];
            let file = File::open(file_path).unwrap();
            let mut rdr = csv::Reader::from_reader(file).has_headers(true);

            let rows:Vec<Pokemon> = rdr.decode().collect::<csv::Result<Vec<Pokemon>>>().unwrap();

            rows
        }

        search("data/en.csv")
    }

    #[allow(dead_code)]
    pub fn get_all() {

    }

    #[allow(dead_code)]
    pub fn get_random() {
        // let pokes = get_pokemon();
        // pokes.0
    }

    #[allow(dead_code, unused_variables)]
    pub fn get_name(id: i32) -> Pokemon {
        let mut poke = &mut *get_pokemon().clone();
        poke[0]
    }

}
<|endoftext|>


<commit_before>//! # Derive Getters
//!
//! Macro for autogenerating getters. Can only be used on named structs. Will generate
//! getters that will reside in the struct namespace through an impl. If the struct already
//! has a method defined with the same name as one of the fields, this crate will barrel on
//! and you'll end up with a duplicate method name.
//!
//! ## Usage
//! Add to your project Cargo.toml;
//! ```toml
//! [dependencies]
//! derive-getters = "0.0.7"
//! ```
//!
//! In lib.rs or main.rs;
//! ```
//! #[macro_use]
//! extern crate derive_getters;
//! #
//! # fn main() { }
//! ```
//!
//! ## Example
//! ```
//! #[macro_use]
//! extern crate derive_getters;
//!
//! #[derive(Getters)]
//! struct Number {
//!     num: u64,
//! }
//!
//! fn main() {
//!     let number = Number { num: 655 };
//!     assert!(number.num() == &655);
//! }
//! ```
//!
//! Here, a method called `num()` has been created for the `Number` struct which gives a
//! reference to the `num` field.

extern crate proc_macro;

use std::convert::From;
use std::iter::Extend;

use quote::quote;
use syn::{Data, Fields, DeriveInput, parse_macro_input, FieldsNamed, Generics, GenericParam, punctuated::Punctuated, Token, Ident};

static INVALID_STRUCT: &str = "Struct must be a named struct. Not unnamed or unit.";
static INVALID_VARIANT: &str = "Variant must be a struct. Not an enum or union.";

fn isolate_named_fields<'a>(ast: &'a DeriveInput) -> Result<&'a FieldsNamed, &'static str> {
    match ast.data {
        Data::Struct(ref structure) => {
            match structure.fields {
                Fields::Named(ref fields) => Ok(fields),
                Fields::Unnamed(_) | Fields::Unit => Err(INVALID_STRUCT),
            }
        },
        Data::Enum(_) | Data::Union(_) => Err(INVALID_VARIANT),
    }
}

fn getters_from_fields<'a>(fields: &'a FieldsNamed) -> Vec<proc_macro2::TokenStream> {
    fields.named
        .iter()
        .map(|field| {
            let field_name = field.ident.as_ref().unwrap(); // Must never fail.
            let method_name = field_name; // It's a getter method.
            let return_type = &field.ty;

            quote!(
                pub fn #method_name(&self) -> &#return_type {
                    &self.#field_name
                }
            )
        })
        .collect()
}

/// Extract the generics that need to be inserted after the `impl` but before the struct
/// name. If there are no generics, the `TokenStream` shall be empty.
fn after_impl_generics<'a>(generics: &'a Generics) -> proc_macro2::TokenStream {
    // If we have a `<` and `>` there's going to be generics.
    if generics.lt_token.is_some() && generics.gt_token.is_some() {
        // Since this is meant to come after the `impl`, we slurp the whole thing.
        let params = &generics.params;
        quote!(<#params>)
    } else {
        proc_macro2::TokenStream::new()
    }
}

/// Same as above but this time we only want the idents as the generics will be inserted
/// after the struct name on the `impl` line.
///
/// ## NOTE
/// We are only bothering with type parameters! Issue 1. Issue 2 (lifetimes) will come...
fn after_struct_generics<'a>(generics: &'a Generics) -> proc_macro2::TokenStream {
    // If we have a `<` and `>` there's going to be generics.
    if generics.lt_token.is_some() && generics.gt_token.is_some() {
        // We only want the idents for type parameters.
        let idents = generics.params
            .iter()
            .filter_map(|gp| match gp { // I didn't want to use filter_map! >:(
                GenericParam::Type(tp) => Some(tp),
                _ => None,
            })
            .fold(Punctuated::new(), |mut idents, tp| -> Punctuated<Ident, Token![,]> {
                idents.push(tp.ident.clone());
                idents
            });
        quote!(<#idents>)
    } else {
        proc_macro2::TokenStream::new()
    }
}

/// Derive getters into a seperate trait for the named struct.
#[proc_macro_derive(Getters)]
pub fn getters(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let ast = parse_macro_input!(input as DeriveInput);

    let struct_name = &ast.ident;

    let fields = isolate_named_fields(&ast).unwrap();
    let methods = getters_from_fields(fields);
    let impl_generics = after_impl_generics(&ast.generics);
    let struct_generics = after_struct_generics(&ast.generics);
    let where_clause = &ast.generics.where_clause;

    quote!(
        impl #impl_generics #struct_name #struct_generics
            #where_clause
        {
            #(#methods)*
        }
    ).into()
}
<commit_msg>Update doc comments<commit_after>//! # Derive Getters
//! Macro for autogenerating getters. Can only be used on named structs. Will generate
//! getters that will reside in the struct namespace through an impl.
//!
//! ## Derives
//! Only named structs can derive `Getters`. Unit structs, unnamed structs, enums and
//! unions cannot derive `Getters`.
//!
//! ## Methods generated
//! The getter methods generated shall bear the same name as the struct fields and be
//! publicly visible. The methods return an immutable reference to the struct field of the
//! same name. If there is already a method defined with that name there'll be a collision.
//!
//! ## Usage
//! Add to your project Cargo.toml;
//! ```toml
//! [dependencies]
//! derive-getters = "0.0.7"
//! ```
//!
//! In lib.rs or main.rs;
//! ```
//! #[macro_use]
//! extern crate derive_getters;
//! #
//! # fn main() { }
//! ```
//!
//! ### Named Structs
//! ```
//! #[macro_use]
//! extern crate derive_getters;
//!
//! #[derive(Getters)]
//! struct Number {
//!     num: u64,
//! }
//!
//! fn main() {
//!     let number = Number { num: 655 };
//!     assert!(number.num() == &655);
//! }
//! ```
//!
//! Here, a method called `num()` has been created for the `Number` struct which gives a
//! reference to the `num` field.
//!
//! ### Generic Types
//! This macro can also derive on structs that have simple generic types. For example;
//! ```
//! # #[macro_use]
//! # extern crate derive_getters;
//! #[derive(Getters)]
//! struct Generic<T, U> {
//!     gen_t: T,
//!     gen_u: U,
//! }
//! #
//! # fn main() { }
//! ```
//!
//! The macro can also handle generic types with trait bounds. For example;
//! ```
//! # #[macro_use]
//! # extern crate derive_getters;
//! #[derive(Getters)]
//! struct Generic<T: Clone, U: Copy> {
//!     gen_t: T,
//!     gen_u: U,
//! }
//! #
//! # fn main() { }
//! ```
//! The trait bounds can also be declared in a `where` clause.
//!
//! ## Cannot Do
//! Lifetimes and const generics aren't handled by this macro nor are they tested.

extern crate proc_macro;

use std::convert::From;
use std::iter::Extend;

use quote::quote;
use syn::{Data, Fields, DeriveInput, parse_macro_input, FieldsNamed, Generics, GenericParam, punctuated::Punctuated, Token, Ident};

static INVALID_STRUCT: &str = "Struct must be a named struct. Not unnamed or unit.";
static INVALID_VARIANT: &str = "Variant must be a struct. Not an enum or union.";

fn isolate_named_fields<'a>(ast: &'a DeriveInput) -> Result<&'a FieldsNamed, &'static str> {
    match ast.data {
        Data::Struct(ref structure) => {
            match structure.fields {
                Fields::Named(ref fields) => Ok(fields),
                Fields::Unnamed(_) | Fields::Unit => Err(INVALID_STRUCT),
            }
        },
        Data::Enum(_) | Data::Union(_) => Err(INVALID_VARIANT),
    }
}

fn getters_from_fields<'a>(fields: &'a FieldsNamed) -> Vec<proc_macro2::TokenStream> {
    fields.named
        .iter()
        .map(|field| {
            let field_name = field.ident.as_ref().unwrap(); // Must never fail.
            let method_name = field_name; // It's a getter method.
            let return_type = &field.ty;

            quote!(
                pub fn #method_name(&self) -> &#return_type {
                    &self.#field_name
                }
            )
        })
        .collect()
}

/// Extract the generics that need to be inserted after the `impl` but before the struct
/// name. If there are no generics, the `TokenStream` shall be empty.
fn after_impl_generics<'a>(generics: &'a Generics) -> proc_macro2::TokenStream {
    // If we have a `<` and `>` there's going to be generics.
    if generics.lt_token.is_some() && generics.gt_token.is_some() {
        // Since this is meant to come after the `impl`, we slurp the whole thing.
        let params = &generics.params;
        quote!(<#params>)
    } else {
        proc_macro2::TokenStream::new()
    }
}

/// Same as above but this time we only want the idents as the generics will be inserted
/// after the struct name on the `impl` line.
///
/// ## NOTE
/// We are only bothering with type parameters! Issue 1. Issue 2 (lifetimes) will come...
fn after_struct_generics<'a>(generics: &'a Generics) -> proc_macro2::TokenStream {
    // If we have a `<` and `>` there's going to be generics.
    if generics.lt_token.is_some() && generics.gt_token.is_some() {
        // We only want the idents for type parameters.
        let idents = generics.params
            .iter()
            .filter_map(|gp| match gp { // I didn't want to use filter_map! >:(
                GenericParam::Type(tp) => Some(tp),
                _ => None,
            })
            .fold(Punctuated::new(), |mut idents, tp| -> Punctuated<Ident, Token![,]> {
                idents.push(tp.ident.clone());
                idents
            });
        quote!(<#idents>)
    } else {
        proc_macro2::TokenStream::new()
    }
}

/// # Derive getters
/// Generate getter methods for all named struct fields in a seperate struct `impl` block.
/// Getter methods share the name of the field they're 'getting'. Methods return an
/// immutable reference to the field.
#[proc_macro_derive(Getters)]
pub fn getters(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let ast = parse_macro_input!(input as DeriveInput);

    let struct_name = &ast.ident;

    let fields = isolate_named_fields(&ast).unwrap();
    let methods = getters_from_fields(fields);
    let impl_generics = after_impl_generics(&ast.generics);
    let struct_generics = after_struct_generics(&ast.generics);
    let where_clause = &ast.generics.where_clause;

    quote!(
        impl #impl_generics #struct_name #struct_generics
            #where_clause
        {
            #(#methods)*
        }
    ).into()
}
<|endoftext|>


<commit_before>//! gcm
//! ===
//!
//! # Usage:
//!
//! Add this to `Cargo.toml`:
//!
//! ```ignore
//! [dependencies]
//! gcm = "0.1.4"
//! ```
//!
//! then add this to your crate root:
//!
//! ```ignore
//! extern crate gcm;
//! ```
//!
//! # Examples:
//!
//! Here is an example to send out a GCM Message with some custom data:
//!
//! ```no_run
//! use gcm::Message;
//! use std::collections::HashMap;
//!
//! let mut map = HashMap::new();
//! map.insert("message", "Howdy!");
//!
//! let result = Message::new("<registration id>")
//!     .data(map)
//!     .send("<GCM API Key>");
//! ```
//!
//! To send a message using GCM Notifications, we first build the notification:
//!
//! ```rust
//! use gcm::{Message, NotificationBuilder};
//!
//! let notification = NotificationBuilder::new("Hey!")
//!     .body("Do you want to catch up later?")
//!     .finalize();
//! ```
//! And then set it in the message, before sending it:
//!
//! ```no_run
//! # use gcm::{Message, NotificationBuilder};
//! # let notification = NotificationBuilder::new("Hey!")
//! #     .body("Do you want to catch up later?")
//! #     .finalize();
//! let result = Message::new("<registration id>")
//!     .notification(notification)
//!     .send("<GCM API Key>");
//! ```
//! You can now handle the result accordingly:
//!
//! ```no_run
//! # use gcm::{Message, NotificationBuilder};
//! # let notification = NotificationBuilder::new("Hey!")
//! #     .body("Do you want to catch up later?")
//! #     .finalize();
//! # let result = Message::new("<registration id>")
//! #     .notification(notification)
//! #     .send("<GCM API Key>");
//! match result {
//!   Ok(response) => println!("message_id: {:?}", response.message_id),
//!   Err(error) => println!("Error: {:?}", error),
//! }
//! ```

extern crate rustc_serialize;
extern crate curl;

mod message;
pub use message::*;
mod notification;
pub use notification::*;

pub use message::response::GcmError as Error;

<commit_msg>Adjust extern crate declaration<commit_after>//! gcm
//! ===
//!
//! # Usage:
//!
//! Add this to `Cargo.toml`:
//!
//! ```ignore
//! [dependencies]
//! gcm = "0.1.4"
//! ```
//!
//! then add this to your crate root:
//!
//! ```ignore
//! extern crate gcm;
//! ```
//!
//! # Examples:
//!
//! Here is an example to send out a GCM Message with some custom data:
//!
//! ```no_run
//! use gcm::Message;
//! use std::collections::HashMap;
//!
//! let mut map = HashMap::new();
//! map.insert("message", "Howdy!");
//!
//! let result = Message::new("<registration id>")
//!     .data(map)
//!     .send("<GCM API Key>");
//! ```
//!
//! To send a message using GCM Notifications, we first build the notification:
//!
//! ```rust
//! use gcm::{Message, NotificationBuilder};
//!
//! let notification = NotificationBuilder::new("Hey!")
//!     .body("Do you want to catch up later?")
//!     .finalize();
//! ```
//! And then set it in the message, before sending it:
//!
//! ```no_run
//! # use gcm::{Message, NotificationBuilder};
//! # let notification = NotificationBuilder::new("Hey!")
//! #     .body("Do you want to catch up later?")
//! #     .finalize();
//! let result = Message::new("<registration id>")
//!     .notification(notification)
//!     .send("<GCM API Key>");
//! ```
//! You can now handle the result accordingly:
//!
//! ```no_run
//! # use gcm::{Message, NotificationBuilder};
//! # let notification = NotificationBuilder::new("Hey!")
//! #     .body("Do you want to catch up later?")
//! #     .finalize();
//! # let result = Message::new("<registration id>")
//! #     .notification(notification)
//! #     .send("<GCM API Key>");
//! match result {
//!   Ok(response) => println!("message_id: {:?}", response.message_id),
//!   Err(error) => println!("Error: {:?}", error),
//! }
//! ```

extern crate rustc_serialize;
extern crate hyper;

mod message;
pub use message::*;
mod notification;
pub use notification::*;

pub use message::response::GcmError as Error;

<|endoftext|>


<commit_before>// tag_safe
//
// A linting plugin to flag calls to methods not marked "tag_safe"
// from methods marked "tag_safe".
//
// Author: John Hodge (thePowersGang/Mutabah)
//
// TODO: Support '#[tag_unsafe(type)]' which is used when a method has no marker
// - Allows default safe fallback, with upwards propagation.
//
#![crate_name="tag_safe"]
#![crate_type="dylib"]
#![feature(plugin_registrar, rustc_private)]

#[macro_use]
extern crate log;

extern crate syntax;
#[macro_use]
extern crate rustc;

extern crate rustc_front;

use syntax::ast;
use rustc::middle::def_id::DefId;
use rustc_front::visit;
use syntax::codemap::Span;
use rustc::lint::{self, LintContext, LintPass, LateLintPass, LintArray};
use rustc::plugin::Registry;
use rustc::middle::{def,ty};
use rustc_front::hir;
use syntax::attr::AttrMetaMethods;

declare_lint!(NOT_TAGGED_SAFE, Warn, "Warn about use of non-tagged methods within tagged function");

#[derive(Copy,Clone,Debug)]
enum SafetyType
{
    Safe,
    Unsafe,
    Unknown,
}

#[derive(Default)]
struct Pass
{
    /// Cache of flag types
    flag_types: Vec<String>,
    /// Node => (Type => IsSafe)
    flag_cache: ::rustc::util::nodemap::NodeMap< ::rustc::util::nodemap::FnvHashMap<usize, SafetyType> >,

    lvl: usize,
}

struct Visitor<'a, 'tcx: 'a, F: FnMut(&Span) + 'a>
{
    pass: &'a mut Pass,
    tcx: &'a ty::ctxt<'tcx>,
    name: &'a str,
    unknown_assume: bool,
    cb: F,
}

// Hack to provide indenting in debug calls
struct Indent(usize);
impl ::std::fmt::Display for Indent {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        for s in ::std::iter::repeat(" ").take(self.0) {
            try!(write!(f, "{}", s));
        }
        Ok( () )
    }
}

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array!(NOT_TAGGED_SAFE)
    }
}

impl LateLintPass for Pass {
    fn check_fn(&mut self, cx: &lint::LateContext, _kind: ::rustc_front::visit::FnKind, _decl: &hir::FnDecl, body: &hir::Block, _: Span, id: ast::NodeId) {
        let attrs = cx.tcx.map.attrs(id);
        for ty in attrs.iter()
            .filter(|a| a.check_name("tag_safe"))
            .filter_map(|a| a.meta_item_list())
            .flat_map(|x| x.iter())
        {
            // Search body for calls to non safe methods
            let mut v = Visitor{
                    pass: self, tcx: cx.tcx, name: &ty.name(),
                    // - Assumes an untagged method is unsafe
                    unknown_assume: false,
                    cb: |span| {
                            cx.span_lint(NOT_TAGGED_SAFE, *span,
                                &format!("Calling {}-unsafe method from a #[tag_safe({})] method", ty.name(), ty.name())[..]
                                );
                        },
                    };
            debug!("Method {:?} is marked safe '{}'", id, ty.name());
            visit::walk_block(&mut v, body);
        }
    }
}

impl Pass
{
    // Searches for the relevant marker
    fn check_for_marker(tcx: &ty::ctxt, id: ast::NodeId, marker: &str, name: &str) -> bool
    {
        debug!("Checking for marker {}({}) on {:?}", marker, name, id);
        tcx.map.attrs(id).iter()
            .filter_map( |a| if a.check_name(marker) { a.meta_item_list() } else { None })
            .flat_map(|x| x.iter())
            .any(|a| a.name() == name)
    }

    /// Recursively check that the provided function is either safe or unsafe.
    // Used to avoid excessive annotating
    fn recurse_fcn_body(&mut self, tcx: &ty::ctxt, node_id: ast::NodeId, name_id: usize, name: &str, unknown_assume: bool) -> bool
    {
        // Cache this method as unknown (to prevent infinite recursion)
        self.flag_cache.entry(node_id)
            .or_insert(Default::default())
            .insert(name_id, SafetyType::Unknown)
            ;

        // and apply a visitor to all
        match tcx.map.get(node_id)
        {
        rustc::front::map::NodeItem(i) =>
            match i.node {
            hir::ItemFn(_, _, _, _, _, ref body) => {
                // Enumerate this function's code, recursively checking for a call to an unsafe method
                let mut is_safe = true;
                {
                    let mut v = Visitor {
                        pass: self, tcx: tcx, name: name,
                        unknown_assume: true,
                        cb: |_| { is_safe = false; }
                        };
                    visit::walk_block(&mut v, body);
                }
                is_safe
                },
            _ => unknown_assume,
            },
        rustc::front::map::NodeImplItem(i) =>
            match i.node {
            hir::MethodImplItem(_, ref body) => {
                let mut is_safe = true;
                {
                    let mut v = Visitor {
                        pass: self, tcx: tcx, name: name,
                        unknown_assume: true,
                        cb: |_| { is_safe = false; }
                        };
                    visit::walk_block(&mut v, body);
                }
                is_safe
                },
            _ => unknown_assume,
            },
        rustc::front::map::NodeForeignItem(i) =>
            if Self::check_for_marker(tcx, i.id, "tag_safe", name) {
                true
            }
            else if Self::check_for_marker(tcx, i.id, "tag_unsafe", name) {
                false
            }
            else {
                unknown_assume
            },
        v @ _ => {
            error!("Node ID {} points to non-item {:?}", node_id, v);
            unknown_assume
            }
        }
    }

    /// Check that a method within this crate is safe with the provided tag
    fn crate_method_is_safe(&mut self, tcx: &ty::ctxt, node_id: ast::NodeId, name: &str, unknown_assume: bool) -> bool
    {
        // Obtain tag name ID (avoids storing a string in the map)
        let name_id =
            match self.flag_types.iter().position(|a| *a == name)
            {
            Some(v) => v,
            None => {
                self.flag_types.push( String::from(name) );
                self.flag_types.len() - 1
                },
            };

        // Check cache first
        if let Some(&st) = self.flag_cache.get(&node_id).and_then(|a| a.get(&name_id))
        {
            match st
            {
            SafetyType::Safe => true,
            SafetyType::Unsafe => false,
            SafetyType::Unknown => unknown_assume,
            }
        }
        else
        {
            // Search for a safety marker, possibly recursing
            let is_safe =
                if Self::check_for_marker(tcx, node_id, "tag_safe", name) {
                    true
                }
                else if Self::check_for_marker(tcx, node_id, "tag_unsafe", name) {
                    false
                }
                else {
                    self.recurse_fcn_body(tcx, node_id, name_id, name, unknown_assume)
                };
            // Save resultant value
            self.flag_cache.entry(node_id)
                .or_insert(Default::default())
                .insert(name_id, if is_safe { SafetyType::Safe } else { SafetyType::Unsafe })
                ;
            is_safe
        }
    }

    /// Locate a #[tag_safe(<name>)] attribute on the passed item
    pub fn method_is_safe(&mut self, tcx: &ty::ctxt, id: DefId, name: &str, unknown_assume: bool) -> bool
    {
        debug!("{}Checking method {:?} (A {})", Indent(self.lvl), id, unknown_assume);
        self.lvl += 1;
        let rv = if id.krate == 0 {
                self.crate_method_is_safe(tcx, tcx.map.as_local_node_id(id).unwrap(), name, unknown_assume)
            }
            else {
                for a in tcx.get_attrs(id).iter()
                {
                    if a.check_name("tag_safe") {
                        if a.meta_item_list().iter().flat_map(|a| a.iter()).any(|a| a.name() == name) {
                            return true;
                        }
                    }
                    if a.check_name("tag_unsafe") {
                        if a.meta_item_list().iter().flat_map(|a| a.iter()).any(|a| a.name() == name) {
                            return false;
                        }
                    }
                }
                warn!("TODO: Crate ID non-zero {:?} (assuming safe)", id);
                // TODO: Check the crate import for an annotation
                true
            };
        self.lvl -= 1;
        debug!("{}Checking method {:?} = {}", Indent(self.lvl), id, rv);
        rv
    }
}

impl<'a, 'tcx: 'a, F: FnMut(&Span)> visit::Visitor<'a> for Visitor<'a,'tcx, F>
{
    // Locate function/method calls in a code block
    // - uses visit_expr_post because it doesn't _need_ to do anything
    fn visit_expr_post(&mut self, ex: &'a hir::Expr) {
        match ex.node
        {
        // Call expressions - check that it's a path call
        hir::ExprCall(ref fcn, _) =>
            match fcn.node
            {
            hir::ExprPath(ref _qs, ref _p) => {
                    if let def::DefFn(did, _) = self.tcx.resolve_expr(&fcn) {
                        // Check for a safety tag
                        if !self.pass.method_is_safe(self.tcx, did, self.name, self.unknown_assume)
                        {
                            (self.cb)(&ex.span);
                        }
                    }
                },
            _ => {},
            },

        // Method call expressions - get the relevant method
        hir::ExprMethodCall(ref _id, ref _tys, ref _exprs) =>
            {
                let tables = self.tcx.tables.borrow();
                let mm = &tables.method_map;

                let callee = mm.get( &ty::MethodCall::expr(ex.id) ).unwrap();
                let id = callee.def_id;

                //if let ty::MethodStatic(id) = callee.origin {
                        // Check for a safety tag
                        if !self.pass.method_is_safe(self.tcx, id, self.name, self.unknown_assume) {
                            (self.cb)(&ex.span);
                        }
                //}
            },

        // Ignore any other type of node
        _ => {},
        }
    }
}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    use syntax::feature_gate::AttributeType;
    reg.register_late_lint_pass( Box::new(Pass::default()) );

    reg.register_attribute(String::from("tag_safe"),   AttributeType::Whitelisted);
    reg.register_attribute(String::from("tag_unsafe"), AttributeType::Whitelisted);
}

// vim: ts=4 expandtab sw=4
<commit_msg>Fix for latest nightly<commit_after>// tag_safe
//
// A linting plugin to flag calls to methods not marked "tag_safe"
// from methods marked "tag_safe".
//
// Author: John Hodge (thePowersGang/Mutabah)
//
// TODO: Support '#[tag_unsafe(type)]' which is used when a method has no marker
// - Allows default safe fallback, with upwards propagation.
//
#![crate_name="tag_safe"]
#![crate_type="dylib"]
#![feature(plugin_registrar, rustc_private)]

#[macro_use]
extern crate log;

extern crate syntax;
#[macro_use]
extern crate rustc;

extern crate rustc_front;

use syntax::ast;
use rustc::middle::def_id::DefId;
use rustc_front::intravisit;
use syntax::codemap::Span;
use rustc::lint::{self, LintContext, LintPass, LateLintPass, LintArray};
use rustc::plugin::Registry;
use rustc::middle::{def,ty};
use rustc_front::hir;
use syntax::attr::AttrMetaMethods;

declare_lint!(NOT_TAGGED_SAFE, Warn, "Warn about use of non-tagged methods within tagged function");

#[derive(Copy,Clone,Debug)]
enum SafetyType
{
    Safe,
    Unsafe,
    Unknown,
}

#[derive(Default)]
struct Pass
{
    /// Cache of flag types
    flag_types: Vec<String>,
    /// Node => (Type => IsSafe)
    flag_cache: ::rustc::util::nodemap::NodeMap< ::rustc::util::nodemap::FnvHashMap<usize, SafetyType> >,

    lvl: usize,
}

struct Visitor<'a, 'tcx: 'a, F: FnMut(&Span) + 'a>
{
    pass: &'a mut Pass,
    tcx: &'a ty::ctxt<'tcx>,
    name: &'a str,
    unknown_assume: bool,
    cb: F,
}

// Hack to provide indenting in debug calls
struct Indent(usize);
impl ::std::fmt::Display for Indent {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        for s in ::std::iter::repeat(" ").take(self.0) {
            try!(write!(f, "{}", s));
        }
        Ok( () )
    }
}

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array!(NOT_TAGGED_SAFE)
    }
}

impl LateLintPass for Pass {
    fn check_fn(&mut self, cx: &lint::LateContext, _kind: ::rustc_front::intravisit::FnKind, _decl: &hir::FnDecl, body: &hir::Block, _: Span, id: ast::NodeId) {
        let attrs = cx.tcx.map.attrs(id);
        for ty in attrs.iter()
            .filter(|a| a.check_name("tag_safe"))
            .filter_map(|a| a.meta_item_list())
            .flat_map(|x| x.iter())
        {
            // Search body for calls to non safe methods
            let mut v = Visitor{
                    pass: self, tcx: cx.tcx, name: &ty.name(),
                    // - Assumes an untagged method is unsafe
                    unknown_assume: false,
                    cb: |span| {
                            cx.span_lint(NOT_TAGGED_SAFE, *span,
                                &format!("Calling {}-unsafe method from a #[tag_safe({})] method", ty.name(), ty.name())[..]
                                );
                        },
                    };
            debug!("Method {:?} is marked safe '{}'", id, ty.name());
            intravisit::walk_block(&mut v, body);
        }
    }
}

impl Pass
{
    // Searches for the relevant marker
    fn check_for_marker(tcx: &ty::ctxt, id: ast::NodeId, marker: &str, name: &str) -> bool
    {
        debug!("Checking for marker {}({}) on {:?}", marker, name, id);
        tcx.map.attrs(id).iter()
            .filter_map( |a| if a.check_name(marker) { a.meta_item_list() } else { None })
            .flat_map(|x| x.iter())
            .any(|a| a.name() == name)
    }

    /// Recursively check that the provided function is either safe or unsafe.
    // Used to avoid excessive annotating
    fn recurse_fcn_body(&mut self, tcx: &ty::ctxt, node_id: ast::NodeId, name_id: usize, name: &str, unknown_assume: bool) -> bool
    {
        // Cache this method as unknown (to prevent infinite recursion)
        self.flag_cache.entry(node_id)
            .or_insert(Default::default())
            .insert(name_id, SafetyType::Unknown)
            ;

        // and apply a visitor to all
        match tcx.map.get(node_id)
        {
        rustc::front::map::NodeItem(i) =>
            match i.node {
            hir::ItemFn(_, _, _, _, _, ref body) => {
                // Enumerate this function's code, recursively checking for a call to an unsafe method
                let mut is_safe = true;
                {
                    let mut v = Visitor {
                        pass: self, tcx: tcx, name: name,
                        unknown_assume: true,
                        cb: |_| { is_safe = false; }
                        };
                    intravisit::walk_block(&mut v, body);
                }
                is_safe
                },
            _ => unknown_assume,
            },
        rustc::front::map::NodeImplItem(i) =>
            match i.node {
            hir::ImplItemKind::Method(_, ref body) => {
                let mut is_safe = true;
                {
                    let mut v = Visitor {
                        pass: self, tcx: tcx, name: name,
                        unknown_assume: true,
                        cb: |_| { is_safe = false; }
                        };
                    intravisit::walk_block(&mut v, body);
                }
                is_safe
                },
            _ => unknown_assume,
            },
        rustc::front::map::NodeForeignItem(i) =>
            if Self::check_for_marker(tcx, i.id, "tag_safe", name) {
                true
            }
            else if Self::check_for_marker(tcx, i.id, "tag_unsafe", name) {
                false
            }
            else {
                unknown_assume
            },
        v @ _ => {
            error!("Node ID {} points to non-item {:?}", node_id, v);
            unknown_assume
            }
        }
    }

    /// Check that a method within this crate is safe with the provided tag
    fn crate_method_is_safe(&mut self, tcx: &ty::ctxt, node_id: ast::NodeId, name: &str, unknown_assume: bool) -> bool
    {
        // Obtain tag name ID (avoids storing a string in the map)
        let name_id =
            match self.flag_types.iter().position(|a| *a == name)
            {
            Some(v) => v,
            None => {
                self.flag_types.push( String::from(name) );
                self.flag_types.len() - 1
                },
            };

        // Check cache first
        if let Some(&st) = self.flag_cache.get(&node_id).and_then(|a| a.get(&name_id))
        {
            match st
            {
            SafetyType::Safe => true,
            SafetyType::Unsafe => false,
            SafetyType::Unknown => unknown_assume,
            }
        }
        else
        {
            // Search for a safety marker, possibly recursing
            let is_safe =
                if Self::check_for_marker(tcx, node_id, "tag_safe", name) {
                    true
                }
                else if Self::check_for_marker(tcx, node_id, "tag_unsafe", name) {
                    false
                }
                else {
                    self.recurse_fcn_body(tcx, node_id, name_id, name, unknown_assume)
                };
            // Save resultant value
            self.flag_cache.entry(node_id)
                .or_insert(Default::default())
                .insert(name_id, if is_safe { SafetyType::Safe } else { SafetyType::Unsafe })
                ;
            is_safe
        }
    }

    /// Locate a #[tag_safe(<name>)] attribute on the passed item
    pub fn method_is_safe(&mut self, tcx: &ty::ctxt, id: DefId, name: &str, unknown_assume: bool) -> bool
    {
        debug!("{}Checking method {:?} (A {})", Indent(self.lvl), id, unknown_assume);
        self.lvl += 1;
        let rv = if id.krate == 0 {
                self.crate_method_is_safe(tcx, tcx.map.as_local_node_id(id).unwrap(), name, unknown_assume)
            }
            else {
                for a in tcx.get_attrs(id).iter()
                {
                    if a.check_name("tag_safe") {
                        if a.meta_item_list().iter().flat_map(|a| a.iter()).any(|a| a.name() == name) {
                            return true;
                        }
                    }
                    if a.check_name("tag_unsafe") {
                        if a.meta_item_list().iter().flat_map(|a| a.iter()).any(|a| a.name() == name) {
                            return false;
                        }
                    }
                }
                warn!("TODO: Crate ID non-zero {:?} (assuming safe)", id);
                // TODO: Check the crate import for an annotation
                true
            };
        self.lvl -= 1;
        debug!("{}Checking method {:?} = {}", Indent(self.lvl), id, rv);
        rv
    }
}

impl<'a, 'tcx: 'a, F: FnMut(&Span)> intravisit::Visitor<'a> for Visitor<'a,'tcx, F>
{
    // Locate function/method calls in a code block
    // - uses visit_expr_post because it doesn't _need_ to do anything
    fn visit_expr_post(&mut self, ex: &'a hir::Expr) {
        match ex.node
        {
        // Call expressions - check that it's a path call
        hir::ExprCall(ref fcn, _) =>
            match fcn.node
            {
            hir::ExprPath(ref _qs, ref _p) => {
                    if let def::DefFn(did, _) = self.tcx.resolve_expr(&fcn) {
                        // Check for a safety tag
                        if !self.pass.method_is_safe(self.tcx, did, self.name, self.unknown_assume)
                        {
                            (self.cb)(&ex.span);
                        }
                    }
                },
            _ => {},
            },

        // Method call expressions - get the relevant method
        hir::ExprMethodCall(ref _id, ref _tys, ref _exprs) =>
            {
                let tables = self.tcx.tables.borrow();
                let mm = &tables.method_map;

                let callee = mm.get( &ty::MethodCall::expr(ex.id) ).unwrap();
                let id = callee.def_id;

                //if let ty::MethodStatic(id) = callee.origin {
                        // Check for a safety tag
                        if !self.pass.method_is_safe(self.tcx, id, self.name, self.unknown_assume) {
                            (self.cb)(&ex.span);
                        }
                //}
            },

        // Ignore any other type of node
        _ => {},
        }
    }
}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    use syntax::feature_gate::AttributeType;
    reg.register_late_lint_pass( Box::new(Pass::default()) );

    reg.register_attribute(String::from("tag_safe"),   AttributeType::Whitelisted);
    reg.register_attribute(String::from("tag_unsafe"), AttributeType::Whitelisted);
}

// vim: ts=4 expandtab sw=4
<|endoftext|>


<commit_before>#![feature(slicing_syntax)]
extern crate test;

use std::default::Default;
use std::cmp::Ordering;
use std::cell::Cell;
use std::hash::{Writer, Hash};
use std::collections::HashMap;
use std::collections::HashSet;
use std::collections::RingBuf;
use std::collections::BitvSet;
use std::collections::BinaryHeap;
use std::collections::hash_map::Entry::{
    Occupied,
    Vacant,
};
use std::fmt;
use std::ops::{Add, Deref};

pub use scored::MinScored;
pub use digraph::DiGraph;
pub use graph::Graph;
pub use ograph::OGraph;
use ograph::{
    EdgeType,
};

pub use self::EdgeDirection::{Outgoing, Incoming};

mod scored;
pub mod digraph;
pub mod graph;
pub mod ograph;

pub mod unionfind;

// Index into the NodeIndex and EdgeIndex arrays
/// Edge direction
#[derive(Copy, Clone, Show, PartialEq)]
pub enum EdgeDirection {
    /// A **Outgoing** edge is an outward edge *from* the current node.
    Outgoing = 0,
    /// An **Incoming** edge is an inbound edge *to* the current node.
    Incoming = 1
}

/// A reference that is hashed and compared by its pointer value.
pub struct Ptr<'b, T: 'b>(pub &'b T);

impl<'b, T> Copy for Ptr<'b, T> {}
impl<'b, T> Clone for Ptr<'b, T>
{
    fn clone(&self) -> Self { *self }
}

fn ptreq<T>(a: &T, b: &T) -> bool {
    a as *const _ == b as *const _
}

impl<'b, T> PartialEq for Ptr<'b, T>
{
    /// Ptr compares by pointer equality, i.e if they point to the same value
    fn eq(&self, other: &Ptr<'b, T>) -> bool {
        ptreq(self.0, other.0)
    }
}

impl<'b, T> PartialOrd for Ptr<'b, T>
{
    fn partial_cmp(&self, other: &Ptr<'b, T>) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl<'b, T> Ord for Ptr<'b, T>
{
    /// Ptr is ordered by pointer value, i.e. an arbitrary but stable and total order.
    fn cmp(&self, other: &Ptr<'b, T>) -> Ordering {
        let a = self.0 as *const _;
        let b = other.0 as *const _;
        a.cmp(&b)
    }
}

impl<'b, T> Deref for Ptr<'b, T> {
    type Target = T;
    fn deref<'a>(&'a self) -> &'a T {
        self.0
    }
}

impl<'b, T> Eq for Ptr<'b, T> {}

impl<'b, T, S: Writer> Hash<S> for Ptr<'b, T>
{
    fn hash(&self, st: &mut S)
    {
        let ptr = (self.0) as *const _;
        ptr.hash(st)
    }
}

impl<'b, T: fmt::Show> fmt::Show for Ptr<'b, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

/// Dijkstra's shortest path algorithm.
pub fn dijkstra<'a, Graph, N, K, F, Edges>(graph: &'a Graph,
                                           start: N,
                                           goal: Option<N>,
                                           mut edges: F) -> HashMap<N, K> where
    Graph: Visitable<N>,
    N: Copy + Clone + Eq + Hash + fmt::Show,
    K: Default + Add<Output=K> + Copy + PartialOrd + fmt::Show,
    F: FnMut(&'a Graph, N) -> Edges,
    Edges: Iterator<Item=(N, K)>,
    <Graph as Visitable<N>>::Map: VisitMap<N>,
{
    let mut visited = graph.visit_map();
    let mut scores = HashMap::new();
    let mut predecessor = HashMap::new();
    let mut visit_next = BinaryHeap::new();
    let zero_score: K = Default::default();
    scores.insert(start, zero_score);
    visit_next.push(MinScored(zero_score, start));
    while let Some(MinScored(node_score, node)) = visit_next.pop() {
        if visited.contains(&node) {
            continue
        }
        for (next, edge) in edges(graph, node) {
            if visited.contains(&next) {
                continue
            }
            let mut next_score = node_score + edge;
            match scores.entry(&next) {
                Occupied(ent) => if next_score < *ent.get() {
                    *ent.into_mut() = next_score;
                    predecessor.insert(next, node);
                } else {
                    next_score = *ent.get();
                },
                Vacant(ent) => {
                    ent.insert(next_score);
                    predecessor.insert(next, node);
                }
            }
            visit_next.push(MinScored(next_score, next));
        }
        if goal.as_ref() == Some(&node) {
            break
        }
        visited.visit(node);
    }
    scores
}

#[derive(Show)]
pub struct Node<T>(pub T);

pub struct NodeCell<T: Copy>(pub Cell<T>);

impl<T: Copy> Deref for NodeCell<T> {
    type Target = Cell<T>;
    #[inline]
    fn deref(&self) -> &Cell<T> {
        &self.0
    }
}

impl<T: Copy + fmt::Show> fmt::Show for NodeCell<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Node({})", self.0.get())
    }
}

/// A graph trait for accessing the neighbors iterator **I**.
pub trait GraphNeighbors<'a, N> {
    type Iter: Iterator<Item=N>;
    fn neighbors(&'a self, n: N) -> Self::Iter;
}

impl<'a, N: 'a, E> GraphNeighbors<'a, N> for Graph<N, E>
where N: Copy + Clone + PartialOrd + Hash + Eq
{
    type Iter = graph::Neighbors<'a, N>;
    fn neighbors(&'a self, n: N) -> graph::Neighbors<'a, N>
    {
        Graph::neighbors(self, n)
    }
}

impl<'a, N: 'a, E: 'a> GraphNeighbors<'a, N> for DiGraph<N, E>
where N: Copy + Clone + Hash + Eq
{
    type Iter = digraph::Neighbors<'a, N, E>;
    fn neighbors(&'a self, n: N) -> digraph::Neighbors<'a, N, E>
    {
        DiGraph::neighbors(self, n)
    }
}

impl<'a, N, E, ETy: EdgeType> GraphNeighbors<'a, ograph::NodeIndex> for OGraph<N, E, ETy>
{
    type Iter = ograph::Neighbors<'a, E>;
    fn neighbors(&'a self, n: ograph::NodeIndex) -> ograph::Neighbors<'a, E>
    {
        OGraph::neighbors(self, n)
    }
}

/// Wrapper type for walking the graph as if it is undirected
pub struct Undirected<G>(pub G);
/// Wrapper type for walking edges the other way
pub struct Reversed<G>(pub G);

impl<'a, 'b, N, E> GraphNeighbors<'a, ograph::NodeIndex> for Undirected<&'b OGraph<N, E>>
{
    type Iter = ograph::Neighbors<'a, E>;
    fn neighbors(&'a self, n: ograph::NodeIndex) -> ograph::Neighbors<'a, E>
    {
        OGraph::neighbors_both(self.0, n)
    }
}

impl<'a, 'b, N, E, ETy: EdgeType> GraphNeighbors<'a, ograph::NodeIndex> for Reversed<&'b OGraph<N, E, ETy>>
{
    type Iter = ograph::Neighbors<'a, E>;
    fn neighbors(&'a self, n: ograph::NodeIndex) -> ograph::Neighbors<'a, E>
    {
        OGraph::neighbors_directed(self.0, n, EdgeDirection::Incoming)
    }
}

pub trait VisitMap<N> {
    fn visit(&mut self, N) -> bool;
    fn contains(&self, &N) -> bool;
}

impl VisitMap<ograph::NodeIndex> for BitvSet {
    fn visit(&mut self, x: ograph::NodeIndex) -> bool {
        self.insert(x.0)
    }
    fn contains(&self, x: &ograph::NodeIndex) -> bool {
        self.contains(&x.0)
    }
}

impl<N: Eq + Hash> VisitMap<N> for HashSet<N> {
    fn visit(&mut self, x: N) -> bool {
        self.insert(x)
    }
    fn contains(&self, x: &N) -> bool {
        self.contains(x)
    }
}

/// Trait for Graph that knows which datastructure is the best for its visitor map
pub trait Visitable<N> {
    type Map: VisitMap<N>;
    fn visit_map(&self) -> Self::Map;
}

impl<N, E, ETy> Visitable<ograph::NodeIndex> for OGraph<N, E, ETy> where
    ETy: ograph::EdgeType,
{
    type Map = BitvSet;
    fn visit_map(&self) -> BitvSet { BitvSet::with_capacity(self.node_count()) }
}

impl<N, E> Visitable<N> for DiGraph<N, E>
    where N: Copy + Clone + Eq + Hash
{
    type Map = HashSet<N>;
    fn visit_map(&self) -> HashSet<N> { HashSet::with_capacity(self.node_count()) }
}

impl<N, E> Visitable<N> for Graph<N, E>
    where N: Copy + Clone + Ord + Eq + Hash
{
    type Map = HashSet<N>;
    fn visit_map(&self) -> HashSet<N> { HashSet::with_capacity(self.node_count()) }
}

impl<'a, N, V: Visitable<N>> Visitable<N> for Undirected<&'a V>
{
    type Map = <V as Visitable<N>>::Map;
    fn visit_map(&self) -> <V as Visitable<N>>::Map {
        self.0.visit_map()
    }
}

impl<'a, N, V: Visitable<N>> Visitable<N> for Reversed<&'a V>
{
    type Map = <V as Visitable<N>>::Map;
    fn visit_map(&self) -> <V as Visitable<N>>::Map {
        self.0.visit_map()
    }
}

/// A breadth first traversal of a graph.
#[derive(Clone)]
pub struct BreadthFirst<'a, G, N> where
    G: 'a,
    N: Eq + Hash,
{
    pub graph: &'a G,
    pub stack: RingBuf<N>,
    pub visited: HashSet<N>,
}

impl<'a, G, N> BreadthFirst<'a, G, N> where
    G: 'a + GraphNeighbors<'a, N>,
    N: Copy + Eq + Hash,
{
    pub fn new(graph: &'a G, start: N) -> BreadthFirst<'a, G, N>
    {
        let mut rb = RingBuf::new();
        rb.push_back(start);
        BreadthFirst{
            graph: graph,
            stack: rb,
            visited: HashSet::new(),
        }
    }
}

impl<'a, G, N> Iterator for BreadthFirst<'a, G, N> where
    G: 'a + GraphNeighbors<'a, N>,
    N: Copy + Eq + Hash,
    <G as GraphNeighbors<'a, N>>::Iter: Iterator<Item=N>,
{
    type Item = N;
    fn next(&mut self) -> Option<N>
    {
        while let Some(node) = self.stack.pop_front() {
            if !self.visited.insert(node) {
                continue;
            }

            for succ in self.graph.neighbors(node) {
                if !self.visited.contains(&succ) {
                    self.stack.push_back(succ);
                }
            }

            return Some(node);
        }
        None
    }
}

/// A depth first traversal of a graph.
#[derive(Clone)]
pub struct DepthFirst<'a, G, N> where
    G: 'a,
    N: Eq + Hash,
{
    pub graph: &'a G,
    pub stack: Vec<N>,
    pub visited: HashSet<N>,
}

impl<'a, G, N> DepthFirst<'a, G, N> where
    G: 'a + GraphNeighbors<'a, N>,
    N: Copy + Eq + Hash,
{
    pub fn new(graph: &'a G, start: N) -> DepthFirst<'a, G, N>
    {
        DepthFirst{
            graph: graph,
            stack: vec![start],
            visited: HashSet::new(),
        }
    }
}

impl<'a, G, N> Iterator for DepthFirst<'a, G, N> where
    G: 'a + GraphNeighbors<'a, N>,
    N: Copy + Eq + Hash,
    <G as GraphNeighbors<'a, N>>::Iter: Iterator<Item=N>,
{
    type Item = N;
    fn next(&mut self) -> Option<N>
    {
        while let Some(node) = self.stack.pop() {
            if !self.visited.insert(node) {
                continue;
            }

            for succ in self.graph.neighbors(node) {
                if !self.visited.contains(&succ) {
                    self.stack.push(succ);
                }
            }

            return Some(node);
        }
        None
    }
}

pub fn depth_first_search<'a, G, N, F>(graph: &'a G, start: N, mut f: F) -> bool where
    G: 'a + GraphNeighbors<'a, N> + Visitable<N>,
    N: Clone,
    <G as GraphNeighbors<'a, N>>::Iter: Iterator<Item=N>,
    <G as Visitable<N>>::Map: VisitMap<N>,
    F: FnMut(N) -> bool,
{
    let mut stack = Vec::new();
    let mut visited = graph.visit_map();

    stack.push(start);
    while let Some(node) = stack.pop() {
        if !visited.visit(node.clone()) {
            continue;
        }

        for succ in graph.neighbors(node.clone()) {
            if !visited.contains(&succ) {
                stack.push(succ);
            }
        }

        if !f(node) {
            return false
        }
    }
    true
}

/// Run a DFS over an **OGraph**, passing a mutable ref to the graph to the
/// iteration function on each step.
///
/// **Note:** The algorithm will not behave correctly if nodes are removed
/// during iteration. It will not necessarily visit added nodes or edges.
pub fn depth_first_search_mut<'a, N, E, ETy, F>(graph: &'a mut OGraph<N, E, ETy>,
                                                start: ograph::NodeIndex,
                                                mut f: F) -> bool where
    ETy: ograph::EdgeType,
    F: FnMut(&mut OGraph<N, E, ETy>, ograph::NodeIndex) -> bool,
{
    let mut stack = Vec::new();
    let mut visited = graph.visit_map();

    stack.push(start);
    while let Some(node) = stack.pop() {
        if !visited.visit(node) {
            continue;
        }

        for succ in graph.neighbors(node) {
            if !visited.contains(&succ.0) {
                stack.push(succ);
            }
        }

        if !f(graph, node) {
            return false
        }
    }
    true
}

<commit_msg>Use IntoNeighbors<commit_after>#![feature(slicing_syntax)]
extern crate test;

use std::default::Default;
use std::cmp::Ordering;
use std::cell::Cell;
use std::hash::{Writer, Hash};
use std::collections::HashMap;
use std::collections::HashSet;
use std::collections::RingBuf;
use std::collections::BitvSet;
use std::collections::BinaryHeap;
use std::collections::hash_map::Entry::{
    Occupied,
    Vacant,
};
use std::fmt;
use std::ops::{Add, Deref};

pub use scored::MinScored;
pub use digraph::DiGraph;
pub use graph::Graph;
pub use ograph::OGraph;
use ograph::{
    EdgeType,
};

pub use self::EdgeDirection::{Outgoing, Incoming};

mod scored;
pub mod digraph;
pub mod graph;
pub mod ograph;

pub mod unionfind;

// Index into the NodeIndex and EdgeIndex arrays
/// Edge direction
#[derive(Copy, Clone, Show, PartialEq)]
pub enum EdgeDirection {
    /// A **Outgoing** edge is an outward edge *from* the current node.
    Outgoing = 0,
    /// An **Incoming** edge is an inbound edge *to* the current node.
    Incoming = 1
}

/// A reference that is hashed and compared by its pointer value.
pub struct Ptr<'b, T: 'b>(pub &'b T);

impl<'b, T> Copy for Ptr<'b, T> {}
impl<'b, T> Clone for Ptr<'b, T>
{
    fn clone(&self) -> Self { *self }
}

fn ptreq<T>(a: &T, b: &T) -> bool {
    a as *const _ == b as *const _
}

impl<'b, T> PartialEq for Ptr<'b, T>
{
    /// Ptr compares by pointer equality, i.e if they point to the same value
    fn eq(&self, other: &Ptr<'b, T>) -> bool {
        ptreq(self.0, other.0)
    }
}

impl<'b, T> PartialOrd for Ptr<'b, T>
{
    fn partial_cmp(&self, other: &Ptr<'b, T>) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl<'b, T> Ord for Ptr<'b, T>
{
    /// Ptr is ordered by pointer value, i.e. an arbitrary but stable and total order.
    fn cmp(&self, other: &Ptr<'b, T>) -> Ordering {
        let a = self.0 as *const _;
        let b = other.0 as *const _;
        a.cmp(&b)
    }
}

impl<'b, T> Deref for Ptr<'b, T> {
    type Target = T;
    fn deref<'a>(&'a self) -> &'a T {
        self.0
    }
}

impl<'b, T> Eq for Ptr<'b, T> {}

impl<'b, T, S: Writer> Hash<S> for Ptr<'b, T>
{
    fn hash(&self, st: &mut S)
    {
        let ptr = (self.0) as *const _;
        ptr.hash(st)
    }
}

impl<'b, T: fmt::Show> fmt::Show for Ptr<'b, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

/// Dijkstra's shortest path algorithm.
pub fn dijkstra<'a, Graph, N, K, F, Edges>(graph: &'a Graph,
                                           start: N,
                                           goal: Option<N>,
                                           mut edges: F) -> HashMap<N, K> where
    Graph: Visitable<N>,
    N: Copy + Clone + Eq + Hash + fmt::Show,
    K: Default + Add<Output=K> + Copy + PartialOrd + fmt::Show,
    F: FnMut(&'a Graph, N) -> Edges,
    Edges: Iterator<Item=(N, K)>,
    <Graph as Visitable<N>>::Map: VisitMap<N>,
{
    let mut visited = graph.visit_map();
    let mut scores = HashMap::new();
    let mut predecessor = HashMap::new();
    let mut visit_next = BinaryHeap::new();
    let zero_score: K = Default::default();
    scores.insert(start, zero_score);
    visit_next.push(MinScored(zero_score, start));
    while let Some(MinScored(node_score, node)) = visit_next.pop() {
        if visited.contains(&node) {
            continue
        }
        for (next, edge) in edges(graph, node) {
            if visited.contains(&next) {
                continue
            }
            let mut next_score = node_score + edge;
            match scores.entry(&next) {
                Occupied(ent) => if next_score < *ent.get() {
                    *ent.into_mut() = next_score;
                    predecessor.insert(next, node);
                } else {
                    next_score = *ent.get();
                },
                Vacant(ent) => {
                    ent.insert(next_score);
                    predecessor.insert(next, node);
                }
            }
            visit_next.push(MinScored(next_score, next));
        }
        if goal.as_ref() == Some(&node) {
            break
        }
        visited.visit(node);
    }
    scores
}

#[derive(Show)]
pub struct Node<T>(pub T);

pub struct NodeCell<T: Copy>(pub Cell<T>);

impl<T: Copy> Deref for NodeCell<T> {
    type Target = Cell<T>;
    #[inline]
    fn deref(&self) -> &Cell<T> {
        &self.0
    }
}

impl<T: Copy + fmt::Show> fmt::Show for NodeCell<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Node({})", self.0.get())
    }
}

/// A graph trait for accessing the neighbors iterator **I**.
pub trait IntoNeighbors<N> : Copy {
    type Iter: Iterator<Item=N>;
    fn neighbors(self, n: N) -> Self::Iter;
}

impl<'a, N: 'a, E> IntoNeighbors<N> for &'a Graph<N, E>
where N: Copy + Clone + PartialOrd + Hash + Eq
{
    type Iter = graph::Neighbors<'a, N>;
    fn neighbors(self, n: N) -> graph::Neighbors<'a, N>
    {
        Graph::neighbors(self, n)
    }
}

impl<'a, N: 'a, E: 'a> IntoNeighbors<N> for &'a DiGraph<N, E>
where N: Copy + Clone + Hash + Eq
{
    type Iter = digraph::Neighbors<'a, N, E>;
    fn neighbors(self, n: N) -> digraph::Neighbors<'a, N, E>
    {
        DiGraph::neighbors(self, n)
    }
}

impl<'a, N, E, ETy: EdgeType> IntoNeighbors< ograph::NodeIndex> for &'a OGraph<N, E, ETy>
{
    type Iter = ograph::Neighbors<'a, E>;
    fn neighbors(self, n: ograph::NodeIndex) -> ograph::Neighbors<'a, E>
    {
        OGraph::neighbors(self, n)
    }
}

/// Wrapper type for walking the graph as if it is undirected
pub struct Undirected<G>(pub G);
/// Wrapper type for walking edges the other way
pub struct Reversed<G>(pub G);

impl<'a, 'b, N, E> IntoNeighbors< ograph::NodeIndex> for &'a Undirected<&'b OGraph<N, E>>
{
    type Iter = ograph::Neighbors<'a, E>;
    fn neighbors(self, n: ograph::NodeIndex) -> ograph::Neighbors<'a, E>
    {
        OGraph::neighbors_both(self.0, n)
    }
}

impl<'a, 'b, N, E, ETy: EdgeType> IntoNeighbors< ograph::NodeIndex> for &'a Reversed<&'b OGraph<N, E, ETy>>
{
    type Iter = ograph::Neighbors<'a, E>;
    fn neighbors(self, n: ograph::NodeIndex) -> ograph::Neighbors<'a, E>
    {
        OGraph::neighbors_directed(self.0, n, EdgeDirection::Incoming)
    }
}

pub trait VisitMap<N> {
    fn visit(&mut self, N) -> bool;
    fn contains(&self, &N) -> bool;
}

impl VisitMap<ograph::NodeIndex> for BitvSet {
    fn visit(&mut self, x: ograph::NodeIndex) -> bool {
        self.insert(x.0)
    }
    fn contains(&self, x: &ograph::NodeIndex) -> bool {
        self.contains(&x.0)
    }
}

impl<N: Eq + Hash> VisitMap<N> for HashSet<N> {
    fn visit(&mut self, x: N) -> bool {
        self.insert(x)
    }
    fn contains(&self, x: &N) -> bool {
        self.contains(x)
    }
}

/// Trait for Graph that knows which datastructure is the best for its visitor map
pub trait Visitable<N> {
    type Map: VisitMap<N>;
    fn visit_map(&self) -> Self::Map;
}

impl<N, E, ETy> Visitable<ograph::NodeIndex> for OGraph<N, E, ETy> where
    ETy: ograph::EdgeType,
{
    type Map = BitvSet;
    fn visit_map(&self) -> BitvSet { BitvSet::with_capacity(self.node_count()) }
}

impl<N, E> Visitable<N> for DiGraph<N, E>
    where N: Copy + Clone + Eq + Hash
{
    type Map = HashSet<N>;
    fn visit_map(&self) -> HashSet<N> { HashSet::with_capacity(self.node_count()) }
}

impl<N, E> Visitable<N> for Graph<N, E>
    where N: Copy + Clone + Ord + Eq + Hash
{
    type Map = HashSet<N>;
    fn visit_map(&self) -> HashSet<N> { HashSet::with_capacity(self.node_count()) }
}

impl<'a, N, V: Visitable<N>> Visitable<N> for Undirected<&'a V>
{
    type Map = <V as Visitable<N>>::Map;
    fn visit_map(&self) -> <V as Visitable<N>>::Map {
        self.0.visit_map()
    }
}

impl<'a, N, V: Visitable<N>> Visitable<N> for Reversed<&'a V>
{
    type Map = <V as Visitable<N>>::Map;
    fn visit_map(&self) -> <V as Visitable<N>>::Map {
        self.0.visit_map()
    }
}

/// A breadth first traversal of a graph.
#[derive(Clone)]
pub struct BreadthFirst<'a, G, N> where
    G: 'a,
    N: Eq + Hash,
{
    pub graph: &'a G,
    pub stack: RingBuf<N>,
    pub visited: HashSet<N>,
}

impl<'a, G, N> BreadthFirst<'a, G, N> where
    G: 'a,
    &'a G: IntoNeighbors< N>,
    N: Copy + Eq + Hash,
{
    pub fn new(graph: &'a G, start: N) -> BreadthFirst<'a, G, N>
    {
        let mut rb = RingBuf::new();
        rb.push_back(start);
        BreadthFirst{
            graph: graph,
            stack: rb,
            visited: HashSet::new(),
        }
    }
}

impl<'a, G: 'a, N> Iterator for BreadthFirst<'a, G, N> where
    &'a G: IntoNeighbors<N>,
    N: Copy + Eq + Hash,
    <&'a G as IntoNeighbors< N>>::Iter: Iterator<Item=N>,
{
    type Item = N;
    fn next(&mut self) -> Option<N>
    {
        while let Some(node) = self.stack.pop_front() {
            if !self.visited.insert(node) {
                continue;
            }

            for succ in self.graph.neighbors(node) {
                if !self.visited.contains(&succ) {
                    self.stack.push_back(succ);
                }
            }

            return Some(node);
        }
        None
    }
}

/// A depth first traversal of a graph.
#[derive(Clone)]
pub struct DepthFirst<'a, G, N> where
    G: 'a,
    N: Eq + Hash,
{
    pub graph: &'a G,
    pub stack: Vec<N>,
    pub visited: HashSet<N>,
}

impl<'a, G, N> DepthFirst<'a, G, N> where
    G: 'a,
    &'a G: IntoNeighbors< N>,
    N: Copy + Eq + Hash,
{
    pub fn new(graph: &'a G, start: N) -> DepthFirst<'a, G, N>
    {
        DepthFirst{
            graph: graph,
            stack: vec![start],
            visited: HashSet::new(),
        }
    }
}

impl<'a, G, N> Iterator for DepthFirst<'a, G, N> where
    G: 'a,
    &'a G: IntoNeighbors< N>,
    N: Copy + Eq + Hash,
    <&'a G as IntoNeighbors< N>>::Iter: Iterator<Item=N>,
{
    type Item = N;
    fn next(&mut self) -> Option<N>
    {
        while let Some(node) = self.stack.pop() {
            if !self.visited.insert(node) {
                continue;
            }

            for succ in self.graph.neighbors(node) {
                if !self.visited.contains(&succ) {
                    self.stack.push(succ);
                }
            }

            return Some(node);
        }
        None
    }
}

pub fn depth_first_search<'a, G, N, F>(graph: &'a G, start: N, mut f: F) -> bool where
    G: 'a + Visitable<N>,
    &'a G: IntoNeighbors<N>,
    N: Clone,
    <&'a G as IntoNeighbors<N>>::Iter: Iterator<Item=N>,
    <G as Visitable<N>>::Map: VisitMap<N>,
    F: FnMut(N) -> bool,
{
    let mut stack = Vec::new();
    let mut visited = graph.visit_map();

    stack.push(start);
    while let Some(node) = stack.pop() {
        if !visited.visit(node.clone()) {
            continue;
        }

        for succ in graph.neighbors(node.clone()) {
            if !visited.contains(&succ) {
                stack.push(succ);
            }
        }

        if !f(node) {
            return false
        }
    }
    true
}

/// Run a DFS over an **OGraph**, passing a mutable ref to the graph to the
/// iteration function on each step.
///
/// **Note:** The algorithm will not behave correctly if nodes are removed
/// during iteration. It will not necessarily visit added nodes or edges.
pub fn depth_first_search_mut<'a, N, E, ETy, F>(graph: &'a mut OGraph<N, E, ETy>,
                                                start: ograph::NodeIndex,
                                                mut f: F) -> bool where
    ETy: ograph::EdgeType,
    F: FnMut(&mut OGraph<N, E, ETy>, ograph::NodeIndex) -> bool,
{
    let mut stack = Vec::new();
    let mut visited = graph.visit_map();

    stack.push(start);
    while let Some(node) = stack.pop() {
        if !visited.visit(node) {
            continue;
        }

        for succ in graph.neighbors(node) {
            if !visited.contains(&succ.0) {
                stack.push(succ);
            }
        }

        if !f(graph, node) {
            return false
        }
    }
    true
}

<|endoftext|>


<commit_before>//! This crate provides (at this time) a single function, `take()`.
//!
//! `take()` allows for taking `T` out of a `&mut T`, doing anything with it including consuming it, and producing another `T` to put back in the `&mut T`.
//!
//! During `take()`, if a panic occurs, the entire process will be exited, as there's no valid `T` to put back into the `&mut T`.
//!
//! Contrast with `std::mem::replace()`, which allows for putting a different `T` into a `&mut T`, but requiring the new `T` to be available before being able to consume the old `T`.

mod exit_on_panic;

use exit_on_panic::exit_on_panic;

/// Allows use of a value pointed to by `&mut T` as though it was owned, as long as a `T` is made available afterwards.
///
/// The closure must return a valid T.
/// # Important
/// Will exit the program (with status code 101) if the closure panics.
///
/// # Example
/// ```
/// struct Foo;
/// let mut foo = Foo;
/// take_mut::take(&mut foo, |foo| {
///     // Can now consume the Foo, and provide a new value later
///     drop(foo);
///     // Do more stuff
///     Foo // Return new Foo from closure, which goes back into the &mut Foo
/// });
/// ```
pub fn take<T, F>(mut_ref: &mut T, closure: F)
  where F: FnOnce(T) -> T {
    use std::ptr;
    exit_on_panic(|| {
        unsafe {
            let old_t = ptr::read(mut_ref);
            let new_t = closure(old_t);
            ptr::write(mut_ref, new_t);
        }
    });
}

#[test]
fn it_works() {
    #[derive(PartialEq, Eq, Debug)]
    enum Foo {A, B};
    impl Drop for Foo {
        fn drop(&mut self) {
            match *self {
                Foo::A => println!("Foo::A dropped"),
                Foo::B => println!("Foo::B dropped")
            }
        }
    }
    let mut foo = Foo::A;
    take(&mut foo, |mut f| {
       drop(f);
       Foo::B
    });
    assert_eq!(&foo, &Foo::B);
}<commit_msg>Revert "Removing scope-based take for a while, which I'm currently uncertain how to make safe."<commit_after>//! This crate provides (at this time) a single function, `take()`.
//!
//! `take()` allows for taking `T` out of a `&mut T`, doing anything with it including consuming it, and producing another `T` to put back in the `&mut T`.
//!
//! During `take()`, if a panic occurs, the entire process will be exited, as there's no valid `T` to put back into the `&mut T`.
//!
//! Contrast with `std::mem::replace()`, which allows for putting a different `T` into a `&mut T`, but requiring the new `T` to be available before being able to consume the old `T`.

mod exit_on_panic;

use exit_on_panic::exit_on_panic;

/// Allows use of a value pointed to by `&mut T` as though it was owned, as long as a `T` is made available afterwards.
///
/// The closure must return a valid T.
/// # Important
/// Will exit the program (with status code 101) if the closure panics.
///
/// # Example
/// ```
/// struct Foo;
/// let mut foo = Foo;
/// take_mut::take(&mut foo, |foo| {
///     // Can now consume the Foo, and provide a new value later
///     drop(foo);
///     // Do more stuff
///     Foo // Return new Foo from closure, which goes back into the &mut Foo
/// });
/// ```
pub fn take<T, F>(mut_ref: &mut T, closure: F)
  where F: FnOnce(T) -> T {
    use std::ptr;
    exit_on_panic(|| {
        unsafe {
            let old_t = ptr::read(mut_ref);
            let new_t = closure(old_t);
            ptr::write(mut_ref, new_t);
        }
    });
}

use std::cell::Cell;

pub struct Scope {
    active_holes: Cell<usize>
}

impl Scope {
    pub fn scope<F>(f: F)
    where F: FnOnce(&Scope) {
        let aborter = AbortOnSuddenDrop::new();
        let this = Scope { active_holes: Cell::new(0) };
        f(&this);
        if this.active_holes.get() != 0 {
            panic!("There are still unfilled Holes!");
        }
        aborter.done();
    }
    // TODO: NEED TO GUARANTEE THAT MUTABLE OBJECT IN QUESTION IS NOT A SMALLER LIFETIME
    pub fn take<'s, 'm: 's, T: 'm>(&'s self, mut_ref: &'m mut T) -> (T, Hole<'s, 'm, T>) {
        use std::ptr;

        let num_holes = self.active_holes.get();
        if num_holes == std::usize::MAX {
            panic!("Failed to create new Hole, already usize::MAX unfilled holes.");
        }
        self.active_holes.set(num_holes + 1);
        let t: T;
        let hole: Hole<'s, 'm, T>;
        unsafe {
            t = ptr::read(mut_ref);
            hole = Hole { scope: self, hole: mut_ref };
        };
        (t, hole)
    }
}

pub struct Hole<'scope, 'm, T: 'm> {
    scope: &'scope Scope,
    hole: &'m mut T
}

impl<'scope, 'm, T: 'm> Hole<'scope, 'm, T> {
    pub fn fill(self, t: T) {
        use std::ptr;

        unsafe {
            ptr::write(self.hole, t);
        }

        self.scope.active_holes.set(self.scope.active_holes.get() - 1);
    }
}

#[test]
fn it_works() {
    #[derive(PartialEq, Eq, Debug)]
    enum Foo {A, B};
    impl Drop for Foo {
        fn drop(&mut self) {
            match *self {
                Foo::A => println!("Foo::A dropped"),
                Foo::B => println!("Foo::B dropped")
            }
        }
    }
    let mut foo = Foo::A;
    take(&mut foo, |mut f| {
       drop(f);
       Foo::B
    });
    assert_eq!(&foo, &Foo::B);
}

#[test]
fn scope_based_take() {
    #[derive(Debug)]
    struct Foo;

    #[derive(Debug)]
    struct Bar {
        a: Foo,
        b: Foo
    }
    let mut bar = Bar { a: Foo, b: Foo };
    Scope::scope(|scope| {
        let (a, a_hole) = scope.take(&mut bar.a);
        let (b, b_hole) = scope.take(&mut bar.b);
        // Imagine consuming a and b
        a_hole.fill(Foo);
        b_hole.fill(Foo);
    });
    println!("{:?}", &bar);
}<|endoftext|>


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

mod rope;

use rope::Rope;
use regex::Regex;
use itertools::Itertools;

#[derive(Debug, Clone)]
pub struct MediaInfo {
    pub title:      Option<String>,
    pub group:      Option<String>,
    pub resolution: Option<String>,
    pub season:     Option<u32>,
    pub episode:    Option<u32>,
    pub source:     Option<String>,
    pub year:       Option<u32>,
    pub codec:      Option<String>,
    pub audio:      Option<String>,
    pub extension:  Option<String>
}

fn parse_pattern(rope: &mut Rope, regex: &Regex) -> Option<String> {
    let mut info: Option<(usize, String, (usize, usize))> = None;

    for (i, part) in rope.iter().enumerate() {
        if let Some(captures) = regex.captures(part.string) {
            let value = captures.iter().skip(1)
                .find(|x| x.is_some())
                .unwrap().unwrap().to_owned();
            let range = captures.pos(0).unwrap();

            info = Some((i, value, range));
            break;
        }
    };

    if let Some((i, value, (start, end))) = info {
        rope.mark_part_range(i, start..end);
        return Some(value);
    }

    None
}

pub fn parse_filename(filename: &str) -> MediaInfo {
    lazy_static! {
        static ref EXTENSION_REGEX: Regex = Regex::new("\\.([A-Za-z0-9]{2,4})$").unwrap();
        static ref RESOLUTION_REGEX: Regex = Regex::new("([0-9]{3,4}p)").unwrap();
        static ref GROUP_REGEX: Regex = Regex::new("(?:^\\[([^]]+)\\]|- ?([^-]+)$)").unwrap();
        static ref EPISODE_REGEX: Regex = Regex::new("(?:[eE]([0-9]{2,3})|[^0-9A-Za-z]([0-9]{2,3})(?:v[0-9])?[^0-9A-Za-z])").unwrap();
        static ref SEASON_REGEX: Regex = Regex::new("[sS]([0-9]{1,2})").unwrap();
        static ref SOURCE_REGEX: Regex = Regex::new("((?i)(?:PPV.)?[HP]DTV|(?:HD)?CAM|BRRIP|TS|(?:PPV )?WEB.?DL(?: DVDRip)?|HDRip|DVDRip|CamRip|W[EB]BRip|BluRay|DvDScr|hdtv)").unwrap();
        static ref YEAR_REGEX: Regex = Regex::new("((19[0-9]|20[01])[0-9])").unwrap();
        static ref CODEC_REGEX: Regex = Regex::new("((?i)xvid|x264|h\\.?264)").unwrap();
        static ref AUDIO_REGEX: Regex = Regex::new("((?i)MP3|DD5\\.?1|Dual[- ]Audio|LiNE|DTS|AAC(?:\\.?2\\.0)?|AC3(?:\\.5\\.1)?)").unwrap();
    }

    let mut rope = Rope::new(&filename);

    MediaInfo {
        extension:  parse_pattern(&mut rope, &EXTENSION_REGEX),
        source:     parse_pattern(&mut rope, &SOURCE_REGEX),
        codec:      parse_pattern(&mut rope, &CODEC_REGEX),
        audio:      parse_pattern(&mut rope, &AUDIO_REGEX),
        resolution: parse_pattern(&mut rope, &RESOLUTION_REGEX),
        group:      parse_pattern(&mut rope, &GROUP_REGEX),
        season:     parse_pattern(&mut rope, &SEASON_REGEX).and_then(|s| s.parse().ok()),
        year:       parse_pattern(&mut rope, &YEAR_REGEX).and_then(|s| s.parse().ok()),
        episode:    parse_pattern(&mut rope, &EPISODE_REGEX).and_then(|s| s.parse().ok()),

        title: {
            let x: &[_] = &['(', ')', '[', ']', ' ', '-', '_', '.'];

            let title = rope.unmarked()
                .map(|p| p.string)
                .sorted_by(|a,b| Ord::cmp(&a.len(), &b.len()))
                .pop();

            let title = title.map(|s| s.trim_matches(x));

            title.map(|s| s.to_owned())
        }
    }
}

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

    macro_rules! assert_parse {
        ( $str:expr, {
            $($field:ident : $value:expr),*
        } ) => {
            {
                let info = parse_filename($str);
                println!("{:?}", info);
                $(assert!(info.$field == Some(($value).into()));)*
            }
        }
    }

    #[test]
    fn parse() {
        assert_parse!("[HorribleSubs] Mayoiga - 03 [720p].mkv", {
            group: "HorribleSubs",
            episode: 03 as u32,
            resolution: "720p",
            title: "Mayoiga"
        });

        assert_parse!("Game of Thrones Season 6 S06E05 720p Web Dl x264 Mrlss", {
            title: "Game of Thrones Season 6",
            season: 06 as u32,
            episode: 05 as u32,
            resolution: "720p",
            source: "Web Dl",
            codec: "x264"
        });

        assert_parse!("The Ones Below 2015 HDRip XViD-ETRG", {
            title: "The Ones Below",
            source: "HDRip",
            group: "ETRG",
            year: 2015 as u32,
            source: "HDRip",
            codec: "XViD"
        });
    }
}
<commit_msg>Now recognizes `BD` and `DVD` as sources and resolutions in format `1234x5678`.<commit_after>#[macro_use] extern crate lazy_static;
extern crate regex;
extern crate itertools;

mod rope;

use rope::Rope;
use regex::Regex;
use itertools::Itertools;

#[derive(Debug, Clone)]
pub struct MediaInfo {
    pub title:      Option<String>,
    pub group:      Option<String>,
    pub resolution: Option<String>,
    pub season:     Option<u32>,
    pub episode:    Option<u32>,
    pub source:     Option<String>,
    pub year:       Option<u32>,
    pub codec:      Option<String>,
    pub audio:      Option<String>,
    pub extension:  Option<String>
}

fn parse_pattern(rope: &mut Rope, regex: &Regex) -> Option<String> {
    let mut info: Option<(usize, String, (usize, usize))> = None;

    for (i, part) in rope.iter().enumerate() {
        if let Some(captures) = regex.captures(part.string) {
            let value = captures.iter().skip(1)
                .find(|x| x.is_some())
                .unwrap().unwrap().to_owned();
            let range = captures.pos(0).unwrap();

            info = Some((i, value, range));
            break;
        }
    };

    if let Some((i, value, (start, end))) = info {
        rope.mark_part_range(i, start..end);
        return Some(value);
    }

    None
}

pub fn parse_filename(filename: &str) -> MediaInfo {
    lazy_static! {
        static ref EXTENSION_REGEX: Regex = Regex::new("\\.([A-Za-z0-9]{2,4})$").unwrap();
        static ref RESOLUTION_REGEX: Regex = Regex::new("([0-9]{3,4}p|[0-9]{3,4}x[0-9]{3,4})").unwrap();
        static ref GROUP_REGEX: Regex = Regex::new("(?:^\\[([^]]+)\\]|- ?([^-]+)$)").unwrap();
        static ref EPISODE_REGEX: Regex = Regex::new("(?:[eE]([0-9]{2,3})|[^0-9A-Za-z]([0-9]{2,3})(?:v[0-9])?[^0-9A-Za-z])").unwrap();
        static ref SEASON_REGEX: Regex = Regex::new("[sS]([0-9]{1,2})").unwrap();
        static ref SOURCE_REGEX: Regex = Regex::new("((?i)(?:PPV.)?[HP]DTV|(?:HD)?CAM|BRRIP|TS|(?:PPV )?WEB.?DL(?: DVDRip)?|HDRip|DVDRip|CamRip|W[EB]BRip|BluRay|BD|DVD|DvDScr|hdtv)").unwrap();
        static ref YEAR_REGEX: Regex = Regex::new("((19[0-9]|20[01])[0-9])").unwrap();
        static ref CODEC_REGEX: Regex = Regex::new("((?i)xvid|x264|h\\.?264)").unwrap();
        static ref AUDIO_REGEX: Regex = Regex::new("((?i)MP3|DD5\\.?1|Dual[- ]Audio|LiNE|DTS|AAC(?:\\.?2\\.0)?|AC3(?:\\.5\\.1)?)").unwrap();
    }

    let mut rope = Rope::new(&filename);

    MediaInfo {
        extension:  parse_pattern(&mut rope, &EXTENSION_REGEX),
        source:     parse_pattern(&mut rope, &SOURCE_REGEX),
        codec:      parse_pattern(&mut rope, &CODEC_REGEX),
        audio:      parse_pattern(&mut rope, &AUDIO_REGEX),
        resolution: parse_pattern(&mut rope, &RESOLUTION_REGEX),
        group:      parse_pattern(&mut rope, &GROUP_REGEX),
        season:     parse_pattern(&mut rope, &SEASON_REGEX).and_then(|s| s.parse().ok()),
        year:       parse_pattern(&mut rope, &YEAR_REGEX).and_then(|s| s.parse().ok()),
        episode:    parse_pattern(&mut rope, &EPISODE_REGEX).and_then(|s| s.parse().ok()),

        title: {
            let x: &[_] = &['(', ')', '[', ']', ' ', '-', '_', '.'];

            let title = rope.unmarked()
                .map(|p| p.string)
                .sorted_by(|a,b| Ord::cmp(&a.len(), &b.len()))
                .pop();

            let title = title.map(|s| s.trim_matches(x));

            title.map(|s| s.to_owned())
        }
    }
}

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

    macro_rules! assert_parse {
        ( $str:expr, {
            $($field:ident : $value:expr),*
        } ) => {
            {
                let info = parse_filename($str);
                println!("{:?}", info);
                $(assert!(info.$field == Some(($value).into()));)*
            }
        }
    }

    #[test]
    fn parse() {
        assert_parse!("[HorribleSubs] Mayoiga - 03 [720p].mkv", {
            group: "HorribleSubs",
            episode: 03 as u32,
            resolution: "720p",
            title: "Mayoiga"
        });

        assert_parse!("Game of Thrones Season 6 S06E05 720p Web Dl x264 Mrlss", {
            title: "Game of Thrones Season 6",
            season: 06 as u32,
            episode: 05 as u32,
            resolution: "720p",
            source: "Web Dl",
            codec: "x264"
        });

        assert_parse!("The Ones Below 2015 HDRip XViD-ETRG", {
            title: "The Ones Below",
            source: "HDRip",
            group: "ETRG",
            year: 2015 as u32,
            source: "HDRip",
            codec: "XViD"
        });

        assert_parse!("Mega Movie (BD 1280x720 10bit)", {
            title: "Mega Movie",
            source: "BD",
            resolution: "1280x720"
        });
    }
}
<|endoftext|>


<commit_before>//! Virtual machine for the CHIP-8 programming language
//!
//! This crate implements a virtual machine for the CHIP-8
//! programming language.
//! It can be used as a backend for CHIP-8 emulators, debuggers
//! and so on.
//!
//!
//! The code is split into the `instructions` module, which provides
//! the translation from raw bits (`RawInstruction`) into valid
//! instructions (`Instruction`).
//!
//! The `vm` module contains the actual virtual machine implementation
//! (`Vm`) and a few shared constants.
//!
//! The `error` module contains the `Chip8Error` implementation of
//! `std:error::Error` for any kinds of errors that might occur using
//! the `chip8_vm` crate.

// Silence 'core' feature warnings
// for `error:Error` and such
#![feature(core)]
// Silence 'io' feature warnings
// for `BufWriter` and such
#![feature(io)]

extern crate rand;

pub mod error;
pub mod instructions;
pub mod vm;

pub use instructions::*;
<commit_msg>Add function to return crate version<commit_after>//! Virtual machine for the CHIP-8 programming language
//!
//! This crate implements a virtual machine for the CHIP-8
//! programming language.
//! It can be used as a backend for CHIP-8 emulators, debuggers
//! and so on.
//!
//!
//! The code is split into the `instructions` module, which provides
//! the translation from raw bits (`RawInstruction`) into valid
//! instructions (`Instruction`).
//!
//! The `vm` module contains the actual virtual machine implementation
//! (`Vm`) and a few shared constants.
//!
//! The `error` module contains the `Chip8Error` implementation of
//! `std:error::Error` for any kinds of errors that might occur using
//! the `chip8_vm` crate.

// Silence 'core' feature warnings
// for `error:Error` and such
#![feature(core)]
// Silence 'io' feature warnings
// for `BufWriter` and such
#![feature(io)]

extern crate rand;

pub mod error;
pub mod instructions;
pub mod vm;

pub use instructions::*;

/// Returns the version of this crate in the format `MAJOR.MINOR.PATCH`.
pub fn version() -> &'static str {
    // TODO: There's also an optional _PRE part
    concat!(
        env!("CARGO_PKG_VERSION_MAJOR"), ".",
        env!("CARGO_PKG_VERSION_MINOR"), ".",
        env!("CARGO_PKG_VERSION_PATCH"),
    )
}
<|endoftext|>


<commit_before>// Copyright 2016 Mozilla
//
// 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.

extern crate datomish_query_parser;
extern crate rusqlite;

use rusqlite::Connection;

pub fn get_name() -> String {
  return String::from("datomish");
}

// Just an example of using a dependency
pub fn get_parser_name() -> String {
  return datomish_query_parser::get_name();
}

// Will ultimately not return the sqlite connection directly
pub fn get_connection() -> Connection {
    return Connection::open_in_memory().unwrap();
}

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

    #[test]
    fn can_import_parser() {
        assert_eq!(String::from("datomish-query-parser"), get_parser_name());
    }
}<commit_msg>Rename to Project Mentat (src).<commit_after>// Copyright 2016 Mozilla
//
// 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.

extern crate mentat_query_parser;
extern crate rusqlite;

use rusqlite::Connection;

pub fn get_name() -> String {
  return String::from("mentat");
}

// Just an example of using a dependency
pub fn get_parser_name() -> String {
  return mentat_query_parser::get_name();
}

// Will ultimately not return the sqlite connection directly
pub fn get_connection() -> Connection {
    return Connection::open_in_memory().unwrap();
}

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

    #[test]
    fn can_import_parser() {
        assert_eq!(String::from("mentat-query-parser"), get_parser_name());
    }
}
<|endoftext|>