<commit_before>//! This library provide a way to evaluate [`Reverse Polish Notated`] expressions for
//! numbers and basic evaluators.
//!
//! [`Floats`] and [`signed integers`] has already been implemented with basic evaluators
//! (cf. `+`, `-`, `*`, `/`, `neg`, `pow`...).
//!
//! Of course you can build your own Evaluators by implementing the [`Evaluate`] Trait,
//! the only constraint is the compatibility with the [`Operand`] type,
//! that can be everything you want (cf. `letters`, `Enums`, `chinese symbols`...).
//!
//! # Example
//!
//! ```
//! use ripin::evaluate::{FloatExpression, IntExpression};
//!
//! let str_expr = "3 4 + 2 *"; // (3 + 4) * 2
//! let tokens = str_expr.split_whitespace();
//! let expr = FloatExpression::<f32>::from_iter(tokens).unwrap();
//!
//! assert_eq!(expr.evaluate(), Ok(14.0)); // yup that's a Float evaluation
//!
//! // let's try an Integer evaluation:
//! let tokens = str_expr.split_whitespace();
//! let expr = IntExpression::<i32>::from_iter(tokens).unwrap();
//! assert_eq!(expr.evaluate(), Ok(14));
//! ```
//!
//! [`Reverse Polish Notated`]: https://en.wikipedia.org/wiki/Reverse_Polish_notation
//! [`str`]: https://doc.rust-lang.org/std/str/index.html
//! [`Floats`]: evaluate/enum.FloatEvaluator.html
//! [`signed integers`]: evaluate/enum.IntEvaluator.html
//! [`Evaluate`]: evaluate/trait.Evaluate.html
//! [`Operand`]: expression/enum.Arithm.html

extern crate num;

mod stack;
mod try_from_ref;

/// Operation on expressions and `Expression` construction methods.
pub mod expression;
/// `Evaluate Trait` and default `Evaluators`.
pub mod evaluate;

pub use stack::Stack;
pub use try_from_ref::TryFromRef;

/// Removes the last two elements from a stack and returns it,
/// or `None` if it is empty.
pub fn pop_two_operands<T>(stack: &mut Stack<T>) -> Option<(T, T)> {
    match (stack.pop(), stack.pop()) {
        (Some(a), Some(b)) => Some((b, a)),
        _ => None,
    }
}
<commit_msg>stack: Correct the doc message of pop_two_operands<commit_after>//! This library provide a way to evaluate [`Reverse Polish Notated`] expressions for
//! numbers and basic evaluators.
//!
//! [`Floats`] and [`signed integers`] has already been implemented with basic evaluators
//! (cf. `+`, `-`, `*`, `/`, `neg`, `pow`...).
//!
//! Of course you can build your own Evaluators by implementing the [`Evaluate`] Trait,
//! the only constraint is the compatibility with the [`Operand`] type,
//! that can be everything you want (cf. `letters`, `Enums`, `chinese symbols`...).
//!
//! # Example
//!
//! ```
//! use ripin::evaluate::{FloatExpression, IntExpression};
//!
//! let str_expr = "3 4 + 2 *"; // (3 + 4) * 2
//! let tokens = str_expr.split_whitespace();
//! let expr = FloatExpression::<f32>::from_iter(tokens).unwrap();
//!
//! assert_eq!(expr.evaluate(), Ok(14.0)); // yup that's a Float evaluation
//!
//! // let's try an Integer evaluation:
//! let tokens = str_expr.split_whitespace();
//! let expr = IntExpression::<i32>::from_iter(tokens).unwrap();
//! assert_eq!(expr.evaluate(), Ok(14));
//! ```
//!
//! [`Reverse Polish Notated`]: https://en.wikipedia.org/wiki/Reverse_Polish_notation
//! [`str`]: https://doc.rust-lang.org/std/str/index.html
//! [`Floats`]: evaluate/enum.FloatEvaluator.html
//! [`signed integers`]: evaluate/enum.IntEvaluator.html
//! [`Evaluate`]: evaluate/trait.Evaluate.html
//! [`Operand`]: expression/enum.Arithm.html

extern crate num;

mod stack;
mod try_from_ref;

/// Operation on expressions and `Expression` construction methods.
pub mod expression;
/// `Evaluate Trait` and default `Evaluators`.
pub mod evaluate;

pub use stack::Stack;
pub use try_from_ref::TryFromRef;

/// Removes the last two elements from a stack and return them,
/// or `None` if there is not enough element.
pub fn pop_two_operands<T>(stack: &mut Stack<T>) -> Option<(T, T)> {
    match (stack.pop(), stack.pop()) {
        (Some(a), Some(b)) => Some((b, a)),
        _ => None,
    }
}
<|endoftext|>


<commit_before>//! This is documentation for the tree_magic crate.
//!
//! See the README in the repository for more information.

#[macro_use] extern crate nom;
#[macro_use] extern crate lazy_static;
extern crate petgraph;
extern crate fnv;

use petgraph::prelude::*;
use fnv::FnvHashMap;
use fnv::FnvHashSet;
//use petgraph::dot::{Dot, Config};
use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;

mod fdo_magic;
mod basetype;

#[cfg(feature="staticmime")] type MIME = &'static str;
#[cfg(not(feature="staticmime"))] type MIME = String;

/// Check these types first
const TYPEORDER: [&'static str; 6] =
[
	"image/png",
	"image/jpeg",
	"image/gif",
	"application/zip",
	"application/x-msdos-executable",
	"application/pdf"
];

struct CheckerStruct {
    from_u8: fn(&[u8], &str) -> bool,
    from_filepath: fn(&str, &str) -> bool,
    get_supported: fn() -> Vec<MIME>,
    get_subclasses: fn() -> Vec<(MIME, MIME)>,
    get_aliaslist: fn() -> FnvHashMap<MIME, MIME>
}

/// List of checker functions
lazy_static! {
    static ref CHECKERS: Vec<CheckerStruct> = {vec![
        #[cfg(not(feature="staticmime"))] // Disable sys checker when using staticmime
        CheckerStruct{
            from_u8: fdo_magic::sys::check::from_u8,
            from_filepath: fdo_magic::sys::check::from_filepath,
            get_supported: fdo_magic::sys::init::get_supported,
            get_subclasses: fdo_magic::sys::init::get_subclasses,
            get_aliaslist: fdo_magic::sys::init::get_aliaslist
        },
        CheckerStruct{
            from_u8: fdo_magic::builtin::check::from_u8,
            from_filepath: fdo_magic::builtin::check::from_filepath,
            get_supported: fdo_magic::builtin::init::get_supported,
            get_subclasses: fdo_magic::builtin::init::get_subclasses,
            get_aliaslist: fdo_magic::builtin::init::get_aliaslist
        },
        CheckerStruct{
            from_u8: basetype::check::from_u8,
            from_filepath: basetype::check::from_filepath,
            get_supported: basetype::init::get_supported,
            get_subclasses: basetype::init::get_subclasses,
            get_aliaslist: basetype::init::get_aliaslist
        }
    ]};
}

/// Mappings between modules and supported mimes (by index in table above)
lazy_static! {
    static ref CHECKER_SUPPORT: FnvHashMap<MIME, usize> = {
        let mut out = FnvHashMap::<MIME, usize>::default();
        for i in 0..CHECKERS.len() {
            for j in (CHECKERS[i].get_supported)() {
                out.insert(j, i);
            }
        }
        out
    };
}

lazy_static! {
    static ref ALIASES:  FnvHashMap<MIME, MIME> = {
        let mut out = FnvHashMap::<MIME, MIME>::default();
        for i in 0..CHECKERS.len() {
            out.extend((CHECKERS[i].get_aliaslist)());
        }
        out
    };
}

/// Information about currently loaded MIME types
///
/// The `graph` contains subclass relations between all given mimes.
/// (EX: `application/json` -> `text/plain` -> `application/octet-stream`)
/// This is a `petgraph` DiGraph, so you can walk the tree if needed.
///
/// The `hash` is a mapping between mime types and nodes on the graph.
/// The root of the graph is "all/all", so start traversing there unless
/// you need to jump to a particular node.
pub struct TypeStruct {
    pub graph: DiGraph<MIME, u32>,
    pub hash: FnvHashMap<MIME, NodeIndex>
}

lazy_static! {
    /// The TypeStruct autogenerated at library init, and used by the library.
    pub static ref TYPE: TypeStruct = {
        graph_init().unwrap_or(
            TypeStruct{
                graph: DiGraph::new(),
                hash: FnvHashMap::default()
            } )
    };
}

#[cfg(not(feature="staticmime"))]
macro_rules! convmime {
    ($x:expr) => {$x.to_string()}
}
#[cfg(feature="staticmime")]
macro_rules! convmime {
    ($x:expr) => {$x}
}

#[cfg(not(feature="staticmime"))]
macro_rules! clonemime {
    ($x:expr) => {$x.clone()}
}
#[cfg(feature="staticmime")]
macro_rules! clonemime {
    ($x:expr) => {$x}
}

// Initialize filetype graph
fn graph_init() -> Result<TypeStruct, std::io::Error> {

    let mut graph = DiGraph::<MIME, u32>::new();
    let mut added_mimes = FnvHashMap::<MIME, NodeIndex>::default();

    // Get list of MIME types and MIME relations
    let mut mimelist = Vec::<MIME>::new();
    let mut edgelist_raw = Vec::<(MIME, MIME)>::new();
    for i in 0..CHECKERS.len() {
        mimelist.extend((CHECKERS[i].get_supported)());
        edgelist_raw.extend((CHECKERS[i].get_subclasses)());
    }
    mimelist.sort();
    mimelist.dedup();
    let mimelist = mimelist;

    // Create all nodes
    for mimetype in mimelist.iter() {
        let node = graph.add_node(clonemime!(mimetype));
        added_mimes.insert(clonemime!(mimetype), node);
    }

    let mut edge_list = FnvHashSet::<(NodeIndex, NodeIndex)>::with_capacity_and_hasher(
        edgelist_raw.len(), Default::default()
    );
    for x in edgelist_raw {
        let child_raw = x.0;
        let parent_raw = x.1;

        let parent = match added_mimes.get(&parent_raw) {
            Some(node) => *node,
            None => {continue;}
        };

        let child = match added_mimes.get(&child_raw) {
            Some(node) => *node,
            None => {continue;}
        };

        edge_list.insert( (child, parent) );
    }

    graph.extend_with_edges(&edge_list);

    //Add to applicaton/octet-stream, all/all, or text/plain, depending on top-level
    //(We'll just do it here because having the graph makes it really nice)
    let added_mimes_tmp = added_mimes.clone();
    let node_text = match added_mimes_tmp.get("text/plain"){
        Some(x) => *x,
        None => {
            let node = graph.add_node(convmime!("text/plain"));
            added_mimes.insert(convmime!("text/plain"), node);
            node
        }
    };
    let node_octet = match added_mimes_tmp.get("application/octet-stream"){
        Some(x) => *x,
        None => {
            let node = graph.add_node(convmime!("application/octet-stream"));
            added_mimes.insert(convmime!("application/octet-stream"), node);
            node
        }
    };
    let node_allall = match added_mimes_tmp.get("all/all"){
        Some(x) => *x,
        None => {
            let node = graph.add_node(convmime!("all/all"));
            added_mimes.insert(convmime!("all/all"), node);
            node
        }
    };
    let node_allfiles = match added_mimes_tmp.get("all/allfiles"){
        Some(x) => *x,
        None => {
            let node = graph.add_node(convmime!("all/allfiles"));
            added_mimes.insert(convmime!("all/allfiles"), node);
            node
        }
    };

    let mut edge_list_2 = FnvHashSet::<(NodeIndex, NodeIndex)>::default();
    for mimenode in graph.externals(Incoming) {

        let ref mimetype = graph[mimenode];
        let toplevel = mimetype.split("/").nth(0).unwrap_or("");

        if mimenode == node_text || mimenode == node_octet ||
           mimenode == node_allfiles || mimenode == node_allall
        {
            continue;
        }

        if toplevel == "text" {
            edge_list_2.insert( (node_text, mimenode) );
        } else if toplevel == "inode" {
            edge_list_2.insert( (node_allall, mimenode) );
        } else {
            edge_list_2.insert( (node_octet, mimenode) );
        }
    }
    // Don't add duplicate entries
    graph.extend_with_edges(edge_list_2.difference(&edge_list));

    let graph = graph;
    let added_mimes = added_mimes;
    //println!("{:?}", Dot::with_config(&graph, &[Config::EdgeNoLabel]));

    Ok( TypeStruct{graph: graph, hash: added_mimes} )
}

/// Just the part of from_*_node that walks the graph
fn typegraph_walker<T: Clone>(
    parentnode: NodeIndex,
    input: T,
    matchfn: fn(&str, T) -> bool
) -> Option<MIME> {

    // Pull most common types towards top
    let mut children: Vec<NodeIndex> = TYPE.graph
        .neighbors_directed(parentnode, Outgoing)
        .collect();

    for i in 0..children.len() {
        let x = children[i];
        if TYPEORDER.contains(&&*TYPE.graph[x]) {
            children.remove(i);
            children.insert(0, x);
        }
    }

    // Walk graph
    for childnode in children {
        let ref mimetype = TYPE.graph[childnode];
        let result = (matchfn)(mimetype, input.clone());
        match result {
            true => {
                match typegraph_walker(
                    childnode, input, matchfn
                ) {
                    Some(foundtype) => return Some(foundtype),
                    None => return Some(clonemime!(mimetype)),
                }
            }
            false => continue,
        }
    }

    None
}

/// Transforms an alias into it's real type
fn get_alias(mimetype: MIME) -> MIME {
    match ALIASES.get(&mimetype) {
        Some(x) => convmime!(x),
        None => mimetype
    }
}

/// Checks if the given bytestream matches the given MIME type.
///
/// Returns true or false if it matches or not. If the given mime type is not known,
/// the function will always return false.
pub fn match_u8(mimetype: &str, bytes: &[u8]) -> bool
{
    // Transform alias if needed
    let x = get_alias(convmime!(mimetype));
    match CHECKER_SUPPORT.get(x.as_str()) {
        None => {panic!("{} not supported", x);},
        Some(y) => (CHECKERS[*y].from_u8)(bytes, &x.as_str())
    }
}

/// Gets the type of a file from a raw bytestream, starting at a certain node
/// in the type graph.
///
/// Returns mime as string wrapped in Some if a type matches, or
/// None if no match is found.
/// Retreive the node from the `TYPE.hash` FnvHashMap, using the MIME as the key.
///
/// ## Panics
/// Will panic if the given node is not found in the graph.
/// As the graph is immutable, this should not happen if the node index comes from
/// TYPE.hash.
pub fn from_u8_node(parentnode: NodeIndex, bytes: &[u8]) -> Option<MIME>
{
	typegraph_walker(parentnode, bytes, match_u8)
}

/// Gets the type of a file from a byte stream.
///
/// Returns mime as string wrapped in Some if a type matches, or
/// None if no match is found. Because this starts from the type graph root,
/// it is a bug if this returns None.
pub fn from_u8(bytes: &[u8]) -> Option<MIME>
{
    let node = match TYPE.graph.externals(Incoming).next() {
        Some(foundnode) => foundnode,
        None => return None
    };
    from_u8_node(node, bytes)
}

/// Check if the given filepath matches the given MIME type.
///
/// Returns true or false if it matches or not, or an Error if the file could
/// not be read. If the given mime type is not known, it will always return false.
pub fn match_filepath(mimetype: &str, filepath: &str) -> bool
{
    // Transform alias if needed
    let x = get_alias(convmime!(mimetype));
    match CHECKER_SUPPORT.get(x.as_str()) {
        None => false,
        Some(y) => (CHECKERS[*y].from_filepath)(filepath, &x.as_str())
    }
}

/// Gets the type of a file from a filepath, starting at a certain node
/// in the type graph.
///
/// Returns mime as string wrapped in Some if a type matches, or
/// None if the file is not found or cannot be opened.
/// Retreive the node from the `TYPE.hash` FnvHashMap, using the MIME as the key.
///
/// ## Panics
/// Will panic if the given node is not found in the graph.
/// As the graph is immutable, this should not happen if the node index comes from
/// TYPE.hash.
pub fn from_filepath_node(parentnode: NodeIndex, filepath: &str) -> Option<MIME>
{
    // We're actually just going to thunk this down to a u8
    // unless we're checking via basetype for speed reasons.

    // Ensure it's at least a application/octet-stream
    if !match_filepath("application/octet-stream", filepath){
        // Check the other base types
        return typegraph_walker(parentnode, filepath, match_filepath);
    }

    // Load the first 4K of file and parse as u8
    // for batch processing like this
    let f = match File::open(filepath) {
        Ok(x) => x,
        Err(_) => return None // How?
    };
    let r = BufReader::new(f);
    let mut b = Vec::<u8>::new();
    match r.take(4096).read_to_end(&mut b) {
        Ok(_) => {},
        Err(_) => return None // Also how?
    }

    from_u8_node(parentnode, b.as_slice())
}

/// Gets the type of a file from a filepath.
///
/// Does not look at file name or extension, just the contents.
/// Returns mime as string wrapped in Some if a type matches, or
/// None if the file is not found or cannot be opened.
pub fn from_filepath(filepath: &str) -> Option<MIME> {

    let node = match TYPE.graph.externals(Incoming).next() {
        Some(foundnode) => foundnode,
        None => return None
    };

    from_filepath_node(node, filepath)
}
<commit_msg>Add is_alias public function<commit_after>//! This is documentation for the tree_magic crate.
//!
//! See the README in the repository for more information.

#[macro_use] extern crate nom;
#[macro_use] extern crate lazy_static;
extern crate petgraph;
extern crate fnv;

use petgraph::prelude::*;
use fnv::FnvHashMap;
use fnv::FnvHashSet;
//use petgraph::dot::{Dot, Config};
use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;

mod fdo_magic;
mod basetype;

#[cfg(feature="staticmime")] type MIME = &'static str;
#[cfg(not(feature="staticmime"))] type MIME = String;

/// Check these types first
const TYPEORDER: [&'static str; 6] =
[
	"image/png",
	"image/jpeg",
	"image/gif",
	"application/zip",
	"application/x-msdos-executable",
	"application/pdf"
];

struct CheckerStruct {
    from_u8: fn(&[u8], &str) -> bool,
    from_filepath: fn(&str, &str) -> bool,
    get_supported: fn() -> Vec<MIME>,
    get_subclasses: fn() -> Vec<(MIME, MIME)>,
    get_aliaslist: fn() -> FnvHashMap<MIME, MIME>
}

/// List of checker functions
lazy_static! {
    static ref CHECKERS: Vec<CheckerStruct> = {vec![
        #[cfg(not(feature="staticmime"))] // Disable sys checker when using staticmime
        CheckerStruct{
            from_u8: fdo_magic::sys::check::from_u8,
            from_filepath: fdo_magic::sys::check::from_filepath,
            get_supported: fdo_magic::sys::init::get_supported,
            get_subclasses: fdo_magic::sys::init::get_subclasses,
            get_aliaslist: fdo_magic::sys::init::get_aliaslist
        },
        CheckerStruct{
            from_u8: fdo_magic::builtin::check::from_u8,
            from_filepath: fdo_magic::builtin::check::from_filepath,
            get_supported: fdo_magic::builtin::init::get_supported,
            get_subclasses: fdo_magic::builtin::init::get_subclasses,
            get_aliaslist: fdo_magic::builtin::init::get_aliaslist
        },
        CheckerStruct{
            from_u8: basetype::check::from_u8,
            from_filepath: basetype::check::from_filepath,
            get_supported: basetype::init::get_supported,
            get_subclasses: basetype::init::get_subclasses,
            get_aliaslist: basetype::init::get_aliaslist
        }
    ]};
}

/// Mappings between modules and supported mimes (by index in table above)
lazy_static! {
    static ref CHECKER_SUPPORT: FnvHashMap<MIME, usize> = {
        let mut out = FnvHashMap::<MIME, usize>::default();
        for i in 0..CHECKERS.len() {
            for j in (CHECKERS[i].get_supported)() {
                out.insert(j, i);
            }
        }
        out
    };
}

lazy_static! {
    static ref ALIASES:  FnvHashMap<MIME, MIME> = {
        let mut out = FnvHashMap::<MIME, MIME>::default();
        for i in 0..CHECKERS.len() {
            out.extend((CHECKERS[i].get_aliaslist)());
        }
        out
    };
}

/// Information about currently loaded MIME types
///
/// The `graph` contains subclass relations between all given mimes.
/// (EX: `application/json` -> `text/plain` -> `application/octet-stream`)
/// This is a `petgraph` DiGraph, so you can walk the tree if needed.
///
/// The `hash` is a mapping between mime types and nodes on the graph.
/// The root of the graph is "all/all", so start traversing there unless
/// you need to jump to a particular node.
pub struct TypeStruct {
    pub graph: DiGraph<MIME, u32>,
    pub hash: FnvHashMap<MIME, NodeIndex>
}

lazy_static! {
    /// The TypeStruct autogenerated at library init, and used by the library.
    pub static ref TYPE: TypeStruct = {
        graph_init().unwrap_or(
            TypeStruct{
                graph: DiGraph::new(),
                hash: FnvHashMap::default()
            } )
    };
}

#[cfg(not(feature="staticmime"))]
macro_rules! convmime {
    ($x:expr) => {$x.to_string()}
}
#[cfg(feature="staticmime")]
macro_rules! convmime {
    ($x:expr) => {$x}
}

#[cfg(not(feature="staticmime"))]
macro_rules! clonemime {
    ($x:expr) => {$x.clone()}
}
#[cfg(feature="staticmime")]
macro_rules! clonemime {
    ($x:expr) => {$x}
}

// Initialize filetype graph
fn graph_init() -> Result<TypeStruct, std::io::Error> {

    let mut graph = DiGraph::<MIME, u32>::new();
    let mut added_mimes = FnvHashMap::<MIME, NodeIndex>::default();

    // Get list of MIME types and MIME relations
    let mut mimelist = Vec::<MIME>::new();
    let mut edgelist_raw = Vec::<(MIME, MIME)>::new();
    for i in 0..CHECKERS.len() {
        mimelist.extend((CHECKERS[i].get_supported)());
        edgelist_raw.extend((CHECKERS[i].get_subclasses)());
    }
    mimelist.sort();
    mimelist.dedup();
    let mimelist = mimelist;

    // Create all nodes
    for mimetype in mimelist.iter() {
        let node = graph.add_node(clonemime!(mimetype));
        added_mimes.insert(clonemime!(mimetype), node);
    }

    let mut edge_list = FnvHashSet::<(NodeIndex, NodeIndex)>::with_capacity_and_hasher(
        edgelist_raw.len(), Default::default()
    );
    for x in edgelist_raw {
        let child_raw = x.0;
        let parent_raw = x.1;

        let parent = match added_mimes.get(&parent_raw) {
            Some(node) => *node,
            None => {continue;}
        };

        let child = match added_mimes.get(&child_raw) {
            Some(node) => *node,
            None => {continue;}
        };

        edge_list.insert( (child, parent) );
    }

    graph.extend_with_edges(&edge_list);

    //Add to applicaton/octet-stream, all/all, or text/plain, depending on top-level
    //(We'll just do it here because having the graph makes it really nice)
    let added_mimes_tmp = added_mimes.clone();
    let node_text = match added_mimes_tmp.get("text/plain"){
        Some(x) => *x,
        None => {
            let node = graph.add_node(convmime!("text/plain"));
            added_mimes.insert(convmime!("text/plain"), node);
            node
        }
    };
    let node_octet = match added_mimes_tmp.get("application/octet-stream"){
        Some(x) => *x,
        None => {
            let node = graph.add_node(convmime!("application/octet-stream"));
            added_mimes.insert(convmime!("application/octet-stream"), node);
            node
        }
    };
    let node_allall = match added_mimes_tmp.get("all/all"){
        Some(x) => *x,
        None => {
            let node = graph.add_node(convmime!("all/all"));
            added_mimes.insert(convmime!("all/all"), node);
            node
        }
    };
    let node_allfiles = match added_mimes_tmp.get("all/allfiles"){
        Some(x) => *x,
        None => {
            let node = graph.add_node(convmime!("all/allfiles"));
            added_mimes.insert(convmime!("all/allfiles"), node);
            node
        }
    };

    let mut edge_list_2 = FnvHashSet::<(NodeIndex, NodeIndex)>::default();
    for mimenode in graph.externals(Incoming) {

        let ref mimetype = graph[mimenode];
        let toplevel = mimetype.split("/").nth(0).unwrap_or("");

        if mimenode == node_text || mimenode == node_octet ||
           mimenode == node_allfiles || mimenode == node_allall
        {
            continue;
        }

        if toplevel == "text" {
            edge_list_2.insert( (node_text, mimenode) );
        } else if toplevel == "inode" {
            edge_list_2.insert( (node_allall, mimenode) );
        } else {
            edge_list_2.insert( (node_octet, mimenode) );
        }
    }
    // Don't add duplicate entries
    graph.extend_with_edges(edge_list_2.difference(&edge_list));

    let graph = graph;
    let added_mimes = added_mimes;
    //println!("{:?}", Dot::with_config(&graph, &[Config::EdgeNoLabel]));

    Ok( TypeStruct{graph: graph, hash: added_mimes} )
}

/// Just the part of from_*_node that walks the graph
fn typegraph_walker<T: Clone>(
    parentnode: NodeIndex,
    input: T,
    matchfn: fn(&str, T) -> bool
) -> Option<MIME> {

    // Pull most common types towards top
    let mut children: Vec<NodeIndex> = TYPE.graph
        .neighbors_directed(parentnode, Outgoing)
        .collect();

    for i in 0..children.len() {
        let x = children[i];
        if TYPEORDER.contains(&&*TYPE.graph[x]) {
            children.remove(i);
            children.insert(0, x);
        }
    }

    // Walk graph
    for childnode in children {
        let ref mimetype = TYPE.graph[childnode];
        let result = (matchfn)(mimetype, input.clone());
        match result {
            true => {
                match typegraph_walker(
                    childnode, input, matchfn
                ) {
                    Some(foundtype) => return Some(foundtype),
                    None => return Some(clonemime!(mimetype)),
                }
            }
            false => continue,
        }
    }

    None
}

/// Transforms an alias into it's real type
fn get_alias(mimetype: MIME) -> MIME {
    match ALIASES.get(&mimetype) {
        Some(x) => convmime!(x),
        None => mimetype
    }
}

/// Checks if the given bytestream matches the given MIME type.
///
/// Returns true or false if it matches or not. If the given mime type is not known,
/// the function will always return false.
pub fn match_u8(mimetype: &str, bytes: &[u8]) -> bool
{
    // Transform alias if needed
    let x = get_alias(convmime!(mimetype));
    match CHECKER_SUPPORT.get(x.as_str()) {
        None => {panic!("{} not supported", x);},
        Some(y) => (CHECKERS[*y].from_u8)(bytes, &x.as_str())
    }
}

/// Gets the type of a file from a raw bytestream, starting at a certain node
/// in the type graph.
///
/// Returns mime as string wrapped in Some if a type matches, or
/// None if no match is found.
/// Retreive the node from the `TYPE.hash` FnvHashMap, using the MIME as the key.
///
/// ## Panics
/// Will panic if the given node is not found in the graph.
/// As the graph is immutable, this should not happen if the node index comes from
/// TYPE.hash.
pub fn from_u8_node(parentnode: NodeIndex, bytes: &[u8]) -> Option<MIME>
{
	typegraph_walker(parentnode, bytes, match_u8)
}

/// Gets the type of a file from a byte stream.
///
/// Returns mime as string wrapped in Some if a type matches, or
/// None if no match is found. Because this starts from the type graph root,
/// it is a bug if this returns None.
pub fn from_u8(bytes: &[u8]) -> Option<MIME>
{
    let node = match TYPE.graph.externals(Incoming).next() {
        Some(foundnode) => foundnode,
        None => return None
    };
    from_u8_node(node, bytes)
}

/// Check if the given filepath matches the given MIME type.
///
/// Returns true or false if it matches or not, or an Error if the file could
/// not be read. If the given mime type is not known, it will always return false.
pub fn match_filepath(mimetype: &str, filepath: &str) -> bool
{
    // Transform alias if needed
    let x = get_alias(convmime!(mimetype));
    match CHECKER_SUPPORT.get(x.as_str()) {
        None => false,
        Some(y) => (CHECKERS[*y].from_filepath)(filepath, &x.as_str())
    }
}

/// Gets the type of a file from a filepath, starting at a certain node
/// in the type graph.
///
/// Returns mime as string wrapped in Some if a type matches, or
/// None if the file is not found or cannot be opened.
/// Retreive the node from the `TYPE.hash` FnvHashMap, using the MIME as the key.
///
/// ## Panics
/// Will panic if the given node is not found in the graph.
/// As the graph is immutable, this should not happen if the node index comes from
/// TYPE.hash.
pub fn from_filepath_node(parentnode: NodeIndex, filepath: &str) -> Option<MIME>
{
    // We're actually just going to thunk this down to a u8
    // unless we're checking via basetype for speed reasons.

    // Ensure it's at least a application/octet-stream
    if !match_filepath("application/octet-stream", filepath){
        // Check the other base types
        return typegraph_walker(parentnode, filepath, match_filepath);
    }

    // Load the first 4K of file and parse as u8
    // for batch processing like this
    let f = match File::open(filepath) {
        Ok(x) => x,
        Err(_) => return None // How?
    };
    let r = BufReader::new(f);
    let mut b = Vec::<u8>::new();
    match r.take(4096).read_to_end(&mut b) {
        Ok(_) => {},
        Err(_) => return None // Also how?
    }

    from_u8_node(parentnode, b.as_slice())
}

/// Gets the type of a file from a filepath.
///
/// Does not look at file name or extension, just the contents.
/// Returns mime as string wrapped in Some if a type matches, or
/// None if the file is not found or cannot be opened.
pub fn from_filepath(filepath: &str) -> Option<MIME> {

    let node = match TYPE.graph.externals(Incoming).next() {
        Some(foundnode) => foundnode,
        None => return None
    };

    from_filepath_node(node, filepath)
}

/// Determines if a MIME is an alias of another MIME
///
/// If this returns true, that means the two MIME types are equivalent.
/// If this returns false, either one of the MIME types are missing, or they are different.
pub fn is_alias(mime1: MIME, mime2: MIME) -> bool {
    let x = get_alias(clonemime!(mime1));
    let y = get_alias(clonemime!(mime2));

    return x == mime2 || y == mime1;
}
<|endoftext|>


<commit_before>// I have no idea what I'm doing with these attributes. Are we using
// semantic versioning? Some packages include their full github URL.
// Documentation for this stuff is extremely scarce.
#[crate_id = "quickcheck#0.1.0"];
#[crate_type = "lib"];
#[license = "UNLICENSE"];
#[doc(html_root_url = "http://burntsushi.net/rustdoc/quickcheck")];

//! This crate is a port of
//! [Haskell's QuickCheck](http://hackage.haskell.org/package/QuickCheck).

extern crate collections;

pub use arbitrary::{Arbitrary, Gen, StdGen, arbitrary, default_gen, gen};
pub use shrink::{ObjIter, Shrink};
pub use tester::{Testable, TestResult, Status};

mod arbitrary;
mod shrink;

mod tester {
    use std::fmt::Show;

    use super::{Arbitrary, Gen};

    fn arby<A: Arbitrary, G: Gen>(g: &mut G) -> A { Arbitrary::arbitrary(g) }

    #[deriving(Clone, Show)]
    pub struct TestResult {
        status: Status,
        arguments: ~[~str],
    }

    #[deriving(Clone, Show)]
    pub enum Status { Pass, Fail, Discard }

    impl TestResult {
        pub fn passed() -> ~TestResult { TestResult::from_bool(true) }
        pub fn failed() -> ~TestResult { TestResult::from_bool(false) }
        pub fn discard() -> ~TestResult {
            ~TestResult { status: Discard, arguments: ~[] }
        }
        pub fn from_bool(b: bool) -> ~TestResult {
            ~TestResult { status: if b { Pass } else { Fail }, arguments: ~[] }
        }
    }

    pub trait Testable {
        fn result<G: Gen>(&self, &mut G) -> ~TestResult;
    }

    impl Testable for bool {
        fn result<G: Gen>(&self, _: &mut G) -> ~TestResult {
            TestResult::from_bool(*self)
        }
    }

    impl Testable for ~TestResult {
        fn result<G: Gen>(&self, _: &mut G) -> ~TestResult { self.clone() }
    }

    // I should really figure out how to use macros. This is painful.
    // N.B. This isn't needed in Haskell because it's currying by default!
    // Perhaps there is a way to circumvent this in Rust too (without macros),
    // but I'm not sure.

    impl<A: Testable> Testable for 'static || -> A {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            (*self)().result(g)
        }
    }

    impl<A: Arbitrary + Show, B: Testable> Testable for 'static |A| -> B {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            let a: A = Arbitrary::arbitrary(g);
            let arg: ~str = a.to_str();
            let mut r: ~TestResult = (*self)(a).result(g);
            r.arguments.unshift(arg);
            r
        }
    }

    impl<A: Arbitrary + Show, B: Arbitrary + Show, C: Testable>
        Testable for 'static |A, B| -> C {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            let (a, b): (A, B) = (arby(g), arby(g));
            let (a_arg, b_arg) = (a.to_str(), b.to_str());
            let mut r: ~TestResult = (*self)(a, b).result(g);
            r.arguments.unshift(b_arg);
            r.arguments.unshift(a_arg);
            r
        }
    }

    impl<A: Arbitrary + Show,
         B: Arbitrary + Show,
         C: Arbitrary + Show,
         D: Testable>
        Testable for 'static |A, B, C| -> D {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            let (a, b, c): (A, B, C) = (arby(g), arby(g), arby(g));
            let (a_arg, b_arg, c_arg) = (a.to_str(), b.to_str(), c.to_str());
            let mut r: ~TestResult = (*self)(a, b, c).result(g);
            r.arguments.unshift(c_arg);
            r.arguments.unshift(b_arg);
            r.arguments.unshift(a_arg);
            r
        }
    }

    impl<A: Testable> Testable for fn() -> A {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            (*self)().result(g)
        }
    }

    impl<A: Arbitrary + Show, B: Testable> Testable for fn(A) -> B {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            let a: A = Arbitrary::arbitrary(g);
            let arg: ~str = a.to_str();
            let mut r: ~TestResult = (*self)(a).result(g);
            r.arguments.unshift(arg);
            r
        }
    }

    impl<A: Arbitrary + Show, B: Arbitrary + Show, C: Testable>
        Testable for fn(A, B) -> C {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            let (a, b): (A, B) = (arby(g), arby(g));
            let (a_arg, b_arg) = (a.to_str(), b.to_str());
            let mut r: ~TestResult = (*self)(a, b).result(g);
            r.arguments.unshift(b_arg);
            r.arguments.unshift(a_arg);
            r
        }
    }

    impl<A: Arbitrary + Show,
         B: Arbitrary + Show,
         C: Arbitrary + Show,
         D: Testable>
        Testable for fn(A, B, C) -> D {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            let (a, b, c): (A, B, C) = (arby(g), arby(g), arby(g));
            let (a_arg, b_arg, c_arg) = (a.to_str(), b.to_str(), c.to_str());
            let mut r: ~TestResult = (*self)(a, b, c).result(g);
            r.arguments.unshift(c_arg);
            r.arguments.unshift(b_arg);
            r.arguments.unshift(a_arg);
            r
        }
    }
}

#[cfg(test)]
mod test {
    use std::iter;

    use super::{Testable, TestResult, default_gen};

    #[test]
    fn reverse_reverse() {
        let g = &mut default_gen();
        fn revrev(xs: ~[uint]) -> bool {
            let rev = xs.clone().move_rev_iter().to_owned_vec()
                        .move_rev_iter().to_owned_vec();
            xs == rev
        }
        for _ in iter::range(0, 10) {
            debug!("{}", (revrev).result(g));
        }
    }

    #[test]
    fn reverse_single() {
        let g = &mut default_gen();
        fn rev_single(xs: ~[uint]) -> ~TestResult {
            if xs.len() != 1 {
                return TestResult::discard()
            }
            return TestResult::from_bool(
                xs.clone().move_rev_iter().to_owned_vec()
                ==
                xs.clone().move_rev_iter().to_owned_vec()
            )
        }
        for _ in iter::range(0, 10) {
            debug!("{}", (rev_single).result(g));
        }
    }

    #[test]
    fn reverse_app() {
        let g = &mut default_gen();
        fn revapp(xs: ~[uint], ys: ~[uint]) -> bool {
            let app = ::std::vec::append(xs.clone(), ys);
            let app_rev = app.move_rev_iter().to_owned_vec();

            let rxs = xs.clone().move_rev_iter().to_owned_vec();
            let rys = ys.clone().move_rev_iter().to_owned_vec();
            let rev_app = ::std::vec::append(rys, rxs);

            app_rev == rev_app
        }
        for _ in iter::range(0, 10) {
            debug!("{}", (revapp).result(g));
        }
    }
}
<commit_msg>Make the TestResult struct opaque.<commit_after>// I have no idea what I'm doing with these attributes. Are we using
// semantic versioning? Some packages include their full github URL.
// Documentation for this stuff is extremely scarce.
#[crate_id = "quickcheck#0.1.0"];
#[crate_type = "lib"];
#[license = "UNLICENSE"];
#[doc(html_root_url = "http://burntsushi.net/rustdoc/quickcheck")];

//! This crate is a port of
//! [Haskell's QuickCheck](http://hackage.haskell.org/package/QuickCheck).

extern crate collections;

pub use arbitrary::{Arbitrary, Gen, StdGen, arbitrary, default_gen, gen};
pub use shrink::{ObjIter, Shrink};
pub use tester::{Testable, TestResult, Status};

mod arbitrary;
mod shrink;

mod tester {
    use std::fmt::Show;

    use super::{Arbitrary, Gen};

    fn arby<A: Arbitrary, G: Gen>(g: &mut G) -> A { Arbitrary::arbitrary(g) }

    #[deriving(Clone, Show)]
    pub struct TestResult {
        priv status: Status,
        priv arguments: ~[~str],
    }

    #[deriving(Clone, Show)]
    pub enum Status { Pass, Fail, Discard }

    impl TestResult {
        pub fn passed() -> ~TestResult { TestResult::from_bool(true) }
        pub fn failed() -> ~TestResult { TestResult::from_bool(false) }
        pub fn discard() -> ~TestResult {
            ~TestResult { status: Discard, arguments: ~[] }
        }
        pub fn from_bool(b: bool) -> ~TestResult {
            ~TestResult { status: if b { Pass } else { Fail }, arguments: ~[] }
        }
    }

    pub trait Testable {
        fn result<G: Gen>(&self, &mut G) -> ~TestResult;
    }

    impl Testable for bool {
        fn result<G: Gen>(&self, _: &mut G) -> ~TestResult {
            TestResult::from_bool(*self)
        }
    }

    impl Testable for ~TestResult {
        fn result<G: Gen>(&self, _: &mut G) -> ~TestResult { self.clone() }
    }

    // I should really figure out how to use macros. This is painful.
    // N.B. This isn't needed in Haskell because it's currying by default!
    // Perhaps there is a way to circumvent this in Rust too (without macros),
    // but I'm not sure.

    impl<A: Testable> Testable for 'static || -> A {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            (*self)().result(g)
        }
    }

    impl<A: Arbitrary + Show, B: Testable> Testable for 'static |A| -> B {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            let a: A = Arbitrary::arbitrary(g);
            let arg: ~str = a.to_str();
            let mut r: ~TestResult = (*self)(a).result(g);
            r.arguments.unshift(arg);
            r
        }
    }

    impl<A: Arbitrary + Show, B: Arbitrary + Show, C: Testable>
        Testable for 'static |A, B| -> C {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            let (a, b): (A, B) = (arby(g), arby(g));
            let (a_arg, b_arg) = (a.to_str(), b.to_str());
            let mut r: ~TestResult = (*self)(a, b).result(g);
            r.arguments.unshift(b_arg);
            r.arguments.unshift(a_arg);
            r
        }
    }

    impl<A: Arbitrary + Show,
         B: Arbitrary + Show,
         C: Arbitrary + Show,
         D: Testable>
        Testable for 'static |A, B, C| -> D {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            let (a, b, c): (A, B, C) = (arby(g), arby(g), arby(g));
            let (a_arg, b_arg, c_arg) = (a.to_str(), b.to_str(), c.to_str());
            let mut r: ~TestResult = (*self)(a, b, c).result(g);
            r.arguments.unshift(c_arg);
            r.arguments.unshift(b_arg);
            r.arguments.unshift(a_arg);
            r
        }
    }

    impl<A: Testable> Testable for fn() -> A {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            (*self)().result(g)
        }
    }

    impl<A: Arbitrary + Show, B: Testable> Testable for fn(A) -> B {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            let a: A = Arbitrary::arbitrary(g);
            let arg: ~str = a.to_str();
            let mut r: ~TestResult = (*self)(a).result(g);
            r.arguments.unshift(arg);
            r
        }
    }

    impl<A: Arbitrary + Show, B: Arbitrary + Show, C: Testable>
        Testable for fn(A, B) -> C {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            let (a, b): (A, B) = (arby(g), arby(g));
            let (a_arg, b_arg) = (a.to_str(), b.to_str());
            let mut r: ~TestResult = (*self)(a, b).result(g);
            r.arguments.unshift(b_arg);
            r.arguments.unshift(a_arg);
            r
        }
    }

    impl<A: Arbitrary + Show,
         B: Arbitrary + Show,
         C: Arbitrary + Show,
         D: Testable>
        Testable for fn(A, B, C) -> D {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            let (a, b, c): (A, B, C) = (arby(g), arby(g), arby(g));
            let (a_arg, b_arg, c_arg) = (a.to_str(), b.to_str(), c.to_str());
            let mut r: ~TestResult = (*self)(a, b, c).result(g);
            r.arguments.unshift(c_arg);
            r.arguments.unshift(b_arg);
            r.arguments.unshift(a_arg);
            r
        }
    }
}

#[cfg(test)]
mod test {
    use std::iter;

    use super::{Testable, TestResult, default_gen};

    #[test]
    fn reverse_reverse() {
        let g = &mut default_gen();
        fn revrev(xs: ~[uint]) -> bool {
            let rev = xs.clone().move_rev_iter().to_owned_vec()
                        .move_rev_iter().to_owned_vec();
            xs == rev
        }
        for _ in iter::range(0, 10) {
            debug!("{}", (revrev).result(g));
        }
    }

    #[test]
    fn reverse_single() {
        let g = &mut default_gen();
        fn rev_single(xs: ~[uint]) -> ~TestResult {
            if xs.len() != 1 {
                return TestResult::discard()
            }
            return TestResult::from_bool(
                xs.clone().move_rev_iter().to_owned_vec()
                ==
                xs.clone().move_rev_iter().to_owned_vec()
            )
        }
        for _ in iter::range(0, 10) {
            debug!("{}", (rev_single).result(g));
        }
    }

    #[test]
    fn reverse_app() {
        let g = &mut default_gen();
        fn revapp(xs: ~[uint], ys: ~[uint]) -> bool {
            let app = ::std::vec::append(xs.clone(), ys);
            let app_rev = app.move_rev_iter().to_owned_vec();

            let rxs = xs.clone().move_rev_iter().to_owned_vec();
            let rys = ys.clone().move_rev_iter().to_owned_vec();
            let rev_app = ::std::vec::append(rys, rxs);

            app_rev == rev_app
        }
        for _ in iter::range(0, 10) {
            debug!("{}", (revapp).result(g));
        }
    }
}
<|endoftext|>


<commit_before>extern crate fiz_math;

pub use fiz_math as math;

mod test{
  #[allow(unused_imports)]
  use super::math::Float;

  #[test]
  fn crate_names() {
    assert!(1.0.equal(1.0));
  }
}
<commit_msg>cargo fmt -- --write-mode=overwrite<commit_after>extern crate fiz_math;

pub use fiz_math as math;

mod test {
    #[allow(unused_imports)]
    use super::math::Float;

    #[test]
    fn crate_names() {
        assert!(1.0.equal(1.0));
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

static S: [u8, ..256] = [
    0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13,
    0x62, 0xA7, 0x05, 0xF3, 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, 0x82, 0xCA,
    0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12,
    0xBE, 0x4E, 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, 0xBB, 0x2F, 0xEE, 0x7A,
    0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21,
    0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03,
    0xFF, 0x19, 0x30, 0xB3, 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, 0xAA, 0xC6,
    0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1,
    0x45, 0x9D, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, 0xE6, 0x2D, 0xA8, 0x02,
    0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F,
    0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C, 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26,
    0x2C, 0x53, 0x0D, 0x6E, 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, 0x4D, 0x52,
    0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A,
    0x78, 0x88, 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE, 0x3B, 0x00, 0x1D, 0x39,
    0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
    0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14
];

#[inline]
fn md2_memcpy(dst: &mut [u8], src: &[u8]) {
    assert!(dst.len() == src.len());

    // Slow but safe memcpy() implementation.
    for (i, byte) in dst.iter_mut().enumerate() { *byte = src[i] }
}

#[inline]
fn md2_pad(msg: &[u8]) -> Vec<u8> {
    let mut msg = msg.to_vec();
    let pad = 16 - msg.len() % 16;
    msg.grow_fn(pad, |_| pad as u8);
    msg
}

#[inline]
fn md2_checksum(msg: &[u8]) -> [u8, ..16] {
    let mut checksum = [0u8, ..16];
    let mut last = 0u8;

    for chunk in msg.chunks(16) {
        for (i, byte) in checksum.iter_mut().enumerate() {
            *byte ^= S[(chunk[i] ^ last) as uint];
            last = *byte;
        }
    }

    checksum
}

#[inline]
fn md2_compress(state: &[u8], msg: &[u8]) -> [u8, ..16] {
    // Two 128 bit blocks in, one 128 bit block out.
    assert!(state.len() == 16 && msg.len() == 16);

    let mut x = [0u8, ..48];
    let mut result = [0u8, ..16];

    // Copy over the previous state.
    md2_memcpy(x.slice_mut(0, 16), state);

    // Copy over the message block.
    md2_memcpy(x.slice_mut(16, 32), msg);

    // XOR the previous state and the message block.
    for (i, byte) in msg.iter().enumerate() {
        x[32 + i] = byte ^ x[i];
    }

    // Encrypt block (18 rounds).
    let mut t = 0u8;
    for i in range(0, 18) {
        for byte in x.iter_mut() {
            *byte ^= S[t as uint];
            t = *byte;
        }
        t += i;
    }

    // Copy the new state.
    md2_memcpy(&mut result, x.slice(0, 16));
    result
}

pub fn md2(msg: &[u8]) -> [u8, ..16] {
    // Pad the message to be a multiple of 16 bytes long.
    let msg = md2_pad(msg);
    assert!(msg.len() % 16 == 0);

    // Compress all message blocks.
    let state = msg.chunks(16).fold([0u8, ..16], |s, m| md2_compress(s, m));

    // Compute the checksum.
    let checksum = md2_checksum(msg.as_slice());

    // Compress checksum and return.
    md2_compress(state, checksum)
}

#[cfg(test)]
mod test {
    use md2;

    fn hex(buf: &[u8]) -> String {
        buf.iter().fold(String::new(), |a, &b| format!("{}{:02x}", a, b))
    }

    fn cmp(d: &str, s: &str) {
        assert_eq!(d.to_string(), hex(md2(s.as_bytes())));
    }

    #[test]
    fn test_md2() {
        cmp("8350e5a3e24c153df2275c9f80692773", "");
        cmp("32ec01ec4a6dac72c0ab96fb34c0b5d1", "a");
        cmp("da853b0d3f88d99b30283a69e6ded6bb", "abc");
        cmp("ab4f496bfb2a530b219ff33031fe06b0", "message digest");
        cmp("4e8ddff3650292ab5a4108c3aa47940b", "abcdefghijklmnopqrstuvwxyz");
        cmp("da33def2a42df13975352846c30338cd", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
        cmp("d5976f79d83d3a0dc9806c3c66f3efd8", "12345678901234567890123456789012345678901234567890123456789012345678901234567890");
    }
}
<commit_msg>rust update<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

static S: [u8, ..256] = [
    0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13,
    0x62, 0xA7, 0x05, 0xF3, 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, 0x82, 0xCA,
    0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12,
    0xBE, 0x4E, 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, 0xBB, 0x2F, 0xEE, 0x7A,
    0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21,
    0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03,
    0xFF, 0x19, 0x30, 0xB3, 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, 0xAA, 0xC6,
    0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1,
    0x45, 0x9D, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, 0xE6, 0x2D, 0xA8, 0x02,
    0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F,
    0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C, 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26,
    0x2C, 0x53, 0x0D, 0x6E, 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, 0x4D, 0x52,
    0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A,
    0x78, 0x88, 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE, 0x3B, 0x00, 0x1D, 0x39,
    0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
    0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14
];

#[inline]
fn md2_memcpy(dst: &mut [u8], src: &[u8]) {
    assert!(dst.len() == src.len());

    // Slow but safe memcpy() implementation.
    for (i, byte) in dst.iter_mut().enumerate() { *byte = src[i] }
}

#[inline]
fn md2_pad(msg: &[u8]) -> Vec<u8> {
    let mut msg = msg.to_vec();
    let pad = 16 - msg.len() % 16;
    msg.grow_fn(pad, |_| pad as u8);
    msg
}

#[inline]
fn md2_checksum(msg: &[u8]) -> [u8, ..16] {
    let mut checksum = [0u8, ..16];
    let mut last = 0u8;

    for chunk in msg.chunks(16) {
        for (i, byte) in checksum.iter_mut().enumerate() {
            *byte ^= S[(chunk[i] ^ last) as uint];
            last = *byte;
        }
    }

    checksum
}

#[inline]
fn md2_compress(state: &[u8], msg: &[u8]) -> [u8, ..16] {
    // Two 128 bit blocks in, one 128 bit block out.
    assert!(state.len() == 16 && msg.len() == 16);

    let mut x = [0u8, ..48];
    let mut result = [0u8, ..16];

    // Copy over the previous state.
    md2_memcpy(x.slice_mut(0, 16), state);

    // Copy over the message block.
    md2_memcpy(x.slice_mut(16, 32), msg);

    // XOR the previous state and the message block.
    for (i, byte) in msg.iter().enumerate() {
        x[32 + i] = *byte ^ x[i];
    }

    // Encrypt block (18 rounds).
    let mut t = 0u8;
    for i in range(0, 18) {
        for byte in x.iter_mut() {
            *byte ^= S[t as uint];
            t = *byte;
        }
        t += i;
    }

    // Copy the new state.
    md2_memcpy(&mut result, x.slice(0, 16));
    result
}

pub fn md2(msg: &[u8]) -> [u8, ..16] {
    // Pad the message to be a multiple of 16 bytes long.
    let msg = md2_pad(msg);
    assert!(msg.len() % 16 == 0);

    // Compress all message blocks.
    let state = msg.chunks(16).fold([0u8, ..16], |s, m| md2_compress(&s, m));

    // Compute the checksum.
    let checksum = md2_checksum(msg.as_slice());

    // Compress checksum and return.
    md2_compress(&state, &checksum)
}

#[cfg(test)]
mod test {
    use md2;

    fn hex(buf: &[u8]) -> String {
        buf.iter().fold(String::new(), |a, &b| format!("{}{:02x}", a, b))
    }

    fn cmp(d: &str, s: &str) {
        assert_eq!(d.to_string(), hex(&md2(s.as_bytes())));
    }

    #[test]
    fn test_md2() {
        cmp("8350e5a3e24c153df2275c9f80692773", "");
        cmp("32ec01ec4a6dac72c0ab96fb34c0b5d1", "a");
        cmp("da853b0d3f88d99b30283a69e6ded6bb", "abc");
        cmp("ab4f496bfb2a530b219ff33031fe06b0", "message digest");
        cmp("4e8ddff3650292ab5a4108c3aa47940b", "abcdefghijklmnopqrstuvwxyz");
        cmp("da33def2a42df13975352846c30338cd", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
        cmp("d5976f79d83d3a0dc9806c3c66f3efd8", "12345678901234567890123456789012345678901234567890123456789012345678901234567890");
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]
#![feature(core_intrinsics)]
extern crate mmap;
extern crate core;

use std::fs::OpenOptions;
use std::os::unix::fs::OpenOptionsExt;
use mmap::{MemoryMap, MapOption};
use std::os::unix::prelude::AsRawFd;
use self::core::intrinsics::{volatile_load, volatile_store};

const BCM2708_PERI_BASE: usize = 0x3F000000;
const GPIO_BASE: usize = BCM2708_PERI_BASE + 0x200000;
const O_SYNC: u32 = 1052672;
const MAP_SHARED: i32 = 0x0001;
const BLOCK_SIZE: usize = 4 * 1024;

pub struct Cylus {
    addr_p: *const usize,
    mem_fd: ::std::fs::File,
    map: ::mmap::MemoryMap,
    addr: *mut usize,
    pin: u32
}

impl Cylus {
    pub fn new(x: u32) -> Cylus {
        let mem_file = OpenOptions::new()
            .read(true)
            .write(true)
            .mode(O_SYNC)
            .open("/dev/mem")
            .expect("unable to open /dev/mem, Are you root?");

        let map_opts = &[
            MapOption::MapNonStandardFlags(MAP_SHARED),
            MapOption::MapReadable,
            MapOption::MapWritable,
            MapOption::MapOffset(GPIO_BASE),
            MapOption::MapFd(mem_file.as_raw_fd())
        ];

        let mmap = match MemoryMap::new(BLOCK_SIZE, map_opts) {
            Ok(mmap) => mmap,
            Err(e) => panic!("ERR: {}", e)
        };

        let result = Cylus {
            addr_p: &GPIO_BASE,
            mem_fd: mem_file,
            addr: mmap.data() as *mut usize,  //switch order to avoid error of moved value `mmap`
            map: mmap,
            pin: x
        };
        //setting mode for GPIO
        unsafe {
            let addr = result.addr.offset((x/10) as isize);
            let mut a = volatile_load(addr);
            a &= !(7 << (((x) % 10) * 3));
            a |= 1 << (((x) % 10) * 3);
            volatile_store(addr, a);
        }
        result
    }
    pub unsafe fn set_alt(&self, y: isize, a: usize) {
        let addr = self.addr.offset(y/10);
        let mut k = volatile_load(addr);
        k |= match a {
            a if a <= 3 => a + 4,
            4 => 3,
            _ => 2,
        } << ((y % 10) * 3);
        volatile_store(addr, k)
    }

    pub unsafe fn high(&self) {
        let val = 1usize << self.pin;
        volatile_store(self.addr.offset(7), val);
    }
    pub unsafe fn low(&self) {
        let val = 1usize << self.pin;
        volatile_store(self.addr.offset(10), val);
    }
    pub unsafe fn read(&self) -> usize {
        let addr = self.addr.offset(13);
        let mut k = volatile_load(addr);
        k &= 1 << self.pin as isize;
        volatile_store(addr, k);
        return k;
    }
}

impl Drop for Cylus {
    fn drop(&mut self) {
        println!("Unmapped Peripheral {:?}", self.map.data())
    }
}
<commit_msg>remove unsafe tag from all functions that are not variant<commit_after>#![allow(dead_code)]
#![feature(core_intrinsics)]
extern crate mmap;
extern crate core;

use std::fs::OpenOptions;
use std::os::unix::fs::OpenOptionsExt;
use mmap::{MemoryMap, MapOption};
use std::os::unix::prelude::AsRawFd;
use self::core::intrinsics::{volatile_load, volatile_store};

const BCM2708_PERI_BASE: usize = 0x3F000000;
const GPIO_BASE: usize = BCM2708_PERI_BASE + 0x200000;
const O_SYNC: u32 = 1052672;
const MAP_SHARED: i32 = 0x0001;
const BLOCK_SIZE: usize = 4 * 1024;

pub struct Cylus {
    addr_p: *const usize,
    mem_fd: ::std::fs::File,
    map: ::mmap::MemoryMap,
    addr: *mut usize,
    pin: u32
}

impl Cylus {
    pub fn new(x: u32) -> Cylus {
        let mem_file = OpenOptions::new()
            .read(true)
            .write(true)
            .mode(O_SYNC)
            .open("/dev/mem")
            .expect("unable to open /dev/mem, Are you root?");

        let map_opts = &[
            MapOption::MapNonStandardFlags(MAP_SHARED),
            MapOption::MapReadable,
            MapOption::MapWritable,
            MapOption::MapOffset(GPIO_BASE),
            MapOption::MapFd(mem_file.as_raw_fd())
        ];

        let mmap = match MemoryMap::new(BLOCK_SIZE, map_opts) {
            Ok(mmap) => mmap,
            Err(e) => panic!("ERR: {}", e)
        };

        let result = Cylus {
            addr_p: &GPIO_BASE,
            mem_fd: mem_file,
            addr: mmap.data() as *mut usize,  //switch order to avoid error of moved value `mmap`
            map: mmap,
            pin: x
        };
        //setting mode for GPIO
        unsafe {
            let addr = result.addr.offset((x/10) as isize);
            let mut a = volatile_load(addr);
            a &= !(7 << (((x) % 10) * 3));
            a |= 1 << (((x) % 10) * 3);
            volatile_store(addr, a);
        }
        result
    }
    pub fn set_alt(&self, a: usize) {
        let y = self.pin as isize;
        unsafe {
            let addr = self.addr.offset(y/10);
            let mut k = volatile_load(addr);
            k |= match a {
                a if a <= 3 => a + 4,
                4 => 3,
                _ => 2,
            } << ((y % 10) * 3);
            volatile_store(addr, k);
       }
    }

    pub fn high(&self) {
        let val = 1usize << self.pin;
        unsafe { volatile_store(self.addr.offset(7), val); }
    }
    pub fn low(&self) {
        let val = 1usize << self.pin;
        unsafe { volatile_store(self.addr.offset(10), val); }
    }
    pub fn read(&self) -> usize {
        unsafe {
            let addr = self.addr.offset(13);
            let mut k = volatile_load(addr);
            k &= 1 << self.pin as isize;
            volatile_store(addr, k);
            return k
        }
    }
}

impl Drop for Cylus {
    fn drop(&mut self) {
        println!("Unmapped Peripheral {:?}", self.map.data())
    }
}
<|endoftext|>


<commit_before>extern crate rand;
use std::str;
use std::fmt;
use rand::Rng;

#[derive(Debug, Eq, PartialEq, PartialOrd)]
pub struct Card {
    suit:  String,
    value: String,
}

impl Card {
    pub fn new(suit: String, value: String) -> Card {
        Card { suit: suit, value: value.to_string() }
    }

    pub fn new_from_str(suit: &str, value: &str) -> Card {
        Card::new(suit.to_string(), value.to_string())
    }
}

impl Ord for Card {
    fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
        self.value.cmp(&other.value)
    }
}

impl fmt::Display for Card {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Suit: {}, Value: {}", self.suit, self.value)
    }
}

pub fn make_standard_deck() -> Vec<Card> {
    let mut result = Vec::new();
    let suits  = &["♣", "♦", "♥", "♠"];
    let values = &["2", "3", "4", "5", "6", "7", "8", "9", "10",
                   "Jack", "Queen", "King", "Ace"];

    for suit in suits {
        for value in values {
            result.push(Card::new_from_str(*suit, value));
        }
    }
    return result;
}

pub fn make_fifth_dimension_deck() -> Vec<Card> {
    let mut result = Vec::new();
    let suits  = &["♣", "♦", "♥", "♠", "★"];
    let values = &["1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
                   "Jack", "Princess", "Queen", "King", "Joker"];

    for suit in suits {
        for value in values {
            result.push(Card::new_from_str(*suit, value));
        }
    }
    return result;
}

pub fn shuffle(deck: &mut Vec<Card>) {
    rand::thread_rng().shuffle(deck);
}
<commit_msg>introduce Deck wrapper<commit_after>extern crate rand;
use std::str;
use std::fmt;
use rand::Rng;

#[derive(Debug, Eq, PartialEq, PartialOrd)]
pub struct Card {
    suit:  String,
    value: String,
}

#[derive(Debug, Eq, PartialEq, PartialOrd)]
pub struct Deck {
    cards: Vec<Card>
}

impl Card {
    pub fn new(suit: String, value: String) -> Card {
        Card { suit: suit, value: value.to_string() }
    }

    pub fn new_from_str(suit: &str, value: &str) -> Card {
        Card::new(suit.to_string(), value.to_string())
    }
}

impl Ord for Card {
    fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
        self.value.cmp(&other.value)
    }
}

impl fmt::Display for Card {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Suit: {}, Value: {}", self.suit, self.value)
    }
}

impl Deck {
    pub fn new_from_vec(input: Vec<Card>) -> Deck {
        Deck { cards: input }
    }

    pub fn make_standard() -> Deck {
        let mut result = Vec::new();
        let suits  = &["♣", "♦", "♥", "♠"];
        let values = &["2", "3", "4", "5", "6", "7", "8", "9", "10",
                       "Jack", "Queen", "King", "Ace"];

        for suit in suits {
            for value in values {
                result.push(Card::new_from_str(*suit, value));
            }
        }
        return Deck::new_from_vec(result);
    }

    pub fn make_fifth_dimension() -> Deck {
        let mut result = Vec::new();
        let suits  = &["♣", "♦", "♥", "♠", "★"];
        let values = &["1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
                       "Jack", "Princess", "Queen", "King", "Joker"];

        for suit in suits {
            for value in values {
                result.push(Card::new_from_str(*suit, value));
            }
        }
        return Deck::new_from_vec(result);
    }

    pub fn shuffle(&mut self) {
        rand::thread_rng().shuffle(&mut self.cards);
    }
}

impl Ord for Deck {
    fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
        self.cards.cmp(&other.cards)
    }
}
<|endoftext|>


<commit_before>
pub fn puzzle(input: &str) -> u32 {
    let initial_world_state = WorldState {
        steps: 0,
        building: BuildingState {
            elevator_floor: 0,
            floors: [
                vec![
                    Component::Microchip(Element::Hydrogen),
                    Component::Microchip(Element::Lithium),
                ],
                vec![
                    Component::Generator(Element::Hydrogen),
                ],
                vec![
                    Component::Generator(Element::Lithium),
                ],
                vec![],
            ],
        }
    };
    let mut queue = vec![initial_world_state];
    while !queue.is_empty() {
        let world = queue.remove(0);
        if world.in_end_state() {
            return world.steps;
        }

        let mut valid_next_moves = world.next_moves();
        queue.append(&mut valid_next_moves);
    }

    panic!("Exhausted all possible moves without finding end condition!");
}

pub struct WorldState {
    steps: u32,
    building: BuildingState,
}

impl WorldState {
    pub fn in_end_state(&self) -> bool {
        self.building.in_end_state()
    }

    pub fn next_moves(&self) -> Vec<WorldState> {
        self.building.next_moves().into_iter().map(|b| {
            WorldState {
                steps: self.steps + 1,
                building: b,
            }
        }).collect()
    }
}

pub enum Component {
    Microchip(Element),
    Generator(Element),
}

pub enum Element {
    Hydrogen,
    Lithium,
}

pub struct BuildingState {
    elevator_floor: usize,
    floors: [Vec<Component>; 4],
}

impl BuildingState {
    pub fn in_end_state(&self) -> bool {
        self.floors[0].is_empty() &&
            self.floors[1].is_empty() &&
            self.floors[2].is_empty()
    }

    pub fn next_moves(&self) -> Vec<BuildingState> {
        // TODO: actually determine valid next moves
        vec![]
    }
}

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

    #[test]
    fn not_in_end_state() {
        let world_state = WorldState {
            steps: 0,
            building: BuildingState {
                elevator_floor: 0,
                floors: [
                    vec![
                        Component::Microchip(Element::Hydrogen),
                        Component::Microchip(Element::Lithium),
                    ],
                    vec![
                        Component::Generator(Element::Hydrogen),
                    ],
                    vec![
                        Component::Generator(Element::Lithium),
                    ],
                    vec![],
                ],
            }
        };
        assert!( ! world_state.in_end_state() );
    }

    #[test]
    fn in_end_state() {
        let world_state = WorldState {
            steps: 0,
            building: BuildingState {
                elevator_floor: 0,
                floors: [
                    vec![],
                    vec![],
                    vec![],
                    vec![
                        Component::Generator(Element::Hydrogen),
                        Component::Microchip(Element::Hydrogen),
                        Component::Microchip(Element::Lithium),
                        Component::Generator(Element::Lithium),
                    ],
                ],
            }
        };

        assert!(world_state.in_end_state());
    }
}
<commit_msg>Make a method that can tell if a component is fried<commit_after>
pub fn puzzle(input: &str) -> u32 {
    let initial_world_state = WorldState {
        steps: 0,
        building: BuildingState {
            elevator_floor: 0,
            floors: [
                vec![
                    Component::Microchip(Element::Hydrogen),
                    Component::Microchip(Element::Lithium),
                ],
                vec![
                    Component::Generator(Element::Hydrogen),
                ],
                vec![
                    Component::Generator(Element::Lithium),
                ],
                vec![],
            ],
        }
    };
    let mut queue = vec![initial_world_state];
    while !queue.is_empty() {
        let world = queue.remove(0);
        if world.in_end_state() {
            return world.steps;
        }

        let mut valid_next_moves = world.next_moves();
        queue.append(&mut valid_next_moves);
    }

    panic!("Exhausted all possible moves without finding end condition!");
}

pub struct WorldState {
    steps: u32,
    building: BuildingState,
}

impl WorldState {
    pub fn in_end_state(&self) -> bool {
        self.building.in_end_state()
    }

    pub fn next_moves(&self) -> Vec<WorldState> {
        self.building.next_moves().into_iter().map(|b| {
            WorldState {
                steps: self.steps + 1,
                building: b,
            }
        }).collect()
    }
}

pub enum Component {
    Microchip(Element),
    Generator(Element),
}

impl Component {
    fn is_fried(&self, others: &Vec<Component>) -> bool {
        match *self {
            // Generators can't be fried, just microchips
            Component::Generator(_) => return false,
            Component::Microchip(my_element) => {
                // There's some generator that is not my element
                (*others).iter().find(|&c| {
                    match *c {
                        Component::Generator(e) if e != my_element => true,
                        _ => false,
                    }
                }).is_some() &&
                // There is no generator that is my element
                (*others).iter().find(|&c| {
                    match *c {
                        Component::Generator(e) if e == my_element => true,
                        _ => false,
                    }
                }).is_none()
            }
        }
    }
}

#[derive(PartialEq, Copy, Clone)]
pub enum Element {
    Hydrogen,
    Lithium,
}

pub struct BuildingState {
    elevator_floor: usize,
    floors: [Vec<Component>; 4],
}

impl BuildingState {
    pub fn in_end_state(&self) -> bool {
        self.floors[0].is_empty() &&
            self.floors[1].is_empty() &&
            self.floors[2].is_empty()
    }

    pub fn next_moves(&self) -> Vec<BuildingState> {
        // TODO: actually determine valid next moves
        vec![]
    }

    pub fn has_fried_chips(&self) -> bool {
        for floor in self.floors.iter() {
            for component in floor {
                // This is doing an extra comparison to itself :shrug:
                if component.is_fried(&floor) {
                    return true
                }
            }
        }
        false
    }
}

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

    #[test]
    fn not_in_end_state() {
        let world_state = WorldState {
            steps: 0,
            building: BuildingState {
                elevator_floor: 0,
                floors: [
                    vec![
                        Component::Microchip(Element::Hydrogen),
                        Component::Microchip(Element::Lithium),
                    ],
                    vec![
                        Component::Generator(Element::Hydrogen),
                    ],
                    vec![
                        Component::Generator(Element::Lithium),
                    ],
                    vec![],
                ],
            }
        };
        assert!( ! world_state.in_end_state() );
    }

    #[test]
    fn in_end_state() {
        let world_state = WorldState {
            steps: 0,
            building: BuildingState {
                elevator_floor: 0,
                floors: [
                    vec![],
                    vec![],
                    vec![],
                    vec![
                        Component::Generator(Element::Hydrogen),
                        Component::Microchip(Element::Hydrogen),
                        Component::Microchip(Element::Lithium),
                        Component::Generator(Element::Lithium),
                    ],
                ],
            }
        };

        assert!(world_state.in_end_state());
    }

    #[test]
    fn two_microchips_not_fried() {
        assert!(
            ! Component::Microchip(Element::Hydrogen).is_fried(
                &vec![Component::Microchip(Element::Lithium)]
            )
        )
    }
}
<|endoftext|>


<commit_before>extern crate rustc_serialize;

use std::collections::BTreeMap;

use rustc_serialize::json::{Json, ToJson};

/// An Optional value can contain Optional::Some<T> or Optional::Absent.
/// It is similar to an Option, but Optional::Absent means it will be
/// omitted when serialized.
#[derive(Debug, Copy, Clone)]
pub enum Optional<T> {
    Value(T),
    Absent,
}

impl<T> Optional<T> {

    /// Applies a function to the contained value or returns a default.  see
    /// [`std::option::Option<T>::map_or`](http://doc.rust-lang.org/std/option/enum.Option.html#method.map_or)
    pub fn map_or<U, F: FnOnce(T) -> U>(self, def: U, f: F) -> U {
        match self {
            Optional::Value(v) => f(v),
            Optional::Absent => def,
        }
    }

    pub fn as_mut<'r>(&'r mut self) -> Optional<&'r mut T> {
        match *self {
            Optional::Value(ref mut x) => Optional::Value(x),
            Optional::Absent => Optional::Absent
        }
    }

    pub fn as_ref<'r>(&'r self) -> Optional<&'r T> {
        match *self {
            Optional::Value(ref x) => Optional::Value(x),
            Optional::Absent => Optional::Absent
        }
    }
}

pub struct Location {
    pub address: Optional<String>,
    pub lat: f64,
    pub lon: f64,
}

pub struct Spacefed {
    pub spacenet: bool,
    pub spacesaml: bool,
    pub spacephone: bool,
}

pub struct Icon {
    pub open: String,
    pub close: String,
}

pub struct State {
    pub open: Option<bool>,
    pub lastchange: Optional<u64>,
    pub trigger_person: Optional<String>,
    pub message: Optional<String>,
    pub icon: Optional<Icon>,
}

pub struct Event {
    pub name: String,
    pub _type: String,
    pub timestamp: u64,
    pub extra: Optional<String>,
}

pub struct Contact {
    pub irc: Optional<String>,
    pub twitter: Optional<String>,
    pub foursquare: Optional<String>,
    pub email: Optional<String>,
}

pub struct Feed {
    pub _type: Optional<String>,
    pub url: String,
}

pub struct Feeds {
    pub blog: Optional<Feed>,
    pub wiki: Optional<Feed>,
    pub calendar: Optional<Feed>,
    pub flickr: Optional<Feed>,
}

pub struct Sensors {
    pub people_now_present: Optional<Vec<PeopleNowPresentSensor>>,
    pub temperature: Optional<Vec<TemperatureSensor>>,
}

pub struct PeopleNowPresentSensor {
    pub value: u32,
    pub location: Optional<String>,
    pub name: Optional<String>,
    pub names: Optional<Vec<String>>,
    pub description: Optional<String>,
}

pub struct TemperatureSensor {
    pub value: f32,
    pub unit: String,
    pub location: String,
    pub name: Optional<String>,
    pub description: Optional<String>,
}

pub struct Cache {
    pub schedule: String,
}

pub struct RadioShow {
    pub name: String,
    pub url: String,
    pub _type: String,
    pub start: String,
    pub end: String,
}

pub struct Status {

    // Hackerspace properties
    pub api: String,
    pub space: String,
    pub logo: String,
    pub url: String,
    pub location: Location,
    pub contact: Contact,

    // Hackerspace features / projects
    pub spacefed: Optional<Spacefed>,
    pub projects: Optional<Vec<String>>,
    pub cam: Optional<Vec<String>>,
    pub feeds: Optional<Feeds>,
    pub events: Optional<Vec<Event>>,
    pub radio_show: Optional<Vec<RadioShow>>,

    // SpaceAPI internal usage
    pub cache: Optional<Cache>,
    pub issue_report_channels: Vec<String>,

    // Mutable data
    pub state: State,
    pub sensors: Optional<Sensors>,

}

impl Status {

    /// Create a new Status object with only the minimum amount of fields
    pub fn new(space: String, logo: String, url: String, location: Location, contact: Contact, issue_report_channels: Vec<String>) -> Status {
        Status {
            api: "0.13".to_string(),
            space: space,
            logo: logo,
            url: url,
            location: location,
            contact: contact,

            spacefed: Optional::Absent,
            projects: Optional::Absent,
            cam: Optional::Absent,
            feeds: Optional::Absent,
            events: Optional::Absent,
            radio_show: Optional::Absent,

            cache: Optional::Absent,
            issue_report_channels: issue_report_channels,

            state: State {
                open: None,
                lastchange: Optional::Absent,
                trigger_person: Optional::Absent,
                message: Optional::Absent,
                icon: Optional::Absent,
            },
            sensors: Optional::Absent,
        }
    }

}

impl ToJson for Status {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();

        d.insert("api".to_string(), self.api.to_json());
        d.insert("space".to_string(), self.space.to_json());
        d.insert("logo".to_string(), self.logo.to_json());
        d.insert("url".to_string(), self.url.to_json());
        d.insert("location".to_string(), self.location.to_json());
        d.insert("contact".to_string(), self.contact.to_json());

        self.spacefed.as_ref().map_or((), |v| { d.insert("spacefed".to_string(), v.to_json()); } );
        self.projects.as_ref().map_or((), |v| { d.insert("projects".to_string(), v.to_json()); });
        self.cam.as_ref().map_or((), |v| { d.insert("cam".to_string(), v.to_json()); });
        self.feeds.as_ref().map_or((), |v| { d.insert("feeds".to_string(), v.to_json()); });
        self.events.as_ref().map_or((), |v| { d.insert("events".to_string(), v.to_json()); });
        self.radio_show.as_ref().map_or((), |v| { d.insert("radio_show".to_string(), v.to_json()); });

        self.cache.as_ref().map_or((), |v| { d.insert("cache".to_string(), v.to_json()); });
        d.insert("issue_report_channels".to_string(), self.issue_report_channels.to_json());

        d.insert("state".to_string(), self.state.to_json());
        self.sensors.as_ref().map_or((), |v| { d.insert("sensors".to_string(), v.to_json()); });

        Json::Object(d)
    }
}

impl ToJson for Location {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("lat".to_string(), self.lat.to_json());
        d.insert("lon".to_string(), self.lon.to_json());
        match self.address {
            Optional::Value(ref address) => {
                d.insert("address".to_string(), address.to_json());
            },
            Optional::Absent => (),
        };
        Json::Object(d)
    }
}

impl ToJson for Spacefed {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("spacenet".to_string(), self.spacenet.to_json());
        d.insert("spacesaml".to_string(), self.spacesaml.to_json());
        d.insert("spacephone".to_string(), self.spacephone.to_json());
        Json::Object(d)
    }
}

impl ToJson for Icon {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("open".to_string(), self.open.to_json());
        d.insert("close".to_string(), self.close.to_json());
        Json::Object(d)
    }
}

impl ToJson for State {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("open".to_string(), self.open.to_json());
        self.lastchange.as_ref().map_or((), |v| { d.insert("lastchange".to_string(), v.to_json()); });
        self.trigger_person.as_ref().map_or((), |v| { d.insert("trigger_person".to_string(), v.to_json()); });
        self.message.as_ref().map_or((), |v| { d.insert("message".to_string(), v.to_json()); });
        self.icon.as_ref().map_or((), |v| { d.insert("icon".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Event {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("name".to_string(), self.name.to_json());
        d.insert("type".to_string(), self._type.to_json());
        d.insert("timestamp".to_string(), self.timestamp.to_json());
        self.extra.as_ref().map_or((), |v| { d.insert("extra".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Contact {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        self.irc.as_ref().map_or((), |v| { d.insert("irc".to_string(), v.to_json()); });
        self.twitter.as_ref().map_or((), |v| { d.insert("twitter".to_string(), v.to_json()); });
        self.foursquare.as_ref().map_or((), |v| { d.insert("foursquare".to_string(), v.to_json()); });
        self.email.as_ref().map_or((), |v| { d.insert("email".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Feed {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("url".to_string(), self.url.to_json());
        self._type.as_ref().map_or((), |v| { d.insert("type".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Feeds {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        self.blog.as_ref().map_or((), |v| { d.insert("blog".to_string(), v.to_json()); });
        self.wiki.as_ref().map_or((), |v| { d.insert("wiki".to_string(), v.to_json()); });
        self.calendar.as_ref().map_or((), |v| { d.insert("calendar".to_string(), v.to_json()); });
        self.flickr.as_ref().map_or((), |v| { d.insert("flickr".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Sensors {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        self.people_now_present.as_ref().map_or((), |v| { d.insert("people_now_present".to_string(), v.to_json()); });
        self.temperature.as_ref().map_or((), |v| { d.insert("temperature".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for PeopleNowPresentSensor {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("value".to_string(), self.value.to_json());
        self.location.as_ref().map_or((), |v| { d.insert("location".to_string(), v.to_json()); });
        self.name.as_ref().map_or((), |v| { d.insert("name".to_string(), v.to_json()); });
        self.names.as_ref().map_or((), |v| { d.insert("names".to_string(), v.to_json()); });
        self.description.as_ref().map_or((), |v| { d.insert("description".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for TemperatureSensor {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("value".to_string(), self.value.to_json());
        d.insert("unit".to_string(), self.unit.to_json());
        d.insert("location".to_string(), self.location.to_json());
        self.name.as_ref().map_or((), |v| { d.insert("name".to_string(), v.to_json()); });
        self.description.as_ref().map_or((), |v| { d.insert("description".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Cache {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("schedule".to_string(), self.schedule.to_json());
        Json::Object(d)
    }
}

impl ToJson for RadioShow {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("name".to_string(), self.name.to_json());
        d.insert("url".to_string(), self.url.to_json());
        d.insert("type".to_string(), self._type.to_json());
        d.insert("start".to_string(), self.start.to_json()); d.insert("end".to_string(), self.end.to_json());
        Json::Object(d)
    }
}
<commit_msg>Improved documentation<commit_after>//! Space API definitions and serialization.
//!
//! This crate contains all data-related definitions that are present in the Space API
//! (http://spaceapi.net/). It also handles serializing that data to JSON by implementing the
//! [`ToJson`](http://doc.rust-lang.org/rustc-serialize/rustc_serialize/json/trait.ToJson.html)
//! trait for all structs.
//!
//! # Examples
//!
//! You can create a new ``Status`` instance by using the ``new`` constructor method:
//!
//!     let status = Status::new(
//!         "coredump".to_string(),
//!         "https://www.coredump.ch/logo.png".to_string(),
//!         "https://www.coredump.ch/".to_string(),
//!         Location {
//!             address: Optional::Value("Spinnereistrasse 2, 8640 Rapperswil, Switzerland".to_string()),
//!             lat: 47.22936,
//!             lon: 8.82949,
//!         },
//!         Contact {
//!             irc: Optional::Value("irc://freenode.net/#coredump".to_string()),
//!             twitter: Optional::Value("@coredump_ch".to_string()),
//!             foursquare: Optional::Value("525c20e5498e875d8231b1e5".to_string()),
//!             email: Optional::Value("danilo@coredump.ch".to_string()),
//!         },
//!         vec![
//!             "email".to_string(),
//!             "twitter".to_string(),
//!         ],
//!     );
//!
//! To serialize this to `Json`, use the ``ToJson`` trait implementation:
//!
//!     let jsonstatus = status.to_json();
//!
//! You can then create a string from the JSON object:
//!
//!     let stringstatus = jsonstatus.to_string();

extern crate rustc_serialize;

use std::collections::BTreeMap;

use rustc_serialize::json::{Json, ToJson};

/// An ``Optional`` can contain ``Optional::Value<T>`` or ``Optional::Absent``.
/// It is similar to an ``Option``, but ``Optional::Absent`` means it will be
/// omitted when serialized, while ``None`` will be serialized to ``null``.
#[derive(Debug, Copy, Clone)]
pub enum Optional<T> {
    Value(T),
    Absent,
}

impl<T> Optional<T> {

    /// Applies a function to the contained value or returns a default.  see
    /// [`std::option::Option<T>::map_or`](http://doc.rust-lang.org/std/option/enum.Option.html#method.map_or)
    pub fn map_or<U, F: FnOnce(T) -> U>(self, def: U, f: F) -> U {
        match self {
            Optional::Value(v) => f(v),
            Optional::Absent => def,
        }
    }

    pub fn as_mut<'r>(&'r mut self) -> Optional<&'r mut T> {
        match *self {
            Optional::Value(ref mut x) => Optional::Value(x),
            Optional::Absent => Optional::Absent
        }
    }

    pub fn as_ref<'r>(&'r self) -> Optional<&'r T> {
        match *self {
            Optional::Value(ref x) => Optional::Value(x),
            Optional::Absent => Optional::Absent
        }
    }
}

pub struct Location {
    pub address: Optional<String>,
    pub lat: f64,
    pub lon: f64,
}

pub struct Spacefed {
    pub spacenet: bool,
    pub spacesaml: bool,
    pub spacephone: bool,
}

pub struct Icon {
    pub open: String,
    pub close: String,
}

pub struct State {
    pub open: Option<bool>,
    pub lastchange: Optional<u64>,
    pub trigger_person: Optional<String>,
    pub message: Optional<String>,
    pub icon: Optional<Icon>,
}

pub struct Event {
    pub name: String,
    pub _type: String,
    pub timestamp: u64,
    pub extra: Optional<String>,
}

pub struct Contact {
    pub irc: Optional<String>,
    pub twitter: Optional<String>,
    pub foursquare: Optional<String>,
    pub email: Optional<String>,
}

pub struct Feed {
    pub _type: Optional<String>,
    pub url: String,
}

pub struct Feeds {
    pub blog: Optional<Feed>,
    pub wiki: Optional<Feed>,
    pub calendar: Optional<Feed>,
    pub flickr: Optional<Feed>,
}

pub struct Sensors {
    pub people_now_present: Optional<Vec<PeopleNowPresentSensor>>,
    pub temperature: Optional<Vec<TemperatureSensor>>,
}

pub struct PeopleNowPresentSensor {
    pub value: u32,
    pub location: Optional<String>,
    pub name: Optional<String>,
    pub names: Optional<Vec<String>>,
    pub description: Optional<String>,
}

pub struct TemperatureSensor {
    pub value: f32,
    pub unit: String,
    pub location: String,
    pub name: Optional<String>,
    pub description: Optional<String>,
}

pub struct Cache {
    pub schedule: String,
}

pub struct RadioShow {
    pub name: String,
    pub url: String,
    pub _type: String,
    pub start: String,
    pub end: String,
}

/// The main Space API status object.
pub struct Status {

    // Hackerspace properties
    pub api: String,
    pub space: String,
    pub logo: String,
    pub url: String,
    pub location: Location,
    pub contact: Contact,

    // Hackerspace features / projects
    pub spacefed: Optional<Spacefed>,
    pub projects: Optional<Vec<String>>,
    pub cam: Optional<Vec<String>>,
    pub feeds: Optional<Feeds>,
    pub events: Optional<Vec<Event>>,
    pub radio_show: Optional<Vec<RadioShow>>,

    // SpaceAPI internal usage
    pub cache: Optional<Cache>,
    pub issue_report_channels: Vec<String>,

    // Mutable data
    pub state: State,
    pub sensors: Optional<Sensors>,

}

impl Status {

    /// Create a new Status object with only the minimum amount of fields.
    pub fn new(space: String, logo: String, url: String, location: Location, contact: Contact, issue_report_channels: Vec<String>) -> Status {
        Status {
            api: "0.13".to_string(),
            space: space,
            logo: logo,
            url: url,
            location: location,
            contact: contact,

            spacefed: Optional::Absent,
            projects: Optional::Absent,
            cam: Optional::Absent,
            feeds: Optional::Absent,
            events: Optional::Absent,
            radio_show: Optional::Absent,

            cache: Optional::Absent,
            issue_report_channels: issue_report_channels,

            state: State {
                open: None,
                lastchange: Optional::Absent,
                trigger_person: Optional::Absent,
                message: Optional::Absent,
                icon: Optional::Absent,
            },
            sensors: Optional::Absent,
        }
    }

}

impl ToJson for Status {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();

        d.insert("api".to_string(), self.api.to_json());
        d.insert("space".to_string(), self.space.to_json());
        d.insert("logo".to_string(), self.logo.to_json());
        d.insert("url".to_string(), self.url.to_json());
        d.insert("location".to_string(), self.location.to_json());
        d.insert("contact".to_string(), self.contact.to_json());

        self.spacefed.as_ref().map_or((), |v| { d.insert("spacefed".to_string(), v.to_json()); } );
        self.projects.as_ref().map_or((), |v| { d.insert("projects".to_string(), v.to_json()); });
        self.cam.as_ref().map_or((), |v| { d.insert("cam".to_string(), v.to_json()); });
        self.feeds.as_ref().map_or((), |v| { d.insert("feeds".to_string(), v.to_json()); });
        self.events.as_ref().map_or((), |v| { d.insert("events".to_string(), v.to_json()); });
        self.radio_show.as_ref().map_or((), |v| { d.insert("radio_show".to_string(), v.to_json()); });

        self.cache.as_ref().map_or((), |v| { d.insert("cache".to_string(), v.to_json()); });
        d.insert("issue_report_channels".to_string(), self.issue_report_channels.to_json());

        d.insert("state".to_string(), self.state.to_json());
        self.sensors.as_ref().map_or((), |v| { d.insert("sensors".to_string(), v.to_json()); });

        Json::Object(d)
    }
}

impl ToJson for Location {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("lat".to_string(), self.lat.to_json());
        d.insert("lon".to_string(), self.lon.to_json());
        match self.address {
            Optional::Value(ref address) => {
                d.insert("address".to_string(), address.to_json());
            },
            Optional::Absent => (),
        };
        Json::Object(d)
    }
}

impl ToJson for Spacefed {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("spacenet".to_string(), self.spacenet.to_json());
        d.insert("spacesaml".to_string(), self.spacesaml.to_json());
        d.insert("spacephone".to_string(), self.spacephone.to_json());
        Json::Object(d)
    }
}

impl ToJson for Icon {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("open".to_string(), self.open.to_json());
        d.insert("close".to_string(), self.close.to_json());
        Json::Object(d)
    }
}

impl ToJson for State {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("open".to_string(), self.open.to_json());
        self.lastchange.as_ref().map_or((), |v| { d.insert("lastchange".to_string(), v.to_json()); });
        self.trigger_person.as_ref().map_or((), |v| { d.insert("trigger_person".to_string(), v.to_json()); });
        self.message.as_ref().map_or((), |v| { d.insert("message".to_string(), v.to_json()); });
        self.icon.as_ref().map_or((), |v| { d.insert("icon".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Event {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("name".to_string(), self.name.to_json());
        d.insert("type".to_string(), self._type.to_json());
        d.insert("timestamp".to_string(), self.timestamp.to_json());
        self.extra.as_ref().map_or((), |v| { d.insert("extra".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Contact {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        self.irc.as_ref().map_or((), |v| { d.insert("irc".to_string(), v.to_json()); });
        self.twitter.as_ref().map_or((), |v| { d.insert("twitter".to_string(), v.to_json()); });
        self.foursquare.as_ref().map_or((), |v| { d.insert("foursquare".to_string(), v.to_json()); });
        self.email.as_ref().map_or((), |v| { d.insert("email".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Feed {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("url".to_string(), self.url.to_json());
        self._type.as_ref().map_or((), |v| { d.insert("type".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Feeds {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        self.blog.as_ref().map_or((), |v| { d.insert("blog".to_string(), v.to_json()); });
        self.wiki.as_ref().map_or((), |v| { d.insert("wiki".to_string(), v.to_json()); });
        self.calendar.as_ref().map_or((), |v| { d.insert("calendar".to_string(), v.to_json()); });
        self.flickr.as_ref().map_or((), |v| { d.insert("flickr".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Sensors {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        self.people_now_present.as_ref().map_or((), |v| { d.insert("people_now_present".to_string(), v.to_json()); });
        self.temperature.as_ref().map_or((), |v| { d.insert("temperature".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for PeopleNowPresentSensor {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("value".to_string(), self.value.to_json());
        self.location.as_ref().map_or((), |v| { d.insert("location".to_string(), v.to_json()); });
        self.name.as_ref().map_or((), |v| { d.insert("name".to_string(), v.to_json()); });
        self.names.as_ref().map_or((), |v| { d.insert("names".to_string(), v.to_json()); });
        self.description.as_ref().map_or((), |v| { d.insert("description".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for TemperatureSensor {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("value".to_string(), self.value.to_json());
        d.insert("unit".to_string(), self.unit.to_json());
        d.insert("location".to_string(), self.location.to_json());
        self.name.as_ref().map_or((), |v| { d.insert("name".to_string(), v.to_json()); });
        self.description.as_ref().map_or((), |v| { d.insert("description".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Cache {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("schedule".to_string(), self.schedule.to_json());
        Json::Object(d)
    }
}

impl ToJson for RadioShow {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("name".to_string(), self.name.to_json());
        d.insert("url".to_string(), self.url.to_json());
        d.insert("type".to_string(), self._type.to_json());
        d.insert("start".to_string(), self.start.to_json()); d.insert("end".to_string(), self.end.to_json());
        Json::Object(d)
    }
}
<|endoftext|>