<commit_before>#![feature(rustc_private, decl_macro, never_type, hash_drain_filter, vec_into_raw_parts)]
#![warn(rust_2018_idioms)]
#![warn(unused_lifetimes)]
#![warn(unreachable_pub)]

extern crate snap;
#[macro_use]
extern crate rustc_middle;
extern crate rustc_ast;
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_session;
extern crate rustc_span;
extern crate rustc_target;

// 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_codegen_ssa::traits::CodegenBackend;
use rustc_codegen_ssa::CodegenResults;
use rustc_errors::ErrorReported;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_middle::middle::cstore::EncodedMetadata;
use rustc_session::config::OutputFilenames;
use rustc_session::Session;

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

pub use crate::config::*;
use crate::prelude::*;

mod abi;
mod allocator;
mod analyze;
mod archive;
mod backend;
mod base;
mod cast;
mod codegen_i128;
mod common;
mod compiler_builtins;
mod config;
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 toolchain;
mod trap;
mod unsize;
mod value_and_place;
mod vtable;

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

    pub(crate) use rustc_span::Span;

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

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

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

    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::ir::{
        AbiParam, Block, ExternalName, FuncRef, Inst, InstBuilder, MemFlags, Signature, SourceLoc,
        StackSlot, StackSlotData, StackSlotKind, TrapCode, Type, Value,
    };
    pub(crate) use cranelift_codegen::isa::{self, CallConv};
    pub(crate) use cranelift_codegen::Context;
    pub(crate) use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable};
    pub(crate) use cranelift_module::{self, DataContext, DataId, FuncId, Linkage, Module};

    pub(crate) use crate::abi::*;
    pub(crate) use crate::base::{codegen_operand, codegen_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)());
        }
    }
}

/// The codegen context holds any information shared between the codegen of individual functions
/// inside a single codegen unit with the exception of the Cranelift [`Module`](cranelift_module::Module).
struct CodegenCx<'tcx> {
    tcx: TyCtxt<'tcx>,
    global_asm: String,
    cached_context: Context,
    debug_context: Option<DebugContext<'tcx>>,
    unwind_context: UnwindContext,
}

impl<'tcx> CodegenCx<'tcx> {
    fn new(
        tcx: TyCtxt<'tcx>,
        backend_config: BackendConfig,
        isa: &dyn TargetIsa,
        debug_info: bool,
    ) -> Self {
        assert_eq!(pointer_ty(tcx), isa.pointer_type());

        let unwind_context =
            UnwindContext::new(tcx, isa, matches!(backend_config.codegen_mode, CodegenMode::Aot));
        let debug_context = if debug_info { Some(DebugContext::new(tcx, isa)) } else { None };
        CodegenCx {
            tcx,
            global_asm: String::new(),
            cached_context: Context::new(),
            debug_context,
            unwind_context,
        }
    }
}

pub struct CraneliftCodegenBackend {
    pub config: Option<BackendConfig>,
}

impl CodegenBackend for CraneliftCodegenBackend {
    fn init(&self, sess: &Session) {
        use rustc_session::config::Lto;
        match sess.lto() {
            Lto::No | Lto::ThinLocal => {}
            Lto::Thin | Lto::Fat => sess.warn("LTO is not supported. You may get a linker error."),
        }
    }

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

    fn codegen_crate(
        &self,
        tcx: TyCtxt<'_>,
        metadata: EncodedMetadata,
        need_metadata_module: bool,
    ) -> Box<dyn Any> {
        tcx.sess.abort_if_errors();
        let config = if let Some(config) = self.config.clone() {
            config
        } else {
            BackendConfig::from_opts(&tcx.sess.opts.cg.llvm_args)
                .unwrap_or_else(|err| tcx.sess.fatal(&err))
        };
        match config.codegen_mode {
            CodegenMode::Aot => driver::aot::run_aot(tcx, config, metadata, need_metadata_module),
            CodegenMode::Jit | CodegenMode::JitLazy => {
                #[cfg(feature = "jit")]
                let _: ! = driver::jit::run_jit(tcx, config);

                #[cfg(not(feature = "jit"))]
                tcx.sess.fatal("jit support was disabled when compiling rustc_codegen_cranelift");
            }
        }
    }

    fn join_codegen(
        &self,
        ongoing_codegen: Box<dyn Any>,
        _sess: &Session,
    ) -> Result<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>), ErrorReported> {
        Ok(*ongoing_codegen
            .downcast::<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>)>()
            .unwrap())
    }

    fn link(
        &self,
        sess: &Session,
        codegen_results: CodegenResults,
        outputs: &OutputFilenames,
    ) -> Result<(), ErrorReported> {
        use rustc_codegen_ssa::back::link::link_binary;

        link_binary::<crate::archive::ArArchiveBuilder<'_>>(
            sess,
            &codegen_results,
            outputs,
            &codegen_results.crate_name.as_str(),
        );

        Ok(())
    }
}

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

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

    let target_triple = crate::target_triple(sess);

    let mut flags_builder = settings::builder();
    flags_builder.enable("is_pic").unwrap();
    flags_builder.set("enable_probestack", "false").unwrap(); // __cranelift_probestack is not provided
    let enable_verifier = if backend_config.enable_verifier { "true" } else { "false" };
    flags_builder.set("enable_verifier", enable_verifier).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();

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

    flags_builder.set("regalloc", &backend_config.regalloc).unwrap();

    use rustc_session::config::OptLevel;
    match sess.opts.optimize {
        OptLevel::No => {
            flags_builder.set("opt_level", "none").unwrap();
        }
        OptLevel::Less | OptLevel::Default => {}
        OptLevel::Size | OptLevel::SizeMin | OptLevel::Aggressive => {
            flags_builder.set("opt_level", "speed_and_size").unwrap();
        }
    }

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

    let variant = cranelift_codegen::isa::BackendVariant::MachInst;

    let isa_builder = match sess.opts.cg.target_cpu.as_deref() {
        Some("native") => {
            let builder = cranelift_native::builder_with_options(variant, true).unwrap();
            builder
        }
        Some(value) => {
            let mut builder =
                cranelift_codegen::isa::lookup_variant(target_triple, variant).unwrap();
            if let Err(_) = builder.enable(value) {
                sess.fatal("The specified target cpu isn't currently supported by Cranelift.");
            }
            builder
        }
        None => {
            let mut builder =
                cranelift_codegen::isa::lookup_variant(target_triple, variant).unwrap();
            // Don't use "haswell" as the default, as it implies `has_lzcnt`.
            // macOS CI is still at Ivy Bridge EP, so `lzcnt` is interpreted as `bsr`.
            builder.enable("nehalem").unwrap();
            builder
        }
    };

    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 { config: None })
}
<commit_msg>Allow printing the version of the default codegen backend if it isn't llvm<commit_after>#![feature(rustc_private, decl_macro, never_type, hash_drain_filter, vec_into_raw_parts)]
#![warn(rust_2018_idioms)]
#![warn(unused_lifetimes)]
#![warn(unreachable_pub)]

extern crate snap;
#[macro_use]
extern crate rustc_middle;
extern crate rustc_ast;
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_session;
extern crate rustc_span;
extern crate rustc_target;

// 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_codegen_ssa::traits::CodegenBackend;
use rustc_codegen_ssa::CodegenResults;
use rustc_errors::ErrorReported;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_middle::middle::cstore::EncodedMetadata;
use rustc_session::config::OutputFilenames;
use rustc_session::Session;

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

pub use crate::config::*;
use crate::prelude::*;

mod abi;
mod allocator;
mod analyze;
mod archive;
mod backend;
mod base;
mod cast;
mod codegen_i128;
mod common;
mod compiler_builtins;
mod config;
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 toolchain;
mod trap;
mod unsize;
mod value_and_place;
mod vtable;

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

    pub(crate) use rustc_span::Span;

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

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

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

    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::ir::{
        AbiParam, Block, ExternalName, FuncRef, Inst, InstBuilder, MemFlags, Signature, SourceLoc,
        StackSlot, StackSlotData, StackSlotKind, TrapCode, Type, Value,
    };
    pub(crate) use cranelift_codegen::isa::{self, CallConv};
    pub(crate) use cranelift_codegen::Context;
    pub(crate) use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable};
    pub(crate) use cranelift_module::{self, DataContext, DataId, FuncId, Linkage, Module};

    pub(crate) use crate::abi::*;
    pub(crate) use crate::base::{codegen_operand, codegen_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)());
        }
    }
}

/// The codegen context holds any information shared between the codegen of individual functions
/// inside a single codegen unit with the exception of the Cranelift [`Module`](cranelift_module::Module).
struct CodegenCx<'tcx> {
    tcx: TyCtxt<'tcx>,
    global_asm: String,
    cached_context: Context,
    debug_context: Option<DebugContext<'tcx>>,
    unwind_context: UnwindContext,
}

impl<'tcx> CodegenCx<'tcx> {
    fn new(
        tcx: TyCtxt<'tcx>,
        backend_config: BackendConfig,
        isa: &dyn TargetIsa,
        debug_info: bool,
    ) -> Self {
        assert_eq!(pointer_ty(tcx), isa.pointer_type());

        let unwind_context =
            UnwindContext::new(tcx, isa, matches!(backend_config.codegen_mode, CodegenMode::Aot));
        let debug_context = if debug_info { Some(DebugContext::new(tcx, isa)) } else { None };
        CodegenCx {
            tcx,
            global_asm: String::new(),
            cached_context: Context::new(),
            debug_context,
            unwind_context,
        }
    }
}

pub struct CraneliftCodegenBackend {
    pub config: Option<BackendConfig>,
}

impl CodegenBackend for CraneliftCodegenBackend {
    fn init(&self, sess: &Session) {
        use rustc_session::config::Lto;
        match sess.lto() {
            Lto::No | Lto::ThinLocal => {}
            Lto::Thin | Lto::Fat => sess.warn("LTO is not supported. You may get a linker error."),
        }
    }

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

    fn print_version(&self) {
        println!("Cranelift version: {}", cranelift_codegen::VERSION);
    }

    fn codegen_crate(
        &self,
        tcx: TyCtxt<'_>,
        metadata: EncodedMetadata,
        need_metadata_module: bool,
    ) -> Box<dyn Any> {
        tcx.sess.abort_if_errors();
        let config = if let Some(config) = self.config.clone() {
            config
        } else {
            BackendConfig::from_opts(&tcx.sess.opts.cg.llvm_args)
                .unwrap_or_else(|err| tcx.sess.fatal(&err))
        };
        match config.codegen_mode {
            CodegenMode::Aot => driver::aot::run_aot(tcx, config, metadata, need_metadata_module),
            CodegenMode::Jit | CodegenMode::JitLazy => {
                #[cfg(feature = "jit")]
                let _: ! = driver::jit::run_jit(tcx, config);

                #[cfg(not(feature = "jit"))]
                tcx.sess.fatal("jit support was disabled when compiling rustc_codegen_cranelift");
            }
        }
    }

    fn join_codegen(
        &self,
        ongoing_codegen: Box<dyn Any>,
        _sess: &Session,
    ) -> Result<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>), ErrorReported> {
        Ok(*ongoing_codegen
            .downcast::<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>)>()
            .unwrap())
    }

    fn link(
        &self,
        sess: &Session,
        codegen_results: CodegenResults,
        outputs: &OutputFilenames,
    ) -> Result<(), ErrorReported> {
        use rustc_codegen_ssa::back::link::link_binary;

        link_binary::<crate::archive::ArArchiveBuilder<'_>>(
            sess,
            &codegen_results,
            outputs,
            &codegen_results.crate_name.as_str(),
        );

        Ok(())
    }
}

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

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

    let target_triple = crate::target_triple(sess);

    let mut flags_builder = settings::builder();
    flags_builder.enable("is_pic").unwrap();
    flags_builder.set("enable_probestack", "false").unwrap(); // __cranelift_probestack is not provided
    let enable_verifier = if backend_config.enable_verifier { "true" } else { "false" };
    flags_builder.set("enable_verifier", enable_verifier).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();

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

    flags_builder.set("regalloc", &backend_config.regalloc).unwrap();

    use rustc_session::config::OptLevel;
    match sess.opts.optimize {
        OptLevel::No => {
            flags_builder.set("opt_level", "none").unwrap();
        }
        OptLevel::Less | OptLevel::Default => {}
        OptLevel::Size | OptLevel::SizeMin | OptLevel::Aggressive => {
            flags_builder.set("opt_level", "speed_and_size").unwrap();
        }
    }

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

    let variant = cranelift_codegen::isa::BackendVariant::MachInst;

    let isa_builder = match sess.opts.cg.target_cpu.as_deref() {
        Some("native") => {
            let builder = cranelift_native::builder_with_options(variant, true).unwrap();
            builder
        }
        Some(value) => {
            let mut builder =
                cranelift_codegen::isa::lookup_variant(target_triple, variant).unwrap();
            if let Err(_) = builder.enable(value) {
                sess.fatal("The specified target cpu isn't currently supported by Cranelift.");
            }
            builder
        }
        None => {
            let mut builder =
                cranelift_codegen::isa::lookup_variant(target_triple, variant).unwrap();
            // Don't use "haswell" as the default, as it implies `has_lzcnt`.
            // macOS CI is still at Ivy Bridge EP, so `lzcnt` is interpreted as `bsr`.
            builder.enable("nehalem").unwrap();
            builder
        }
    };

    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 { config: None })
}
<|endoftext|>


<commit_before>//! # Console progress bar for Rust
//!
//! Console progress bar for Rust Inspired from [pb](http://github.com/cheggaaa/pb).
//! support and tested on MacOS and Linux(should work on Windows too, but not tested yet).
//!
//! ![Screenshot](https://raw.githubusercontent.com/a8m/pb/master/gif/rec_v2.gif)
//!
//! ### Examples
//! 1. simple example
//!
//! ```no_run
//! extern crate pbr;
//!
//! use pbr::ProgressBar;
//! use std::thread;
//!
//! fn main() {
//!     let count = 1000;
//!     let mut pb = ProgressBar::new(count);
//!     for _ in 0..count {
//!         pb.inc();
//!         thread::sleep_ms(200);
//!     }
//!     println!("done!");
//! }
//! ```
//!
//! 2. Broadcast writing(simple file copying)
//!
//! ```ignore
//! #![feature(io)]
//! extern crate pbr;
//!
//! use std::io::copy;
//! use std::io::prelude::*;
//! use std::fs::File;
//! use pbr::{ProgressBar, Units};
//!
//! fn main() {
//!     let mut file = File::open("/usr/share/dict/words").unwrap();
//!     let n_bytes = file.metadata().unwrap().len() as usize;
//!     let mut pb = ProgressBar::new(n_bytes);
//!     pb.set_units(Units::Bytes);
//!     let mut handle = File::create("copy-words").unwrap().broadcast(&mut pb);
//!     copy(&mut file, &mut handle).unwrap();
//!     println!("done!");
//! }
//! ```
extern crate time;
mod tty;
mod pb;
pub use pb::{ProgressBar, Units};
use std::io::{Write, Stdout, stdout};

pub struct PbIter<T, I>
where I: Iterator,
      T: Write
{
    iter: I,
    progress_bar: ProgressBar<T>,
}

impl<I> PbIter<Stdout, I>
where I: Iterator
{
    pub fn new(iter: I) -> Self {
        Self::on(stdout(), iter)
    }
}

impl<T, I> PbIter<T, I>
where I: Iterator,
      T: Write
{
    pub fn on(handle: T, iter: I) -> Self {
        let size = iter.size_hint().0;
        PbIter {iter: iter, progress_bar: ProgressBar::on(handle, size as u64)}
    }
}

impl<T, I> Iterator for PbIter<T, I>
where I: Iterator,
      T: Write
{
    type Item = I::Item;

    fn next(&mut self) -> Option<I::Item> {
        match self.iter.next() {
            Some(i) => {
                self.progress_bar.inc();
                Some(i)
            }
            None => None,
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}
<commit_msg>fix: docs heading<commit_after>//! # Console progress bar for Rust
//!
//! Console progress bar for Rust Inspired from [pb](http://github.com/cheggaaa/pb).
//! support and tested on MacOS, Linux and Window
//!
//! ![Screenshot](https://raw.githubusercontent.com/a8m/pb/master/gif/rec_v2.gif)
//!
//! ### Examples
//! 1. simple example
//!
//! ```no_run
//! extern crate pbr;
//!
//! use pbr::ProgressBar;
//! use std::thread;
//!
//! fn main() {
//!     let count = 1000;
//!     let mut pb = ProgressBar::new(count);
//!     for _ in 0..count {
//!         pb.inc();
//!         thread::sleep_ms(200);
//!     }
//!     println!("done!");
//! }
//! ```
//!
//! 2. Broadcast writing(simple file copying)
//!
//! ```ignore
//! #![feature(io)]
//! extern crate pbr;
//!
//! use std::io::copy;
//! use std::io::prelude::*;
//! use std::fs::File;
//! use pbr::{ProgressBar, Units};
//!
//! fn main() {
//!     let mut file = File::open("/usr/share/dict/words").unwrap();
//!     let n_bytes = file.metadata().unwrap().len() as usize;
//!     let mut pb = ProgressBar::new(n_bytes);
//!     pb.set_units(Units::Bytes);
//!     let mut handle = File::create("copy-words").unwrap().broadcast(&mut pb);
//!     copy(&mut file, &mut handle).unwrap();
//!     println!("done!");
//! }
//! ```
extern crate time;
mod tty;
mod pb;
pub use pb::{ProgressBar, Units};
use std::io::{Write, Stdout, stdout};

pub struct PbIter<T, I>
where I: Iterator,
      T: Write
{
    iter: I,
    progress_bar: ProgressBar<T>,
}

impl<I> PbIter<Stdout, I>
where I: Iterator
{
    pub fn new(iter: I) -> Self {
        Self::on(stdout(), iter)
    }
}

impl<T, I> PbIter<T, I>
where I: Iterator,
      T: Write
{
    pub fn on(handle: T, iter: I) -> Self {
        let size = iter.size_hint().0;
        PbIter {iter: iter, progress_bar: ProgressBar::on(handle, size as u64)}
    }
}

impl<T, I> Iterator for PbIter<T, I>
where I: Iterator,
      T: Write
{
    type Item = I::Item;

    fn next(&mut self) -> Option<I::Item> {
        match self.iter.next() {
            Some(i) => {
                self.progress_bar.inc();
                Some(i)
            }
            None => None,
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}
<|endoftext|>


<commit_before>//! Crate `retry` provides utilities for retrying operations that can fail.
//!
//! # Usage
//!
//! Retry an operation using the `retry` function. `retry` accepts an iterator over `Duration`s and
//! a closure that returns a `Result` (or `OperationResult`; see below). The iterator is used to
//! determine how long to wait after each unsuccessful try and how many times to try before giving
//! up and returning `Result::Err`. The closure determines either the final successful value, or
//! an error value, which can either be returned immediately or used to indicate that the
//! operation should be retried.
//!
//! Any type that implements `Iterator<Item = Duration>` can be used to determine retry behavior,
//! though a few useful implementations are provided in the `delay` module, including a fixed delay
//! and exponential back-off.
//!
//! ```
//! # use retry::retry;
//! # use retry::delay::Fixed;
//! let mut collection = vec![1, 2, 3].into_iter();
//!
//! let result = retry(Fixed::from_millis(100), || {
//!     match collection.next() {
//!         Some(n) if n == 3 => Ok("n is 3!"),
//!         Some(_) => Err("n must be 3!"),
//!         None => Err("n was never 3!"),
//!     }
//! });
//!
//! assert!(result.is_ok());
//! ```
//!
//! The `Iterator` API can be used to limit or modify the delay strategy. For example, to limit the
//! number of retries to 1:
//!
//! ```
//! # use retry::retry;
//! # use retry::delay::Fixed;
//! let mut collection = vec![1, 2, 3].into_iter();
//!
//! let result = retry(Fixed::from_millis(100).take(1), || {
//!     match collection.next() {
//!         Some(n) if n == 3 => Ok("n is 3!"),
//!         Some(_) => Err("n must be 3!"),
//!         None => Err("n was never 3!"),
//!     }
//! });
//!
//! assert!(result.is_err());
//! ```
//!
//! To apply random jitter to any delay strategy, the `jitter` function can be used in combination
//! with the `Iterator` API:
//!
//! ```
//! # use retry::retry;
//! # use retry::delay::{Exponential, jitter};
//! let mut collection = vec![1, 2, 3].into_iter();
//!
//! let result = retry(Exponential::from_millis(10).map(jitter).take(3), || {
//!     match collection.next() {
//!         Some(n) if n == 3 => Ok("n is 3!"),
//!         Some(_) => Err("n must be 3!"),
//!         None => Err("n was never 3!"),
//!     }
//! });
//!
//! assert!(result.is_ok());
//! ```
//!
//! To deal with fatal errors, return `retry::OperationResult`, which is like std's `Result`, but
//! with a third case to distinguish between errors that should cause a retry and errors that
//! should immediately return, halting retry behavior. (Internally, `OperationResult` is always
//! used, and closures passed to `retry` that return plain `Result` are converted into
//! `OperationResult`.)
//!
//! ```
//! # use retry::retry;
//! # use retry::delay::Fixed;
//! use retry::OperationResult;
//! let mut collection = vec![1, 2].into_iter();
//! let value = retry(Fixed::from_millis(1), || {
//!     match collection.next() {
//!         Some(n) if n == 2 => OperationResult::Ok(n),
//!         Some(_) => OperationResult::Retry("not 2"),
//!         None => OperationResult::Err("not found"),
//!     }
//! }).unwrap();
//!
//! assert_eq!(value, 2);
//! ```

#![deny(missing_debug_implementations, missing_docs, warnings)]

use std::{
    error::Error as StdError,
    fmt::{Display, Error as FmtError, Formatter},
    thread::sleep,
    time::Duration,
};

pub mod delay;
mod opresult;

#[doc(inline)]
pub use opresult::OperationResult;

/// Retry the given operation synchronously until it succeeds, or until the given `Duration`
/// iterator ends.
pub fn retry<I, O, R, E, OR>(iterable: I, mut operation: O) -> Result<R, Error<E>>
where
    I: IntoIterator<Item = Duration>,
    O: FnMut() -> OR,
    OR: Into<OperationResult<R, E>>,
{
    let mut iterator = iterable.into_iter();
    let mut current_try = 1;
    let mut total_delay = Duration::default();

    loop {
        match operation().into() {
            OperationResult::Ok(value) => return Ok(value),
            OperationResult::Retry(error) => {
                if let Some(delay) = iterator.next() {
                    sleep(delay);
                    current_try += 1;
                    total_delay += delay;
                } else {
                    return Err(Error::Operation {
                        error,
                        total_delay,
                        tries: current_try,
                    });
                }
            }
            OperationResult::Err(error) => {
                return Err(Error::Operation {
                    error,
                    total_delay,
                    tries: current_try,
                });
            }
        }
    }
}

/// Retry with iteration number. See also [retry](fn.retry.html)
pub fn retryi<I, O, R, E, OR>(iterable: I, mut operation: O) -> Result<R, Error<E>>
where
    I: IntoIterator<Item = Duration>,
    O: FnMut(u64) -> OR,
    OR: Into<OperationResult<R, E>>,
{
    let mut iterator = iterable.into_iter();
    let mut current_try = 1;
    let mut total_delay = Duration::default();

    loop {
        match operation(current_try).into() {
            OperationResult::Ok(value) => return Ok(value),
            OperationResult::Retry(error) => {
                if let Some(delay) = iterator.next() {
                    sleep(delay);
                    current_try += 1;
                    total_delay += delay;
                } else {
                    return Err(Error::Operation {
                        error,
                        total_delay,
                        tries: current_try,
                    });
                }
            }
            OperationResult::Err(error) => {
                return Err(Error::Operation {
                    error,
                    total_delay,
                    tries: current_try,
                });
            }
        }
    }
}

/// An error with a retryable operation.
#[derive(Debug, PartialEq, Eq)]
pub enum Error<E> {
    /// The operation's last error, plus the number of times the operation was tried and the
    /// duration spent waiting between tries.
    Operation {
        /// The error returned by the operation on the last try.
        error: E,
        /// The duration spent waiting between retries of the operation.
        ///
        /// Note that this does not include the time spent running the operation itself.
        total_delay: Duration,
        /// The total number of times the operation was tried.
        tries: u64,
    },
    /// Something went wrong in the internal logic.
    Internal(String),
}

impl<E> Display for Error<E>
where
    E: StdError,
{
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), FmtError> {
        write!(formatter, "{}", self.description())
    }
}

impl<E> StdError for Error<E>
where
    E: StdError,
{
    fn description(&self) -> &str {
        match *self {
            Error::Operation { ref error, .. } => error.description(),
            Error::Internal(ref description) => description,
        }
    }

    fn cause(&self) -> Option<&dyn StdError> {
        match *self {
            Error::Operation { ref error, .. } => Some(error),
            Error::Internal(_) => None,
        }
    }
}

#[cfg(test)]
mod tests {
    use std::time::Duration;

    use super::delay::{Exponential, Fixed, NoDelay, Range};
    use super::opresult::OperationResult;
    use super::{retry, Error};

    #[test]
    fn succeeds_with_infinite_retries() {
        let mut collection = vec![1, 2, 3, 4, 5].into_iter();

        let value = retry(NoDelay, || match collection.next() {
            Some(n) if n == 5 => Ok(n),
            Some(_) => Err("not 5"),
            None => Err("not 5"),
        })
        .unwrap();

        assert_eq!(value, 5);
    }

    #[test]
    fn succeeds_with_maximum_retries() {
        let mut collection = vec![1, 2].into_iter();

        let value = retry(NoDelay.take(1), || match collection.next() {
            Some(n) if n == 2 => Ok(n),
            Some(_) => Err("not 2"),
            None => Err("not 2"),
        })
        .unwrap();

        assert_eq!(value, 2);
    }

    #[test]
    fn fails_after_last_try() {
        let mut collection = vec![1].into_iter();

        let res = retry(NoDelay.take(1), || match collection.next() {
            Some(n) if n == 2 => Ok(n),
            Some(_) => Err("not 2"),
            None => Err("not 2"),
        });

        assert_eq!(
            res,
            Err(Error::Operation {
                error: "not 2",
                tries: 2,
                total_delay: Duration::from_millis(0)
            })
        );
    }

    #[test]
    fn fatal_errors() {
        let mut collection = vec![1].into_iter();

        let res = retry(NoDelay.take(2), || match collection.next() {
            Some(n) if n == 2 => OperationResult::Ok(n),
            Some(_) => OperationResult::Err("no retry"),
            None => OperationResult::Err("not 2"),
        });

        assert_eq!(
            res,
            Err(Error::Operation {
                error: "no retry",
                tries: 1,
                total_delay: Duration::from_millis(0)
            })
        );
    }

    #[test]
    fn succeeds_with_fixed_delay() {
        let mut collection = vec![1, 2].into_iter();

        let value = retry(Fixed::from_millis(1), || match collection.next() {
            Some(n) if n == 2 => Ok(n),
            Some(_) => Err("not 2"),
            None => Err("not 2"),
        })
        .unwrap();

        assert_eq!(value, 2);
    }

    #[test]
    fn fixed_delay_from_duration() {
        assert_eq!(
            Fixed::from_millis(1_000).next(),
            Fixed::from(Duration::from_secs(1)).next(),
        );
    }

    #[test]
    fn succeeds_with_exponential_delay() {
        let mut collection = vec![1, 2].into_iter();

        let value = retry(Exponential::from_millis(1), || match collection.next() {
            Some(n) if n == 2 => Ok(n),
            Some(_) => Err("not 2"),
            None => Err("not 2"),
        })
        .unwrap();

        assert_eq!(value, 2);
    }

    #[test]
    fn succeeds_with_ranged_delay() {
        let mut collection = vec![1, 2].into_iter();

        let value = retry(Range::from_millis_exclusive(1, 10), || {
            match collection.next() {
                Some(n) if n == 2 => Ok(n),
                Some(_) => Err("not 2"),
                None => Err("not 2"),
            }
        })
        .unwrap();

        assert_eq!(value, 2);
    }
}
<commit_msg>unify the implementation of retry*<commit_after>//! Crate `retry` provides utilities for retrying operations that can fail.
//!
//! # Usage
//!
//! Retry an operation using the `retry` function. `retry` accepts an iterator over `Duration`s and
//! a closure that returns a `Result` (or `OperationResult`; see below). The iterator is used to
//! determine how long to wait after each unsuccessful try and how many times to try before giving
//! up and returning `Result::Err`. The closure determines either the final successful value, or
//! an error value, which can either be returned immediately or used to indicate that the
//! operation should be retried.
//!
//! Any type that implements `Iterator<Item = Duration>` can be used to determine retry behavior,
//! though a few useful implementations are provided in the `delay` module, including a fixed delay
//! and exponential back-off.
//!
//! ```
//! # use retry::retry;
//! # use retry::delay::Fixed;
//! let mut collection = vec![1, 2, 3].into_iter();
//!
//! let result = retry(Fixed::from_millis(100), || {
//!     match collection.next() {
//!         Some(n) if n == 3 => Ok("n is 3!"),
//!         Some(_) => Err("n must be 3!"),
//!         None => Err("n was never 3!"),
//!     }
//! });
//!
//! assert!(result.is_ok());
//! ```
//!
//! The `Iterator` API can be used to limit or modify the delay strategy. For example, to limit the
//! number of retries to 1:
//!
//! ```
//! # use retry::retry;
//! # use retry::delay::Fixed;
//! let mut collection = vec![1, 2, 3].into_iter();
//!
//! let result = retry(Fixed::from_millis(100).take(1), || {
//!     match collection.next() {
//!         Some(n) if n == 3 => Ok("n is 3!"),
//!         Some(_) => Err("n must be 3!"),
//!         None => Err("n was never 3!"),
//!     }
//! });
//!
//! assert!(result.is_err());
//! ```
//!
//! To apply random jitter to any delay strategy, the `jitter` function can be used in combination
//! with the `Iterator` API:
//!
//! ```
//! # use retry::retry;
//! # use retry::delay::{Exponential, jitter};
//! let mut collection = vec![1, 2, 3].into_iter();
//!
//! let result = retry(Exponential::from_millis(10).map(jitter).take(3), || {
//!     match collection.next() {
//!         Some(n) if n == 3 => Ok("n is 3!"),
//!         Some(_) => Err("n must be 3!"),
//!         None => Err("n was never 3!"),
//!     }
//! });
//!
//! assert!(result.is_ok());
//! ```
//!
//! To deal with fatal errors, return `retry::OperationResult`, which is like std's `Result`, but
//! with a third case to distinguish between errors that should cause a retry and errors that
//! should immediately return, halting retry behavior. (Internally, `OperationResult` is always
//! used, and closures passed to `retry` that return plain `Result` are converted into
//! `OperationResult`.)
//!
//! ```
//! # use retry::retry;
//! # use retry::delay::Fixed;
//! use retry::OperationResult;
//! let mut collection = vec![1, 2].into_iter();
//! let value = retry(Fixed::from_millis(1), || {
//!     match collection.next() {
//!         Some(n) if n == 2 => OperationResult::Ok(n),
//!         Some(_) => OperationResult::Retry("not 2"),
//!         None => OperationResult::Err("not found"),
//!     }
//! }).unwrap();
//!
//! assert_eq!(value, 2);
//! ```

#![deny(missing_debug_implementations, missing_docs, warnings)]

use std::{
    error::Error as StdError,
    fmt::{Display, Error as FmtError, Formatter},
    thread::sleep,
    time::Duration,
};

pub mod delay;
mod opresult;

#[doc(inline)]
pub use opresult::OperationResult;

/// Retry the given operation synchronously until it succeeds, or until the given `Duration`
/// iterator ends.
pub fn retry<I, O, R, E, OR>(iterable: I, mut operation: O) -> Result<R, Error<E>>
where
    I: IntoIterator<Item = Duration>,
    O: FnMut() -> OR,
    OR: Into<OperationResult<R, E>>,
{
    retryi(iterable, |_| operation())
}

/// Retry with iteration number. See also [retry](fn.retry.html)
pub fn retryi<I, O, R, E, OR>(iterable: I, mut operation: O) -> Result<R, Error<E>>
where
    I: IntoIterator<Item = Duration>,
    O: FnMut(u64) -> OR,
    OR: Into<OperationResult<R, E>>,
{
    let mut iterator = iterable.into_iter();
    let mut current_try = 1;
    let mut total_delay = Duration::default();

    loop {
        match operation(current_try).into() {
            OperationResult::Ok(value) => return Ok(value),
            OperationResult::Retry(error) => {
                if let Some(delay) = iterator.next() {
                    sleep(delay);
                    current_try += 1;
                    total_delay += delay;
                } else {
                    return Err(Error::Operation {
                        error,
                        total_delay,
                        tries: current_try,
                    });
                }
            }
            OperationResult::Err(error) => {
                return Err(Error::Operation {
                    error,
                    total_delay,
                    tries: current_try,
                });
            }
        }
    }
}

/// An error with a retryable operation.
#[derive(Debug, PartialEq, Eq)]
pub enum Error<E> {
    /// The operation's last error, plus the number of times the operation was tried and the
    /// duration spent waiting between tries.
    Operation {
        /// The error returned by the operation on the last try.
        error: E,
        /// The duration spent waiting between retries of the operation.
        ///
        /// Note that this does not include the time spent running the operation itself.
        total_delay: Duration,
        /// The total number of times the operation was tried.
        tries: u64,
    },
    /// Something went wrong in the internal logic.
    Internal(String),
}

impl<E> Display for Error<E>
where
    E: StdError,
{
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), FmtError> {
        write!(formatter, "{}", self.description())
    }
}

impl<E> StdError for Error<E>
where
    E: StdError,
{
    fn description(&self) -> &str {
        match *self {
            Error::Operation { ref error, .. } => error.description(),
            Error::Internal(ref description) => description,
        }
    }

    fn cause(&self) -> Option<&dyn StdError> {
        match *self {
            Error::Operation { ref error, .. } => Some(error),
            Error::Internal(_) => None,
        }
    }
}

#[cfg(test)]
mod tests {
    use std::time::Duration;

    use super::delay::{Exponential, Fixed, NoDelay, Range};
    use super::opresult::OperationResult;
    use super::{retry, Error};

    #[test]
    fn succeeds_with_infinite_retries() {
        let mut collection = vec![1, 2, 3, 4, 5].into_iter();

        let value = retry(NoDelay, || match collection.next() {
            Some(n) if n == 5 => Ok(n),
            Some(_) => Err("not 5"),
            None => Err("not 5"),
        })
        .unwrap();

        assert_eq!(value, 5);
    }

    #[test]
    fn succeeds_with_maximum_retries() {
        let mut collection = vec![1, 2].into_iter();

        let value = retry(NoDelay.take(1), || match collection.next() {
            Some(n) if n == 2 => Ok(n),
            Some(_) => Err("not 2"),
            None => Err("not 2"),
        })
        .unwrap();

        assert_eq!(value, 2);
    }

    #[test]
    fn fails_after_last_try() {
        let mut collection = vec![1].into_iter();

        let res = retry(NoDelay.take(1), || match collection.next() {
            Some(n) if n == 2 => Ok(n),
            Some(_) => Err("not 2"),
            None => Err("not 2"),
        });

        assert_eq!(
            res,
            Err(Error::Operation {
                error: "not 2",
                tries: 2,
                total_delay: Duration::from_millis(0)
            })
        );
    }

    #[test]
    fn fatal_errors() {
        let mut collection = vec![1].into_iter();

        let res = retry(NoDelay.take(2), || match collection.next() {
            Some(n) if n == 2 => OperationResult::Ok(n),
            Some(_) => OperationResult::Err("no retry"),
            None => OperationResult::Err("not 2"),
        });

        assert_eq!(
            res,
            Err(Error::Operation {
                error: "no retry",
                tries: 1,
                total_delay: Duration::from_millis(0)
            })
        );
    }

    #[test]
    fn succeeds_with_fixed_delay() {
        let mut collection = vec![1, 2].into_iter();

        let value = retry(Fixed::from_millis(1), || match collection.next() {
            Some(n) if n == 2 => Ok(n),
            Some(_) => Err("not 2"),
            None => Err("not 2"),
        })
        .unwrap();

        assert_eq!(value, 2);
    }

    #[test]
    fn fixed_delay_from_duration() {
        assert_eq!(
            Fixed::from_millis(1_000).next(),
            Fixed::from(Duration::from_secs(1)).next(),
        );
    }

    #[test]
    fn succeeds_with_exponential_delay() {
        let mut collection = vec![1, 2].into_iter();

        let value = retry(Exponential::from_millis(1), || match collection.next() {
            Some(n) if n == 2 => Ok(n),
            Some(_) => Err("not 2"),
            None => Err("not 2"),
        })
        .unwrap();

        assert_eq!(value, 2);
    }

    #[test]
    fn succeeds_with_ranged_delay() {
        let mut collection = vec![1, 2].into_iter();

        let value = retry(Range::from_millis_exclusive(1, 10), || {
            match collection.next() {
                Some(n) if n == 2 => Ok(n),
                Some(_) => Err("not 2"),
                None => Err("not 2"),
            }
        })
        .unwrap();

        assert_eq!(value, 2);
    }
}
<|endoftext|>


<commit_before>#![crate_name = "rusoto"]
#![crate_type = "lib"]
#![cfg_attr(feature = "unstable", feature(proc_macro))]
#![cfg_attr(feature = "nightly-testing", feature(plugin))]
#![cfg_attr(feature = "nightly-testing", plugin(clippy))]
#![cfg_attr(feature = "nightly-testing", allow(cyclomatic_complexity, used_underscore_binding, ptr_arg, suspicious_else_formatting))]
#![allow(dead_code)]
#![cfg_attr(not(feature = "unstable"), deny(warnings))]

//! Rusoto is an [AWS](https://aws.amazon.com/) SDK for Rust.
//! A high level overview is available in `README.md` at https://github.com/rusoto/rusoto.
//!
//! # Example
//!
//! The following code shows a simple example of using Rusoto's DynamoDB API to
//! list the names of all tables in a database.
//!
//! ```rust,ignore
//! use std::default::Default;
//!
//! use rusoto::{DefaultCredentialsProvider, Region};
//! use rusoto::dynamodb::{DynamoDbClient, ListTablesInput};
//!
//! let provider = DefaultCredentialsProvider::new().unwrap();
//! let client = DynamoDbClient::new(provider, Region::UsEast1);
//! let list_tables_input: ListTablesInput = Default::default();
//!
//! match client.list_tables(&list_tables_input) {
//!     Ok(output) => {
//!         match output.table_names {
//!             Some(table_name_list) => {
//!                 println!("Tables in database:");
//!
//!                 for table_name in table_name_list {
//!                     println!("{}", table_name);
//!                 }
//!             },
//!             None => println!("No tables in database!"),
//!         }
//!     },
//!     Err(error) => {
//!         println!("Error: {:?}", error);
//!     },
//! }

extern crate chrono;
extern crate hyper;
extern crate hyper_native_tls;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate md5;
extern crate regex;
extern crate ring;
extern crate rusoto_credential;
extern crate rustc_serialize;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate time;
extern crate url;
extern crate xml;

pub use region::{ParseRegionError, Region};
pub use rusoto_credential::{AwsCredentials, ChainProvider, ContainerProvider, CredentialsError,
                            EnvironmentProvider, InstanceMetadataProvider, ProfileProvider,
                            ProvideAwsCredentials, DefaultCredentialsProvider,
                            DefaultCredentialsProviderSync, claims,
                            AutoRefreshingProviderSync, AutoRefreshingProvider,
                            BaseAutoRefreshingProvider};
pub use request::{DispatchSignedRequest, HttpResponse, HttpDispatchError, TlsError};
pub use signature::SignedRequest;
pub use request::default_tls_client;
pub use region::default_region;

mod param;
mod region;
mod request;
mod xmlerror;
mod xmlutil;
mod serialization;
#[macro_use]
mod signature;

#[cfg(test)]
mod mock;

#[cfg(feature = "acm")]
pub mod acm;
#[cfg(feature = "autoscaling")]
pub mod autoscaling;
#[allow(unused_imports)]
#[cfg(feature = "cloudformation")]
pub mod cloudformation;
#[cfg(feature = "cloudfront")]
pub mod cloudfront;
#[cfg(feature = "cloudhsm")]
pub mod cloudhsm;
#[cfg(feature = "cloudsearch")]
pub mod cloudsearch;
#[cfg(feature = "cloudtrail")]
pub mod cloudtrail;
#[cfg(feature = "cloudwatch")]
pub mod cloudwatch;
#[cfg(feature = "codecommit")]
pub mod codecommit;
#[cfg(feature = "codedeploy")]
pub mod codedeploy;
#[cfg(feature = "codepipeline")]
pub mod codepipeline;
#[cfg(feature = "cognito-identity")]
pub mod cognitoidentity;
#[cfg(feature = "config")]
pub mod config;
#[cfg(feature = "datapipeline")]
pub mod datapipeline;
#[cfg(feature = "devicefarm")]
pub mod devicefarm;
#[cfg(feature = "directconnect")]
pub mod directconnect;
#[cfg(feature = "ds")]
pub mod ds;
#[cfg(feature = "dynamodb")]
pub mod dynamodb;
#[cfg(feature = "dynamodbstreams")]
pub mod dynamodbstreams;
#[cfg(feature = "ec2")]
pub mod ec2;
#[cfg(feature = "ecr")]
pub mod ecr;
#[cfg(feature = "ecs")]
pub mod ecs;
#[cfg(feature = "emr")]
pub mod emr;
#[cfg(feature = "elasticache")]
pub mod elasticache;
#[cfg(feature = "elasticbeanstalk")]
pub mod elasticbeanstalk;
#[cfg(feature = "elastictranscoder")]
pub mod elastictranscoder;
#[cfg(feature = "elb")]
pub mod elb;
#[cfg(feature = "elbv2")]
pub mod elbv2;
#[cfg(feature = "events")]
pub mod events;
#[cfg(feature = "firehose")]
pub mod firehose;
#[cfg(feature = "iam")]
pub mod iam;
#[cfg(feature = "importexport")]
pub mod importexport;
#[cfg(feature = "inspector")]
pub mod inspector;
#[cfg(feature = "iot")]
pub mod iot;
#[cfg(feature = "kinesis")]
pub mod kinesis;
#[cfg(feature = "kms")]
pub mod kms;
#[cfg(feature = "lambda")]
pub mod lambda;
#[cfg(feature = "logs")]
pub mod logs;
#[cfg(feature = "machinelearning")]
pub mod machinelearning;
#[cfg(feature = "marketplacecommerceanalytics")]
pub mod marketplacecommerceanalytics;
#[cfg(feature = "opsworks")]
pub mod opsworks;
#[cfg(feature = "redshift")]
pub mod redshift;
#[cfg(feature = "rds")]
pub mod rds;
#[cfg(feature = "route53")]
pub mod route53;
#[cfg(feature = "route53domains")]
pub mod route53domains;
#[cfg(feature = "s3")]
pub mod s3;
#[cfg(feature = "sdb")]
pub mod sdb;
#[cfg(feature = "sns")]
pub mod sns;
#[cfg(feature = "sqs")]
pub mod sqs;
#[cfg(feature = "ssm")]
pub mod ssm;
#[cfg(feature = "storagegateway")]
pub mod storagegateway;
#[cfg(feature = "sts")]
pub mod sts;
#[cfg(feature = "swf")]
pub mod swf;
#[cfg(feature = "waf")]
pub mod waf;
#[cfg(feature = "workspaces")]
pub mod workspaces;

/*
#[cfg(feature = "gamelift")]
pub mod gamelift;
#[cfg(feature = "support")]
pub mod support;
*/
<commit_msg>Proof of concept for building without errors due to unused serde_derive macro.<commit_after>#![crate_name = "rusoto"]
#![crate_type = "lib"]
#![cfg_attr(feature = "unstable", feature(proc_macro))]
#![cfg_attr(feature = "nightly-testing", feature(plugin))]
#![cfg_attr(feature = "nightly-testing", plugin(clippy))]
#![cfg_attr(feature = "nightly-testing", allow(cyclomatic_complexity, used_underscore_binding, ptr_arg, suspicious_else_formatting))]
#![allow(dead_code)]
#![cfg_attr(not(feature = "unstable"), deny(warnings))]

//! Rusoto is an [AWS](https://aws.amazon.com/) SDK for Rust.
//! A high level overview is available in `README.md` at https://github.com/rusoto/rusoto.
//!
//! # Example
//!
//! The following code shows a simple example of using Rusoto's DynamoDB API to
//! list the names of all tables in a database.
//!
//! ```rust,ignore
//! use std::default::Default;
//!
//! use rusoto::{DefaultCredentialsProvider, Region};
//! use rusoto::dynamodb::{DynamoDbClient, ListTablesInput};
//!
//! let provider = DefaultCredentialsProvider::new().unwrap();
//! let client = DynamoDbClient::new(provider, Region::UsEast1);
//! let list_tables_input: ListTablesInput = Default::default();
//!
//! match client.list_tables(&list_tables_input) {
//!     Ok(output) => {
//!         match output.table_names {
//!             Some(table_name_list) => {
//!                 println!("Tables in database:");
//!
//!                 for table_name in table_name_list {
//!                     println!("{}", table_name);
//!                 }
//!             },
//!             None => println!("No tables in database!"),
//!         }
//!     },
//!     Err(error) => {
//!         println!("Error: {:?}", error);
//!     },
//! }

extern crate chrono;
extern crate hyper;
extern crate hyper_native_tls;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate md5;
extern crate regex;
extern crate ring;
extern crate rusoto_credential;
extern crate rustc_serialize;
extern crate serde;
#[cfg(any(feature = "ecs", feature = "all", feature = "packagea", feature = "packageb"))]
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate time;
extern crate url;
extern crate xml;

pub use region::{ParseRegionError, Region};
pub use rusoto_credential::{AwsCredentials, ChainProvider, ContainerProvider, CredentialsError,
                            EnvironmentProvider, InstanceMetadataProvider, ProfileProvider,
                            ProvideAwsCredentials, DefaultCredentialsProvider,
                            DefaultCredentialsProviderSync, claims,
                            AutoRefreshingProviderSync, AutoRefreshingProvider,
                            BaseAutoRefreshingProvider};
pub use request::{DispatchSignedRequest, HttpResponse, HttpDispatchError, TlsError};
pub use signature::SignedRequest;
pub use request::default_tls_client;
pub use region::default_region;

mod param;
mod region;
mod request;
mod xmlerror;
mod xmlutil;
mod serialization;
#[macro_use]
mod signature;

#[cfg(test)]
mod mock;

#[cfg(feature = "acm")]
pub mod acm;
#[cfg(feature = "autoscaling")]
pub mod autoscaling;
#[allow(unused_imports)]
#[cfg(feature = "cloudformation")]
pub mod cloudformation;
#[cfg(feature = "cloudfront")]
pub mod cloudfront;
#[cfg(feature = "cloudhsm")]
pub mod cloudhsm;
#[cfg(feature = "cloudsearch")]
pub mod cloudsearch;
#[cfg(feature = "cloudtrail")]
pub mod cloudtrail;
#[cfg(feature = "cloudwatch")]
pub mod cloudwatch;
#[cfg(feature = "codecommit")]
pub mod codecommit;
#[cfg(feature = "codedeploy")]
pub mod codedeploy;
#[cfg(feature = "codepipeline")]
pub mod codepipeline;
#[cfg(feature = "cognito-identity")]
pub mod cognitoidentity;
#[cfg(feature = "config")]
pub mod config;
#[cfg(feature = "datapipeline")]
pub mod datapipeline;
#[cfg(feature = "devicefarm")]
pub mod devicefarm;
#[cfg(feature = "directconnect")]
pub mod directconnect;
#[cfg(feature = "ds")]
pub mod ds;
#[cfg(feature = "dynamodb")]
pub mod dynamodb;
#[cfg(feature = "dynamodbstreams")]
pub mod dynamodbstreams;
#[cfg(feature = "ec2")]
pub mod ec2;
#[cfg(feature = "ecr")]
pub mod ecr;
#[cfg(feature = "ecs")]
pub mod ecs;
#[cfg(feature = "emr")]
pub mod emr;
#[cfg(feature = "elasticache")]
pub mod elasticache;
#[cfg(feature = "elasticbeanstalk")]
pub mod elasticbeanstalk;
#[cfg(feature = "elastictranscoder")]
pub mod elastictranscoder;
#[cfg(feature = "elb")]
pub mod elb;
#[cfg(feature = "elbv2")]
pub mod elbv2;
#[cfg(feature = "events")]
pub mod events;
#[cfg(feature = "firehose")]
pub mod firehose;
#[cfg(feature = "iam")]
pub mod iam;
#[cfg(feature = "importexport")]
pub mod importexport;
#[cfg(feature = "inspector")]
pub mod inspector;
#[cfg(feature = "iot")]
pub mod iot;
#[cfg(feature = "kinesis")]
pub mod kinesis;
#[cfg(feature = "kms")]
pub mod kms;
#[cfg(feature = "lambda")]
pub mod lambda;
#[cfg(feature = "logs")]
pub mod logs;
#[cfg(feature = "machinelearning")]
pub mod machinelearning;
#[cfg(feature = "marketplacecommerceanalytics")]
pub mod marketplacecommerceanalytics;
#[cfg(feature = "opsworks")]
pub mod opsworks;
#[cfg(feature = "redshift")]
pub mod redshift;
#[cfg(feature = "rds")]
pub mod rds;
#[cfg(feature = "route53")]
pub mod route53;
#[cfg(feature = "route53domains")]
pub mod route53domains;
#[cfg(feature = "s3")]
pub mod s3;
#[cfg(feature = "sdb")]
pub mod sdb;
#[cfg(feature = "sns")]
pub mod sns;
#[cfg(feature = "sqs")]
pub mod sqs;
#[cfg(feature = "ssm")]
pub mod ssm;
#[cfg(feature = "storagegateway")]
pub mod storagegateway;
#[cfg(feature = "sts")]
pub mod sts;
#[cfg(feature = "swf")]
pub mod swf;
#[cfg(feature = "waf")]
pub mod waf;
#[cfg(feature = "workspaces")]
pub mod workspaces;

/*
#[cfg(feature = "gamelift")]
pub mod gamelift;
#[cfg(feature = "support")]
pub mod support;
*/
<|endoftext|>


<commit_before>//! Implementation of a basic linear space trait.
//!
//! The main interface is `Lin` with an implementation for a vector of real
//! numbers: `Rn<F>`.
//!
//! ```rust
//! use linear_space::lin::{Lin,Rn};
//!
//! let x = Rn::new(vec![1.,2.]);
//! let y = Rn::new(vec![2.,-3.]);
//!
//! assert_eq!(x.dot(&y), -4.);
//! assert_eq!(Rn::new(vec![3., -1.]), x.clone() + y);
//! assert_eq!(Rn::new(vec![2., 4.]), x * 2.);
//! ```
use num::{Zero, One, Float};
use std::ops::{Add, Mul, Deref, DerefMut};
use std::iter::repeat;

/// Trait defining basic operations for an element of a linear space.
///
/// The focus is on operations _in place_: methods that return a Lin object
/// modify the object in place.
pub trait Lin {
    type F: Float;

    /// Dot product (inner product).
    fn dot(&self, other: &Self) -> Self::F;

    /// Multiplication by a constant.
    fn scale(&mut self, a: Self::F) -> &mut Self;

    /// Adds a vector multiplied by a constant to this vector.
    fn ray_to(&mut self, other: &Self, t: Self::F) -> &mut Self;

    /// Return the origin of the vector space to which self belongs too.
    fn origin(&self) -> Self;

    /// Norm of the vector.
    fn norm(&self) -> Self::F {
        self.norm_squared().sqrt()
    }

    /// Square of the norm.
    fn norm_squared(&self) -> Self::F {
        self.dot(self)
    }

    /// Scale the vector so that it has a norm one.
    ///
    /// If norm is zero, causes division by zero.
    fn normalize(&mut self) -> &mut Self {
        let norm = self.norm();
        self.scale(Self::F::one() / norm)
    }

    /// Distance between two vectors.
    ///
    /// Default implementation uses
    /// `|x - v| = x.x - 2 x.y + y.y`
    /// to avoid copying.
    /// Therefore it is recommended to reimplement this method.
    fn dist(&self, other: &Self) -> Self::F {
        (self.norm_squared() + other.norm_squared()
            - (Self::F::one() + Self::F::one()) * self.dot(other)).sqrt()
    }

    /// Adds a vector to this vector.
    fn add_mut(&mut self, other: &Self) -> &mut Self {
        self.ray_to(other, Self::F::one())
    }

    /// Creates a linear combination.
    fn combine(&mut self,  a: Self::F, other: &Self, b: Self::F) -> &mut Self {
        self.scale(a).ray_to(other,b)
    }
}

/// An implementation of the Lin trait: an n-dimensional real vector.
///
/// Backed by a `Vec<F>`, where `F` is `Float`.
#[derive(Clone,Debug,PartialEq)]
pub struct Rn<F: Float> {
    vec: Vec<F>,
}

impl<F: Float> Rn<F> {
    pub fn new(v: Vec<F>) -> Self {
        Rn {vec: v}
    }
}

impl<F: Float> Deref for Rn<F> {
    type Target = Vec<F>;

    fn deref<'a>(&'a self) -> &'a Vec<F> {
        &self.vec
    }
}

impl<F: Float> DerefMut for Rn<F> {
    fn deref_mut<'a>(&'a mut self) -> &'a mut Vec<F> {
        &mut self.vec
    }
}

impl<F: Float> Mul<F> for Rn<F> {
    type Output = Rn<F>;

    fn mul(mut self, other: F) -> Self {
        self.scale(other);
        self
    }
}

impl<F: Float> Add for Rn<F> {
    type Output = Rn<F>;

    fn add(mut self, other: Self) -> Self {
        self.add_mut(&other);
        self
    }
}

impl<F: Float> Lin for Rn<F> {
    type F = F;

    fn norm(&self) -> Self::F {
        self.dot(self).sqrt()
    }

    fn dist(&self, other: &Self) -> Self::F {
        assert_eq!(self.len(), other.len());
        self.iter().zip(other.iter())
            .fold(Self::F::zero(),
                |sum, (&x, &y)| sum + (x - y).powi(2))
            .sqrt()
    }

    fn dot(&self, other: &Self) -> Self::F {
        assert_eq!(self.len(), other.len());
        self.iter().zip(other.iter())
            .fold(Self::F::zero(), |sum, (&x, &y)| sum + x * y)
    }

    fn scale(&mut self, a: Self::F) -> &mut Self {
        for x in self.iter_mut() {
            *x = *x * a;
        }
        self
    }

    fn combine(&mut self,  a: Self::F, other: &Self, b: Self::F) -> &mut Self {
        assert_eq!(self.len(), other.len());
        for (x, y) in self.iter_mut().zip(other.iter()) {
            *x = *x * a + *y * b;
        }
        self
    }

    fn ray_to(&mut self,  other: &Self, b: Self::F) -> &mut Self {
        assert_eq!(self.len(), other.len());
        for (x, y) in self.iter_mut().zip(other.iter()) {
            *x = *x + *y * b;
        }
        self
    }

    fn origin(&self) -> Self {
        Rn::new(repeat(Self::F::zero()).take(self.len()).collect())
    }
}

impl<F: Float> Lin for F {
    type F = F;

    fn dot(&self, other: &Self) -> Self::F {
        *self * *other
    }

    fn scale(&mut self, a: Self::F) -> &mut Self {
        *self = *self * a;
        self
    }

    fn combine(&mut self,  a: Self::F, other: &Self, b: Self::F) -> &mut Self {
        *self = *self * a + *other * b;
        self
    }

    fn ray_to(&mut self,  other: &Self, b: Self::F) -> &mut Self {
        *self = *self + *other * b;
        self
    }

    fn origin(&self) -> Self {
        F::zero()
    }

    fn dist(&self, other: &Self) -> Self::F {
        (*self - *other).abs()
    }

    fn norm(&self) -> Self::F {
        self.abs()
    }
}

#[cfg(test)]
mod test {
    extern crate quickcheck;

    use super::Lin;
    use super::Rn;
    use std::cmp::min;

    // relative error: this shouldn't be to small
    const EPS: f64 = 1e-10;

    fn eps_eq(a: f64, b: f64) -> bool {
        let m = a.abs() + b.abs();
        (a - b).abs() <= EPS * m
    }

    #[test]
    fn test_lin_f64() {
        fn prop(a: f64, b: f64, c: f64) -> bool {
            let mut d = a;
            d.ray_to(&b,c);
            eps_eq(a.norm(), a.dist(&a.origin())) &&
                eps_eq(d.dot(&a), a.norm_squared() + c * a * b)

        }

        quickcheck::quickcheck(prop as fn(f64, f64, f64) -> bool);
        let mut a = 1.;
        a.combine(2.,&3.,4.);
        assert_eq!(a.norm(), 1. * 2. + 3. * 4.);
    }

    #[test]
    fn scale_norm_zero() {
        fn prop(v: Vec<f64>) -> bool {
            let mut v = Rn::new(v);
            eps_eq(0., v.scale(0.).norm())
        }
        quickcheck::quickcheck(prop as fn(Vec<f64>) -> bool);
    }

    #[test]
    fn dot_equal_norm_squared() {
        fn prop(v: Vec<f64>) -> bool {
            let v = Rn::new(v);
            eps_eq(v.dot(&v), v.norm().powi(2))
        }
        quickcheck::quickcheck(prop as fn(Vec<f64>) -> bool);
    }

    #[test]
    fn origin() {
        fn prop(v: Vec<f64>) -> bool {
            let v = Rn::new(v);
            let o = v.origin();
            eps_eq(o.norm(), 0.) && o.len() == v.len()
        }
        quickcheck::quickcheck(prop as fn(Vec<f64>) -> bool);
    }

    #[test]
    fn dist_norm() {
        fn prop(v: Vec<f64>, w: Vec<f64>) -> bool {
            let mut v = Rn::new(v);
            let mut w = Rn::new(w);
            let l = min(v.len(), w.len());
            v.truncate(l);
            w.truncate(l);

            let d = v.dist(&w);
            v.ray_to(&w, -1.);

            eps_eq(d, v.norm())
        }
        quickcheck::quickcheck(prop as fn(Vec<f64>, Vec<f64>) -> bool);
    }

    #[test]
    fn combine_ray_to() {
        fn prop(v: Vec<f64>, w: Vec<f64>, a: f64) -> bool {
            let mut v = Rn::new(v);
            let mut w = Rn::new(w);
            let l = min(v.len(), w.len());
            v.truncate(l);
            w.truncate(l);

            let mut v1 = v.clone();
            v.combine(1., &w, a);
            v1.ray_to(&w, a);

            eps_eq(v.dist(&v1), 0.)
        }
        quickcheck::quickcheck(prop as fn(Vec<f64>, Vec<f64>, f64) -> bool);
    }

    #[test]
    fn combine_dot() {
        fn prop(v: Vec<f64>, w: Vec<f64>, z: Vec<f64>, a: f64) -> bool {
            let mut v = Rn::new(v);
            let mut w = Rn::new(w);
            let mut z = Rn::new(z);
            let l = min(v.len(), min(w.len(), z.len()));
            v.truncate(l);
            w.truncate(l);
            z.truncate(l);

            let b = 3.5;

            let dv = v.dot(&z);
            let dw = w.dot(&z);

            v.combine(a, &w, b);

            let dvw = v.dot(&z);
            eps_eq(a * dv + b * dw, dvw)
        }
        quickcheck::quickcheck(prop as fn(Vec<f64>, Vec<f64>, Vec<f64>, f64) -> bool);
    }
}
<commit_msg>add project_*<commit_after>//! Implementation of a basic linear space trait.
//!
//! The main interface is `Lin` with an implementation for a vector of real
//! numbers: `Rn<F>`.
//!
//! ```rust
//! use linear_space::lin::{Lin,Rn};
//!
//! let x = Rn::new(vec![1.,2.]);
//! let y = Rn::new(vec![2.,-3.]);
//!
//! assert_eq!(x.dot(&y), -4.);
//! assert_eq!(Rn::new(vec![3., -1.]), x.clone() + y);
//! assert_eq!(Rn::new(vec![2., 4.]), x * 2.);
//! ```
use num::{Zero, One, Float};
use std::ops::{Add, Mul, Deref, DerefMut};
use std::iter::repeat;

/// Trait defining basic operations for an element of a linear space.
///
/// The focus is on operations _in place_: methods that return a `Lin` object
/// modify the object in place.
pub trait Lin {
    /// Scalars for this linear space.
    type F: Float;

    /// Dot product (inner product).
    fn dot(&self, other: &Self) -> Self::F;

    /// Multiplication by a constant.
    fn scale(&mut self, a: Self::F) -> &mut Self;

    /// Adds a vector multiplied by a constant to this vector.
    fn ray_to(&mut self, other: &Self, t: Self::F) -> &mut Self;

    /// Return the origin of the vector space to which self belongs too.
    fn origin(&self) -> Self;

    /// Norm of the vector.
    fn norm(&self) -> Self::F {
        self.norm_squared().sqrt()
    }

    /// Square of the norm.
    fn norm_squared(&self) -> Self::F {
        self.dot(self)
    }

    /// Scale the vector so that it has a norm one.
    ///
    /// If norm is zero, causes division by zero.
    fn normalize(&mut self) -> &mut Self {
        let norm = self.norm();
        self.scale(Self::F::one() / norm)
    }

    /// Distance between two vectors.
    ///
    /// Default implementation uses
    /// `|x - v| = sqrt(x.x - 2 x.y + y.y)`
    /// to avoid copying.
    /// Therefore it is recommended to reimplement this method.
    fn dist(&self, other: &Self) -> Self::F {
        (self.norm_squared() + other.norm_squared()
            - (Self::F::one() + Self::F::one()) * self.dot(other)).sqrt()
    }

    /// Adds a vector to this vector.
    fn add_mut(&mut self, other: &Self) -> &mut Self {
        self.ray_to(other, Self::F::one())
    }

    /// Creates a linear combination.
    fn combine(&mut self,  a: Self::F, other: &Self, b: Self::F) -> &mut Self {
        self.scale(a).ray_to(other,b)
    }

    /// Project on a line given by a given direction.
    ///
    /// `dir` does not have to be normalized, but must be nonzero.
    fn project_on(&mut self, dir: &Self) -> &mut Self {
        let a = self.dot(dir) / dir.norm_squared();
        self.combine(Self::F::zero(), dir, a)
    }

    /// Project on a plane orthogonal to the given direction.
    ///
    /// `dir` does not have to be normalized, but must be nonzero.
    fn project_ortho(&mut self, dir: &Self) -> &mut Self {
        let a = self.dot(dir) / dir.norm_squared();
        self.combine(Self::F::one(), dir, -a)
    }
}

/// An implementation of the Lin trait: an n-dimensional real vector.
///
/// Backed by a `Vec<F>`, where `F` is `Float`.
#[derive(Clone,Debug,PartialEq)]
pub struct Rn<F: Float> {
    vec: Vec<F>,
}

impl<F: Float> Rn<F> {
    pub fn new(v: Vec<F>) -> Self {
        Rn {vec: v}
    }
}

impl<F: Float> Deref for Rn<F> {
    type Target = Vec<F>;

    fn deref<'a>(&'a self) -> &'a Vec<F> {
        &self.vec
    }
}

impl<F: Float> DerefMut for Rn<F> {
    fn deref_mut<'a>(&'a mut self) -> &'a mut Vec<F> {
        &mut self.vec
    }
}

impl<F: Float> Mul<F> for Rn<F> {
    type Output = Rn<F>;

    fn mul(mut self, other: F) -> Self {
        self.scale(other);
        self
    }
}

impl<F: Float> Add for Rn<F> {
    type Output = Rn<F>;

    fn add(mut self, other: Self) -> Self {
        self.add_mut(&other);
        self
    }
}

impl<F: Float> Lin for Rn<F> {
    type F = F;

    fn norm(&self) -> Self::F {
        self.dot(self).sqrt()
    }

    fn dist(&self, other: &Self) -> Self::F {
        assert_eq!(self.len(), other.len());
        self.iter().zip(other.iter())
            .fold(Self::F::zero(),
                |sum, (&x, &y)| sum + (x - y).powi(2))
            .sqrt()
    }

    fn dot(&self, other: &Self) -> Self::F {
        assert_eq!(self.len(), other.len());
        self.iter().zip(other.iter())
            .fold(Self::F::zero(), |sum, (&x, &y)| sum + x * y)
    }

    fn scale(&mut self, a: Self::F) -> &mut Self {
        for x in self.iter_mut() {
            *x = *x * a;
        }
        self
    }

    fn combine(&mut self,  a: Self::F, other: &Self, b: Self::F) -> &mut Self {
        assert_eq!(self.len(), other.len());
        for (x, y) in self.iter_mut().zip(other.iter()) {
            *x = *x * a + *y * b;
        }
        self
    }

    fn ray_to(&mut self,  other: &Self, b: Self::F) -> &mut Self {
        assert_eq!(self.len(), other.len());
        for (x, y) in self.iter_mut().zip(other.iter()) {
            *x = *x + *y * b;
        }
        self
    }

    fn origin(&self) -> Self {
        Rn::new(repeat(Self::F::zero()).take(self.len()).collect())
    }
}

impl<F: Float> Lin for F {
    type F = F;

    fn dot(&self, other: &Self) -> Self::F {
        *self * *other
    }

    fn scale(&mut self, a: Self::F) -> &mut Self {
        *self = *self * a;
        self
    }

    fn combine(&mut self,  a: Self::F, other: &Self, b: Self::F) -> &mut Self {
        *self = *self * a + *other * b;
        self
    }

    fn ray_to(&mut self,  other: &Self, b: Self::F) -> &mut Self {
        *self = *self + *other * b;
        self
    }

    fn origin(&self) -> Self {
        F::zero()
    }

    fn dist(&self, other: &Self) -> Self::F {
        (*self - *other).abs()
    }

    fn norm(&self) -> Self::F {
        self.abs()
    }
}

#[cfg(test)]
mod test {
    extern crate quickcheck;

    use super::Lin;
    use super::Rn;
    use std::cmp::min;
    use num::Float;

    // relative error: this shouldn't be to small
    const EPS: f64 = 1e-10;

    fn eps_eq(a: f64, b: f64) -> bool {
        let m = a.abs() + b.abs();
        (a - b).abs() <= EPS * m
    }

    fn trunc<T: Float>(v: Vec<T>, w: Vec<T>) -> (Rn<T>, Rn<T>) {
            let mut v = Rn::new(v);
            let mut w = Rn::new(w);
            let l = min(v.len(), w.len());
            v.truncate(l);
            w.truncate(l);
            (v, w)
    }

    #[test]
    fn test_lin_f64() {
        fn prop(a: f64, b: f64, c: f64) -> bool {
            let mut d = a;
            d.ray_to(&b,c);
            eps_eq(a.norm(), a.dist(&a.origin())) &&
                eps_eq(d.dot(&a), a.norm_squared() + c * a * b)

        }

        quickcheck::quickcheck(prop as fn(f64, f64, f64) -> bool);
        let mut a = 1.;
        a.combine(2.,&3.,4.);
        assert_eq!(a.norm(), 1. * 2. + 3. * 4.);
    }

    #[test]
    fn scale_norm_zero() {
        fn prop(v: Vec<f64>) -> bool {
            let mut v = Rn::new(v);
            eps_eq(0., v.scale(0.).norm())
        }
        quickcheck::quickcheck(prop as fn(Vec<f64>) -> bool);
    }

    #[test]
    fn dot_equal_norm_squared() {
        fn prop(v: Vec<f64>) -> bool {
            let v = Rn::new(v);
            eps_eq(v.dot(&v), v.norm().powi(2))
        }
        quickcheck::quickcheck(prop as fn(Vec<f64>) -> bool);
    }

    #[test]
    fn origin() {
        fn prop(v: Vec<f64>) -> bool {
            let v = Rn::new(v);
            let o = v.origin();
            eps_eq(o.norm(), 0.) && o.len() == v.len()
        }
        quickcheck::quickcheck(prop as fn(Vec<f64>) -> bool);
    }

    #[test]
    fn dist_norm() {
        fn prop(v: Vec<f64>, w: Vec<f64>) -> bool {
            let (mut v, w) = trunc(v, w);

            let d = v.dist(&w);
            v.ray_to(&w, -1.);

            eps_eq(d, v.norm())
        }
        quickcheck::quickcheck(prop as fn(Vec<f64>, Vec<f64>) -> bool);
    }

    #[test]
    fn combine_ray_to() {
        fn prop(v: Vec<f64>, w: Vec<f64>, a: f64) -> bool {
            let (mut v, w) = trunc(v, w);

            let mut v1 = v.clone();
            v.combine(1., &w, a);
            v1.ray_to(&w, a);

            eps_eq(v.dist(&v1), 0.)
        }
        quickcheck::quickcheck(prop as fn(Vec<f64>, Vec<f64>, f64) -> bool);
    }

    #[test]
    fn combine_dot() {
        fn prop(v: Vec<f64>, w: Vec<f64>, z: Vec<f64>, a: f64) -> bool {
            let mut v = Rn::new(v);
            let mut w = Rn::new(w);
            let mut z = Rn::new(z);
            let l = min(v.len(), min(w.len(), z.len()));
            v.truncate(l);
            w.truncate(l);
            z.truncate(l);

            let b = 3.5;

            let dv = v.dot(&z);
            let dw = w.dot(&z);

            v.combine(a, &w, b);

            let dvw = v.dot(&z);
            eps_eq(a * dv + b * dw, dvw)
        }
        quickcheck::quickcheck(prop as fn(Vec<f64>, Vec<f64>, Vec<f64>, f64) -> bool);
    }

    #[test]
    fn project_pythagoras() {
        fn prop(v: Vec<f64>, w: Vec<f64>) -> bool {
            let (v, w) = trunc(v, w);

            let mut p = v.clone();
            let mut perp = v.clone();

            p.project_on(&w);
            perp.project_ortho(&w);
            eps_eq(p.norm_squared() + perp.norm_squared(), v.norm_squared())
        }
        quickcheck::quickcheck(prop as fn(Vec<f64>, Vec<f64>) -> bool);
    }

}
<|endoftext|>


<commit_before>use std::io;
use std::io::Write;
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};

use na::Point2;

/// A block of pixels that a thread is responsible for rendering (i.e a bucket).
#[derive(Debug)]
pub struct Block {
    start: Point2<usize>,
    current: Point2<usize>,
    end: Point2<usize>,
}

impl Block {
    pub fn new(start: (usize, usize), size: usize) -> Block {
        Block {
            start: Point2::new(start.0, start.1),
            current: Point2::new(start.0, start.1),
            end: Point2::new(start.0 + size, start.1 + size),
        }
    }

    /// Return the area of this block in pixels (i.e. number of pixels this
    /// block covers)
    pub fn area(&self) -> usize {
        (self.end.x - self.start.x) * (self.end.y - self.start.y)
    }
}

impl Iterator for Block {
    type Item = Point2<usize>;

    fn next(&mut self) -> Option<Point2<usize>> {
        if self.current.x >= self.end.x || self.current.y >= self.end.y {
            None
        } else {

            let cur = self.current;

            if self.current.x == self.end.x - 1 {
                self.current.x = self.start.x;
                self.current.y += 1;
            } else {
                self.current.x += 1;
            }

            Some(cur)
        }
    }
}

pub struct BlockQueue {
    dims: (usize, usize),
    block_size: usize,
    counter: AtomicUsize,
    pub num_blocks: usize,
}

impl BlockQueue {
    pub fn new(dims: (usize, usize), block_size: usize) -> BlockQueue {
        BlockQueue {
            dims: dims,
            block_size: block_size,
            counter: ATOMIC_USIZE_INIT,
            num_blocks: (dims.0 / block_size) * (dims.1 / block_size),
        }
    }

    pub fn next(&self) -> Option<Block> {
        let c = self.counter.fetch_add(1, Ordering::AcqRel);
        if c >= self.num_blocks {
            None
        } else {
            let num_blocks_width = self.dims.0 / self.block_size;
            Some(Block::new((c % num_blocks_width * self.block_size,
                             c / num_blocks_width * self.block_size),
                            self.block_size))
        }
    }

    pub fn report_progress(&self) {
        print!("\rRendering block {}/{}...  ",
               self.counter.load(Ordering::Relaxed),
               self.num_blocks);
        io::stdout().flush().expect("Could not flush stdout");;
    }
}

#[test]
fn test_area() {
    let block = Block::new((12, 12), 8);
    assert_eq!(block.area(), 64);
}

#[test]
fn test_iter() {
    let block = Block::new((12, 12), 8);
    let pixels: Vec<Point2<usize>> = block.into_iter().collect();

    assert_eq!(pixels.len(), 64);
    assert_eq!(pixels[0].x, 12);
    assert_eq!(pixels[0].y, 12);
    assert_eq!(pixels[63].x, 19);
    assert_eq!(pixels[63].y, 19);
}
<commit_msg>Fix number of blocks needed to cover the whole image<commit_after>use std::io;
use std::io::Write;
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};

use na::Point2;

/// A block of pixels that a thread is responsible for rendering (i.e a bucket).
#[derive(Debug)]
pub struct Block {
    start: Point2<usize>,
    current: Point2<usize>,
    end: Point2<usize>,
}

impl Block {
    pub fn new(start: (usize, usize), size: usize) -> Block {
        Block {
            start: Point2::new(start.0, start.1),
            current: Point2::new(start.0, start.1),
            end: Point2::new(start.0 + size, start.1 + size),
        }
    }

    /// Return the area of this block in pixels (i.e. number of pixels this
    /// block covers)
    pub fn area(&self) -> usize {
        (self.end.x - self.start.x) * (self.end.y - self.start.y)
    }
}

impl Iterator for Block {
    type Item = Point2<usize>;

    fn next(&mut self) -> Option<Point2<usize>> {
        if self.current.x >= self.end.x || self.current.y >= self.end.y {
            None
        } else {

            let cur = self.current;

            if self.current.x == self.end.x - 1 {
                self.current.x = self.start.x;
                self.current.y += 1;
            } else {
                self.current.x += 1;
            }

            Some(cur)
        }
    }
}

pub struct BlockQueue {
    dims: (usize, usize),
    block_size: usize,
    counter: AtomicUsize,
    pub num_blocks: usize,
}

impl BlockQueue {
    pub fn new(dims: (usize, usize), block_size: usize) -> BlockQueue {
        let xblocks = (dims.0 as f32 / block_size as f32).ceil() as usize;
        let yblocks = (dims.1 as f32 / block_size as f32).ceil() as usize;
        BlockQueue {
            dims: dims,
            block_size: block_size,
            counter: ATOMIC_USIZE_INIT,
            num_blocks: xblocks * yblocks,
        }
    }

    pub fn next(&self) -> Option<Block> {
        let c = self.counter.fetch_add(1, Ordering::AcqRel);
        if c >= self.num_blocks {
            None
        } else {
            let num_blocks_width = self.dims.0 / self.block_size;
            Some(Block::new((c % num_blocks_width * self.block_size,
                             c / num_blocks_width * self.block_size),
                            self.block_size))
        }
    }

    pub fn report_progress(&self) {
        print!("\rRendering block {}/{}...  ",
               self.counter.load(Ordering::Relaxed),
               self.num_blocks);
        io::stdout().flush().expect("Could not flush stdout");;
    }
}

impl Iterator for BlockQueue {
    type Item = Block;

    fn next(&mut self) -> Option<Block> {
        BlockQueue::next(self)
    }
}

#[test]
fn test_area() {
    let block = Block::new((12, 12), 8);
    assert_eq!(block.area(), 64);
}

#[test]
fn test_iter() {
    let block = Block::new((12, 12), 8);
    let pixels: Vec<Point2<usize>> = block.into_iter().collect();

    assert_eq!(pixels.len(), 64);
    assert_eq!(pixels[0].x, 12);
    assert_eq!(pixels[0].y, 12);
    assert_eq!(pixels[63].x, 19);
    assert_eq!(pixels[63].y, 19);
}

#[test]
fn test_queue_iter() {
    let queue = BlockQueue::new((100, 100), 8);
    let blocks: Vec<Block> = queue.into_iter().collect();

    // 100 is not a multiple of 8, so make sure we generate enough blocks to cover the whole image.
    // In this case, we need 13 * 13.
    assert_eq!(blocks.len(), 169);
}
<|endoftext|>


<commit_before>// Copyright 2015-2018 Deyan Ginev. See the LICENSE
// file at the top-level directory of this distribution.
//
// Licensed under the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed
// except according to those terms.

extern crate Archive;
extern crate cortex;
extern crate libxml;
extern crate regex;
extern crate time;

use cortex::backend::Backend;
use cortex::helpers::TaskStatus;
use cortex::models::{Corpus, Service};
use libxml::parser::Parser;
use regex::Regex;
use std::env;
use std::str;
use Archive::*;

/// Bundle a (corpus,service) pair's results into a self-contained redistributable dataset.
fn main() {
  let start_bundle = time::get_time();
  let chunk_size = 10_240;
  // Setup CorTeX backend data
  let backend = Backend::default();
  let mut input_args = env::args();
  let _ = input_args.next(); // discard the script filename
  let corpus_name = match input_args.next() {
    Some(name) => name,
    None => "arXMLiv".to_string(),
  };
  let service_name = match input_args.next() {
    Some(name) => name,
    None => "tex_to_html".to_string(),
  };
  let dataset_path = match input_args.next() {
    Some(path) => path,
    None => "./dataset.zip".to_string(),
  };
  let corpus = match Corpus::find_by_name(&corpus_name, &backend.connection) {
    Ok(c) => c,
    Err(e) => {
      println!("Failed to load corpus: {:?}", e);
      return;
    },
  };
  let service = match Service::find_by_name(&service_name, &backend.connection) {
    Ok(s) => s,
    Err(e) => {
      println!("Failed to load service: {:?}", e);
      return;
    },
  };
  // Setup document parser
  let parser = Parser::default_html();
  // Set the extension regex
  let entry_name_regex = Regex::new(r"([^/]+)/([^/]+)/([^/]+)\.zip$").unwrap();
  // Set the database archive file
  let mut total_dataset_entries = 0;
  let mut archive_writer_new = Writer::new().unwrap()
    .set_compression(ArchiveFilter::None) // could be imporoved later (libarchive-sys needs an upgrade ?)
    .set_format(ArchiveFormat::Zip);
  archive_writer_new
    .open_filename(&dataset_path.clone())
    .unwrap();
  // Bundle each usable status code:
  for status in vec![
    TaskStatus::NoProblem,
    TaskStatus::Warning,
    TaskStatus::Error,
  ] {
    let entries = backend.entries(&corpus, &service, &status);
    println!(
      "Entries found for severity {:?}: {:?}",
      status.to_key(),
      entries.len()
    );
    for entry in entries {
      // Let's open the zip file and grab the result from it
      if let Ok(archive_reader) = Reader::new()
        .unwrap()
        .support_filter_all()
        .support_format_all()
        .open_filename(&entry, chunk_size)
      {
        while let Ok(e) = archive_reader.next_header() {
          // Which file are we looking at?
          let pathname = e.pathname();
          let is_html = pathname.ends_with(".html");
          if !is_html {
            continue;
          }
          let mut raw_entry_data = Vec::new();
          while let Ok(chunk) = archive_reader.read_data(chunk_size) {
            raw_entry_data.extend(chunk.into_iter());
          }
          let is_well_formed = match str::from_utf8(&raw_entry_data) {
            Ok(some_utf_string) => {
              if parser.is_well_formed_html(some_utf_string) {
                // well-formed, include in the dataset
                true
              } else {
                println!("-- Ill-formed XML: {:?}", entry);
                false // ill-formed, do nothing
              }
            },
            Err(_) => {
              println!("-- Ill-formed UTF8 archive data: {:?}", entry);
              false
            },
          };
          if is_well_formed {
            if let Some(cap) = entry_name_regex.captures(&entry) {
              let month_dir = cap.get(1).map_or("monthXX", |m| m.as_str());
              let paper_dir = cap.get(2).map_or("paperXX", |m| m.as_str());
              let dataset_path = status.to_key() + "/" + month_dir + "/" + paper_dir + ".html";
              println!("Writing: {:?} ", dataset_path);
              total_dataset_entries += 1;
              match archive_writer_new.write_header_new(&dataset_path, raw_entry_data.len() as i64)
              {
                Ok(_) => {},
                Err(e) => {
                  println!("Couldn't write header: {:?}", e);
                  break;
                },
              };
              match archive_writer_new.write_data(raw_entry_data) {
                Ok(_) => {},
                Err(e) => println!(
                  "Failed to write data to {:?} because {:?}",
                  dataset_path.clone(),
                  e
                ),
              };
            }
          }
          break; // only one HTML file per archive
        }
      }
    }
  }
  let end_bundle = time::get_time();

  let bundle_duration = (end_bundle - start_bundle).num_milliseconds();
  println!(
    "-- Dataset bundler for corpus {:?} and service {:?} took {:?}ms",
    corpus.name, service.name, bundle_duration
  );
  println!("-- Bundled {:?} dataset entries.", total_dataset_entries);
}
<commit_msg>minor<commit_after>// Copyright 2015-2018 Deyan Ginev. See the LICENSE
// file at the top-level directory of this distribution.
//
// Licensed under the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed
// except according to those terms.

extern crate Archive;
extern crate cortex;
extern crate libxml;
extern crate regex;
extern crate time;

use cortex::backend::Backend;
use cortex::helpers::TaskStatus;
use cortex::models::{Corpus, Service};
use libxml::parser::Parser;
use regex::Regex;
use std::env;
use std::str;
use Archive::*;

/// Bundle a (corpus,service) pair's results into a self-contained redistributable dataset.
fn main() {
  let start_bundle = time::get_time();
  let chunk_size = 10_240;
  // Setup CorTeX backend data
  let backend = Backend::default();
  let mut input_args = env::args();
  let _ = input_args.next(); // discard the script filename
  let corpus_name = match input_args.next() {
    Some(name) => name,
    None => "arXMLiv".to_string(),
  };
  let service_name = match input_args.next() {
    Some(name) => name,
    None => "tex_to_html".to_string(),
  };
  let dataset_path = match input_args.next() {
    Some(path) => path,
    None => "./dataset.zip".to_string(),
  };
  let corpus = match Corpus::find_by_name(&corpus_name, &backend.connection) {
    Ok(c) => c,
    Err(e) => {
      println!("Failed to load corpus: {:?}", e);
      return;
    },
  };
  let service = match Service::find_by_name(&service_name, &backend.connection) {
    Ok(s) => s,
    Err(e) => {
      println!("Failed to load service: {:?}", e);
      return;
    },
  };
  // Setup document parser
  let parser = Parser::default_html();
  // Set the extension regex
  let entry_name_regex = Regex::new(r"([^/]+)/([^/]+)/([^/]+)\.zip$").unwrap();
  // Set the database archive file
  let mut total_dataset_entries = 0;
  let mut archive_writer_new = Writer::new()
    .unwrap()
    .set_compression(ArchiveFilter::None) // could be imporoved later (libarchive-sys needs an upgrade ?)
    .set_format(ArchiveFormat::Zip);
  archive_writer_new
    .open_filename(&dataset_path.clone())
    .unwrap();
  // Bundle each usable status code:
  for status in vec![
    TaskStatus::NoProblem,
    TaskStatus::Warning,
    TaskStatus::Error,
  ] {
    let entries = backend.entries(&corpus, &service, &status);
    println!(
      "Entries found for severity {:?}: {:?}",
      status.to_key(),
      entries.len()
    );
    for entry in entries {
      // Let's open the zip file and grab the result from it
      if let Ok(archive_reader) = Reader::new()
        .unwrap()
        .support_filter_all()
        .support_format_all()
        .open_filename(&entry, chunk_size)
      {
        while let Ok(e) = archive_reader.next_header() {
          // Which file are we looking at?
          let pathname = e.pathname();
          if !pathname.ends_with(".html") {
            continue;
          }
          let mut raw_entry_data = Vec::new();
          while let Ok(chunk) = archive_reader.read_data(chunk_size) {
            raw_entry_data.extend(chunk.into_iter());
          }
          let is_well_formed = match str::from_utf8(&raw_entry_data) {
            Ok(some_utf_string) => {
              if parser.is_well_formed_html(some_utf_string) {
                // well-formed, include in the dataset
                true
              } else {
                println!("-- Ill-formed XML: {:?}", entry);
                false // ill-formed, do nothing
              }
            },
            Err(_) => {
              println!("-- Ill-formed UTF8 archive data: {:?}", entry);
              false
            },
          };
          if is_well_formed {
            if let Some(cap) = entry_name_regex.captures(&entry) {
              let month_dir = cap.get(1).map_or("monthXX", |m| m.as_str());
              let paper_dir = cap.get(2).map_or("paperXX", |m| m.as_str());
              let dataset_path = status.to_key() + "/" + month_dir + "/" + paper_dir + ".html";
              println!("Writing: {:?} ", dataset_path);
              total_dataset_entries += 1;
              match archive_writer_new.write_header_new(&dataset_path, raw_entry_data.len() as i64)
              {
                Ok(_) => {},
                Err(e) => {
                  println!("Couldn't write header: {:?}", e);
                  break;
                },
              };
              match archive_writer_new.write_data(raw_entry_data) {
                Ok(_) => {},
                Err(e) => println!(
                  "Failed to write data to {:?} because {:?}",
                  dataset_path.clone(),
                  e
                ),
              };
            }
          }
          break; // only one HTML file per archive
        }
      }
    }
  }
  let end_bundle = time::get_time();

  let bundle_duration = (end_bundle - start_bundle).num_milliseconds();
  println!(
    "-- Dataset bundler for corpus {:?} and service {:?} took {:?}ms",
    corpus.name, service.name, bundle_duration
  );
  println!("-- Bundled {:?} dataset entries.", total_dataset_entries);
}
<|endoftext|>