<commit_before>#![feature(rustc_private, decl_macro, type_alias_impl_trait, associated_type_bounds, never_type)]
#![allow(intra_doc_link_resolution_failure)]
#![warn(rust_2018_idioms)]
#![warn(unused_lifetimes)]

extern crate flate2;
#[cfg(feature = "jit")]
extern crate libc;
extern crate rustc_middle;
extern crate rustc_codegen_ssa;
extern crate rustc_data_structures;
extern crate rustc_errors;
extern crate rustc_fs_util;
extern crate rustc_hir;
extern crate rustc_incremental;
extern crate rustc_index;
extern crate rustc_mir;
extern crate rustc_session;
extern crate rustc_span;
extern crate rustc_symbol_mangling;
extern crate rustc_target;
extern crate rustc_ast;

// This prevents duplicating functions and statics that are already part of the host rustc process.
#[allow(unused_extern_crates)]
extern crate rustc_driver;

use std::any::Any;

use rustc_errors::ErrorReported;
use rustc_middle::dep_graph::{DepGraph, WorkProduct, WorkProductId};
use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoader};
use rustc_session::Session;
use rustc_session::config::OutputFilenames;
use rustc_middle::ty::query::Providers;
use rustc_codegen_ssa::CodegenResults;
use rustc_codegen_ssa::traits::CodegenBackend;

use cranelift_codegen::settings::{self, Configurable};

use crate::constant::ConstantCx;
use crate::prelude::*;

mod abi;
mod allocator;
mod analyze;
mod archive;
mod atomic_shim;
mod base;
mod backend;
mod cast;
mod codegen_i128;
mod common;
mod constant;
mod debuginfo;
mod discriminant;
mod driver;
mod inline_asm;
mod intrinsics;
mod linkage;
mod main_shim;
mod metadata;
mod num;
mod optimize;
mod pointer;
mod pretty_clif;
mod target_features_whitelist;
mod toolchain;
mod trap;
mod unsize;
mod value_and_place;
mod vtable;

mod prelude {
    pub(crate) use std::convert::{TryFrom, TryInto};

    pub(crate) use rustc_ast::ast::{FloatTy, IntTy, UintTy};
    pub(crate) use rustc_span::Span;

    pub(crate) use rustc_middle::bug;
    pub(crate) use rustc_hir::def_id::{DefId, LOCAL_CRATE};
    pub(crate) use rustc_middle::mir::{self, *};
    pub(crate) use rustc_middle::ty::layout::{self, TyAndLayout};
    pub(crate) use rustc_target::abi::{Abi, LayoutOf, Scalar, Size, VariantIdx};
    pub(crate) use rustc_middle::ty::{
        self, FnSig, Instance, InstanceDef, ParamEnv, Ty, TyCtxt, TypeAndMut, TypeFoldable,
    };

    pub(crate) use rustc_data_structures::fx::FxHashMap;

    pub(crate) use rustc_index::vec::Idx;

    pub(crate) use cranelift_codegen::Context;
    pub(crate) use cranelift_codegen::entity::EntitySet;
    pub(crate) use cranelift_codegen::ir::{AbiParam, Block, ExternalName, FuncRef, Inst, InstBuilder, MemFlags, Signature, SourceLoc, StackSlot, StackSlotData, StackSlotKind, TrapCode, Type, Value};
    pub(crate) use cranelift_codegen::ir::condcodes::{FloatCC, IntCC};
    pub(crate) use cranelift_codegen::ir::function::Function;
    pub(crate) use cranelift_codegen::ir::types;
    pub(crate) use cranelift_codegen::isa::{self, CallConv};
    pub(crate) use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable};
    pub(crate) use cranelift_module::{
        self, Backend, DataContext, DataId, FuncId, Linkage, Module,
    };

    pub(crate) use crate::abi::*;
    pub(crate) use crate::base::{trans_operand, trans_place};
    pub(crate) use crate::cast::*;
    pub(crate) use crate::common::*;
    pub(crate) use crate::debuginfo::{DebugContext, UnwindContext};
    pub(crate) use crate::pointer::Pointer;
    pub(crate) use crate::trap::*;
    pub(crate) use crate::value_and_place::{CPlace, CPlaceInner, CValue};
}

struct PrintOnPanic<F: Fn() -> String>(F);
impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
    fn drop(&mut self) {
        if ::std::thread::panicking() {
            println!("{}", (self.0)());
        }
    }
}

struct CodegenCx<'tcx, B: Backend + 'static> {
    tcx: TyCtxt<'tcx>,
    module: Module<B>,
    global_asm: String,
    constants_cx: ConstantCx,
    cached_context: Context,
    vtables: FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), DataId>,
    debug_context: Option<DebugContext<'tcx>>,
    unwind_context: UnwindContext<'tcx>,
}

impl<'tcx, B: Backend + 'static> CodegenCx<'tcx, B> {
    fn new(
        tcx: TyCtxt<'tcx>,
        module: Module<B>,
        debug_info: bool,
    ) -> Self {
        let unwind_context = UnwindContext::new(tcx, module.isa());
        let debug_context = if debug_info {
            Some(DebugContext::new(
                tcx,
                module.isa(),
            ))
        } else {
            None
        };
        CodegenCx {
            tcx,
            module,
            global_asm: String::new(),
            constants_cx: ConstantCx::default(),
            cached_context: Context::new(),
            vtables: FxHashMap::default(),
            debug_context,
            unwind_context,
        }
    }

    fn finalize(mut self) -> (Module<B>, String, Option<DebugContext<'tcx>>, UnwindContext<'tcx>) {
        self.constants_cx.finalize(self.tcx, &mut self.module);
        (self.module, self.global_asm, self.debug_context, self.unwind_context)
    }
}

struct CraneliftCodegenBackend;

impl CodegenBackend for CraneliftCodegenBackend {
    fn init(&self, sess: &Session) {
        if sess.lto() != rustc_session::config::Lto::No && sess.opts.cg.embed_bitcode {
            sess.warn("LTO is not supported. You may get a linker error.");
        }
    }

    fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync> {
        Box::new(crate::metadata::CraneliftMetadataLoader)
    }

    fn provide(&self, providers: &mut Providers) {
        providers.supported_target_features = |tcx, cnum| {
            assert_eq!(cnum, LOCAL_CRATE);
            if tcx.sess.opts.actually_rustdoc {
                // rustdoc needs to be able to document functions that use all the features, so
                // whitelist them all
                target_features_whitelist::all_known_features()
                    .chain(Some(("cg_clif", None)))
                    .map(|(a, b)| (a.to_string(), b))
                    .collect()
            } else {
                target_features_whitelist::target_feature_whitelist(tcx.sess)
                    .iter()
                    .chain(&Some(("cg_clif", None)))
                    .map(|&(a, b)| (a.to_string(), b))
                    .collect()
            }
        };
    }
    fn provide_extern(&self, _providers: &mut Providers) {}

    fn target_features(&self, _sess: &Session) -> Vec<rustc_span::Symbol> {
        vec![rustc_span::Symbol::intern("cg_clif")]
    }

    fn codegen_crate<'tcx>(
        &self,
        tcx: TyCtxt<'tcx>,
        metadata: EncodedMetadata,
        need_metadata_module: bool,
    ) -> Box<dyn Any> {
        let res = driver::codegen_crate(tcx, metadata, need_metadata_module);

        rustc_symbol_mangling::test::report_symbol_names(tcx);

        res
    }

    fn join_codegen(
        &self,
        ongoing_codegen: Box<dyn Any>,
        sess: &Session,
        dep_graph: &DepGraph,
    ) -> Result<Box<dyn Any>, ErrorReported> {
        let (codegen_results, work_products) = *ongoing_codegen.downcast::<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>)>().unwrap();

        sess.time("serialize_work_products", move || {
            rustc_incremental::save_work_product_index(sess, &dep_graph, work_products)
        });

        Ok(Box::new(codegen_results))
    }

    fn link(
        &self,
        sess: &Session,
        res: Box<dyn Any>,
        outputs: &OutputFilenames,
    ) -> Result<(), ErrorReported> {
        use rustc_codegen_ssa::back::link::link_binary;

        sess.abort_if_errors();

        let codegen_results = *res
            .downcast::<CodegenResults>()
            .expect("Expected CraneliftCodegenBackend's CodegenResult, found Box<Any>");

        let _timer = sess.prof.generic_activity("link_crate");

        sess.time("linking", || {
            let target_cpu = crate::target_triple(sess).to_string();
            link_binary::<crate::archive::ArArchiveBuilder<'_>>(
                sess,
                &codegen_results,
                outputs,
                &codegen_results.crate_name.as_str(),
                &target_cpu,
            );
        });

        rustc_incremental::finalize_session_directory(sess, codegen_results.crate_hash);

        Ok(())
    }
}

fn target_triple(sess: &Session) -> target_lexicon::Triple {
    sess.target.target.llvm_target.parse().unwrap()
}

fn build_isa(sess: &Session, enable_pic: bool) -> Box<dyn isa::TargetIsa + 'static> {
    use target_lexicon::BinaryFormat;

    let target_triple = crate::target_triple(sess);

    let mut flags_builder = settings::builder();
    if enable_pic {
        flags_builder.enable("is_pic").unwrap();
    } else {
        flags_builder.set("is_pic", "false").unwrap();
    }
    flags_builder.set("enable_probestack", "false").unwrap(); // __cranelift_probestack is not provided
    flags_builder
        .set(
            "enable_verifier",
            if cfg!(debug_assertions) {
                "true"
            } else {
                "false"
            },
        )
        .unwrap();

    let tls_model = match target_triple.binary_format {
        BinaryFormat::Elf => "elf_gd",
        BinaryFormat::Macho => "macho",
        BinaryFormat::Coff => "coff",
        _ => "none",
    };
    flags_builder.set("tls_model", tls_model).unwrap();

    flags_builder.set("enable_simd", "true").unwrap();

    // FIXME(CraneStation/cranelift#732) fix LICM in presence of jump tables
    /*
    use rustc_session::config::OptLevel;
    match sess.opts.optimize {
        OptLevel::No => {
            flags_builder.set("opt_level", "none").unwrap();
        }
        OptLevel::Less | OptLevel::Default => {}
        OptLevel::Aggressive => {
            flags_builder.set("opt_level", "speed_and_size").unwrap();
        }
        OptLevel::Size | OptLevel::SizeMin => {
            sess.warn("Optimizing for size is not supported. Just ignoring the request");
        }
    }*/

    let flags = settings::Flags::new(flags_builder);

    let mut isa_builder = cranelift_codegen::isa::lookup(target_triple).unwrap();
    isa_builder.enable("haswell").unwrap();
    isa_builder.finish(flags)
}

/// This is the entrypoint for a hot plugged rustc_codegen_cranelift
#[no_mangle]
pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
    Box::new(CraneliftCodegenBackend)
}
<commit_msg>Use nehalem instead of haswell as target cpu<commit_after>#![feature(rustc_private, decl_macro, type_alias_impl_trait, associated_type_bounds, never_type)]
#![allow(intra_doc_link_resolution_failure)]
#![warn(rust_2018_idioms)]
#![warn(unused_lifetimes)]

extern crate flate2;
#[cfg(feature = "jit")]
extern crate libc;
extern crate rustc_middle;
extern crate rustc_codegen_ssa;
extern crate rustc_data_structures;
extern crate rustc_errors;
extern crate rustc_fs_util;
extern crate rustc_hir;
extern crate rustc_incremental;
extern crate rustc_index;
extern crate rustc_mir;
extern crate rustc_session;
extern crate rustc_span;
extern crate rustc_symbol_mangling;
extern crate rustc_target;
extern crate rustc_ast;

// This prevents duplicating functions and statics that are already part of the host rustc process.
#[allow(unused_extern_crates)]
extern crate rustc_driver;

use std::any::Any;

use rustc_errors::ErrorReported;
use rustc_middle::dep_graph::{DepGraph, WorkProduct, WorkProductId};
use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoader};
use rustc_session::Session;
use rustc_session::config::OutputFilenames;
use rustc_middle::ty::query::Providers;
use rustc_codegen_ssa::CodegenResults;
use rustc_codegen_ssa::traits::CodegenBackend;

use cranelift_codegen::settings::{self, Configurable};

use crate::constant::ConstantCx;
use crate::prelude::*;

mod abi;
mod allocator;
mod analyze;
mod archive;
mod atomic_shim;
mod base;
mod backend;
mod cast;
mod codegen_i128;
mod common;
mod constant;
mod debuginfo;
mod discriminant;
mod driver;
mod inline_asm;
mod intrinsics;
mod linkage;
mod main_shim;
mod metadata;
mod num;
mod optimize;
mod pointer;
mod pretty_clif;
mod target_features_whitelist;
mod toolchain;
mod trap;
mod unsize;
mod value_and_place;
mod vtable;

mod prelude {
    pub(crate) use std::convert::{TryFrom, TryInto};

    pub(crate) use rustc_ast::ast::{FloatTy, IntTy, UintTy};
    pub(crate) use rustc_span::Span;

    pub(crate) use rustc_middle::bug;
    pub(crate) use rustc_hir::def_id::{DefId, LOCAL_CRATE};
    pub(crate) use rustc_middle::mir::{self, *};
    pub(crate) use rustc_middle::ty::layout::{self, TyAndLayout};
    pub(crate) use rustc_target::abi::{Abi, LayoutOf, Scalar, Size, VariantIdx};
    pub(crate) use rustc_middle::ty::{
        self, FnSig, Instance, InstanceDef, ParamEnv, Ty, TyCtxt, TypeAndMut, TypeFoldable,
    };

    pub(crate) use rustc_data_structures::fx::FxHashMap;

    pub(crate) use rustc_index::vec::Idx;

    pub(crate) use cranelift_codegen::Context;
    pub(crate) use cranelift_codegen::entity::EntitySet;
    pub(crate) use cranelift_codegen::ir::{AbiParam, Block, ExternalName, FuncRef, Inst, InstBuilder, MemFlags, Signature, SourceLoc, StackSlot, StackSlotData, StackSlotKind, TrapCode, Type, Value};
    pub(crate) use cranelift_codegen::ir::condcodes::{FloatCC, IntCC};
    pub(crate) use cranelift_codegen::ir::function::Function;
    pub(crate) use cranelift_codegen::ir::types;
    pub(crate) use cranelift_codegen::isa::{self, CallConv};
    pub(crate) use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable};
    pub(crate) use cranelift_module::{
        self, Backend, DataContext, DataId, FuncId, Linkage, Module,
    };

    pub(crate) use crate::abi::*;
    pub(crate) use crate::base::{trans_operand, trans_place};
    pub(crate) use crate::cast::*;
    pub(crate) use crate::common::*;
    pub(crate) use crate::debuginfo::{DebugContext, UnwindContext};
    pub(crate) use crate::pointer::Pointer;
    pub(crate) use crate::trap::*;
    pub(crate) use crate::value_and_place::{CPlace, CPlaceInner, CValue};
}

struct PrintOnPanic<F: Fn() -> String>(F);
impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
    fn drop(&mut self) {
        if ::std::thread::panicking() {
            println!("{}", (self.0)());
        }
    }
}

struct CodegenCx<'tcx, B: Backend + 'static> {
    tcx: TyCtxt<'tcx>,
    module: Module<B>,
    global_asm: String,
    constants_cx: ConstantCx,
    cached_context: Context,
    vtables: FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), DataId>,
    debug_context: Option<DebugContext<'tcx>>,
    unwind_context: UnwindContext<'tcx>,
}

impl<'tcx, B: Backend + 'static> CodegenCx<'tcx, B> {
    fn new(
        tcx: TyCtxt<'tcx>,
        module: Module<B>,
        debug_info: bool,
    ) -> Self {
        let unwind_context = UnwindContext::new(tcx, module.isa());
        let debug_context = if debug_info {
            Some(DebugContext::new(
                tcx,
                module.isa(),
            ))
        } else {
            None
        };
        CodegenCx {
            tcx,
            module,
            global_asm: String::new(),
            constants_cx: ConstantCx::default(),
            cached_context: Context::new(),
            vtables: FxHashMap::default(),
            debug_context,
            unwind_context,
        }
    }

    fn finalize(mut self) -> (Module<B>, String, Option<DebugContext<'tcx>>, UnwindContext<'tcx>) {
        self.constants_cx.finalize(self.tcx, &mut self.module);
        (self.module, self.global_asm, self.debug_context, self.unwind_context)
    }
}

struct CraneliftCodegenBackend;

impl CodegenBackend for CraneliftCodegenBackend {
    fn init(&self, sess: &Session) {
        if sess.lto() != rustc_session::config::Lto::No && sess.opts.cg.embed_bitcode {
            sess.warn("LTO is not supported. You may get a linker error.");
        }
    }

    fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync> {
        Box::new(crate::metadata::CraneliftMetadataLoader)
    }

    fn provide(&self, providers: &mut Providers) {
        providers.supported_target_features = |tcx, cnum| {
            assert_eq!(cnum, LOCAL_CRATE);
            if tcx.sess.opts.actually_rustdoc {
                // rustdoc needs to be able to document functions that use all the features, so
                // whitelist them all
                target_features_whitelist::all_known_features()
                    .chain(Some(("cg_clif", None)))
                    .map(|(a, b)| (a.to_string(), b))
                    .collect()
            } else {
                target_features_whitelist::target_feature_whitelist(tcx.sess)
                    .iter()
                    .chain(&Some(("cg_clif", None)))
                    .map(|&(a, b)| (a.to_string(), b))
                    .collect()
            }
        };
    }
    fn provide_extern(&self, _providers: &mut Providers) {}

    fn target_features(&self, _sess: &Session) -> Vec<rustc_span::Symbol> {
        vec![rustc_span::Symbol::intern("cg_clif")]
    }

    fn codegen_crate<'tcx>(
        &self,
        tcx: TyCtxt<'tcx>,
        metadata: EncodedMetadata,
        need_metadata_module: bool,
    ) -> Box<dyn Any> {
        let res = driver::codegen_crate(tcx, metadata, need_metadata_module);

        rustc_symbol_mangling::test::report_symbol_names(tcx);

        res
    }

    fn join_codegen(
        &self,
        ongoing_codegen: Box<dyn Any>,
        sess: &Session,
        dep_graph: &DepGraph,
    ) -> Result<Box<dyn Any>, ErrorReported> {
        let (codegen_results, work_products) = *ongoing_codegen.downcast::<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>)>().unwrap();

        sess.time("serialize_work_products", move || {
            rustc_incremental::save_work_product_index(sess, &dep_graph, work_products)
        });

        Ok(Box::new(codegen_results))
    }

    fn link(
        &self,
        sess: &Session,
        res: Box<dyn Any>,
        outputs: &OutputFilenames,
    ) -> Result<(), ErrorReported> {
        use rustc_codegen_ssa::back::link::link_binary;

        sess.abort_if_errors();

        let codegen_results = *res
            .downcast::<CodegenResults>()
            .expect("Expected CraneliftCodegenBackend's CodegenResult, found Box<Any>");

        let _timer = sess.prof.generic_activity("link_crate");

        sess.time("linking", || {
            let target_cpu = crate::target_triple(sess).to_string();
            link_binary::<crate::archive::ArArchiveBuilder<'_>>(
                sess,
                &codegen_results,
                outputs,
                &codegen_results.crate_name.as_str(),
                &target_cpu,
            );
        });

        rustc_incremental::finalize_session_directory(sess, codegen_results.crate_hash);

        Ok(())
    }
}

fn target_triple(sess: &Session) -> target_lexicon::Triple {
    sess.target.target.llvm_target.parse().unwrap()
}

fn build_isa(sess: &Session, enable_pic: bool) -> Box<dyn isa::TargetIsa + 'static> {
    use target_lexicon::BinaryFormat;

    let target_triple = crate::target_triple(sess);

    let mut flags_builder = settings::builder();
    if enable_pic {
        flags_builder.enable("is_pic").unwrap();
    } else {
        flags_builder.set("is_pic", "false").unwrap();
    }
    flags_builder.set("enable_probestack", "false").unwrap(); // __cranelift_probestack is not provided
    flags_builder
        .set(
            "enable_verifier",
            if cfg!(debug_assertions) {
                "true"
            } else {
                "false"
            },
        )
        .unwrap();

    let tls_model = match target_triple.binary_format {
        BinaryFormat::Elf => "elf_gd",
        BinaryFormat::Macho => "macho",
        BinaryFormat::Coff => "coff",
        _ => "none",
    };
    flags_builder.set("tls_model", tls_model).unwrap();

    flags_builder.set("enable_simd", "true").unwrap();

    // FIXME(CraneStation/cranelift#732) fix LICM in presence of jump tables
    /*
    use rustc_session::config::OptLevel;
    match sess.opts.optimize {
        OptLevel::No => {
            flags_builder.set("opt_level", "none").unwrap();
        }
        OptLevel::Less | OptLevel::Default => {}
        OptLevel::Aggressive => {
            flags_builder.set("opt_level", "speed_and_size").unwrap();
        }
        OptLevel::Size | OptLevel::SizeMin => {
            sess.warn("Optimizing for size is not supported. Just ignoring the request");
        }
    }*/

    let flags = settings::Flags::new(flags_builder);

    let mut isa_builder = cranelift_codegen::isa::lookup(target_triple).unwrap();
    // Don't use "haswell", as it implies `has_lzcnt`.macOS CI is still at Ivy Bridge EP, so `lzcnt`
    // is interpreted as `bsr`.
    isa_builder.enable("nehalem").unwrap();
    isa_builder.finish(flags)
}

/// This is the entrypoint for a hot plugged rustc_codegen_cranelift
#[no_mangle]
pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
    Box::new(CraneliftCodegenBackend)
}
<|endoftext|>


<commit_before>//! Load MagicaVoxel .vox files into Rust
#![deny(missing_docs)]

extern crate byteorder;
#[cfg(test)]
extern crate env_logger;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate nom;

#[cfg(test)]
extern crate avow;

mod dot_vox_data;
mod model;
mod palette;
mod parser;
mod scene;

pub use dot_vox_data::DotVoxData;

pub use parser::{Dict, Material};

pub use model::Model;
pub use model::Size;
pub use model::Voxel;

pub use scene::*;

pub use palette::DEFAULT_PALETTE;

use parser::parse_vox_file;

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

/// Loads the supplied MagicaVoxel .vox file
///
/// Loads the supplied file, parses it, and returns a `DotVoxData` containing
/// the version of the MagicaVoxel file, a `Vec<Model>` containing all `Model`s
/// contained within the file, a `Vec<u32>` containing the palette information
/// (RGBA), and a `Vec<Material>` containing all the specialized materials.
///
/// # Panics
/// No panics should occur with this library - if you find one, please raise a
/// GitHub issue for it.
///
/// # Errors
/// All errors are strings, and should describe the issue that caused them to
/// occur.
///
/// # Examples
///
/// Loading a file:
///
/// ```
/// use dot_vox::*;
///
/// let result = load("src/resources/placeholder.vox");
/// assert_eq!(result.unwrap(), DotVoxData {
///   version: 150,
///   models: vec!(
///     Model {
///       size: Size { x: 2, y: 2, z: 2 },
///       voxels: vec!(
///         Voxel { x: 0, y: 0, z: 0, i: 225 },
///         Voxel { x: 0, y: 1, z: 1, i: 215 },
///         Voxel { x: 1, y: 0, z: 1, i: 235 },
///         Voxel { x: 1, y: 1, z: 0, i: 5 }
///       )
///     }
///   ),
///   palette: DEFAULT_PALETTE.to_vec(),
///   materials: (0..256).into_iter()
///     .map(|i| Material {
///       id: i,
///       properties: {
///         let mut map = Dict::new();
///         map.insert("_ior".to_owned(), "0.3".to_owned());
///         map.insert("_spec".to_owned(), "0.5".to_owned());
///         map.insert("_rough".to_owned(), "0.1".to_owned());
///         map.insert("_type".to_owned(), "_diffuse".to_owned());
///         map.insert("_weight".to_owned(), "1".to_owned());
///         map
///       }
///     })
///     .collect(),
///   });
/// ```
pub fn load(filename: &str) -> Result<DotVoxData, &'static str> {
    match File::open(filename) {
        Ok(mut f) => {
            let mut buffer = Vec::new();
            f.read_to_end(&mut buffer).expect("Unable to read file");
            load_bytes(&buffer)
        }
        Err(_) => Err("Unable to load file"),
    }
}

/// Parses the byte array as a .vox file.
///
/// Parses the byte array and returns a `DotVoxData` containing  the version of the MagicaVoxel
/// file, a `Vec<Model>` containing all `Model`s contained within the file, a `Vec<u32>` containing
/// the palette information (RGBA), and a `Vec<Material>` containing all the specialized materials.
///
/// # Panics
/// No panics should occur with this library - if you find one, please raise a
/// GitHub issue for it.
///
/// # Errors
/// All errors are strings, and should describe the issue that caused them to
/// occur.
///
/// # Examples
///
/// Reading a byte array:
///
/// ```
/// use dot_vox::*;
///
/// let result = load_bytes(include_bytes!("resources/placeholder.vox"));
/// assert_eq!(result.unwrap(), DotVoxData {
///   version: 150,
///   models: vec!(
///     Model {
///       size: Size { x: 2, y: 2, z: 2 },
///       voxels: vec!(
///         Voxel { x: 0, y: 0, z: 0, i: 225 },
///         Voxel { x: 0, y: 1, z: 1, i: 215 },
///         Voxel { x: 1, y: 0, z: 1, i: 235 },
///         Voxel { x: 1, y: 1, z: 0, i: 5 }
///       )
///     }
///   ),
///   palette: DEFAULT_PALETTE.to_vec(),
///   materials: (0..256).into_iter()
///     .map(|i| Material {
///       id: i,
///       properties: {
///         let mut map = Dict::new();
///         map.insert("_ior".to_owned(), "0.3".to_owned());
///         map.insert("_spec".to_owned(), "0.5".to_owned());
///         map.insert("_rough".to_owned(), "0.1".to_owned());
///         map.insert("_type".to_owned(), "_diffuse".to_owned());
///         map.insert("_weight".to_owned(), "1".to_owned());
///         map
///       }
///     })
///     .collect(),
///   });
/// ```
pub fn load_bytes(bytes: &[u8]) -> Result<DotVoxData, &'static str> {
    match parse_vox_file(bytes) {
        Ok((_, parsed)) => Ok(parsed),
        Err(_) => Err("Not a valid MagicaVoxel .vox file"),
    }
}

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

    lazy_static! {
        static ref DEFAULT_MATERIALS: Vec<Material> = (0..256)
            .into_iter()
            .map(|i| Material {
                id: i,
                properties: {
                    let mut map = Dict::new();
                    map.insert("_ior".to_owned(), "0.3".to_owned());
                    map.insert("_spec".to_owned(), "0.5".to_owned());
                    map.insert("_rough".to_owned(), "0.1".to_owned());
                    map.insert("_type".to_owned(), "_diffuse".to_owned());
                    map.insert("_weight".to_owned(), "1".to_owned());
                    map
                }
            })
            .collect();
    }

    fn placeholder(palette: Vec<u32>, materials: Vec<Material>) -> DotVoxData {
        DotVoxData {
            version: 150,
            models: vec![Model {
                size: Size { x: 2, y: 2, z: 2 },
                voxels: vec![
                    Voxel {
                        x: 0,
                        y: 0,
                        z: 0,
                        i: 225,
                    },
                    Voxel {
                        x: 0,
                        y: 1,
                        z: 1,
                        i: 215,
                    },
                    Voxel {
                        x: 1,
                        y: 0,
                        z: 1,
                        i: 235,
                    },
                    Voxel {
                        x: 1,
                        y: 1,
                        z: 0,
                        i: 5,
                    },
                ],
            }],
            palette: palette,
            materials: materials,
        }
    }

    fn compare_data(actual: DotVoxData, expected: DotVoxData) {
        assert_eq!(actual.version, expected.version);
        assert_eq!(actual.models.len(), expected.models.len());
        actual
            .models
            .into_iter()
            .zip(expected.models.into_iter())
            .for_each(|(actual, expected)| {
                assert_eq!(actual.size, expected.size);
                vec::are_eq(actual.voxels, expected.voxels);
            });
        vec::are_eq(actual.palette, expected.palette);
        vec::are_eq(actual.materials, expected.materials);
    }

    #[test]
    fn valid_file_with_palette_is_read_successfully() {
        let result = load("src/resources/placeholder.vox");
        assert!(result.is_ok());
        compare_data(
            result.unwrap(),
            placeholder(DEFAULT_PALETTE.to_vec(), DEFAULT_MATERIALS.to_vec()),
        );
    }

    #[test]
    fn not_present_file_causes_error() {
        let result = load("src/resources/not_here.vox");
        assert!(result.is_err());
        assert_eq!(result.unwrap_err(), "Unable to load file");
    }

    #[test]
    fn non_vox_file_causes_error() {
        let result = load("src/resources/not_a.vox");
        assert!(result.is_err());
        assert_eq!(result.unwrap_err(), "Not a valid MagicaVoxel .vox file");
    }

    #[test]
    fn can_parse_vox_file_with_palette() {
        let bytes = include_bytes!("resources/placeholder.vox").to_vec();
        let result = super::parse_vox_file(&bytes);
        assert!(result.is_ok());
        let (_, models) = result.unwrap();
        compare_data(
            models,
            placeholder(DEFAULT_PALETTE.to_vec(), DEFAULT_MATERIALS.to_vec()),
        );
    }

    #[test]
    fn can_parse_vox_file_with_materials() {
        let _log = env_logger::init();
        let bytes = include_bytes!("resources/placeholder-with-materials.vox").to_vec();
        let result = super::parse_vox_file(&bytes);
        assert!(result.is_ok());
        let (_, voxel_data) = result.unwrap();
        let mut materials: Vec<Material> = DEFAULT_MATERIALS.to_vec();
        materials[216] = Material {
            id: 216,
            properties: {
                let mut map = Dict::new();
                map.insert("_ior".to_owned(), "0.3".to_owned());
                map.insert("_spec".to_owned(), "0.821053".to_owned());
                map.insert("_rough".to_owned(), "0.389474".to_owned());
                map.insert("_type".to_owned(), "_metal".to_owned());
                map.insert("_plastic".to_owned(), "1".to_owned());
                map.insert("_weight".to_owned(), "0.694737".to_owned());
                map
            },
        };
        compare_data(voxel_data, placeholder(DEFAULT_PALETTE.to_vec(), materials));
    }

    fn write_and_load(data: DotVoxData) {
        let mut buffer = Vec::new();
        let write_result = data.write_vox(&mut buffer);
        assert!(write_result.is_ok());
        let load_result = load_bytes(&buffer);
        assert!(load_result.is_ok());
        compare_data(load_result.unwrap(), data);
    }

    #[test]
    fn can_write_vox_format_without_palette_nor_materials() {
        write_and_load(placeholder(Vec::new(), Vec::new()));
    }

    #[test]
    fn can_write_vox_format_without_materials() {
        write_and_load(placeholder(DEFAULT_PALETTE.to_vec(), Vec::new()));
    }
}
<commit_msg>Fix unit tests (#25)<commit_after>//! Load MagicaVoxel .vox files into Rust
#![deny(missing_docs)]

extern crate byteorder;
#[cfg(test)]
extern crate env_logger;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate nom;

#[cfg(test)]
extern crate avow;

mod dot_vox_data;
mod model;
mod palette;
mod parser;
mod scene;

pub use dot_vox_data::DotVoxData;

pub use parser::{Dict, Material};

pub use model::Model;
pub use model::Size;
pub use model::Voxel;

pub use scene::*;

pub use palette::DEFAULT_PALETTE;

use parser::parse_vox_file;

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

/// Loads the supplied MagicaVoxel .vox file
///
/// Loads the supplied file, parses it, and returns a `DotVoxData` containing
/// the version of the MagicaVoxel file, a `Vec<Model>` containing all `Model`s
/// contained within the file, a `Vec<u32>` containing the palette information
/// (RGBA), and a `Vec<Material>` containing all the specialized materials.
///
/// # Panics
/// No panics should occur with this library - if you find one, please raise a
/// GitHub issue for it.
///
/// # Errors
/// All errors are strings, and should describe the issue that caused them to
/// occur.
///
/// # Examples
///
/// Loading a file:
///
/// ```
/// use dot_vox::*;
/// use std::collections::HashMap;
///
/// let result = load("src/resources/placeholder.vox");
/// assert_eq!(result.unwrap(), DotVoxData {
///   version: 150,
///   models: vec!(
///     Model {
///       size: Size { x: 2, y: 2, z: 2 },
///       voxels: vec!(
///         Voxel { x: 0, y: 0, z: 0, i: 225 },
///         Voxel { x: 0, y: 1, z: 1, i: 215 },
///         Voxel { x: 1, y: 0, z: 1, i: 235 },
///         Voxel { x: 1, y: 1, z: 0, i: 5 }
///       )
///     }
///   ),
///   palette: DEFAULT_PALETTE.to_vec(),
///   materials: (0..256).into_iter()
///     .map(|i| Material {
///       id: i,
///       properties: {
///         let mut map = Dict::new();
///         map.insert("_ior".to_owned(), "0.3".to_owned());
///         map.insert("_spec".to_owned(), "0.5".to_owned());
///         map.insert("_rough".to_owned(), "0.1".to_owned());
///         map.insert("_type".to_owned(), "_diffuse".to_owned());
///         map.insert("_weight".to_owned(), "1".to_owned());
///         map
///       }
///     })
///     .collect(),
///     scene: vec![
///       SceneNode::Transform { attributes: [].into(), frames: [HashMap::new()].into(), child: 1 },
///       SceneNode::Group { attributes: [].into(), children: vec![2] },
///       SceneNode::Transform { attributes: [].into(), frames: [[("_t".to_string(), "0 0 1".to_string())].into()].into(), child: 3 },
///       SceneNode::Shape { attributes: [].into(), models: vec![ShapeModel { model_id: 0, attributes: [].into() }] }],
///     layers: [
///       ("_name", "0"),
///       ("_name", "1"),
///       ("_name", "2"),
///       ("_name", "3"),
///       ("_name", "4"),
///       ("_name", "5"),
///       ("_name", "6"),
///       ("_name", "7"),
///     ].map(|pair| [(pair.0.to_string(), pair.1.to_string())].into()).to_vec(),
///   });
/// ```
pub fn load(filename: &str) -> Result<DotVoxData, &'static str> {
    match File::open(filename) {
        Ok(mut f) => {
            let mut buffer = Vec::new();
            f.read_to_end(&mut buffer).expect("Unable to read file");
            load_bytes(&buffer)
        }
        Err(_) => Err("Unable to load file"),
    }
}

/// Parses the byte array as a .vox file.
///
/// Parses the byte array and returns a `DotVoxData` containing  the version of the MagicaVoxel
/// file, a `Vec<Model>` containing all `Model`s contained within the file, a `Vec<u32>` containing
/// the palette information (RGBA), and a `Vec<Material>` containing all the specialized materials.
///
/// # Panics
/// No panics should occur with this library - if you find one, please raise a
/// GitHub issue for it.
///
/// # Errors
/// All errors are strings, and should describe the issue that caused them to
/// occur.
///
/// # Examples
///
/// Reading a byte array:
///
/// ```
/// use dot_vox::*;
/// use std::collections::HashMap;
///
/// let result = load_bytes(include_bytes!("resources/placeholder.vox"));
/// assert_eq!(result.unwrap(), DotVoxData {
///   version: 150,
///   models: vec!(
///     Model {
///       size: Size { x: 2, y: 2, z: 2 },
///       voxels: vec!(
///         Voxel { x: 0, y: 0, z: 0, i: 225 },
///         Voxel { x: 0, y: 1, z: 1, i: 215 },
///         Voxel { x: 1, y: 0, z: 1, i: 235 },
///         Voxel { x: 1, y: 1, z: 0, i: 5 }
///       )
///     }
///   ),
///   palette: DEFAULT_PALETTE.to_vec(),
///   materials: (0..256).into_iter()
///     .map(|i| Material {
///       id: i,
///       properties: {
///         let mut map = Dict::new();
///         map.insert("_ior".to_owned(), "0.3".to_owned());
///         map.insert("_spec".to_owned(), "0.5".to_owned());
///         map.insert("_rough".to_owned(), "0.1".to_owned());
///         map.insert("_type".to_owned(), "_diffuse".to_owned());
///         map.insert("_weight".to_owned(), "1".to_owned());
///         map
///       }
///     })
///     .collect(),
///     scene: vec![
///       SceneNode::Transform { attributes: [].into(), frames: [HashMap::new()].into(), child: 1 },
///       SceneNode::Group { attributes: [].into(), children: vec![2] },
///       SceneNode::Transform { attributes: [].into(), frames: [[("_t".to_string(), "0 0 1".to_string())].into()].into(), child: 3 },
///       SceneNode::Shape { attributes: [].into(), models: vec![ShapeModel { model_id: 0, attributes: [].into() }] }],
///     layers: [
///       ("_name", "0"),
///       ("_name", "1"),
///       ("_name", "2"),
///       ("_name", "3"),
///       ("_name", "4"),
///       ("_name", "5"),
///       ("_name", "6"),
///       ("_name", "7"),
///     ].map(|pair| [(pair.0.to_string(), pair.1.to_string())].into()).to_vec(),
///   });
/// ```
pub fn load_bytes(bytes: &[u8]) -> Result<DotVoxData, &'static str> {
    match parse_vox_file(bytes) {
        Ok((_, parsed)) => Ok(parsed),
        Err(_) => Err("Not a valid MagicaVoxel .vox file"),
    }
}

#[cfg(test)]
mod tests {
    use std::collections::HashMap;

    use super::*;
    use avow::vec;

    lazy_static! {
        static ref DEFAULT_MATERIALS: Vec<Material> = (0..256)
            .into_iter()
            .map(|i| Material {
                id: i,
                properties: {
                    let mut map = Dict::new();
                    map.insert("_ior".to_owned(), "0.3".to_owned());
                    map.insert("_spec".to_owned(), "0.5".to_owned());
                    map.insert("_rough".to_owned(), "0.1".to_owned());
                    map.insert("_type".to_owned(), "_diffuse".to_owned());
                    map.insert("_weight".to_owned(), "1".to_owned());
                    map
                }
            })
            .collect();
    }

    fn placeholder(palette: Vec<u32>, materials: Vec<Material>) -> DotVoxData {
        DotVoxData {
            version: 150,
            models: vec![Model {
                size: Size { x: 2, y: 2, z: 2 },
                voxels: vec![
                    Voxel {
                        x: 0,
                        y: 0,
                        z: 0,
                        i: 225,
                    },
                    Voxel {
                        x: 0,
                        y: 1,
                        z: 1,
                        i: 215,
                    },
                    Voxel {
                        x: 1,
                        y: 0,
                        z: 1,
                        i: 235,
                    },
                    Voxel {
                        x: 1,
                        y: 1,
                        z: 0,
                        i: 5,
                    },
                ],
            }],
            palette: palette,
            materials: materials,
            scene: vec![
                SceneNode::Transform {
                    attributes: [].into(),
                    frames: [HashMap::new()].into(),
                    child: 1,
                },
                SceneNode::Group {
                    attributes: [].into(),
                    children: vec![2],
                },
                SceneNode::Transform {
                    attributes: [].into(),
                    frames: [[("_t".to_string(), "0 0 1".to_string())].into()].into(),
                    child: 3,
                },
                SceneNode::Shape {
                    attributes: [].into(),
                    models: vec![ShapeModel {
                        model_id: 0,
                        attributes: [].into(),
                    }],
                },
            ],
            layers: [
                ("_name", "0"),
                ("_name", "1"),
                ("_name", "2"),
                ("_name", "3"),
                ("_name", "4"),
                ("_name", "5"),
                ("_name", "6"),
                ("_name", "7"),
            ]
            .map(|pair| [(pair.0.to_string(), pair.1.to_string())].into())
            .to_vec(),
        }
    }

    fn compare_data(actual: DotVoxData, expected: DotVoxData) {
        assert_eq!(actual.version, expected.version);
        assert_eq!(actual.models.len(), expected.models.len());
        actual
            .models
            .into_iter()
            .zip(expected.models.into_iter())
            .for_each(|(actual, expected)| {
                assert_eq!(actual.size, expected.size);
                vec::are_eq(actual.voxels, expected.voxels);
            });
        vec::are_eq(actual.palette, expected.palette);
        vec::are_eq(actual.materials, expected.materials);
    }

    #[test]
    fn valid_file_with_palette_is_read_successfully() {
        let result = load("src/resources/placeholder.vox");
        assert!(result.is_ok());
        compare_data(
            result.unwrap(),
            placeholder(DEFAULT_PALETTE.to_vec(), DEFAULT_MATERIALS.to_vec()),
        );
    }

    #[test]
    fn not_present_file_causes_error() {
        let result = load("src/resources/not_here.vox");
        assert!(result.is_err());
        assert_eq!(result.unwrap_err(), "Unable to load file");
    }

    #[test]
    fn non_vox_file_causes_error() {
        let result = load("src/resources/not_a.vox");
        assert!(result.is_err());
        assert_eq!(result.unwrap_err(), "Not a valid MagicaVoxel .vox file");
    }

    #[test]
    fn can_parse_vox_file_with_palette() {
        let bytes = include_bytes!("resources/placeholder.vox").to_vec();
        let result = super::parse_vox_file(&bytes);
        assert!(result.is_ok());
        let (_, models) = result.unwrap();
        compare_data(
            models,
            placeholder(DEFAULT_PALETTE.to_vec(), DEFAULT_MATERIALS.to_vec()),
        );
    }

    #[test]
    fn can_parse_vox_file_with_materials() {
        let _log = env_logger::init();
        let bytes = include_bytes!("resources/placeholder-with-materials.vox").to_vec();
        let result = super::parse_vox_file(&bytes);
        assert!(result.is_ok());
        let (_, voxel_data) = result.unwrap();
        let mut materials: Vec<Material> = DEFAULT_MATERIALS.to_vec();
        materials[216] = Material {
            id: 216,
            properties: {
                let mut map = Dict::new();
                map.insert("_ior".to_owned(), "0.3".to_owned());
                map.insert("_spec".to_owned(), "0.821053".to_owned());
                map.insert("_rough".to_owned(), "0.389474".to_owned());
                map.insert("_type".to_owned(), "_metal".to_owned());
                map.insert("_plastic".to_owned(), "1".to_owned());
                map.insert("_weight".to_owned(), "0.694737".to_owned());
                map
            },
        };
        compare_data(voxel_data, placeholder(DEFAULT_PALETTE.to_vec(), materials));
    }

    fn write_and_load(data: DotVoxData) {
        let mut buffer = Vec::new();
        let write_result = data.write_vox(&mut buffer);
        assert!(write_result.is_ok());
        let load_result = load_bytes(&buffer);
        assert!(load_result.is_ok());
        compare_data(load_result.unwrap(), data);
    }

    #[test]
    fn can_write_vox_format_without_palette_nor_materials() {
        write_and_load(placeholder(Vec::new(), Vec::new()));
    }

    #[test]
    fn can_write_vox_format_without_materials() {
        write_and_load(placeholder(DEFAULT_PALETTE.to_vec(), Vec::new()));
    }
}
<|endoftext|>


<commit_before>use std::slice;

#[no_mangle]
pub extern fn mse_c (obs_pointer: *const f64,
    sim_pointer: *const f64, arr_size: usize
) -> f64 {

    let obs_arr = unsafe {
            std::slice::from_raw_parts(
                obs_pointer as *const f64,
                arr_size as usize)
    };
    let sim_arr = unsafe {
            std::slice::from_raw_parts(
                sim_pointer as *const f64,
                arr_size as usize)
    };

    return mse( obs_arr, sim_arr);
}

fn mse(obs: &[f64], sim: &[f64]) -> f64 {
    let mut sum_y: f64 = 0.0;

    for (o, s) in obs.iter().zip(sim.iter()) {
        let delta = s - o;
        sum_y += delta.powf(2.0);
    }
    let len: f64 = obs.len() as f64;
    return sum_y / len;
}

#[test]
fn test_mse() {
    let test_obs = &[13.,17.,18.,20.,24.];
    let test_sim = &[12.,15.,20.,22.,24.];

    let result = mse(test_obs, test_sim);
    assert_eq!(result, 2.6);
}

#[test]
fn test_mse_perfect() {
    let result = mse(&[1.,2.,3.,4.,5.],
                  &[1.,2.,3.,4.,5.]);

    assert_eq!(result, 0.0);
}

#[test]
fn test_mse_bad() {
    let obs: [f64; 5] = [1.,2.,3.,4.,5.];

    // Hard coded because I haven't worked out how to sum Vec in rust successfully
    let sum: f64 = 15.0;
    let m = sum / (obs.len() as f64);
    let sim = [m, m, m, m, m];
    let result = mse(
        &[1.,2.,3.,4.,5.],
        &sim
    );

    assert_eq!(result, 2.0);
}
<commit_msg>Add RMSE implementation<commit_after>use std::slice;

#[no_mangle]
pub extern fn mse_c (obs_pointer: *const f64,
    sim_pointer: *const f64, arr_size: usize
) -> f64 {

    let obs_arr = unsafe {
            std::slice::from_raw_parts(
                obs_pointer as *const f64,
                arr_size as usize)
    };
    let sim_arr = unsafe {
            std::slice::from_raw_parts(
                sim_pointer as *const f64,
                arr_size as usize)
    };

    return mse( obs_arr, sim_arr);
}

#[no_mangle]
pub extern fn rmse_c (obs_pointer: *const f64,
    sim_pointer: *const f64, arr_size: usize
) -> f64 {

    let obs_arr = unsafe {
            std::slice::from_raw_parts(
                obs_pointer as *const f64,
                arr_size as usize)
    };
    let sim_arr = unsafe {
            std::slice::from_raw_parts(
                sim_pointer as *const f64,
                arr_size as usize)
    };

    return rmse( obs_arr, sim_arr);
}

fn mse(obs: &[f64], sim: &[f64]) -> f64 {
    let mut sum_y: f64 = 0.0;

    for (o, s) in obs.iter().zip(sim.iter()) {
        let delta = s - o;
        sum_y += delta.powf(2.0);
    }
    let len: f64 = obs.len() as f64;
    return sum_y / len;
}

fn rmse(obs: &[f64], sim: &[f64]) -> f64 {
    return mse(obs, sim).sqrt();
}

#[test]
fn test_rmse() {
    let test_obs = &[13.,17.,18.,20.,24.];
    let test_sim = &[12.,15.,20.,22.,24.];

    let result = rmse(test_obs, test_sim);
    assert_eq!(result, (2.6 as f64).sqrt());
}

#[test]
fn test_rmse_perfect() {
    let test_obs = &[1.,2.,3.,4.,5.];
    let test_sim = &[1.,2.,3.,4.,5.];

    let result = rmse(test_obs, test_sim);
    assert_eq!(result, (0 as f64));
}

#[test]
fn test_rmse_bad() {
    let obs: [f64; 5] = [1.,2.,3.,4.,5.];

    let sum: f64 = obs.iter().fold((0 as f64), std::ops::Add::add);
    let m = sum / (obs.len() as f64);
    let sim = [m, m, m, m, m];
    let result = rmse(
        &[1.,2.,3.,4.,5.],
        &sim
    );

    assert_eq!(result, (2.0 as f64).sqrt());
}

#[test]
fn test_mse() {
    let test_obs = &[13.,17.,18.,20.,24.];
    let test_sim = &[12.,15.,20.,22.,24.];

    let result = mse(test_obs, test_sim);
    assert_eq!(result, 2.6);
}

#[test]
fn test_mse_perfect() {
    let result = mse(&[1.,2.,3.,4.,5.],
                  &[1.,2.,3.,4.,5.]);

    assert_eq!(result, 0.0);
}

#[test]
fn test_mse_bad() {
    let obs: [f64; 5] = [1.,2.,3.,4.,5.];

    // Hard coded because I haven't worked out how to sum Vec in rust successfully
    let sum: f64 = 15.0;
    let m = sum / (obs.len() as f64);
    let sim = [m, m, m, m, m];
    let result = mse(
        &[1.,2.,3.,4.,5.],
        &sim
    );

    assert_eq!(result, 2.0);
}
<|endoftext|>


<commit_before>use runtime::Messageable;
use id::{class, ClassName, Id};
use super::NSString;

pub trait INSObject : Messageable {
	fn class_name() -> ClassName<Self>;

	fn hash_code(&self) -> uint {
		let result = unsafe {
			msg_send![self hash]
		};
		result as uint
	}

	fn is_equal<T: INSObject>(&self, other: &T) -> bool {
		let result = unsafe {
			msg_send![self isEqual:other.as_ptr()]
		};
		!result.is_null()
	}

	fn description(&self) -> Id<NSString> {
		unsafe {
			let result = msg_send![self description];
			Id::from_ptr(result as *NSString)
		}
	}

	fn new() -> Id<Self> {
		let cls = class::<Self>();
		unsafe {
			let obj = msg_send![cls alloc];
			let obj = msg_send![obj init];
			Id::from_retained_ptr(obj as *Self)
		}
	}
}

object_struct!(NSObject)
<commit_msg>Added NSObject tests.<commit_after>use runtime::Messageable;
use id::{class, ClassName, Id};
use super::NSString;

pub trait INSObject : Messageable {
	fn class_name() -> ClassName<Self>;

	fn hash_code(&self) -> uint {
		let result = unsafe {
			msg_send![self hash]
		};
		result as uint
	}

	fn is_equal<T: INSObject>(&self, other: &T) -> bool {
		let result = unsafe {
			msg_send![self isEqual:other.as_ptr()]
		};
		!result.is_null()
	}

	fn description(&self) -> Id<NSString> {
		unsafe {
			let result = msg_send![self description];
			Id::from_ptr(result as *NSString)
		}
	}

	fn new() -> Id<Self> {
		let cls = class::<Self>();
		unsafe {
			let obj = msg_send![cls alloc];
			let obj = msg_send![obj init];
			Id::from_retained_ptr(obj as *Self)
		}
	}
}

object_struct!(NSObject)

#[cfg(test)]
mod tests {
	use id::{ClassName, Id};
	use foundation::INSString;
	use super::{INSObject, NSObject};

	#[test]
	fn test_class_name() {
		let name: ClassName<NSObject> = INSObject::class_name();
		assert!(name.as_str() == "NSObject");
	}

	#[test]
	fn test_is_equal() {
		let obj1: Id<NSObject> = INSObject::new();
		assert!(obj1.is_equal(obj1.deref()));

		let obj2: Id<NSObject> = INSObject::new();
		assert!(!obj1.is_equal(obj2.deref()));
	}

	#[test]
	fn test_hash_code() {
		let obj: Id<NSObject> = INSObject::new();
		assert!(obj.hash_code() == obj.hash_code());
	}

	#[test]
	fn test_description() {
		let obj: Id<NSObject> = INSObject::new();
		let description = obj.description();
		let expected = format!("<NSObject: {}>", obj.deref() as *NSObject);
		assert!(description.as_str() == expected.as_slice());
	}
}
<|endoftext|>


<commit_before>#![feature(process_abort)]

extern "C" {
    #![allow(improper_ctypes)] // we do not actually cross the FFI bound here

    fn rust_fuzzer_test_input(input: &[u8]);
}

#[export_name="LLVMFuzzerTestOneInput"]
pub fn test_input_wrap(data: *const u8, size: usize) -> i32 {
    ::std::panic::catch_unwind(|| unsafe {
        let data_slice = ::std::slice::from_raw_parts(data, size);
        rust_fuzzer_test_input(data_slice);
    }).err().map(|_| ::std::process::abort());
    0
}
<commit_msg>Macro to expand from Rust function to libfuzzer compatible function. Issue #4<commit_after>#![feature(process_abort)]

extern "C" {
    #![allow(improper_ctypes)] // we do not actually cross the FFI bound here

    fn rust_fuzzer_test_input(input: &[u8]);
}

#[export_name="LLVMFuzzerTestOneInput"]
pub fn test_input_wrap(data: *const u8, size: usize) -> i32 {
    ::std::panic::catch_unwind(|| unsafe {
        let data_slice = ::std::slice::from_raw_parts(data, size);
        rust_fuzzer_test_input(data_slice);
    }).err().map(|_| ::std::process::abort());
    0
}

#[macro_export]
macro_rules! fuzzer_target {
    (|$bytes:ident| $body:block) => {
        #[no_mangle]
        pub extern fn rust_fuzzer_test_input($bytes: &[u8]) {
            $body
        }
    }
}
<|endoftext|>


<commit_before>#![feature(old_io,io)]
extern crate hyper;

#[macro_use]
extern crate log;

use std::fmt;
use std::old_io::{IoResult, MemReader, MemWriter, stderr, LineBufferedWriter};
use std::old_io::stdio::StdWriter;
use std::old_io::net::ip::SocketAddr;

use hyper::net::{NetworkStream, NetworkConnector};

pub struct MockStream {
    pub read: MemReader,
    pub write: MemWriter,
}

pub struct TeeStream<T> {
    pub read_write: T,
    pub copy_to: LineBufferedWriter<StdWriter>,
}

impl<T> Clone for TeeStream<T>
    where T: Clone {
    fn clone(&self) -> TeeStream<T> {
        TeeStream {
            read_write: self.read_write.clone(),
            copy_to: stderr(),
        }
    }
}

impl<T> Reader for TeeStream<T>
    where T: Reader {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
        let res = self.read_write.read(buf);
        match res {
            Ok(s) => {
                self.copy_to.write_all(&buf[..s]).ok();
            }
            _ => {}
        };
        res
    }
}

impl<T> Writer for TeeStream<T>
    where T: Writer {
    fn write_all(&mut self, msg: &[u8]) -> IoResult<()> {
        self.copy_to.write_all(msg).ok();
        self.read_write.write_all(msg)
    }
}

impl<T> NetworkStream for TeeStream<T>
    where T: NetworkStream + Send + Clone {
    fn peer_name(&mut self) -> IoResult<SocketAddr> {
        self.read_write.peer_name()
    }
}

impl Clone for MockStream {
    fn clone(&self) -> MockStream {
        MockStream {
            read: MemReader::new(self.read.get_ref().to_vec()),
            write: MemWriter::from_vec(self.write.get_ref().to_vec()),
        }
    }
}

impl PartialEq for MockStream {
    fn eq(&self, other: &MockStream) -> bool {
        self.read.get_ref() == other.read.get_ref() &&
            self.write.get_ref() == other.write.get_ref()
    }
}

impl fmt::Debug for MockStream {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "MockStream {{ read: {:?}, write: {:?} }}",
               self.read.get_ref(), self.write.get_ref())
    }

}

impl MockStream {
    pub fn new() -> MockStream {
        MockStream {
            read: MemReader::new(vec![]),
            write: MemWriter::new(),
        }
    }

    pub fn with_input(input: &[u8]) -> MockStream {
        MockStream {
            read: MemReader::new(input.to_vec()),
            write: MemWriter::new(),
        }
    }
}
impl Reader for MockStream {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
        self.read.read(buf)
    }
}

impl Writer for MockStream {
    fn write_all(&mut self, msg: &[u8]) -> IoResult<()> {
        self.write.write_all(msg)
    }
}

impl NetworkStream for MockStream {
    fn peer_name(&mut self) -> IoResult<SocketAddr> {
        Ok("127.0.0.1:1337".parse().unwrap())
    }
}

pub struct MockConnector;

impl NetworkConnector for MockConnector {
    type Stream = MockStream;

    fn connect(&mut self, _host: &str, _port: u16, _scheme: &str) -> IoResult<MockStream> {
        Ok(MockStream::new())
    }
}

pub struct TeeConnector<C>
    where C: NetworkConnector {
    pub connector: C,
}

impl<C> NetworkConnector for TeeConnector<C>
    where C: NetworkConnector,
          <C as NetworkConnector>::Stream: Clone {
    type Stream = TeeStream<<C as NetworkConnector>::Stream>;

    fn connect(&mut self, _host: &str, _port: u16, _scheme: &str)
        -> IoResult<TeeStream<<C as NetworkConnector>::Stream>> {
        match self.connector.connect(_host, _port, _scheme) {
            Ok(s) => {
                Ok(TeeStream {
                        read_write: s,
                        copy_to: stderr(),
                    }
                )
            },
            Err(err) => Err(err),
        }
    }
}

/// new connectors must be created if you wish to intercept requests.
#[macro_export]
macro_rules! mock_connector (
    ($name:ident {
        $($url:expr => $res:expr)*
    }) => (

        struct $name;

        impl hyper::net::NetworkConnector for $name {
            type Stream = $crate::MockStream;
            fn connect(&mut self, host: &str, port: u16, scheme: &str) -> ::std::old_io::IoResult<$crate::MockStream> {
                use std::collections::HashMap;
                debug!("MockStream::connect({:?}, {:?}, {:?})", host, port, scheme);
                let mut map = HashMap::new();
                $(map.insert($url, $res);)*

                let key = format!("{}://{}", scheme, host);
                // ignore port for now
                match map.get(&*key) {
                    Some(res) => Ok($crate::MockStream {
                        write: ::std::old_io::MemWriter::new(),
                        read: ::std::old_io::MemReader::new(res.to_string().into_bytes())
                    }),
                    None => panic!("{:?} doesn't know url {}", stringify!($name), key)
                }
            }

        }

    )
);

#[macro_export]
macro_rules! mock_connector_in_order (
    ($name:ident {
        $( $res:expr )*
    }) => (

        #[derive(Default)]
        struct $name {
            streamers: Vec<String>,
            current: usize,
        }

        impl hyper::net::NetworkConnector for $name {
            type Stream = $crate::MockStream;
            fn connect(&mut self, host: &str, port: u16, scheme: &str) -> ::std::old_io::IoResult<$crate::MockStream> {
                debug!("MockStream::connect({:?}, {:?}, {:?})", host, port, scheme);

                if self.streamers.len() == 0 {
                    let mut v = Vec::new();
                    $(v.push($res.to_string());)*
                    self.streamers = v;
                    self.current = 0;
                }
                assert!(self.streamers.len() != 0, "Not a single streamer return value specified");

                let r = Ok($crate::MockStream {
                        write: ::std::old_io::MemWriter::new(),
                        read: ::std::old_io::MemReader::new(self.streamers[self.current]
                                                            .clone().into_bytes())
                });
                self.current += 1;
                r
            }
        }
    )
);

<commit_msg>Added missing documentation<commit_after>//! Contains various utility types and macros useful for testing hyper clients.
//!
//! # Macros
//! The `mock_connector!` and `mock_connector_in_order!` macros can be used to
//! feed a client with preset data. That way you can control exactly what it will
//! see, confining the test-case to its own sandbox that way.
//!
//! # Usage
//!
//! Set it up for use in tests in `Cargo.toml`
//!
//! ```toml
//! [dev-dependencies]
//! yup-hyper-mock = "*"
//! log = "*"  # log macros are used within yup-hyper-mock
//! ```
//!
//! Link it into your `src/(lib.rs|main.rs)`
//!
//! ```Rust
//! #[cfg(test)] #[macro_use]
//! extern crate "yup-hyper-mock" as hyper_mock
//! ```

#![feature(old_io,io)]
extern crate hyper;

#[macro_use]
extern crate log;

use std::fmt;
use std::old_io::{IoResult, MemReader, MemWriter, stderr, LineBufferedWriter};
use std::old_io::stdio::StdWriter;
use std::old_io::net::ip::SocketAddr;

use hyper::net::{NetworkStream, NetworkConnector};

/// A `NetworkStream` compatible stream that writes into memory, and reads from memory.
pub struct MockStream {
    pub read: MemReader,
    pub write: MemWriter,
}

/// A `NetworkStream` compatible stream which contains another `NetworkStream`,
/// whose traffic will be written to another stream.
/// Currently that stream will always be standard error.
pub struct TeeStream<T> {
    pub read_write: T,
    pub copy_to: LineBufferedWriter<StdWriter>,
}

impl<T> Clone for TeeStream<T>
    where T: Clone {
    fn clone(&self) -> TeeStream<T> {
        TeeStream {
            read_write: self.read_write.clone(),
            copy_to: stderr(),
        }
    }
}

impl<T> Reader for TeeStream<T>
    where T: Reader {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
        let res = self.read_write.read(buf);
        match res {
            Ok(s) => {
                self.copy_to.write_all(&buf[..s]).ok();
            }
            _ => {}
        };
        res
    }
}

impl<T> Writer for TeeStream<T>
    where T: Writer {
    fn write_all(&mut self, msg: &[u8]) -> IoResult<()> {
        self.copy_to.write_all(msg).ok();
        self.read_write.write_all(msg)
    }
}

impl<T> NetworkStream for TeeStream<T>
    where T: NetworkStream + Send + Clone {
    fn peer_name(&mut self) -> IoResult<SocketAddr> {
        self.read_write.peer_name()
    }
}

impl Clone for MockStream {
    fn clone(&self) -> MockStream {
        MockStream {
            read: MemReader::new(self.read.get_ref().to_vec()),
            write: MemWriter::from_vec(self.write.get_ref().to_vec()),
        }
    }
}

impl PartialEq for MockStream {
    fn eq(&self, other: &MockStream) -> bool {
        self.read.get_ref() == other.read.get_ref() &&
            self.write.get_ref() == other.write.get_ref()
    }
}

impl fmt::Debug for MockStream {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "MockStream {{ read: {:?}, write: {:?} }}",
               self.read.get_ref(), self.write.get_ref())
    }

}

impl MockStream {
    pub fn new() -> MockStream {
        MockStream {
            read: MemReader::new(vec![]),
            write: MemWriter::new(),
        }
    }

    pub fn with_input(input: &[u8]) -> MockStream {
        MockStream {
            read: MemReader::new(input.to_vec()),
            write: MemWriter::new(),
        }
    }
}
impl Reader for MockStream {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
        self.read.read(buf)
    }
}

impl Writer for MockStream {
    fn write_all(&mut self, msg: &[u8]) -> IoResult<()> {
        self.write.write_all(msg)
    }
}

impl NetworkStream for MockStream {
    fn peer_name(&mut self) -> IoResult<SocketAddr> {
        Ok("127.0.0.1:1337".parse().unwrap())
    }
}

/// A `NetworkConnector` which creates `MockStream` instances exclusively.
/// It may be useful to intercept writes.
pub struct MockConnector;

impl NetworkConnector for MockConnector {
    type Stream = MockStream;

    fn connect(&mut self, _host: &str, _port: u16, _scheme: &str) -> IoResult<MockStream> {
        Ok(MockStream::new())
    }
}

/// A `NetworkConnector` embedding another `NetworkConnector` instance,
/// and sets it up to write all reads and writes to standard error as well.
///
/// > **NOTE** It was originally intended to allow arbitrary streams to copy data to,
/// > but I couldn't get passt the compiler with that as normal streams, like files,
/// > are not normally clonable. Maybe an Arc+Mutex would have helped ... .
pub struct TeeConnector<C>
    where C: NetworkConnector {
    pub connector: C,
}

impl<C> NetworkConnector for TeeConnector<C>
    where C: NetworkConnector,
          <C as NetworkConnector>::Stream: Clone {
    type Stream = TeeStream<<C as NetworkConnector>::Stream>;

    fn connect(&mut self, _host: &str, _port: u16, _scheme: &str)
        -> IoResult<TeeStream<<C as NetworkConnector>::Stream>> {
        match self.connector.connect(_host, _port, _scheme) {
            Ok(s) => {
                Ok(TeeStream {
                        read_write: s,
                        copy_to: stderr(),
                    }
                )
            },
            Err(err) => Err(err),
        }
    }
}

/// This macro maps host URLs to a respective reply, which is given in plain-text.
/// It ignores, but stores, everything that is written to it. However, the stored
/// values are not accessible just yet.
#[macro_export]
macro_rules! mock_connector (
    ($name:ident {
        $($url:expr => $res:expr)*
    }) => (

        struct $name;

        impl hyper::net::NetworkConnector for $name {
            type Stream = $crate::MockStream;
            fn connect(&mut self, host: &str, port: u16, scheme: &str) -> ::std::old_io::IoResult<$crate::MockStream> {
                use std::collections::HashMap;
                debug!("MockStream::connect({:?}, {:?}, {:?})", host, port, scheme);
                let mut map = HashMap::new();
                $(map.insert($url, $res);)*

                let key = format!("{}://{}", scheme, host);
                // ignore port for now
                match map.get(&*key) {
                    Some(res) => Ok($crate::MockStream {
                        write: ::std::old_io::MemWriter::new(),
                        read: ::std::old_io::MemReader::new(res.to_string().into_bytes())
                    }),
                    None => panic!("{:?} doesn't know url {}", stringify!($name), key)
                }
            }

        }

    )
);

/// This macro yields all given server replies in the order they are given.
/// The destination host URL doesn't matter at all.
#[macro_export]
macro_rules! mock_connector_in_order (
    ($name:ident {
        $( $res:expr )*
    }) => (

        #[derive(Default)]
        struct $name {
            streamers: Vec<String>,
            current: usize,
        }

        impl hyper::net::NetworkConnector for $name {
            type Stream = $crate::MockStream;
            fn connect(&mut self, host: &str, port: u16, scheme: &str) -> ::std::old_io::IoResult<$crate::MockStream> {
                debug!("MockStream::connect({:?}, {:?}, {:?})", host, port, scheme);

                if self.streamers.len() == 0 {
                    let mut v = Vec::new();
                    $(v.push($res.to_string());)*
                    self.streamers = v;
                    self.current = 0;
                }
                assert!(self.streamers.len() != 0, "Not a single streamer return value specified");

                let r = Ok($crate::MockStream {
                        write: ::std::old_io::MemWriter::new(),
                        read: ::std::old_io::MemReader::new(self.streamers[self.current]
                                                            .clone().into_bytes())
                });
                self.current += 1;
                r
            }
        }
    )
);

<|endoftext|>


<commit_before>#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]

//! A set of middleware for sharing data between requests in the Iron
//! framework.

extern crate iron;
extern crate plugin;

use iron::{Request, Response, BeforeMiddleware, AfterMiddleware, IronResult};
use iron::typemap::Key;
use std::sync::{Arc, RwLock, Mutex};
use plugin::Plugin;

/// The type that can be returned by `eval` to indicate error.
#[derive(Clone, Debug)]
pub enum PersistentError {
    /// The value was not found.
    NotFound
}

/// Middleware for data that persists between requests with read and write capabilities.
///
/// The data is stored behind a `RwLock`, so multiple read locks
/// can be taken out concurrently.
///
/// If most threads need to take out a write lock, you may want to
/// consider `Write`, which stores the data behind a `Mutex`, which
/// has a faster locking speed.
///
/// `State` can be linked as `BeforeMiddleware` to add data to the `Request`
/// extensions and it can be linked as an `AfterMiddleware` to add data to
/// the `Response` extensions.
///
/// `State` also implements `Plugin`, so the data stored within can be
/// accessed through `request.get::<State<P>>()` as an `Arc<RwLock<P::Value>>`.
pub struct State<P: Key> {
    data: Arc<RwLock<P::Value>>
}

/// Middleware for data that persists between Requests with read-only capabilities.
///
/// The data is stored behind an Arc, so multiple threads can have
/// concurrent, non-blocking access.
///
/// `Read` can be linked as `BeforeMiddleware` to add data to the `Request`
/// extensions and it can be linked as an `AfterMiddleware` to add data to
/// the `Response` extensions.
///
/// `Read` also implements `Plugin`, so the data stored within can be
/// accessed through `request.get::<Read<P>>()` as an `Arc<P::Value>`.
pub struct Read<P: Key> {
    data: Arc<P::Value>
}

/// Middleware for data that persists between Requests for data which mostly
/// needs to be written instead of read.
///
/// The data is stored behind a `Mutex`, so only one request at a time can
/// access the data. This is more performant than `State` in the case where
/// most uses of the data require a write lock.
///
/// `Write` can be linked as `BeforeMiddleware` to add data to the `Request`
/// extensions and it can be linked as an `AfterMiddleware` to add data to
/// the `Response` extensions.
///
/// `Write` also implements `Plugin`, so the data stored within can be
/// accessed through `request.get::<Write<P>>()` as an `Arc<Mutex<P::Value>>`.
pub struct Write<P: Key> {
    data: Arc<Mutex<P::Value>>
}

macro_rules! impl_persistent {
    ($name:ty, $out:ty, $param:ident) => {
    }
}

impl<P: Key> Clone for Read<P> where P::Value: Send + Sync {
    fn clone(&self) -> Read<P> {
        Read { data: self.data.clone() }
    }
}

impl<P: Key> Clone for State<P> where P::Value: Send + Sync {
    fn clone(&self) -> State<P> {
        State { data: self.data.clone() }
    }
}

impl<P: Key> Clone for Write<P> where P::Value: Send {
    fn clone(&self) -> Write<P> {
        Write { data: self.data.clone() }
    }
}

impl<P: Key> Key for State<P> where P::Value: 'static {
    type Value = Arc<RwLock<P::Value>>;
}

impl<P: Key> Key for Read<P> where P::Value: 'static {
    type Value = Arc<P::Value>;
}

impl<P: Key> Key for Write<P> where P::Value: 'static {
    type Value = Arc<Mutex<P::Value>>;
}

impl<'a, 'b, P: Key> Plugin<Request<'a, 'b>> for State<P> where P::Value: Send + Sync {
    type Error = PersistentError;
    fn eval(req: &mut Request<'a, 'b>) -> Result<Arc<RwLock<P::Value>>, PersistentError> {
        req.extensions.get::<State<P>>().cloned().ok_or(PersistentError::NotFound)
    }
}

impl<'a, 'b, P: Key> Plugin<Request<'a, 'b>> for Read<P> where P::Value: Send + Sync {
    type Error = PersistentError;
    fn eval(req: &mut Request<'a, 'b>) -> Result<Arc<P::Value>, PersistentError> {
        req.extensions.get::<Read<P>>().cloned().ok_or(PersistentError::NotFound)
    }
}

impl<'a, 'b, P: Key> Plugin<Request<'a, 'b>> for Write<P> where P::Value: Send {
    type Error = PersistentError;
    fn eval(req: &mut Request<'a, 'b>) -> Result<Arc<Mutex<P::Value>>, PersistentError> {
        req.extensions.get::<Write<P>>().cloned().ok_or(PersistentError::NotFound)
    }
}

impl<P: Key> BeforeMiddleware for State<P> where P::Value: Send + Sync {
    fn before(&self, req: &mut Request) -> IronResult<()> {
        req.extensions.insert::<State<P>>(self.data.clone());
        Ok(())
    }
}

impl<P: Key> BeforeMiddleware for Read<P> where P::Value: Send + Sync {
    fn before(&self, req: &mut Request) -> IronResult<()> {
        req.extensions.insert::<Read<P>>(self.data.clone());
        Ok(())
    }
}

impl<P: Key> BeforeMiddleware for Write<P> where P::Value: Send {
    fn before(&self, req: &mut Request) -> IronResult<()> {
        req.extensions.insert::<Write<P>>(self.data.clone());
        Ok(())
    }
}

impl<P: Key> AfterMiddleware for State<P> where P::Value: Send + Sync {
    fn after(&self, _: &mut Request, mut res: Response) -> IronResult<Response> {
        res.extensions.insert::<State<P>>(self.data.clone());
        Ok(res)
    }
}

impl<P: Key> AfterMiddleware for Read<P> where P::Value: Send + Sync {
    fn after(&self, _: &mut Request, mut res: Response) -> IronResult<Response> {
        res.extensions.insert::<Read<P>>(self.data.clone());
        Ok(res)
    }
}

impl<P: Key> AfterMiddleware for Write<P> where P::Value: Send {
    fn after(&self, _: &mut Request, mut res: Response) -> IronResult<Response> {
        res.extensions.insert::<Write<P>>(self.data.clone());
        Ok(res)
    }
}

impl<P: Key> State<P> where P::Value: Send + Sync {
    /// Construct a new pair of `State` that can be passed directly to `Chain::link`.
    ///
    /// The data is initialized with the passed-in value.
    pub fn both(start: P::Value) -> (State<P>, State<P>) {
        let x = State { data: Arc::new(RwLock::new(start)) };
        (x.clone(), x)
    }

    /// Construct a new `State` that can be passed directly to
    /// `Chain::link_before` or `Chain::link_after`.
    ///
    /// The data is initialized with the passed-in value.
    pub fn one(start: P::Value) -> State<P> {
        State { data: Arc::new(RwLock::new(start)) }
    }
}

impl<P: Key> Read<P> where P::Value: Send + Sync {
    /// Construct a new pair of `Read` that can be passed directly to `Chain::link`.
    ///
    /// The data is initialized with the passed-in value.
    pub fn both(start: P::Value) -> (Read<P>, Read<P>) {
        let x = Read { data: Arc::new(start) };
        (x.clone(), x)
    }

    /// Construct a new `Read` that can be passed directly to
    /// `Chain::link_before` or `Chain::link_after`.
    ///
    /// The data is initialized with the passed-in value.
    pub fn one(start: P::Value) -> Read<P> {
        Read { data: Arc::new(start) }
    }
}

impl<P: Key> Write<P> where P::Value: Send {
    /// Construct a new pair of `Write` that can be passed directly to `Chain::link`.
    ///
    /// The data is initialized with the passed-in value.
    pub fn both(start: P::Value) -> (Write<P>, Write<P>) {
        let x = Write { data: Arc::new(Mutex::new(start)) };
        (x.clone(), x)
    }

    /// Construct a new `Write` that can be passed directly to
    /// `Chain::link_before` or `Chain::link_after`.
    ///
    /// The data is initialized with the passed-in value.
    pub fn one(start: P::Value) -> Write<P> {
        Write { data: Arc::new(Mutex::new(start)) }
    }
}
<commit_msg>Implement std::error::Error for PersistentError<commit_after>#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]

//! A set of middleware for sharing data between requests in the Iron
//! framework.

extern crate iron;
extern crate plugin;

use iron::{Request, Response, BeforeMiddleware, AfterMiddleware, IronResult};
use iron::typemap::Key;
use std::sync::{Arc, RwLock, Mutex};
use std::{error,fmt};
use plugin::Plugin;

/// The type that can be returned by `eval` to indicate error.
#[derive(Clone, Debug)]
pub enum PersistentError {
    /// The value was not found.
    NotFound
}

impl fmt::Display for PersistentError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        fmt::Display::fmt(self, f)
    }
}

impl error::Error for PersistentError {
    fn description(&self) -> &str {
        match *self {
            PersistentError::NotFound => "Value not found in extensions."
        }
    }
}

/// Middleware for data that persists between requests with read and write capabilities.
///
/// The data is stored behind a `RwLock`, so multiple read locks
/// can be taken out concurrently.
///
/// If most threads need to take out a write lock, you may want to
/// consider `Write`, which stores the data behind a `Mutex`, which
/// has a faster locking speed.
///
/// `State` can be linked as `BeforeMiddleware` to add data to the `Request`
/// extensions and it can be linked as an `AfterMiddleware` to add data to
/// the `Response` extensions.
///
/// `State` also implements `Plugin`, so the data stored within can be
/// accessed through `request.get::<State<P>>()` as an `Arc<RwLock<P::Value>>`.
pub struct State<P: Key> {
    data: Arc<RwLock<P::Value>>
}

/// Middleware for data that persists between Requests with read-only capabilities.
///
/// The data is stored behind an Arc, so multiple threads can have
/// concurrent, non-blocking access.
///
/// `Read` can be linked as `BeforeMiddleware` to add data to the `Request`
/// extensions and it can be linked as an `AfterMiddleware` to add data to
/// the `Response` extensions.
///
/// `Read` also implements `Plugin`, so the data stored within can be
/// accessed through `request.get::<Read<P>>()` as an `Arc<P::Value>`.
pub struct Read<P: Key> {
    data: Arc<P::Value>
}

/// Middleware for data that persists between Requests for data which mostly
/// needs to be written instead of read.
///
/// The data is stored behind a `Mutex`, so only one request at a time can
/// access the data. This is more performant than `State` in the case where
/// most uses of the data require a write lock.
///
/// `Write` can be linked as `BeforeMiddleware` to add data to the `Request`
/// extensions and it can be linked as an `AfterMiddleware` to add data to
/// the `Response` extensions.
///
/// `Write` also implements `Plugin`, so the data stored within can be
/// accessed through `request.get::<Write<P>>()` as an `Arc<Mutex<P::Value>>`.
pub struct Write<P: Key> {
    data: Arc<Mutex<P::Value>>
}

macro_rules! impl_persistent {
    ($name:ty, $out:ty, $param:ident) => {
    }
}

impl<P: Key> Clone for Read<P> where P::Value: Send + Sync {
    fn clone(&self) -> Read<P> {
        Read { data: self.data.clone() }
    }
}

impl<P: Key> Clone for State<P> where P::Value: Send + Sync {
    fn clone(&self) -> State<P> {
        State { data: self.data.clone() }
    }
}

impl<P: Key> Clone for Write<P> where P::Value: Send {
    fn clone(&self) -> Write<P> {
        Write { data: self.data.clone() }
    }
}

impl<P: Key> Key for State<P> where P::Value: 'static {
    type Value = Arc<RwLock<P::Value>>;
}

impl<P: Key> Key for Read<P> where P::Value: 'static {
    type Value = Arc<P::Value>;
}

impl<P: Key> Key for Write<P> where P::Value: 'static {
    type Value = Arc<Mutex<P::Value>>;
}

impl<'a, 'b, P: Key> Plugin<Request<'a, 'b>> for State<P> where P::Value: Send + Sync {
    type Error = PersistentError;
    fn eval(req: &mut Request<'a, 'b>) -> Result<Arc<RwLock<P::Value>>, PersistentError> {
        req.extensions.get::<State<P>>().cloned().ok_or(PersistentError::NotFound)
    }
}

impl<'a, 'b, P: Key> Plugin<Request<'a, 'b>> for Read<P> where P::Value: Send + Sync {
    type Error = PersistentError;
    fn eval(req: &mut Request<'a, 'b>) -> Result<Arc<P::Value>, PersistentError> {
        req.extensions.get::<Read<P>>().cloned().ok_or(PersistentError::NotFound)
    }
}

impl<'a, 'b, P: Key> Plugin<Request<'a, 'b>> for Write<P> where P::Value: Send {
    type Error = PersistentError;
    fn eval(req: &mut Request<'a, 'b>) -> Result<Arc<Mutex<P::Value>>, PersistentError> {
        req.extensions.get::<Write<P>>().cloned().ok_or(PersistentError::NotFound)
    }
}

impl<P: Key> BeforeMiddleware for State<P> where P::Value: Send + Sync {
    fn before(&self, req: &mut Request) -> IronResult<()> {
        req.extensions.insert::<State<P>>(self.data.clone());
        Ok(())
    }
}

impl<P: Key> BeforeMiddleware for Read<P> where P::Value: Send + Sync {
    fn before(&self, req: &mut Request) -> IronResult<()> {
        req.extensions.insert::<Read<P>>(self.data.clone());
        Ok(())
    }
}

impl<P: Key> BeforeMiddleware for Write<P> where P::Value: Send {
    fn before(&self, req: &mut Request) -> IronResult<()> {
        req.extensions.insert::<Write<P>>(self.data.clone());
        Ok(())
    }
}

impl<P: Key> AfterMiddleware for State<P> where P::Value: Send + Sync {
    fn after(&self, _: &mut Request, mut res: Response) -> IronResult<Response> {
        res.extensions.insert::<State<P>>(self.data.clone());
        Ok(res)
    }
}

impl<P: Key> AfterMiddleware for Read<P> where P::Value: Send + Sync {
    fn after(&self, _: &mut Request, mut res: Response) -> IronResult<Response> {
        res.extensions.insert::<Read<P>>(self.data.clone());
        Ok(res)
    }
}

impl<P: Key> AfterMiddleware for Write<P> where P::Value: Send {
    fn after(&self, _: &mut Request, mut res: Response) -> IronResult<Response> {
        res.extensions.insert::<Write<P>>(self.data.clone());
        Ok(res)
    }
}

impl<P: Key> State<P> where P::Value: Send + Sync {
    /// Construct a new pair of `State` that can be passed directly to `Chain::link`.
    ///
    /// The data is initialized with the passed-in value.
    pub fn both(start: P::Value) -> (State<P>, State<P>) {
        let x = State { data: Arc::new(RwLock::new(start)) };
        (x.clone(), x)
    }

    /// Construct a new `State` that can be passed directly to
    /// `Chain::link_before` or `Chain::link_after`.
    ///
    /// The data is initialized with the passed-in value.
    pub fn one(start: P::Value) -> State<P> {
        State { data: Arc::new(RwLock::new(start)) }
    }
}

impl<P: Key> Read<P> where P::Value: Send + Sync {
    /// Construct a new pair of `Read` that can be passed directly to `Chain::link`.
    ///
    /// The data is initialized with the passed-in value.
    pub fn both(start: P::Value) -> (Read<P>, Read<P>) {
        let x = Read { data: Arc::new(start) };
        (x.clone(), x)
    }

    /// Construct a new `Read` that can be passed directly to
    /// `Chain::link_before` or `Chain::link_after`.
    ///
    /// The data is initialized with the passed-in value.
    pub fn one(start: P::Value) -> Read<P> {
        Read { data: Arc::new(start) }
    }
}

impl<P: Key> Write<P> where P::Value: Send {
    /// Construct a new pair of `Write` that can be passed directly to `Chain::link`.
    ///
    /// The data is initialized with the passed-in value.
    pub fn both(start: P::Value) -> (Write<P>, Write<P>) {
        let x = Write { data: Arc::new(Mutex::new(start)) };
        (x.clone(), x)
    }

    /// Construct a new `Write` that can be passed directly to
    /// `Chain::link_before` or `Chain::link_after`.
    ///
    /// The data is initialized with the passed-in value.
    pub fn one(start: P::Value) -> Write<P> {
        Write { data: Arc::new(Mutex::new(start)) }
    }
}
<|endoftext|>


<commit_before>
use std::fmt;
use std::ops::{Add, Div, Mul, Neg, Sub};

extern crate num;
use num::{Num, Float, Zero, One};

#[cfg(test)]
use std::f32::consts;
#[cfg(test)]
use std::f32;

/// Dual Numbers
#[derive(Copy, Clone, PartialEq, Hash, Debug)]
pub struct Dual<F> {
    pub real: F,
    pub dual: F,
}

pub type Dual32 = Dual<f32>;
pub type Dual64 = Dual<f64>;

impl<F: Copy + Num> Dual<F> {
    pub fn new(real: F, deriv: F) -> Dual<F> {
        Dual {
            real: real,
            dual: deriv,
        }
    }

    pub fn derivative(self) -> F {
        self.dual
    }
}

impl<F: Copy + Num> Zero for Dual<F> {
    fn zero() -> Dual<F> {
        Dual::new(F::zero(), F::zero())
    }

    fn is_zero(&self) -> bool {
        self.real.is_zero() && self.dual.is_zero()
    }
}

impl<F: Copy + Num> One for Dual<F> {
    fn one() -> Dual<F> {
        Dual::new(One::one(), One::one())
    }
}

impl<F: Copy + Num> Add<Dual<F>> for Dual<F> {
    type Output = Dual<F>;

    fn add(self, other: Dual<F>) -> Dual<F> {
        Dual::new(self.real + other.real, self.dual + other.dual)
    }
}

#[test]
fn test_add_struct() {
    let x = Dual::new(3.0, 4.0);
    let y = Dual::new(2.0, 3.0);

    let z = x + y;
    assert!(z.real == 5.0);
    assert!(z.dual == 7.0);
}

impl<F: Copy + Num> Sub<Dual<F>> for Dual<F> {
    type Output = Dual<F>;

    fn sub(self, other: Dual<F>) -> Dual<F> {
        Dual::new(self.real - other.real, self.dual - other.dual)
    }
}

#[test]
fn test_sub() {
    let x = Dual::new(3.0, 4.0);
    let y = Dual::new(2.0, 12.0);

    let z = x - y;
    assert!(z.real == 1.0);
    assert!(z.dual == -8.0);
}

impl<F: Copy + Num + Neg<Output = F>> Neg for Dual<F> {
    type Output = Dual<F>;

    fn neg(self) -> Dual<F> {
        Dual::new(-self.real, -self.dual)
    }
}

#[test]
fn test_neg_plus() {
    let x = Dual::new(3.0, 4.0);
    let y = Dual::new(2.0, 12.0);

    let z1 = x - y;
    let z2 = x + (-y);
    assert!(z1 == z2);
}

#[test]
fn test_neg_zero() {
    let x = Dual::new(3.0, 4.0);
    let zero: Dual32 = Zero::zero();

    let z1 = -x;
    let z2 = zero - x;
    assert!(z1 == z2);
}

impl<F: Copy + Num> Mul<Dual<F>> for Dual<F> {
    type Output = Dual<F>;

    fn mul(self, other: Dual<F>) -> Dual<F> {
        Dual::new(self.real * other.real,
                  (self.real * other.dual) + (self.dual * other.real))
    }
}

#[test]
fn test_mul() {
    let x = Dual::new(3.0, 4.0);
    let y = Dual::new(1.0, 2.0);

    let z = x * y;
    assert!(z.real == 3.0);
    assert!(z.dual == 10.0);
}

impl<F: Copy + Num> Div<Dual<F>> for Dual<F> {
    type Output = Dual<F>;

    fn div(self, other: Dual<F>) -> Dual<F> {
        Dual::new(self.real / other.real,
                  ((self.dual * other.real) - (self.real * other.dual)) / (other.real * other.real))
    }
}

#[test]
fn test_div() {
    let x = Dual::new(3.0, 4.0);
    let y = Dual::new(1.0, 2.0);

    let z = x / y;
    assert!(z.real == 3.0);
    assert!(z.dual == -2.0);
}

impl<F: Copy + Float> Dual<F> {
    pub fn sin(self) -> Dual<F> {
        Dual::new(self.real.sin(), self.dual * self.real.cos())
    }

    pub fn cos(self) -> Dual<F> {
        Dual::new(self.real.cos(), (-F::one()) * self.dual * self.real.sin())
    }

    pub fn tan(self) -> Dual<F> {
        self.sin() / self.cos()
    }

    pub fn exp(self) -> Dual<F> {
        Dual::new(self.real.exp(), self.dual * self.real.exp())
    }

    pub fn ln(self) -> Dual<F> {
        Dual::new(self.real.ln(), self.dual / self.real)
    }

    pub fn sqrt(self) -> Dual<F> {
        let two = F::one() + F::one();
        Dual::new(self.real.sqrt(),
                  self.dual / (two * self.real.sqrt()))
    }
}

impl<F: Copy + Num> From<F> for Dual<F> {
    fn from(real: F) -> Dual<F> {
        Dual::new(real, F::one())
    }
}

impl<F> fmt::Display for Dual<F>
    where F: fmt::Display + Num + PartialOrd + Copy
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.real < Zero::zero() {
            write!(f, "{}-{}ε", self.real, F::zero() - self.dual)
        } else {
            write!(f, "{}+{}ε", self.real, self.dual)
        }
    }
}

#[cfg(test)]
fn diff(x : f32, y : f32) -> f32 {
    (x - y).abs()
}

#[test]
fn test_sin() {
    let x: Dual32 = From::from(0.0);
    let y = x.sin();

    let real_diff = diff(y.real, 0.0);
    let dual_diff = diff(y.dual, 1.0);

    assert!(real_diff < f32::EPSILON);
    assert!(dual_diff < f32::EPSILON);
}

#[test]
fn test_cos() {
    let x: Dual32 = From::from(consts::PI);
    let y = x.cos();

    let real_diff = diff(y.real, -1.0);
    let dual_diff = diff(y.dual, 0.0);

    assert!(real_diff < f32::EPSILON);
    assert!(dual_diff < f32::EPSILON);
}

#[test]
fn test_exp() {
    let x: Dual32 = From::from(1.0);
    let y = x.exp();

    let real_diff = diff(y.real, consts::E);
    let dual_diff = diff(y.dual, consts::E);

    assert!(real_diff < f32::EPSILON);
    assert!(dual_diff < f32::EPSILON);
}

#[test]
fn test_ln() {
    let x: Dual32 = From::from(1.0);
    let y = x.ln();

    let real_diff = diff(y.real, 0.0);
    let dual_diff = diff(y.dual, 1.0);

    assert!(real_diff < f32::EPSILON);
    assert!(dual_diff < f32::EPSILON);
}

#[test]
fn test_sqrt() {
    let x: Dual32 = From::from(4.0);
    let y = x.sqrt();

    println!("{}", y);

    let real_diff = diff(y.real, 2.0);
    let dual_diff = diff(y.dual, 0.25);

    assert!(real_diff < f32::EPSILON);
    assert!(dual_diff < f32::EPSILON);
}
<commit_msg>Test for tan<commit_after>
use std::fmt;
use std::ops::{Add, Div, Mul, Neg, Sub};

extern crate num;
use num::{Num, Float, Zero, One};

#[cfg(test)]
use std::f32::consts;
#[cfg(test)]
use std::f32;

/// Dual Numbers
#[derive(Copy, Clone, PartialEq, Hash, Debug)]
pub struct Dual<F> {
    pub real: F,
    pub dual: F,
}

pub type Dual32 = Dual<f32>;
pub type Dual64 = Dual<f64>;

impl<F: Copy + Num> Dual<F> {
    pub fn new(real: F, deriv: F) -> Dual<F> {
        Dual {
            real: real,
            dual: deriv,
        }
    }

    pub fn derivative(self) -> F {
        self.dual
    }
}

impl<F: Copy + Num> Zero for Dual<F> {
    fn zero() -> Dual<F> {
        Dual::new(F::zero(), F::zero())
    }

    fn is_zero(&self) -> bool {
        self.real.is_zero() && self.dual.is_zero()
    }
}

impl<F: Copy + Num> One for Dual<F> {
    fn one() -> Dual<F> {
        Dual::new(One::one(), One::one())
    }
}

impl<F: Copy + Num> Add<Dual<F>> for Dual<F> {
    type Output = Dual<F>;

    fn add(self, other: Dual<F>) -> Dual<F> {
        Dual::new(self.real + other.real, self.dual + other.dual)
    }
}

#[test]
fn test_add_struct() {
    let x = Dual::new(3.0, 4.0);
    let y = Dual::new(2.0, 3.0);

    let z = x + y;
    assert!(z.real == 5.0);
    assert!(z.dual == 7.0);
}

impl<F: Copy + Num> Sub<Dual<F>> for Dual<F> {
    type Output = Dual<F>;

    fn sub(self, other: Dual<F>) -> Dual<F> {
        Dual::new(self.real - other.real, self.dual - other.dual)
    }
}

#[test]
fn test_sub() {
    let x = Dual::new(3.0, 4.0);
    let y = Dual::new(2.0, 12.0);

    let z = x - y;
    assert!(z.real == 1.0);
    assert!(z.dual == -8.0);
}

impl<F: Copy + Num + Neg<Output = F>> Neg for Dual<F> {
    type Output = Dual<F>;

    fn neg(self) -> Dual<F> {
        Dual::new(-self.real, -self.dual)
    }
}

#[test]
fn test_neg_plus() {
    let x = Dual::new(3.0, 4.0);
    let y = Dual::new(2.0, 12.0);

    let z1 = x - y;
    let z2 = x + (-y);
    assert!(z1 == z2);
}

#[test]
fn test_neg_zero() {
    let x = Dual::new(3.0, 4.0);
    let zero: Dual32 = Zero::zero();

    let z1 = -x;
    let z2 = zero - x;
    assert!(z1 == z2);
}

impl<F: Copy + Num> Mul<Dual<F>> for Dual<F> {
    type Output = Dual<F>;

    fn mul(self, other: Dual<F>) -> Dual<F> {
        Dual::new(self.real * other.real,
                  (self.real * other.dual) + (self.dual * other.real))
    }
}

#[test]
fn test_mul() {
    let x = Dual::new(3.0, 4.0);
    let y = Dual::new(1.0, 2.0);

    let z = x * y;
    assert!(z.real == 3.0);
    assert!(z.dual == 10.0);
}

impl<F: Copy + Num> Div<Dual<F>> for Dual<F> {
    type Output = Dual<F>;

    fn div(self, other: Dual<F>) -> Dual<F> {
        Dual::new(self.real / other.real,
                  ((self.dual * other.real) - (self.real * other.dual)) / (other.real * other.real))
    }
}

#[test]
fn test_div() {
    let x = Dual::new(3.0, 4.0);
    let y = Dual::new(1.0, 2.0);

    let z = x / y;
    assert!(z.real == 3.0);
    assert!(z.dual == -2.0);
}

impl<F: Copy + Float> Dual<F> {
    pub fn sin(self) -> Dual<F> {
        Dual::new(self.real.sin(), self.dual * self.real.cos())
    }

    pub fn cos(self) -> Dual<F> {
        Dual::new(self.real.cos(), (-F::one()) * self.dual * self.real.sin())
    }

    pub fn tan(self) -> Dual<F> {
        self.sin() / self.cos()
    }

    pub fn exp(self) -> Dual<F> {
        Dual::new(self.real.exp(), self.dual * self.real.exp())
    }

    pub fn ln(self) -> Dual<F> {
        Dual::new(self.real.ln(), self.dual / self.real)
    }

    pub fn sqrt(self) -> Dual<F> {
        let two = F::one() + F::one();
        Dual::new(self.real.sqrt(),
                  self.dual / (two * self.real.sqrt()))
    }
}

impl<F: Copy + Num> From<F> for Dual<F> {
    fn from(real: F) -> Dual<F> {
        Dual::new(real, F::one())
    }
}

impl<F> fmt::Display for Dual<F>
    where F: fmt::Display + Num + PartialOrd + Copy
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.real < Zero::zero() {
            write!(f, "{}-{}ε", self.real, F::zero() - self.dual)
        } else {
            write!(f, "{}+{}ε", self.real, self.dual)
        }
    }
}

#[cfg(test)]
fn diff(x : f32, y : f32) -> f32 {
    (x - y).abs()
}

#[test]
fn test_sin() {
    let x: Dual32 = From::from(0.0);
    let y = x.sin();

    let real_diff = diff(y.real, 0.0);
    let dual_diff = diff(y.dual, 1.0);

    assert!(real_diff < f32::EPSILON);
    assert!(dual_diff < f32::EPSILON);
}

#[test]
fn test_cos() {
    let x: Dual32 = From::from(consts::PI);
    let y = x.cos();

    let real_diff = diff(y.real, -1.0);
    let dual_diff = diff(y.dual, 0.0);

    assert!(real_diff < f32::EPSILON);
    assert!(dual_diff < f32::EPSILON);
}

#[test]
fn test_tan() {
    let x: Dual32 = From::from(0.0);
    let y = x.tan();

    let real_diff = diff(y.real, 0.0);
    let dual_diff = diff(y.dual, 1.0);

    assert!(real_diff < f32::EPSILON);
    assert!(dual_diff < f32::EPSILON);
}

#[test]
fn test_exp() {
    let x: Dual32 = From::from(1.0);
    let y = x.exp();

    let real_diff = diff(y.real, consts::E);
    let dual_diff = diff(y.dual, consts::E);

    assert!(real_diff < f32::EPSILON);
    assert!(dual_diff < f32::EPSILON);
}

#[test]
fn test_ln() {
    let x: Dual32 = From::from(1.0);
    let y = x.ln();

    let real_diff = diff(y.real, 0.0);
    let dual_diff = diff(y.dual, 1.0);

    assert!(real_diff < f32::EPSILON);
    assert!(dual_diff < f32::EPSILON);
}

#[test]
fn test_sqrt() {
    let x: Dual32 = From::from(4.0);
    let y = x.sqrt();

    println!("{}", y);

    let real_diff = diff(y.real, 2.0);
    let dual_diff = diff(y.dual, 0.25);

    assert!(real_diff < f32::EPSILON);
    assert!(dual_diff < f32::EPSILON);
}
<|endoftext|>