<commit_before>use libc::{c_int, c_uint, c_ulonglong};
use ffi::{core, target};
use ffi::execution_engine as engine;
use ffi::execution_engine::*;
use ffi::target_machine::LLVMCodeModel;
use cbox::CBox;
use std::marker::PhantomData;
use std::{mem, ptr};
use std::ops::*;
use compile::Compile;
use context::{Context, GetContext};
use module::Module;
use ty::{StructType, Type};
use util::{self, CastFrom};
use value::{Function, Value};

/// An abstract interface for implementation execution of LLVM modules.
///
/// This is designed to support both interpreter and just-in-time (JIT) compiler implementations.
pub trait ExecutionEngine<'a, 'b:'a> where LLVMExecutionEngineRef:From<&'b Self> {
    /// The options given to the engine upon creation.
    type Options : Copy;

    /// Create a new execution engine with the given `Module` and options, or return a
    /// description of the error.
    fn new(module: &'a Module, options: Self::Options) -> Result<Self, CBox<str>>;

    /// Add a module to the list of modules to interpret or compile.
    fn add_module(&'b self, module: &'a Module) {
        unsafe { engine::LLVMAddModule(self.into(), (&*module).into()) }
    }
    /// Remove a module from the list of modules to interpret or compile.
    fn remove_module(&'b self, module: &'a Module) -> &'a Module {
        unsafe {
            let mut out = mem::uninitialized();
            engine::LLVMRemoveModule(self.into(), module.into(), &mut out, ptr::null_mut());
            out.into()
        }
    }
    /// Execute all of the static constructors for this program.
    fn run_static_constructors(&'b self) {
        unsafe { engine::LLVMRunStaticConstructors(self.into()) }
    }
    /// Execute all of the static destructors for this program.
    fn run_static_destructors(&'b self) {
        unsafe { engine::LLVMRunStaticDestructors(self.into()) }
    }
    /// Attempt to find a function with the name given, or `None` if there wasn't
    /// a function with that name.
    fn find_function(&'b self, name: &str) -> Option<&'a Function> {
        util::with_cstr(name, |c_name| unsafe {
            let mut out = mem::zeroed();
            engine::LLVMFindFunction(self.into(), c_name, &mut out);
            mem::transmute(out)
        })
    }
    /// Run `function` with the arguments given as ``GenericValue`s, then return the result as one.
    ///
    /// Note that if this engine is a `JitEngine`, it only supports a small fraction of combinations
    /// for the arguments and return value, so be warned.
    ///
    /// To convert the arguments to `GenericValue`s, you should use the `GenericValueCast::to_generic` method.
    /// To convert the return value from a `GenericValue`, you should use the `GenericValueCast::from_generic` method.
    fn run_function(&'b self, function: &'a Function, args: &[GenericValue<'a>]) -> GenericValue<'a> {
        let ptr = args.as_ptr() as *mut LLVMGenericValueRef;
        unsafe { engine::LLVMRunFunction(self.into(), function.into(), args.len() as c_uint, ptr).into() }
    }
    /// Returns a pointer to the global value given.
    ///
    /// This is marked as unsafe because the type cannot be guranteed to be the same as the
    /// type of the global value at this point.
    unsafe fn get_global<T>(&'b self, global: &'a Value) -> &'b T {
        mem::transmute(engine::LLVMGetPointerToGlobal(self.into(), global.into()))
    }
    /// Returns a pointer to the global value with the name given.
    ///
    /// This is marked as unsafe because the type cannot be guranteed to be the same as the
    /// type of the global value at this point.
    unsafe fn find_global<T>(&'b self, name: &str) -> Option<&'b T> {
        util::with_cstr(name, |ptr|
            mem::transmute(engine::LLVMGetGlobalValueAddress(self.into(), ptr))
        )
    }
}

/// The options to pass to the MCJIT backend.
#[derive(Copy, Clone)]
pub struct JitOptions {
    /// The degree to which optimizations should be done, between 0 and 3.
    ///
    /// 0 represents no optimizations, 3 represents maximum optimization
    pub opt_level: usize
}
/// The MCJIT backend, which compiles functions and values into machine code.
pub struct JitEngine<'a> {
    engine: LLVMExecutionEngineRef,
    marker: PhantomData<&'a ()>
}
native_ref!{contra JitEngine, engine: LLVMExecutionEngineRef}
impl<'a, 'b> JitEngine<'a> {
    /// Run the closure `cb` with the machine code for the function `function`.
    ///
    /// This will check that the types match at runtime when in debug mode, but not release mode.
    /// You should make sure to use debug mode if you want it to error when the types don't match.
    pub fn with_function<C, A, R>(&self, function: &'b Function, cb: C) where A:Compile<'b>, R:Compile<'b>, C:FnOnce(extern fn(A) -> R) {
        if cfg!(not(ndebug)) {
            let ctx = function.get_context();
            let sig = function.get_signature();
            assert_eq!(Type::get::<R>(ctx), sig.get_return());
            let arg = Type::get::<A>(ctx);
            if let Some(args) = StructType::cast(arg) {
                assert_eq!(sig.get_params(), args.get_elements());

            } else {
              let nparams = sig.get_params().len();
              if nparams == 1 {
                assert_eq!(arg, sig.get_params()[0]);
              } else if nparams == 0 {
                assert_eq!(arg, Type::get::<()>(ctx));
              } else {
                panic!("array type arguments are not yet supported; use a tuple or struct instead");
              }
            }
        }
        unsafe {
            cb(self.get_function::<A, R>(function));
        }
    }
    /// Run the closure `cb` with the machine code for the function `function`.
    pub unsafe fn with_function_unchecked<C, A, R>(&self, function: &'b Function, cb: C) where A:Compile<'b>, R:Compile<'b>, C:FnOnce(extern fn(A) -> R) {
        cb(self.get_function::<A, R>(function));
    }
    /// Returns a pointer to the machine code for the function `function`.
    ///
    /// This is marked as unsafe because the types given as arguments and return could be different
    /// from their internal representation.
    pub unsafe fn get_function<A, R>(&self, function: &'b Function) -> extern fn(A) -> R {
        let ptr:&u8 = self.get_global(function);
        mem::transmute(ptr)
    }
}
impl<'a, 'b:'a> ExecutionEngine<'a, 'b> for JitEngine<'a> {
    type Options = JitOptions;
    fn new(module: &'a Module, options: JitOptions) -> Result<JitEngine<'a>, CBox<str>> {
        unsafe {
            let mut ee = mem::uninitialized();
            let mut out = mem::zeroed();
            engine::LLVMLinkInMCJIT();
            if target::LLVM_InitializeNativeTarget() == 1 {
                return Err("failed to initialize native target".into())
            }
            if target::LLVM_InitializeNativeAsmPrinter() == 1 {
                return Err("failed to initialize native asm printer".into())
            }
            let mut options = LLVMMCJITCompilerOptions {
                OptLevel: options.opt_level as c_uint,
                CodeModel: LLVMCodeModel::LLVMCodeModelDefault,
                NoFramePointerElim: 0,
                EnableFastISel: 1,
                MCJMM: ptr::null_mut()
            };
            let size = mem::size_of::<LLVMMCJITCompilerOptions>();
            let result = engine::LLVMCreateMCJITCompilerForModule(&mut ee, (&*module).into(), &mut options, size as u64, &mut out);
            if result == 0 {
                Ok(ee.into())
            } else {
                Err(CBox::new(out))
            }
        }
    }
}
/// The interpreter backend
pub struct Interpreter<'a> {
    engine: LLVMExecutionEngineRef,
    marker: PhantomData<&'a ()>
}
native_ref!{contra Interpreter, engine: LLVMExecutionEngineRef}
impl<'a> Interpreter<'a> {
    /// Run `function` with the arguments given as ``GenericValue`s, then return the result as one.
    ///
    /// To convert the arguments to `GenericValue`s, you should use the `GenericValueCast::to_generic` method.
    /// To convert the return value from a `GenericValue`, you should use the `GenericValueCast::from_generic` method.
    pub fn run_function(&self, function: &'a Function, args: &[GenericValue<'a>]) -> GenericValue<'a> {
        let ptr = args.as_ptr() as *mut LLVMGenericValueRef;
        unsafe { engine::LLVMRunFunction(self.into(), function.into(), args.len() as c_uint, ptr).into() }
    }
}
impl<'a, 'b:'a> ExecutionEngine<'a, 'b> for Interpreter<'a> {
    type Options = ();
    fn new(module: &'a Module, _: ()) -> Result<Interpreter<'a>, CBox<str>> {
        unsafe {
            let mut ee = mem::uninitialized();
            let mut out = mem::zeroed();
            engine::LLVMLinkInInterpreter();
            let result = engine::LLVMCreateInterpreterForModule(&mut ee, (&*module).into(), &mut out);
            if result == 0 {
                Ok(ee.into())
            } else {
                Err(CBox::new(out))
            }
        }
    }
}
/// A wrapped value that can be passed to an interpreted function or returned from one
pub struct GenericValue<'a> {
    value: LLVMGenericValueRef,
    marker: PhantomData<&'a ()>
}
native_ref!(contra GenericValue, value: LLVMGenericValueRef);
impl<'a> Drop for GenericValue<'a> {
    fn drop(&mut self) {
        unsafe {
            engine::LLVMDisposeGenericValue(self.value)
        }
    }
}

/// A value that can be cast into a `GenericValue` and that a `GenericValue` can be cast into.
///
/// Both these methods require contexts because some `Type` constructors are needed for the
/// conversion and these constructors need a context.
pub trait GenericValueCast<'a> {
    /// Create a `GenericValue` from this value.
    fn to_generic(self, context: &'a Context) -> GenericValue<'a>;
    /// Convert the `GenericValue` into a value of this type again.
    fn from_generic(value: GenericValue<'a>, context: &'a Context) -> Self;
}

impl<'a> GenericValueCast<'a> for f64 {
    fn to_generic(self, ctx: &'a Context) -> GenericValue<'a> {
        unsafe {
            let ty = core::LLVMDoubleTypeInContext(ctx.into());
            engine::LLVMCreateGenericValueOfFloat(ty, self).into()
        }
    }
    fn from_generic(value: GenericValue<'a>, ctx: &'a Context) -> f64 {
        unsafe {
            let ty = core::LLVMDoubleTypeInContext(ctx.into());
            engine::LLVMGenericValueToFloat(ty, value.into())
        }
    }
}
impl<'a> GenericValueCast<'a> for f32 {
    fn to_generic(self, ctx: &'a Context) -> GenericValue<'a> {
        unsafe {
            let ty = core::LLVMFloatTypeInContext(ctx.into());
            engine::LLVMCreateGenericValueOfFloat(ty, self as f64).into()
        }
    }
    fn from_generic(value: GenericValue<'a>, ctx: &'a Context) -> f32 {
        unsafe {
            let ty = core::LLVMFloatTypeInContext(ctx.into());
            engine::LLVMGenericValueToFloat(ty, value.into()) as f32
        }
    }
}
macro_rules! generic_int(
    ($ty:ty, $signed:expr) => (
        impl<'a> GenericValueCast<'a> for $ty {
            fn to_generic(self, ctx: &'a Context) -> GenericValue<'a> {
                unsafe {
                    let ty = <Self as Compile<'a>>::get_type(ctx);
                    engine::LLVMCreateGenericValueOfInt(ty.into(), self as c_ulonglong, $signed as c_int).into()
                }
            }
            fn from_generic(value: GenericValue<'a>, _: &'a Context) -> $ty {
                unsafe {
                    engine::LLVMGenericValueToInt(value.into(), $signed as c_int) as $ty
                }
            }
        }
    );
    (some $signed:ty, $unsigned:ty) => (
        generic_int!{$signed, true}
        generic_int!{$unsigned, false}
    );
);

impl<'a> GenericValueCast<'a> for bool {
    fn to_generic(self, ctx: &'a Context) -> GenericValue<'a> {
        unsafe {
            let ty = <Self as Compile<'a>>::get_type(ctx);
            engine::LLVMCreateGenericValueOfInt(ty.into(), self as c_ulonglong, 0).into()
        }
    }
    fn from_generic(value: GenericValue<'a>, _: &'a Context) -> bool {
        unsafe {
            engine::LLVMGenericValueToInt(value.into(), 0) != 0
        }
    }
}
generic_int!{some i8, u8}
generic_int!{some i16, u16}
generic_int!{some i32, u32}
generic_int!{some i64, u64}
<commit_msg>Make the JIT use the JITDefault code model, fixes segfault with globals.<commit_after>use libc::{c_int, c_uint, c_ulonglong};
use ffi::{core, target};
use ffi::execution_engine as engine;
use ffi::execution_engine::*;
use ffi::target_machine::LLVMCodeModel;
use cbox::CBox;
use std::marker::PhantomData;
use std::{mem, ptr};
use std::ops::*;
use compile::Compile;
use context::{Context, GetContext};
use module::Module;
use ty::{StructType, Type};
use util::{self, CastFrom};
use value::{Function, Value};

/// An abstract interface for implementation execution of LLVM modules.
///
/// This is designed to support both interpreter and just-in-time (JIT) compiler implementations.
pub trait ExecutionEngine<'a, 'b:'a> where LLVMExecutionEngineRef:From<&'b Self> {
    /// The options given to the engine upon creation.
    type Options : Copy;

    /// Create a new execution engine with the given `Module` and options, or return a
    /// description of the error.
    fn new(module: &'a Module, options: Self::Options) -> Result<Self, CBox<str>>;

    /// Add a module to the list of modules to interpret or compile.
    fn add_module(&'b self, module: &'a Module) {
        unsafe { engine::LLVMAddModule(self.into(), (&*module).into()) }
    }
    /// Remove a module from the list of modules to interpret or compile.
    fn remove_module(&'b self, module: &'a Module) -> &'a Module {
        unsafe {
            let mut out = mem::uninitialized();
            engine::LLVMRemoveModule(self.into(), module.into(), &mut out, ptr::null_mut());
            out.into()
        }
    }
    /// Execute all of the static constructors for this program.
    fn run_static_constructors(&'b self) {
        unsafe { engine::LLVMRunStaticConstructors(self.into()) }
    }
    /// Execute all of the static destructors for this program.
    fn run_static_destructors(&'b self) {
        unsafe { engine::LLVMRunStaticDestructors(self.into()) }
    }
    /// Attempt to find a function with the name given, or `None` if there wasn't
    /// a function with that name.
    fn find_function(&'b self, name: &str) -> Option<&'a Function> {
        util::with_cstr(name, |c_name| unsafe {
            let mut out = mem::zeroed();
            engine::LLVMFindFunction(self.into(), c_name, &mut out);
            mem::transmute(out)
        })
    }
    /// Run `function` with the arguments given as ``GenericValue`s, then return the result as one.
    ///
    /// Note that if this engine is a `JitEngine`, it only supports a small fraction of combinations
    /// for the arguments and return value, so be warned.
    ///
    /// To convert the arguments to `GenericValue`s, you should use the `GenericValueCast::to_generic` method.
    /// To convert the return value from a `GenericValue`, you should use the `GenericValueCast::from_generic` method.
    fn run_function(&'b self, function: &'a Function, args: &[GenericValue<'a>]) -> GenericValue<'a> {
        let ptr = args.as_ptr() as *mut LLVMGenericValueRef;
        unsafe { engine::LLVMRunFunction(self.into(), function.into(), args.len() as c_uint, ptr).into() }
    }
    /// Returns a pointer to the global value given.
    ///
    /// This is marked as unsafe because the type cannot be guranteed to be the same as the
    /// type of the global value at this point.
    unsafe fn get_global<T>(&'b self, global: &'a Value) -> &'b T {
        mem::transmute(engine::LLVMGetPointerToGlobal(self.into(), global.into()))
    }
    /// Returns a pointer to the global value with the name given.
    ///
    /// This is marked as unsafe because the type cannot be guranteed to be the same as the
    /// type of the global value at this point.
    unsafe fn find_global<T>(&'b self, name: &str) -> Option<&'b T> {
        util::with_cstr(name, |ptr|
            mem::transmute(engine::LLVMGetGlobalValueAddress(self.into(), ptr))
        )
    }
}

/// The options to pass to the MCJIT backend.
#[derive(Copy, Clone)]
pub struct JitOptions {
    /// The degree to which optimizations should be done, between 0 and 3.
    ///
    /// 0 represents no optimizations, 3 represents maximum optimization
    pub opt_level: usize
}
/// The MCJIT backend, which compiles functions and values into machine code.
pub struct JitEngine<'a> {
    engine: LLVMExecutionEngineRef,
    marker: PhantomData<&'a ()>
}
native_ref!{contra JitEngine, engine: LLVMExecutionEngineRef}
impl<'a, 'b> JitEngine<'a> {
    /// Run the closure `cb` with the machine code for the function `function`.
    ///
    /// This will check that the types match at runtime when in debug mode, but not release mode.
    /// You should make sure to use debug mode if you want it to error when the types don't match.
    pub fn with_function<C, A, R>(&self, function: &'b Function, cb: C) where A:Compile<'b>, R:Compile<'b>, C:FnOnce(extern fn(A) -> R) {
        if cfg!(not(ndebug)) {
            let ctx = function.get_context();
            let sig = function.get_signature();
            assert_eq!(Type::get::<R>(ctx), sig.get_return());
            let arg = Type::get::<A>(ctx);
            if let Some(args) = StructType::cast(arg) {
                assert_eq!(sig.get_params(), args.get_elements());

            } else {
              let nparams = sig.get_params().len();
              if nparams == 1 {
                assert_eq!(arg, sig.get_params()[0]);
              } else if nparams == 0 {
                assert_eq!(arg, Type::get::<()>(ctx));
              } else {
                panic!("array type arguments are not yet supported; use a tuple or struct instead");
              }
            }
        }
        unsafe {
            cb(self.get_function::<A, R>(function));
        }
    }
    /// Run the closure `cb` with the machine code for the function `function`.
    pub unsafe fn with_function_unchecked<C, A, R>(&self, function: &'b Function, cb: C) where A:Compile<'b>, R:Compile<'b>, C:FnOnce(extern fn(A) -> R) {
        cb(self.get_function::<A, R>(function));
    }
    /// Returns a pointer to the machine code for the function `function`.
    ///
    /// This is marked as unsafe because the types given as arguments and return could be different
    /// from their internal representation.
    pub unsafe fn get_function<A, R>(&self, function: &'b Function) -> extern fn(A) -> R {
        let ptr:&u8 = self.get_global(function);
        mem::transmute(ptr)
    }
}
impl<'a, 'b:'a> ExecutionEngine<'a, 'b> for JitEngine<'a> {
    type Options = JitOptions;
    fn new(module: &'a Module, options: JitOptions) -> Result<JitEngine<'a>, CBox<str>> {
        unsafe {
            let mut ee = mem::uninitialized();
            let mut out = mem::zeroed();
            engine::LLVMLinkInMCJIT();
            if target::LLVM_InitializeNativeTarget() == 1 {
                return Err("failed to initialize native target".into())
            }
            if target::LLVM_InitializeNativeAsmPrinter() == 1 {
                return Err("failed to initialize native asm printer".into())
            }
            let mut options = LLVMMCJITCompilerOptions {
                OptLevel: options.opt_level as c_uint,
                CodeModel: LLVMCodeModel::LLVMCodeModelJITDefault,
                NoFramePointerElim: 0,
                EnableFastISel: 1,
                MCJMM: ptr::null_mut()
            };
            let size = mem::size_of::<LLVMMCJITCompilerOptions>();
            let result = engine::LLVMCreateMCJITCompilerForModule(&mut ee, (&*module).into(), &mut options, size as u64, &mut out);
            if result == 0 {
                Ok(ee.into())
            } else {
                Err(CBox::new(out))
            }
        }
    }
}
/// The interpreter backend
pub struct Interpreter<'a> {
    engine: LLVMExecutionEngineRef,
    marker: PhantomData<&'a ()>
}
native_ref!{contra Interpreter, engine: LLVMExecutionEngineRef}
impl<'a> Interpreter<'a> {
    /// Run `function` with the arguments given as ``GenericValue`s, then return the result as one.
    ///
    /// To convert the arguments to `GenericValue`s, you should use the `GenericValueCast::to_generic` method.
    /// To convert the return value from a `GenericValue`, you should use the `GenericValueCast::from_generic` method.
    pub fn run_function(&self, function: &'a Function, args: &[GenericValue<'a>]) -> GenericValue<'a> {
        let ptr = args.as_ptr() as *mut LLVMGenericValueRef;
        unsafe { engine::LLVMRunFunction(self.into(), function.into(), args.len() as c_uint, ptr).into() }
    }
}
impl<'a, 'b:'a> ExecutionEngine<'a, 'b> for Interpreter<'a> {
    type Options = ();
    fn new(module: &'a Module, _: ()) -> Result<Interpreter<'a>, CBox<str>> {
        unsafe {
            let mut ee = mem::uninitialized();
            let mut out = mem::zeroed();
            engine::LLVMLinkInInterpreter();
            let result = engine::LLVMCreateInterpreterForModule(&mut ee, (&*module).into(), &mut out);
            if result == 0 {
                Ok(ee.into())
            } else {
                Err(CBox::new(out))
            }
        }
    }
}
/// A wrapped value that can be passed to an interpreted function or returned from one
pub struct GenericValue<'a> {
    value: LLVMGenericValueRef,
    marker: PhantomData<&'a ()>
}
native_ref!(contra GenericValue, value: LLVMGenericValueRef);
impl<'a> Drop for GenericValue<'a> {
    fn drop(&mut self) {
        unsafe {
            engine::LLVMDisposeGenericValue(self.value)
        }
    }
}

/// A value that can be cast into a `GenericValue` and that a `GenericValue` can be cast into.
///
/// Both these methods require contexts because some `Type` constructors are needed for the
/// conversion and these constructors need a context.
pub trait GenericValueCast<'a> {
    /// Create a `GenericValue` from this value.
    fn to_generic(self, context: &'a Context) -> GenericValue<'a>;
    /// Convert the `GenericValue` into a value of this type again.
    fn from_generic(value: GenericValue<'a>, context: &'a Context) -> Self;
}

impl<'a> GenericValueCast<'a> for f64 {
    fn to_generic(self, ctx: &'a Context) -> GenericValue<'a> {
        unsafe {
            let ty = core::LLVMDoubleTypeInContext(ctx.into());
            engine::LLVMCreateGenericValueOfFloat(ty, self).into()
        }
    }
    fn from_generic(value: GenericValue<'a>, ctx: &'a Context) -> f64 {
        unsafe {
            let ty = core::LLVMDoubleTypeInContext(ctx.into());
            engine::LLVMGenericValueToFloat(ty, value.into())
        }
    }
}
impl<'a> GenericValueCast<'a> for f32 {
    fn to_generic(self, ctx: &'a Context) -> GenericValue<'a> {
        unsafe {
            let ty = core::LLVMFloatTypeInContext(ctx.into());
            engine::LLVMCreateGenericValueOfFloat(ty, self as f64).into()
        }
    }
    fn from_generic(value: GenericValue<'a>, ctx: &'a Context) -> f32 {
        unsafe {
            let ty = core::LLVMFloatTypeInContext(ctx.into());
            engine::LLVMGenericValueToFloat(ty, value.into()) as f32
        }
    }
}
macro_rules! generic_int(
    ($ty:ty, $signed:expr) => (
        impl<'a> GenericValueCast<'a> for $ty {
            fn to_generic(self, ctx: &'a Context) -> GenericValue<'a> {
                unsafe {
                    let ty = <Self as Compile<'a>>::get_type(ctx);
                    engine::LLVMCreateGenericValueOfInt(ty.into(), self as c_ulonglong, $signed as c_int).into()
                }
            }
            fn from_generic(value: GenericValue<'a>, _: &'a Context) -> $ty {
                unsafe {
                    engine::LLVMGenericValueToInt(value.into(), $signed as c_int) as $ty
                }
            }
        }
    );
    (some $signed:ty, $unsigned:ty) => (
        generic_int!{$signed, true}
        generic_int!{$unsigned, false}
    );
);

impl<'a> GenericValueCast<'a> for bool {
    fn to_generic(self, ctx: &'a Context) -> GenericValue<'a> {
        unsafe {
            let ty = <Self as Compile<'a>>::get_type(ctx);
            engine::LLVMCreateGenericValueOfInt(ty.into(), self as c_ulonglong, 0).into()
        }
    }
    fn from_generic(value: GenericValue<'a>, _: &'a Context) -> bool {
        unsafe {
            engine::LLVMGenericValueToInt(value.into(), 0) != 0
        }
    }
}
generic_int!{some i8, u8}
generic_int!{some i16, u16}
generic_int!{some i32, u32}
generic_int!{some i64, u64}
<|endoftext|>


<commit_before>use serde_json;
use std::convert::Into;
use std::error::Error as StdError;
use std::fmt;

/// The kind of an error (non-exhaustive)
#[derive(Debug)]
pub enum ErrorKind {
    /// Generic error
    Msg(String),
    /// A loop was found while looking up the inheritance chain
    CircularExtend {
        /// Name of the template with the loop
        tpl: String,
        /// All the parents templates we found so far
        inheritance_chain: Vec<String>,
    },
    /// A template is extending a template that wasn't found in the Tera instance
    MissingParent {
        /// The template we are currently looking at
        current: String,
        /// The missing template
        parent: String,
    },
    /// A template was missing (more generic version of MissingParent)
    TemplateNotFound(String),
    /// A filter wasn't found
    FilterNotFound(String),
    /// A test wasn't found
    TestNotFound(String),
    /// A function wasn't found
    FunctionNotFound(String),
    /// An error happened while serializing JSON
    Json(serde_json::Error),
    /// This enum may grow additional variants, so this makes sure clients
    /// don't count on exhaustive matching. (Otherwise, adding a new variant
    /// could break existing code.)
    #[doc(hidden)]
    __Nonexhaustive,
}

/// The Error type
#[derive(Debug)]
pub struct Error {
    /// Kind of error
    pub kind: ErrorKind,
    source: Option<Box<dyn StdError>>,
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.kind {
            ErrorKind::Msg(ref message) => write!(f, "{}", message),
            ErrorKind::CircularExtend { ref tpl, ref inheritance_chain } => write!(
                f,
                "Circular extend detected for template '{}'. Inheritance chain: `{:?}`",
                tpl, inheritance_chain
            ),
            ErrorKind::MissingParent { ref current, ref parent } => write!(
                f,
                "Template '{}' is inheriting from '{}', which doesn't exist or isn't loaded.",
                current, parent
            ),
            ErrorKind::TemplateNotFound(ref name) => write!(f, "Template '{}' not found", name),
            ErrorKind::FilterNotFound(ref name) => write!(f, "Filter '{}' not found", name),
            ErrorKind::TestNotFound(ref name) => write!(f, "Test '{}' not found", name),
            ErrorKind::FunctionNotFound(ref name) => write!(f, "Function '{}' not found", name),
            ErrorKind::Json(ref e) => write!(f, "{}", e),
            ErrorKind::__Nonexhaustive => write!(f, "Nonexhaustive"),
        }
    }
}

impl StdError for Error {
    fn source(&self) -> Option<&(dyn StdError + 'static)> {
        self.source.as_ref().map(|c| &**c)
    }
}

impl Error {
    /// Creates generic error
    pub fn msg(value: impl ToString) -> Self {
        Self { kind: ErrorKind::Msg(value.to_string()), source: None }
    }

    /// Creates a circular extend error
    pub fn circular_extend(tpl: impl ToString, inheritance_chain: Vec<String>) -> Self {
        Self {
            kind: ErrorKind::CircularExtend { tpl: tpl.to_string(), inheritance_chain },
            source: None,
        }
    }

    /// Creates a missing parent error
    pub fn missing_parent(current: impl ToString, parent: impl ToString) -> Self {
        Self {
            kind: ErrorKind::MissingParent {
                current: current.to_string(),
                parent: parent.to_string(),
            },
            source: None,
        }
    }

    /// Creates a template not found error
    pub fn template_not_found(tpl: impl ToString) -> Self {
        Self { kind: ErrorKind::TemplateNotFound(tpl.to_string()), source: None }
    }

    /// Creates a filter not found error
    pub fn filter_not_found(name: impl ToString) -> Self {
        Self { kind: ErrorKind::FilterNotFound(name.to_string()), source: None }
    }

    /// Creates a test not found error
    pub fn test_not_found(name: impl ToString) -> Self {
        Self { kind: ErrorKind::TestNotFound(name.to_string()), source: None }
    }

    /// Creates a function not found error
    pub fn function_not_found(name: impl ToString) -> Self {
        Self { kind: ErrorKind::FunctionNotFound(name.to_string()), source: None }
    }

    /// Creates generic error with a source
    pub fn chain(value: impl ToString, source: impl Into<Box<dyn StdError>>) -> Self {
        Self { kind: ErrorKind::Msg(value.to_string()), source: Some(source.into()) }
    }

    /// Creates JSON error
    pub fn json(value: serde_json::Error) -> Self {
        Self { kind: ErrorKind::Json(value), source: None }
    }
}

/// Convenient wrapper around std::Result.
pub type Result<T> = ::std::result::Result<T, Error>;
<commit_msg>Add some From impl for Error<commit_after>use serde_json;
use std::convert::Into;
use std::error::Error as StdError;
use std::fmt;

/// The kind of an error (non-exhaustive)
#[derive(Debug)]
pub enum ErrorKind {
    /// Generic error
    Msg(String),
    /// A loop was found while looking up the inheritance chain
    CircularExtend {
        /// Name of the template with the loop
        tpl: String,
        /// All the parents templates we found so far
        inheritance_chain: Vec<String>,
    },
    /// A template is extending a template that wasn't found in the Tera instance
    MissingParent {
        /// The template we are currently looking at
        current: String,
        /// The missing template
        parent: String,
    },
    /// A template was missing (more generic version of MissingParent)
    TemplateNotFound(String),
    /// A filter wasn't found
    FilterNotFound(String),
    /// A test wasn't found
    TestNotFound(String),
    /// A function wasn't found
    FunctionNotFound(String),
    /// An error happened while serializing JSON
    Json(serde_json::Error),
    /// This enum may grow additional variants, so this makes sure clients
    /// don't count on exhaustive matching. (Otherwise, adding a new variant
    /// could break existing code.)
    #[doc(hidden)]
    __Nonexhaustive,
}

/// The Error type
#[derive(Debug)]
pub struct Error {
    /// Kind of error
    pub kind: ErrorKind,
    source: Option<Box<dyn StdError>>,
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.kind {
            ErrorKind::Msg(ref message) => write!(f, "{}", message),
            ErrorKind::CircularExtend { ref tpl, ref inheritance_chain } => write!(
                f,
                "Circular extend detected for template '{}'. Inheritance chain: `{:?}`",
                tpl, inheritance_chain
            ),
            ErrorKind::MissingParent { ref current, ref parent } => write!(
                f,
                "Template '{}' is inheriting from '{}', which doesn't exist or isn't loaded.",
                current, parent
            ),
            ErrorKind::TemplateNotFound(ref name) => write!(f, "Template '{}' not found", name),
            ErrorKind::FilterNotFound(ref name) => write!(f, "Filter '{}' not found", name),
            ErrorKind::TestNotFound(ref name) => write!(f, "Test '{}' not found", name),
            ErrorKind::FunctionNotFound(ref name) => write!(f, "Function '{}' not found", name),
            ErrorKind::Json(ref e) => write!(f, "{}", e),
            ErrorKind::__Nonexhaustive => write!(f, "Nonexhaustive"),
        }
    }
}

impl StdError for Error {
    fn source(&self) -> Option<&(dyn StdError + 'static)> {
        self.source.as_ref().map(|c| &**c)
    }
}

impl Error {
    /// Creates generic error
    pub fn msg(value: impl ToString) -> Self {
        Self { kind: ErrorKind::Msg(value.to_string()), source: None }
    }

    /// Creates a circular extend error
    pub fn circular_extend(tpl: impl ToString, inheritance_chain: Vec<String>) -> Self {
        Self {
            kind: ErrorKind::CircularExtend { tpl: tpl.to_string(), inheritance_chain },
            source: None,
        }
    }

    /// Creates a missing parent error
    pub fn missing_parent(current: impl ToString, parent: impl ToString) -> Self {
        Self {
            kind: ErrorKind::MissingParent {
                current: current.to_string(),
                parent: parent.to_string(),
            },
            source: None,
        }
    }

    /// Creates a template not found error
    pub fn template_not_found(tpl: impl ToString) -> Self {
        Self { kind: ErrorKind::TemplateNotFound(tpl.to_string()), source: None }
    }

    /// Creates a filter not found error
    pub fn filter_not_found(name: impl ToString) -> Self {
        Self { kind: ErrorKind::FilterNotFound(name.to_string()), source: None }
    }

    /// Creates a test not found error
    pub fn test_not_found(name: impl ToString) -> Self {
        Self { kind: ErrorKind::TestNotFound(name.to_string()), source: None }
    }

    /// Creates a function not found error
    pub fn function_not_found(name: impl ToString) -> Self {
        Self { kind: ErrorKind::FunctionNotFound(name.to_string()), source: None }
    }

    /// Creates generic error with a source
    pub fn chain(value: impl ToString, source: impl Into<Box<dyn StdError>>) -> Self {
        Self { kind: ErrorKind::Msg(value.to_string()), source: Some(source.into()) }
    }

    /// Creates JSON error
    pub fn json(value: serde_json::Error) -> Self {
        Self { kind: ErrorKind::Json(value), source: None }
    }
}

impl From<&str> for Error {
    fn from(e: &str) -> Self {
        Self::msg(e)
    }
}
impl From<String> for Error {
    fn from(e: String) -> Self {
        Self::msg(e)
    }
}
impl From<serde_json::Error> for Error {
    fn from(e: serde_json::Error) -> Self {
        Self::json(e)
    }
}
/// Convenient wrapper around std::Result.
pub type Result<T> = ::std::result::Result<T, Error>;
<|endoftext|>


<commit_before>extern crate r2d2;

quick_error! {
    /// The most generic error message in ReQL
    #[derive(Debug)]
    pub enum Error {
        Compile(descr: &'static str) {}
        Runtime(err: RuntimeError) {}
        Driver(err: DriverError) {}
    }
}

quick_error! {
    /// The parent class of all runtime errors
    ///
    /// All errors on the server unrelated to compilation. Programs may use this to catch any runtime
    /// error, but the server will always return a more specific error class.
    #[derive(Debug)]
    pub enum RuntimeError {
        QueryLogic(err: QueryLogicError) {}
        ResourceLimit(descr: &'static str) {}
        User(descr: &'static str) {}
        Internal(descr: &'static str) {}
        Timeout(descr: &'static str) {}
        Availability(err: AvailabilityError) {}
        Permissions(descr: &'static str) {}
    }
}

quick_error! {
    /// The query contains a logical impossibility, such as adding a number to a string.
    #[derive(Debug)]
    pub enum QueryLogicError {
        NonExistence(descr: &'static str) {}
    }
}

quick_error! {
    /// A server in the cluster is unavailable
    ///
    /// The parent class of `OpFailedError` and `OpIndeterminateError`. Programs may use this
    /// to catch any availability error, but the server will always return one of this class’s
    /// children.
    #[derive(Debug)]
    pub enum AvailabilityError {
        OpFailed(descr: &'static str) {}
        OpIndeterminate(descr: &'static str) {}
    }
}

quick_error! {
    /// An error has occurred within the driver
    ///
    /// This may be a driver bug, or it may be an unfulfillable command, such as an unserializable
    /// query.
    #[derive(Debug)]
    pub enum DriverError {
        Auth(descr: &'static str) {}
        Initialization(err: r2d2::InitializationError) {}
    }
}
<commit_msg>Initialization: Add From implementation<commit_after>extern crate r2d2;

quick_error! {
    /// The most generic error message in ReQL
    #[derive(Debug)]
    pub enum Error {
        Compile(descr: &'static str) {}
        Runtime(err: RuntimeError) {}
        Driver(err: DriverError) {}
    }
}

quick_error! {
    /// The parent class of all runtime errors
    ///
    /// All errors on the server unrelated to compilation. Programs may use this to catch any runtime
    /// error, but the server will always return a more specific error class.
    #[derive(Debug)]
    pub enum RuntimeError {
        QueryLogic(err: QueryLogicError) {}
        ResourceLimit(descr: &'static str) {}
        User(descr: &'static str) {}
        Internal(descr: &'static str) {}
        Timeout(descr: &'static str) {}
        Availability(err: AvailabilityError) {}
        Permissions(descr: &'static str) {}
    }
}

quick_error! {
    /// The query contains a logical impossibility, such as adding a number to a string.
    #[derive(Debug)]
    pub enum QueryLogicError {
        NonExistence(descr: &'static str) {}
    }
}

quick_error! {
    /// A server in the cluster is unavailable
    ///
    /// The parent class of `OpFailedError` and `OpIndeterminateError`. Programs may use this
    /// to catch any availability error, but the server will always return one of this class’s
    /// children.
    #[derive(Debug)]
    pub enum AvailabilityError {
        OpFailed(descr: &'static str) {}
        OpIndeterminate(descr: &'static str) {}
    }
}

quick_error! {
    /// An error has occurred within the driver
    ///
    /// This may be a driver bug, or it may be an unfulfillable command, such as an unserializable
    /// query.
    #[derive(Debug)]
    pub enum DriverError {
        Auth(descr: &'static str) {}
        Initialization(err: r2d2::InitializationError) {
            from()
        }
    }
}
<|endoftext|>


<commit_before>use super::common::Log;

use hyper;
use serde_json;
use std::io::Read;

const LOG_LIST_URL: &'static str = "https://www.gstatic.com/ct/log_list/log_list.json";
#[derive(Deserialize)]
struct LogsResponseLogs {
    description: String,
    url: String,
    operated_by: Vec<u32>,
    disqualified_at: Option<u64>,
}

#[derive(Deserialize)]
struct LogsResponseOperators {
    name: String,
    id: u32,
}

#[derive(Deserialize)]
struct LogsResponse {
    logs: Vec<LogsResponseLogs>,
    operators: Vec<LogsResponseOperators>,
}

pub fn fetch_trusted_ct_logs(http_client: &hyper::Client) -> Vec<Log> {
    let response = http_client.get(LOG_LIST_URL).send().unwrap();
    // Limit the response to 10MB at most, to be resillient to DoS.
    let logs_response: LogsResponse = serde_json::from_reader(response.take(10 * 1024 * 1024))
        .unwrap();

    let google_id = logs_response
        .operators
        .iter()
        .find(|o| o.name == "Google")
        .map(|o| o.id);

    logs_response
        .logs
        .into_iter()
        .filter(|log| log.disqualified_at.is_none())
        .map(|log| {
                 Log {
                     url: log.url,
                     description: log.description,
                     is_google: log.operated_by.contains(&google_id.unwrap()),
                 }
             })
        .collect()
}
<commit_msg>cargo fmt<commit_after>use super::common::Log;

use hyper;
use serde_json;
use std::io::Read;

const LOG_LIST_URL: &'static str = "https://www.gstatic.com/ct/log_list/log_list.json";
#[derive(Deserialize)]
struct LogsResponseLogs {
    description: String,
    url: String,
    operated_by: Vec<u32>,
    disqualified_at: Option<u64>,
}

#[derive(Deserialize)]
struct LogsResponseOperators {
    name: String,
    id: u32,
}

#[derive(Deserialize)]
struct LogsResponse {
    logs: Vec<LogsResponseLogs>,
    operators: Vec<LogsResponseOperators>,
}

pub fn fetch_trusted_ct_logs(http_client: &hyper::Client) -> Vec<Log> {
    let response = http_client.get(LOG_LIST_URL).send().unwrap();
    // Limit the response to 10MB at most, to be resillient to DoS.
    let logs_response: LogsResponse = serde_json::from_reader(response.take(10 * 1024 * 1024))
        .unwrap();

    let google_id = logs_response
        .operators
        .iter()
        .find(|o| o.name == "Google")
        .map(|o| o.id);

    logs_response
        .logs
        .into_iter()
        .filter(|log| log.disqualified_at.is_none())
        .map(|log| {
            Log {
                url: log.url,
                description: log.description,
                is_google: log.operated_by.contains(&google_id.unwrap()),
            }
        })
        .collect()
}
<|endoftext|>


<commit_before>
use BuildQuery;
use Groups;

// https://docs.gitlab.com/ce/api/groups.html
// List groups:                 GET /groups
// List owned groups:           GET /groups/owned
// List a group's projects:     GET /groups/:id/projects
// Details of a group:          GET /groups/:id
// New group:                   POST /groups
// Transfer project to group:   POST  /groups/:id/projects/:project_id
// Update group:                PUT /groups/:id
// Remove group:                DELETE /groups/:id
// Search for group:            GET /groups?search=foobar

// https://docs.gitlab.com/ce/api/groups.html#list-groups

#[derive(Debug, Copy, Clone)]
enum GroupListerOptionsOrderBy {
    Name,
    Path,
}

// impl Default for GroupListerOptionsOrderBy {
//     fn default() -> GroupListerOptionsOrderBy { GroupListerOptionsOrderBy::Name }
// }

#[derive(Debug, Copy, Clone)]
enum GroupListerOptionsSort {
    Asc,
    Desc,
}

// impl Default for GroupListerOptionsSort {
//     fn default() -> GroupListerOptionsSort { GroupListerOptionsSort::Asc }
// }

fn append_group_lister_options_order_by(order_by: GroupListerOptionsOrderBy, s: &mut String) {
    s.push_str(match order_by {
        GroupListerOptionsOrderBy::Name => "name",
        GroupListerOptionsOrderBy::Path => "path",
    });
}

fn append_group_lister_options_sort(order_by: GroupListerOptionsSort, s: &mut String) {
    s.push_str(match order_by {
        GroupListerOptionsSort::Asc => "asc",
        GroupListerOptionsSort::Desc => "desc",
    });
}

/// https://docs.gitlab.com/ce/api/groups.html#list-groups
#[derive(Default, Debug)]
struct GroupListerOptions {
    /// Skip the group IDs passes
    pub skip_groups: Option<Vec<i64>>,
    /// Show all the groups you have access to
    pub all_available: Option<bool>,
    /// Return list of authorized groups matching the search criteria
    pub search: Option<String>,
    /// Order groups by `name` or `path`. Default is `name`
    pub order_by: Option<GroupListerOptionsOrderBy>,
    /// Order groups in `asc` or `desc` order. Default is `asc`
    pub sort: Option<GroupListerOptionsSort>,
}

#[derive(Default, Debug)]
pub struct GroupListing {
    options: GroupListerOptions,
}

impl BuildQuery for GroupListing {
    fn build_query(&self) -> String {

        let options = &self.options;

        let mut query = String::from("groups");
        let mut previous_option_present = false;

        let amp_char = "&";
        let none_char = "";
        let split_char = &none_char;

        // Append a "?", only if one of the `Option` is `Some(_)`
        query.push_str(match (&options.skip_groups,
                              &options.all_available,
                              &options.search,
                              &options.order_by,
                              &options.sort) {
            (&None, &None, &None, &None, &None) => "",
            _ => "?",
        });

        options.skip_groups.as_ref().map(|skip_groups| {
            if previous_option_present && !skip_groups.is_empty() {
                query.push_str(&amp_char);
            }
            let mut array_split_char = &none_char;
            for &skip_group in skip_groups {
                query.push_str(array_split_char);
                query.push_str("skip_groups[]=");
                query.push_str(&skip_group.to_string());
                array_split_char = &amp_char;
            }
            previous_option_present = true;
        });

        options.all_available.map(|all_available| {
            if previous_option_present {
                query.push_str("&");
            }
            if all_available {
                query.push_str("all_available=true")
            } else {
                query.push_str("all_available=false")
            }
            previous_option_present = true;
        });

        options.search.as_ref().map(|search| {
            if previous_option_present {
                query.push_str("&");
            }
            query.push_str("search=");
            query.push_str(search);
            previous_option_present = true;
        });

        options.order_by.map(|order_by| {
            if previous_option_present {
                query.push_str("&");
            }
            query.push_str("order_by=");
            append_group_lister_options_order_by(order_by, &mut query);
            previous_option_present = true;
        });

        options.sort.map(|sort| {
            if previous_option_present {
                query.push_str("&");
            }
            query.push_str("sort=");
            append_group_lister_options_sort(sort, &mut query);
            previous_option_present = true;
        });

        query
    }
}

impl GroupListing {
    fn list(&self) -> Groups {
        let groups: Groups = vec![];

        groups
    }
}

#[test]
fn test_append_group_lister_options_order_by() {
    let expected_string = "Initialnamepathpathname";

    let mut s = String::from("Initial");

    append_group_lister_options_order_by(GroupListerOptionsOrderBy::Name, &mut s);
    append_group_lister_options_order_by(GroupListerOptionsOrderBy::Path, &mut s);
    append_group_lister_options_order_by(GroupListerOptionsOrderBy::Path, &mut s);
    append_group_lister_options_order_by(GroupListerOptionsOrderBy::Name, &mut s);

    assert_eq!(s, expected_string);
}

#[test]
fn test_append_group_lister_options_sort() {
    let expected_string = "Initialascdescascdesc";

    let mut s = String::from("Initial");

    append_group_lister_options_sort(GroupListerOptionsSort::Asc, &mut s);
    append_group_lister_options_sort(GroupListerOptionsSort::Desc, &mut s);
    append_group_lister_options_sort(GroupListerOptionsSort::Asc, &mut s);
    append_group_lister_options_sort(GroupListerOptionsSort::Desc, &mut s);

    assert_eq!(s, expected_string);
}

#[test]
fn groups_build_query_default() {
    let expected_string = "groups";
    let listing: GroupListing = Default::default();
    let query = listing.build_query();
    assert_eq!(query, expected_string);

    let expected_string = "groups";
    let listing = GroupListing { options: Default::default() };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_skip_groups() {
    let expected_string = "groups?skip_groups[]=1&skip_groups[]=2&skip_groups[]=3";
    let listing = GroupListing {
        options: GroupListerOptions {
            skip_groups: Some(vec![1,2,3]),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_all_available() {
    let expected_string = "groups?all_available=true";
    let listing = GroupListing {
        options: GroupListerOptions {
            all_available: Some(true),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);

    let expected_string = "groups?all_available=false";
    let listing = GroupListing {
        options: GroupListerOptions {
            all_available: Some(false),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_search() {
    let expected_string = "groups?search=SearchPattern";
    let listing = GroupListing {
        options: GroupListerOptions {
            search: Some(String::from("SearchPattern")),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_order_by_name() {
    let expected_string = "groups?order_by=name";
    let listing = GroupListing {
        options: GroupListerOptions {
            order_by: Some(GroupListerOptionsOrderBy::Name),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_order_by_path() {
    let expected_string = "groups?order_by=path";
    let listing = GroupListing {
        options: GroupListerOptions {
            order_by: Some(GroupListerOptionsOrderBy::Path),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_sort() {
    let expected_string = "groups?sort=asc";
    let listing = GroupListing {
        options: GroupListerOptions {
            sort: Some(GroupListerOptionsSort::Asc),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);

    let expected_string = "groups?sort=desc";
    let listing = GroupListing {
        options: GroupListerOptions {
            sort: Some(GroupListerOptionsSort::Desc),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_search_order_by_path() {
    let expected_string = "groups?search=SearchPattern&order_by=path";
    let listing = GroupListing {
        options: GroupListerOptions {
            order_by: Some(GroupListerOptionsOrderBy::Path),
            search: Some(String::from("SearchPattern")),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}
<commit_msg>Cleanup: Use &str instead of ugly bools<commit_after>
use BuildQuery;
use Groups;

// https://docs.gitlab.com/ce/api/groups.html
// List groups:                 GET /groups
// List owned groups:           GET /groups/owned
// List a group's projects:     GET /groups/:id/projects
// Details of a group:          GET /groups/:id
// New group:                   POST /groups
// Transfer project to group:   POST  /groups/:id/projects/:project_id
// Update group:                PUT /groups/:id
// Remove group:                DELETE /groups/:id
// Search for group:            GET /groups?search=foobar

// https://docs.gitlab.com/ce/api/groups.html#list-groups

#[derive(Debug, Copy, Clone)]
enum GroupListerOptionsOrderBy {
    Name,
    Path,
}

// impl Default for GroupListerOptionsOrderBy {
//     fn default() -> GroupListerOptionsOrderBy { GroupListerOptionsOrderBy::Name }
// }

#[derive(Debug, Copy, Clone)]
enum GroupListerOptionsSort {
    Asc,
    Desc,
}

// impl Default for GroupListerOptionsSort {
//     fn default() -> GroupListerOptionsSort { GroupListerOptionsSort::Asc }
// }

fn append_group_lister_options_order_by(order_by: GroupListerOptionsOrderBy, s: &mut String) {
    s.push_str(match order_by {
        GroupListerOptionsOrderBy::Name => "name",
        GroupListerOptionsOrderBy::Path => "path",
    });
}

fn append_group_lister_options_sort(order_by: GroupListerOptionsSort, s: &mut String) {
    s.push_str(match order_by {
        GroupListerOptionsSort::Asc => "asc",
        GroupListerOptionsSort::Desc => "desc",
    });
}

/// https://docs.gitlab.com/ce/api/groups.html#list-groups
#[derive(Default, Debug)]
struct GroupListerOptions {
    /// Skip the group IDs passes
    pub skip_groups: Option<Vec<i64>>,
    /// Show all the groups you have access to
    pub all_available: Option<bool>,
    /// Return list of authorized groups matching the search criteria
    pub search: Option<String>,
    /// Order groups by `name` or `path`. Default is `name`
    pub order_by: Option<GroupListerOptionsOrderBy>,
    /// Order groups in `asc` or `desc` order. Default is `asc`
    pub sort: Option<GroupListerOptionsSort>,
}

#[derive(Default, Debug)]
pub struct GroupListing {
    options: GroupListerOptions,
}

impl BuildQuery for GroupListing {
    fn build_query(&self) -> String {

        let options = &self.options;

        let mut query = String::from("groups");

        let amp_char = "&";
        let none_char = "";
        let mut split_char = &none_char;

        // Append a "?", only if one of the `Option` is `Some(_)`
        query.push_str(match (&options.skip_groups,
                              &options.all_available,
                              &options.search,
                              &options.order_by,
                              &options.sort) {
            (&None, &None, &None, &None, &None) => "",
            _ => "?",
        });

        options.skip_groups.as_ref().map(|skip_groups| {
            if !skip_groups.is_empty() {
                query.push_str(&split_char);
                split_char = &amp_char;

                let mut array_split_char = &none_char;
                for &skip_group in skip_groups {
                    query.push_str(array_split_char);
                    query.push_str("skip_groups[]=");
                    query.push_str(&skip_group.to_string());
                    array_split_char = &amp_char;
                }
            }
        });

        options.all_available.map(|all_available| {
            query.push_str(&split_char);
            split_char = &amp_char;

            if all_available {
                query.push_str("all_available=true")
            } else {
                query.push_str("all_available=false")
            }
        });

        options.search.as_ref().map(|search| {
            query.push_str(&split_char);
            split_char = &amp_char;

            query.push_str("search=");
            query.push_str(search);
        });

        options.order_by.map(|order_by| {
            query.push_str(&split_char);
            split_char = &amp_char;

            query.push_str("order_by=");
            append_group_lister_options_order_by(order_by, &mut query);
        });

        options.sort.map(|sort| {
            query.push_str(&split_char);
            split_char = &amp_char;

            query.push_str("sort=");
            append_group_lister_options_sort(sort, &mut query);
        });

        query
    }
}

impl GroupListing {
    fn list(&self) -> Groups {
        let groups: Groups = vec![];

        groups
    }
}

#[test]
fn test_append_group_lister_options_order_by() {
    let expected_string = "Initialnamepathpathname";

    let mut s = String::from("Initial");

    append_group_lister_options_order_by(GroupListerOptionsOrderBy::Name, &mut s);
    append_group_lister_options_order_by(GroupListerOptionsOrderBy::Path, &mut s);
    append_group_lister_options_order_by(GroupListerOptionsOrderBy::Path, &mut s);
    append_group_lister_options_order_by(GroupListerOptionsOrderBy::Name, &mut s);

    assert_eq!(s, expected_string);
}

#[test]
fn test_append_group_lister_options_sort() {
    let expected_string = "Initialascdescascdesc";

    let mut s = String::from("Initial");

    append_group_lister_options_sort(GroupListerOptionsSort::Asc, &mut s);
    append_group_lister_options_sort(GroupListerOptionsSort::Desc, &mut s);
    append_group_lister_options_sort(GroupListerOptionsSort::Asc, &mut s);
    append_group_lister_options_sort(GroupListerOptionsSort::Desc, &mut s);

    assert_eq!(s, expected_string);
}

#[test]
fn groups_build_query_default() {
    let expected_string = "groups";
    let listing: GroupListing = Default::default();
    let query = listing.build_query();
    assert_eq!(query, expected_string);

    let expected_string = "groups";
    let listing = GroupListing { options: Default::default() };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_skip_groups() {
    let expected_string = "groups?skip_groups[]=1&skip_groups[]=2&skip_groups[]=3";
    let listing = GroupListing {
        options: GroupListerOptions {
            skip_groups: Some(vec![1,2,3]),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_all_available() {
    let expected_string = "groups?all_available=true";
    let listing = GroupListing {
        options: GroupListerOptions {
            all_available: Some(true),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);

    let expected_string = "groups?all_available=false";
    let listing = GroupListing {
        options: GroupListerOptions {
            all_available: Some(false),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_search() {
    let expected_string = "groups?search=SearchPattern";
    let listing = GroupListing {
        options: GroupListerOptions {
            search: Some(String::from("SearchPattern")),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_order_by_name() {
    let expected_string = "groups?order_by=name";
    let listing = GroupListing {
        options: GroupListerOptions {
            order_by: Some(GroupListerOptionsOrderBy::Name),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_order_by_path() {
    let expected_string = "groups?order_by=path";
    let listing = GroupListing {
        options: GroupListerOptions {
            order_by: Some(GroupListerOptionsOrderBy::Path),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_sort() {
    let expected_string = "groups?sort=asc";
    let listing = GroupListing {
        options: GroupListerOptions {
            sort: Some(GroupListerOptionsSort::Asc),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);

    let expected_string = "groups?sort=desc";
    let listing = GroupListing {
        options: GroupListerOptions {
            sort: Some(GroupListerOptionsSort::Desc),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_search_order_by_path() {
    let expected_string = "groups?search=SearchPattern&order_by=path";
    let listing = GroupListing {
        options: GroupListerOptions {
            order_by: Some(GroupListerOptionsOrderBy::Path),
            search: Some(String::from("SearchPattern")),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}
<|endoftext|>


<commit_before>
use std::env::{remove_var, var};
use std::path::PathBuf;
use std::process::Command;

macro_rules! variable(($name:expr) => (var($name).unwrap()));

fn main() {
    let root = PathBuf::from(".");
    let source = PathBuf::from("fftw-3.3.6-pl1");
    let output = PathBuf::from(variable!("OUT_DIR").replace(r"\", "/"));

    remove_var("TARGET");
    if !source.exists() {
        run(Command::new("wget")
            .arg("http://www.fftw.org/fftw-3.3.6-pl1.tar.gz")
            .current_dir(&root));
        run(Command::new("tar").args(&["zxvf", "fftw-3.3.6-pl1.tar.gz"]).current_dir(&root));
    }
    run(Command::new("./configure")
        .args(&["--enable-shared", "--enable-single"])
        .current_dir(&source));

    run(Command::new("make")
        .arg(format!("-j{}", variable!("NUM_JOBS")))
        .current_dir(&source));

    run(Command::new("make")
        .arg("install")
        .arg(format!("DESTDIR={}", output.display()))
        .current_dir(&source));

    println!("cargo:rustc-link-search={}",
             output.join("usr/local/lib").display());
    println!("cargo:rustc-link-lib=dylib=fftw3");
    println!("cargo:rustc-link-lib=dylib=fftw3f");
}

fn run(command: &mut Command) {
    println!("Running: {:?}", command);
    match command.status() {
        Ok(status) => {
            if !status.success() {
                panic!("`{:?}` failed: {}", command, status);
            }
        }
        Err(error) => {
            panic!("failed to execute `{:?}`: {}", command, error);
        }
    }
}
<commit_msg>Add libfftw3 (only libfftw3f is compiled)<commit_after>
use std::env::{remove_var, var};
use std::path::PathBuf;
use std::process::Command;

macro_rules! variable(($name:expr) => (var($name).unwrap()));

fn main() {
    let root = PathBuf::from(".");
    let source = PathBuf::from("fftw-3.3.6-pl1");
    let output = PathBuf::from(variable!("OUT_DIR").replace(r"\", "/"));

    remove_var("TARGET");
    if !source.exists() {
        run(Command::new("wget")
            .arg("http://www.fftw.org/fftw-3.3.6-pl1.tar.gz")
            .current_dir(&root));
        run(Command::new("tar").args(&["zxvf", "fftw-3.3.6-pl1.tar.gz"]).current_dir(&root));
    }

    // build for f32
    run(Command::new("./configure")
        .args(&["--enable-shared", "--enable-single"])
        .current_dir(&source));
    run(Command::new("make")
        .arg(format!("-j{}", variable!("NUM_JOBS")))
        .current_dir(&source));
    run(Command::new("make")
        .arg("install")
        .arg(format!("DESTDIR={}", output.display()))
        .current_dir(&source));

    // build for f64
    run(Command::new("./configure")
        .args(&["--enable-shared"])
        .current_dir(&source));
    run(Command::new("make")
        .arg(format!("-j{}", variable!("NUM_JOBS")))
        .current_dir(&source));
    run(Command::new("make")
        .arg("install")
        .arg(format!("DESTDIR={}", output.display()))
        .current_dir(&source));

    println!("cargo:rustc-link-search={}",
             output.join("usr/local/lib").display());

    println!("cargo:rustc-link-lib=dylib=fftw3");
    println!("cargo:rustc-link-lib=dylib=fftw3f");
}

fn run(command: &mut Command) {
    println!("Running: {:?}", command);
    match command.status() {
        Ok(status) => {
            if !status.success() {
                panic!("`{:?}` failed: {}", command, status);
            }
        }
        Err(error) => {
            panic!("failed to execute `{:?}`: {}", command, error);
        }
    }
}
<|endoftext|>


<commit_before>//! Module containing the `import()` function

use std::io::Read;

use serde_json;

use result::Result;
use task::Task;
use error::{TaskError, TaskErrorKind};

/// Import taskwarrior-exported JSON. This expects an JSON Array of objects, as exported by
/// taskwarrior.
pub fn import<R: Read>(r: R) -> Result<Vec<Task>> {
    serde_json::from_reader(r)
        .map_err(|e| {
            TaskError::new(TaskErrorKind::ParserError, Some(Box::new(e)))
        })
}

/// Import a single JSON-formatted Task
pub fn import_task(s : &str) -> Result<Task> {
    serde_json::from_str(s)
        .map_err(|e| {
            TaskError::new(TaskErrorKind::ParserError, Some(Box::new(e)))
        })
}

#[test]
fn test_one() {
    let s = r#"
[
    {
        "id": 1,
        "description": "some description",
        "entry": "20150619T165438Z",
        "modified": "20160327T164007Z",
        "project": "someproject",
        "status": "waiting",
        "tags": ["some", "tags", "are", "here"],
        "uuid": "8ca953d5-18b4-4eb9-bd56-18f2e5b752f0",
        "wait": "20160508T164007Z",
        "urgency": 0.583562
    }
]
"#;

    let imported = import(s.as_bytes());
    assert!(imported.is_ok());
    let imported = imported.unwrap();
    assert!(imported.len() == 1);
}

#[test]
fn test_two() {
    let s = r#"
[
    {
        "id"          : 1,
        "description" : "test",
        "entry"       : "20150619T165438Z",
        "modified"    : "20160327T164007Z",
        "project"     : "self.software",
        "status"      : "waiting",
        "tags"        : ["check", "this", "crate", "out"],
        "uuid"        : "8ca953d5-18b4-4eb9-bd56-18f2e5b752f0",
        "wait"        : "20160508T164007Z",
        "urgency"     : 0.583562
    },
    {
        "id"          : 2,
        "description" : "another test",
        "entry"       : "20150623T181011Z",
        "modified"    : "20160327T163718Z",
        "priority"    : "L",
        "project"     : "studying",
        "status"      : "waiting",
        "tags"        : ["I", "have", "awesome", "kittens"],
        "uuid"        : "54d49ffc-a06b-4dd8-b7d1-db5f50594312",
        "wait"        : "20160508T163718Z",
        "annotations" : [
            {
                "entry"       : "20150623T181018Z",
                "description" : "fooooooobar"
            }
        ],
        "urgency"     : 3.16164
    },
    {
        "id"          : 3,
        "description" : "I love kittens, really!",
        "entry"       : "20150919T222323Z",
        "modified"    : "20160327T163718Z",
        "project"     : "getkittens",
        "status"      : "waiting",
        "tags"        : ["kittens", "are", "so", "damn", "awesome"],
        "uuid"        : "08ee8dce-cb97-4c8c-9940-c9a440e90119",
        "wait"        : "20160508T163718Z",
        "urgency"     : 1.07397
    }
]

"#;

    let imported = import(s.as_bytes());
    assert!(imported.is_ok());
    let imported = imported.unwrap();
    assert!(imported.len() == 3);
}

#[test]
fn test_one_single() {
    use status::TaskStatus;
    let s = r#"
{
    "id": 1,
    "description": "some description",
    "entry": "20150619T165438Z",
    "modified": "20160327T164007Z",
    "project": "someproject",
    "status": "waiting",
    "tags": ["some", "tags", "are", "here"],
    "uuid": "8ca953d5-18b4-4eb9-bd56-18f2e5b752f0",
    "wait": "20160508T164007Z",
    "urgency": 0.583562
}
"#;
    let imported = import_task(&s);
    assert!(imported.is_ok());
    let imported = imported.unwrap();
    assert!(imported.status() == &TaskStatus::Waiting);
}

<commit_msg>impl import_tasks<commit_after>//! Module containing the `import()` function

use std::io::BufRead;
use std::io::Read;

use serde_json;

use result::Result;
use task::Task;
use error::{TaskError, TaskErrorKind};

/// Import taskwarrior-exported JSON. This expects an JSON Array of objects, as exported by
/// taskwarrior.
pub fn import<R: Read>(r: R) -> Result<Vec<Task>> {
    serde_json::from_reader(r)
        .map_err(|e| {
            TaskError::new(TaskErrorKind::ParserError, Some(Box::new(e)))
        })
}

/// Import a single JSON-formatted Task
pub fn import_task(s : &str) -> Result<Task> {
    serde_json::from_str(s)
        .map_err(|e| {
            TaskError::new(TaskErrorKind::ParserError, Some(Box::new(e)))
        })
}

/// Reads line by line and tries to parse a task-object per line.
pub fn import_tasks<BR: BufRead>(r : BR) -> Result<Vec<Task>> {
    let vt = r.lines().filter_map(|l| l.ok())
        .filter(|s| s.len() > 0)
        .map(|s| import_task(s.as_str()))
        .filter_map(|t| t.ok())
        .collect();
    Ok(vt)
}

#[test]
fn test_one() {
    let s = r#"
[
    {
        "id": 1,
        "description": "some description",
        "entry": "20150619T165438Z",
        "modified": "20160327T164007Z",
        "project": "someproject",
        "status": "waiting",
        "tags": ["some", "tags", "are", "here"],
        "uuid": "8ca953d5-18b4-4eb9-bd56-18f2e5b752f0",
        "wait": "20160508T164007Z",
        "urgency": 0.583562
    }
]
"#;

    let imported = import(s.as_bytes());
    assert!(imported.is_ok());
    let imported = imported.unwrap();
    assert!(imported.len() == 1);
}

#[test]
fn test_two() {
    let s = r#"
[
    {
        "id"          : 1,
        "description" : "test",
        "entry"       : "20150619T165438Z",
        "modified"    : "20160327T164007Z",
        "project"     : "self.software",
        "status"      : "waiting",
        "tags"        : ["check", "this", "crate", "out"],
        "uuid"        : "8ca953d5-18b4-4eb9-bd56-18f2e5b752f0",
        "wait"        : "20160508T164007Z",
        "urgency"     : 0.583562
    },
    {
        "id"          : 2,
        "description" : "another test",
        "entry"       : "20150623T181011Z",
        "modified"    : "20160327T163718Z",
        "priority"    : "L",
        "project"     : "studying",
        "status"      : "waiting",
        "tags"        : ["I", "have", "awesome", "kittens"],
        "uuid"        : "54d49ffc-a06b-4dd8-b7d1-db5f50594312",
        "wait"        : "20160508T163718Z",
        "annotations" : [
            {
                "entry"       : "20150623T181018Z",
                "description" : "fooooooobar"
            }
        ],
        "urgency"     : 3.16164
    },
    {
        "id"          : 3,
        "description" : "I love kittens, really!",
        "entry"       : "20150919T222323Z",
        "modified"    : "20160327T163718Z",
        "project"     : "getkittens",
        "status"      : "waiting",
        "tags"        : ["kittens", "are", "so", "damn", "awesome"],
        "uuid"        : "08ee8dce-cb97-4c8c-9940-c9a440e90119",
        "wait"        : "20160508T163718Z",
        "urgency"     : 1.07397
    }
]

"#;

    let imported = import(s.as_bytes());
    assert!(imported.is_ok());
    let imported = imported.unwrap();
    assert!(imported.len() == 3);
}

#[test]
fn test_one_single() {
    use status::TaskStatus;
    let s = r#"
{
    "id": 1,
    "description": "some description",
    "entry": "20150619T165438Z",
    "modified": "20160327T164007Z",
    "project": "someproject",
    "status": "waiting",
    "tags": ["some", "tags", "are", "here"],
    "uuid": "8ca953d5-18b4-4eb9-bd56-18f2e5b752f0",
    "wait": "20160508T164007Z",
    "urgency": 0.583562
}
"#;
    let imported = import_task(&s);
    assert!(imported.is_ok());
    let imported = imported.unwrap();
    assert!(imported.status() == &TaskStatus::Waiting);
}

#[test]
fn test_two_single() {
    use std::io::BufReader;
    use status::TaskStatus;
    let s = r#"
{"id":1,"description":"some description","entry":"20150619T165438Z","modified":"20160327T164007Z","project":"someproject","status":"waiting","tags":["some","tags","are","here"],"uuid":"8ca953d5-18b4-4eb9-bd56-18f2e5b752f0","wait":"20160508T164007Z","urgency":0.583562}
{"id":1,"description":"some description","entry":"20150619T165438Z","modified":"20160327T164007Z","project":"someproject","status":"waiting","tags":["some","tags","are","here"],"uuid":"8ca953d5-18b4-4eb9-bd56-18f2e5b752f0","wait":"20160508T164007Z","urgency":0.583562}"#;
    let imported = import_tasks(BufReader::new(s.as_bytes()));
    assert!(imported.is_ok());
    let imported = imported.unwrap();
    assert!(imported.len() == 2);
    assert!(imported[0].status() == &TaskStatus::Waiting);
    assert!(imported[1].status() == &TaskStatus::Waiting);
}

<|endoftext|>


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

//! Module containing the `import()` function

use std::io::BufRead;
use std::io::Read;

use serde_json;

use result::Result;
use task::Task;
use error::{TaskError, TaskErrorKind};

/// Import taskwarrior-exported JSON. This expects an JSON Array of objects, as exported by
/// taskwarrior.
pub fn import<R: Read>(r: R) -> Result<Vec<Task>> {
    serde_json::from_reader(r)
        .map_err(|e| {
            TaskError::new(TaskErrorKind::ParserError, Some(Box::new(e)))
        })
}

/// Import a single JSON-formatted Task
pub fn import_task(s : &str) -> Result<Task> {
    serde_json::from_str(s)
        .map_err(|e| {
            TaskError::new(TaskErrorKind::ParserError, Some(Box::new(e)))
        })
}

/// Reads line by line and tries to parse a task-object per line.
pub fn import_tasks<BR: BufRead>(r : BR) -> Vec<Result<Task>> {
    let mut vt = Vec::new();
    for line in r.lines() {
        if line.is_err() {
            vt.push(Err(TaskError::new(TaskErrorKind::ReaderError, Some(Box::new(line.unwrap_err())))));
            continue;
        }
        // Unwrap is safe because of continue above
        if line.as_ref().unwrap().len() <= 0 {
            // Empty strings are not usable, and shall be silently ignored
            continue;
        }
        vt.push(import_task(line.unwrap().as_str()));
    }
    vt
}

#[test]
fn test_one() {
    let s = r#"
[
    {
        "id": 1,
        "description": "some description",
        "entry": "20150619T165438Z",
        "modified": "20160327T164007Z",
        "project": "someproject",
        "status": "waiting",
        "tags": ["some", "tags", "are", "here"],
        "uuid": "8ca953d5-18b4-4eb9-bd56-18f2e5b752f0",
        "wait": "20160508T164007Z",
        "urgency": 0.583562
    }
]
"#;

    let imported = import(s.as_bytes());
    assert!(imported.is_ok());
    let imported = imported.unwrap();
    assert!(imported.len() == 1);
}

#[test]
fn test_two() {
    let s = r#"
[
    {
        "id"          : 1,
        "description" : "test",
        "entry"       : "20150619T165438Z",
        "modified"    : "20160327T164007Z",
        "project"     : "self.software",
        "status"      : "waiting",
        "tags"        : ["check", "this", "crate", "out"],
        "uuid"        : "8ca953d5-18b4-4eb9-bd56-18f2e5b752f0",
        "wait"        : "20160508T164007Z",
        "urgency"     : 0.583562
    },
    {
        "id"          : 2,
        "description" : "another test",
        "entry"       : "20150623T181011Z",
        "modified"    : "20160327T163718Z",
        "priority"    : "L",
        "project"     : "studying",
        "status"      : "waiting",
        "tags"        : ["I", "have", "awesome", "kittens"],
        "uuid"        : "54d49ffc-a06b-4dd8-b7d1-db5f50594312",
        "wait"        : "20160508T163718Z",
        "annotations" : [
            {
                "entry"       : "20150623T181018Z",
                "description" : "fooooooobar"
            }
        ],
        "urgency"     : 3.16164
    },
    {
        "id"          : 3,
        "description" : "I love kittens, really!",
        "entry"       : "20150919T222323Z",
        "modified"    : "20160327T163718Z",
        "project"     : "getkittens",
        "status"      : "waiting",
        "tags"        : ["kittens", "are", "so", "damn", "awesome"],
        "uuid"        : "08ee8dce-cb97-4c8c-9940-c9a440e90119",
        "wait"        : "20160508T163718Z",
        "urgency"     : 1.07397
    }
]

"#;

    let imported = import(s.as_bytes());
    assert!(imported.is_ok());
    let imported = imported.unwrap();
    assert!(imported.len() == 3);
}

#[test]
fn test_one_single() {
    use status::TaskStatus;
    use date::Date;
    use date::TASKWARRIOR_DATETIME_TEMPLATE;
    use uuid::Uuid;
    use chrono::naive::datetime::NaiveDateTime;
    fn mkdate(s: &str) -> Date {
        let n = NaiveDateTime::parse_from_str(s, TASKWARRIOR_DATETIME_TEMPLATE);
        Date::from(n.unwrap())
    }
    let s = r#"
{
    "id": 1,
    "description": "some description",
    "entry": "20150619T165438Z",
    "modified": "20160327T164007Z",
    "project": "someproject",
    "status": "waiting",
    "tags": ["some", "tags", "are", "here"],
    "uuid": "8ca953d5-18b4-4eb9-bd56-18f2e5b752f0",
    "wait": "20160508T164007Z",
    "urgency": 0.583562
}
"#;
    let imported = import_task(&s);
    assert!(imported.is_ok());

    // Check for every information
    let task = imported.unwrap();
    assert!(task.status() == &TaskStatus::Waiting);
    assert!(task.description() == "some description");
    assert!(task.entry().clone() == mkdate("20150619T165438Z"));
    assert!(task.uuid().clone() == Uuid::parse_str("8ca953d5-18b4-4eb9-bd56-18f2e5b752f0").unwrap());
    assert!(task.modified() == Some(&mkdate("20160327T164007Z")));
    assert!(task.project() == Some(&String::from("someproject")));
    if let Some(tags) = task.tags() {
        for tag in tags {
            let any_tag = [ "some", "tags", "are", "here", ]
                .into_iter().any(|t| tag == *t);
            assert!(any_tag, "Tag {} missing", tag);
        }
    } else {
        assert!(false, "Tags completely missing");
    }

    assert!(task.wait() == Some(&mkdate("20160508T164007Z")));
}

#[test]
fn test_two_single() {
    use std::io::BufReader;
    use status::TaskStatus;
    let s = r#"
{"id":1,"description":"some description","entry":"20150619T165438Z","modified":"20160327T164007Z","project":"someproject","status":"waiting","tags":["some","tags","are","here"],"uuid":"8ca953d5-18b4-4eb9-bd56-18f2e5b752f0","wait":"20160508T164007Z","urgency":0.583562}
{"id":1,"description":"some description","entry":"20150619T165438Z","modified":"20160327T164007Z","project":"someproject","status":"waiting","tags":["some","tags","are","here"],"uuid":"8ca953d5-18b4-4eb9-bd56-18f2e5b752f0","wait":"20160508T164007Z","urgency":0.583562}"#;
    let imported = import_tasks(BufReader::new(s.as_bytes()));
    assert!(imported.len() == 2);
    assert!(imported[0].is_ok());
    assert!(imported[1].is_ok());
    let import0 = imported[0].as_ref().unwrap();
    let import1 = imported[1].as_ref().unwrap();
    assert!(import0.status() == &TaskStatus::Waiting);
    assert!(import1.status() == &TaskStatus::Waiting);
}

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

//! Module containing the `import()` function

use std::io::BufRead;
use std::io::Read;

use serde_json;

use result::Result;
use task::Task;
use error::{TaskError, TaskErrorKind};

/// Import taskwarrior-exported JSON. This expects an JSON Array of objects, as exported by
/// taskwarrior.
pub fn import<R: Read>(r: R) -> Result<Vec<Task>> {
    serde_json::from_reader(r)
        .map_err(|e| {
            TaskError::new(TaskErrorKind::ParserError, Some(Box::new(e)))
        })
}

/// Import a single JSON-formatted Task
pub fn import_task(s : &str) -> Result<Task> {
    serde_json::from_str(s)
        .map_err(|e| {
            TaskError::new(TaskErrorKind::ParserError, Some(Box::new(e)))
        })
}

/// Reads line by line and tries to parse a task-object per line.
pub fn import_tasks<BR: BufRead>(r : BR) -> Vec<Result<Task>> {
    let mut vt = Vec::new();
    for line in r.lines() {
        if line.is_err() {
            vt.push(Err(TaskError::new(TaskErrorKind::ReaderError, Some(Box::new(line.unwrap_err())))));
            continue;
        }
        // Unwrap is safe because of continue above
        if line.as_ref().unwrap().len() <= 0 {
            // Empty strings are not usable, and shall be silently ignored
            continue;
        }
        vt.push(import_task(line.unwrap().as_str()));
    }
    vt
}

#[test]
fn test_one() {
    let s = r#"
[
    {
        "id": 1,
        "description": "some description",
        "entry": "20150619T165438Z",
        "modified": "20160327T164007Z",
        "project": "someproject",
        "status": "waiting",
        "tags": ["some", "tags", "are", "here"],
        "uuid": "8ca953d5-18b4-4eb9-bd56-18f2e5b752f0",
        "wait": "20160508T164007Z",
        "urgency": 0.583562
    }
]
"#;

    let imported = import(s.as_bytes());
    assert!(imported.is_ok());
    let imported = imported.unwrap();
    assert!(imported.len() == 1);
}

#[test]
fn test_two() {
    let s = r#"
[
    {
        "id"          : 1,
        "description" : "test",
        "entry"       : "20150619T165438Z",
        "modified"    : "20160327T164007Z",
        "project"     : "self.software",
        "status"      : "waiting",
        "tags"        : ["check", "this", "crate", "out"],
        "uuid"        : "8ca953d5-18b4-4eb9-bd56-18f2e5b752f0",
        "wait"        : "20160508T164007Z",
        "urgency"     : 0.583562
    },
    {
        "id"          : 2,
        "description" : "another test",
        "entry"       : "20150623T181011Z",
        "modified"    : "20160327T163718Z",
        "priority"    : "L",
        "project"     : "studying",
        "status"      : "waiting",
        "tags"        : ["I", "have", "awesome", "kittens"],
        "uuid"        : "54d49ffc-a06b-4dd8-b7d1-db5f50594312",
        "wait"        : "20160508T163718Z",
        "annotations" : [
            {
                "entry"       : "20150623T181018Z",
                "description" : "fooooooobar"
            }
        ],
        "urgency"     : 3.16164
    },
    {
        "id"          : 3,
        "description" : "I love kittens, really!",
        "entry"       : "20150919T222323Z",
        "modified"    : "20160327T163718Z",
        "project"     : "getkittens",
        "status"      : "waiting",
        "tags"        : ["kittens", "are", "so", "damn", "awesome"],
        "uuid"        : "08ee8dce-cb97-4c8c-9940-c9a440e90119",
        "wait"        : "20160508T163718Z",
        "urgency"     : 1.07397
    }
]

"#;

    assert!(import(s.as_bytes()).unwrap().len() == 3);
}

#[test]
fn test_one_single() {
    use status::TaskStatus;
    use date::Date;
    use date::TASKWARRIOR_DATETIME_TEMPLATE;
    use uuid::Uuid;
    use chrono::naive::datetime::NaiveDateTime;
    fn mkdate(s: &str) -> Date {
        let n = NaiveDateTime::parse_from_str(s, TASKWARRIOR_DATETIME_TEMPLATE);
        Date::from(n.unwrap())
    }
    let s = r#"
{
    "id": 1,
    "description": "some description",
    "entry": "20150619T165438Z",
    "modified": "20160327T164007Z",
    "project": "someproject",
    "status": "waiting",
    "tags": ["some", "tags", "are", "here"],
    "uuid": "8ca953d5-18b4-4eb9-bd56-18f2e5b752f0",
    "wait": "20160508T164007Z",
    "urgency": 0.583562
}
"#;
    let imported = import_task(&s);
    assert!(imported.is_ok());

    // Check for every information
    let task = imported.unwrap();
    assert!(task.status() == &TaskStatus::Waiting);
    assert!(task.description() == "some description");
    assert!(task.entry().clone() == mkdate("20150619T165438Z"));
    assert!(task.uuid().clone() == Uuid::parse_str("8ca953d5-18b4-4eb9-bd56-18f2e5b752f0").unwrap());
    assert!(task.modified() == Some(&mkdate("20160327T164007Z")));
    assert!(task.project() == Some(&String::from("someproject")));
    if let Some(tags) = task.tags() {
        for tag in tags {
            let any_tag = [ "some", "tags", "are", "here", ]
                .into_iter().any(|t| tag == *t);
            assert!(any_tag, "Tag {} missing", tag);
        }
    } else {
        assert!(false, "Tags completely missing");
    }

    assert!(task.wait() == Some(&mkdate("20160508T164007Z")));
}

#[test]
fn test_two_single() {
    use std::io::BufReader;
    use status::TaskStatus;
    let s = r#"
{"id":1,"description":"some description","entry":"20150619T165438Z","modified":"20160327T164007Z","project":"someproject","status":"waiting","tags":["some","tags","are","here"],"uuid":"8ca953d5-18b4-4eb9-bd56-18f2e5b752f0","wait":"20160508T164007Z","urgency":0.583562}
{"id":1,"description":"some description","entry":"20150619T165438Z","modified":"20160327T164007Z","project":"someproject","status":"waiting","tags":["some","tags","are","here"],"uuid":"8ca953d5-18b4-4eb9-bd56-18f2e5b752f0","wait":"20160508T164007Z","urgency":0.583562}"#;
    let imported = import_tasks(BufReader::new(s.as_bytes()));
    assert!(imported.len() == 2);
    assert!(imported[0].is_ok());
    assert!(imported[1].is_ok());
    let import0 = imported[0].as_ref().unwrap();
    let import1 = imported[1].as_ref().unwrap();
    assert!(import0.status() == &TaskStatus::Waiting);
    assert!(import1.status() == &TaskStatus::Waiting);
}

<|endoftext|>


<commit_before>//! Contains modules related to image I/O.

use self::traits::ImageDecoder;
use core::DynamicImage;

use failure::Error;

use std::fs::File;
use std::path::Path;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// Enumerate the image formats supported by the library.
pub enum Format {
    /// PNG format.
    Png,
    /// TIFF format.
    Tiff,
}

fn parse_extension<P>(filepath: &P) -> Option<Format>
where
    P: AsRef<Path>,
{
    let ext = filepath
        .as_ref()
        .extension()?
        .to_string_lossy()
        .to_ascii_lowercase();
    match ext.as_str() {
        "tiff" => Some(Format::Tiff),
        "png" => Some(Format::Png),
        _ => None,
    }
}

/// Open an image on the filesystem. Try to guess the image format from the file extension.
pub fn open<P>(filepath: P) -> Result<DynamicImage, Error>
where
    P: AsRef<Path>,
{
    if let Some(format) = parse_extension(&filepath) {
        let file = File::open(filepath)?;
        match format {
            Format::Png => png::Decoder::new(file)?.read_image(),
            Format::Tiff => tiff::Decoder::new(file)?.read_image(),
        }
    } else {
        bail!("Could not infer image format from file extension!")
    }
}

pub mod png;
pub mod tiff;
pub mod traits;

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

    use core::{BitDepth, Channels};

    #[test]
    fn test_parse_extension() {
        assert_eq!(parse_extension(&"img.tiff".to_owned()), Some(Format::Tiff));
        assert_eq!(parse_extension(&"img.png".to_owned()), Some(Format::Png));
        assert_eq!(parse_extension(&"img.TIFF".to_owned()), Some(Format::Tiff));
    }

    #[test]
    fn test_open_png() {
        let img_luma_u8 = open("./test_data/io/png/grayscale_8bit.png").unwrap();
        assert_eq!(img_luma_u8.image_type(), (Channels::Luma, BitDepth::_8));
        let img_luma_u16 = open("./test_data/io/png/grayscale_16bit.png").unwrap();
        assert_eq!(img_luma_u16.image_type(), (Channels::Luma, BitDepth::_16));
        let img_luma_alpha_u8 = open("./test_data/io/png/grayscale_alpha_8bit.png").unwrap();
        assert_eq!(
            img_luma_alpha_u8.image_type(),
            (Channels::LumaA, BitDepth::_8)
        );
        let img_luma_alpha_u16 = open("./test_data/io/png/grayscale_alpha_16bit.png").unwrap();
        assert_eq!(
            img_luma_alpha_u16.image_type(),
            (Channels::LumaA, BitDepth::_16)
        );
        let img_rgb_u8 = open("./test_data/io/png/rgb_8bit.png").unwrap();
        assert_eq!(img_rgb_u8.image_type(), (Channels::Rgb, BitDepth::_8));
        let img_rgb_u16 = open("./test_data/io/png/rgb_16bit.png").unwrap();
        assert_eq!(img_rgb_u16.image_type(), (Channels::Rgb, BitDepth::_16));
        let img_rgb_alpha_u8 = open("./test_data/io/png/rgba_8bit.png").unwrap();
        assert_eq!(
            img_rgb_alpha_u8.image_type(),
            (Channels::RgbA, BitDepth::_8)
        );
        let img_rgb_alpha_u16 = open("./test_data/io/png/rgba_16bit.png").unwrap();
        assert_eq!(
            img_rgb_alpha_u16.image_type(),
            (Channels::RgbA, BitDepth::_16)
        );
    }

    #[test]
    fn test_open_tiff() {
        let img_luma_u8 = open("./test_data/io/tiff/grayscale_8bit.tiff").unwrap();
        assert_eq!(img_luma_u8.image_type(), (Channels::Luma, BitDepth::_8));
        let img_luma_u16 = open("./test_data/io/tiff/grayscale_16bit.tiff").unwrap();
        assert_eq!(img_luma_u16.image_type(), (Channels::Luma, BitDepth::_16));
        //let img_luma_alpha_u8 = open("./test_data/io/tiff/grayscale_alpha_8bit.tiff").unwrap();
        //assert_eq!(img_luma_alpha_u8.image_type(), (Channels::LumaA, BitDepth::_8));
        //let img_luma_alpha_u16 = open("./test_data/io/tiff/grayscale_alpha_16bit.tiff").unwrap();
        //assert_eq!(img_luma_alpha_u16.image_type(), (Channels::LumaA, BitDepth::_16));
        let img_rgb_u8 = open("./test_data/io/tiff/rgb_8bit.tiff").unwrap();
        assert_eq!(img_rgb_u8.image_type(), (Channels::Rgb, BitDepth::_8));
        let img_rgb_u16 = open("./test_data/io/tiff/rgb_16bit.tiff").unwrap();
        assert_eq!(img_rgb_u16.image_type(), (Channels::Rgb, BitDepth::_16));
        let img_rgb_alpha_u8 = open("./test_data/io/tiff/rgba_8bit.tiff").unwrap();
        assert_eq!(
            img_rgb_alpha_u8.image_type(),
            (Channels::RgbA, BitDepth::_8)
        );
        let img_rgb_alpha_u16 = open("./test_data/io/tiff/rgba_16bit.tiff").unwrap();
        assert_eq!(
            img_rgb_alpha_u16.image_type(),
            (Channels::RgbA, BitDepth::_16)
        );
    }
}
<commit_msg>Improve test coverage<commit_after>//! Contains modules related to image I/O.

use self::traits::ImageDecoder;
use core::DynamicImage;

use failure::Error;

use std::fs::File;
use std::path::Path;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// Enumerate the image formats supported by the library.
pub enum Format {
    /// PNG format.
    Png,
    /// TIFF format.
    Tiff,
}

fn parse_extension<P>(filepath: &P) -> Option<Format>
where
    P: AsRef<Path>,
{
    let ext = filepath
        .as_ref()
        .extension()?
        .to_string_lossy()
        .to_ascii_lowercase();
    match ext.as_str() {
        "tiff" => Some(Format::Tiff),
        "png" => Some(Format::Png),
        _ => None,
    }
}

/// Open an image on the filesystem. Try to guess the image format from the file extension.
pub fn open<P>(filepath: P) -> Result<DynamicImage, Error>
where
    P: AsRef<Path>,
{
    if let Some(format) = parse_extension(&filepath) {
        let file = File::open(filepath)?;
        match format {
            Format::Png => png::Decoder::new(file)?.read_image(),
            Format::Tiff => tiff::Decoder::new(file)?.read_image(),
        }
    } else {
        bail!("Could not infer image format from file extension!")
    }
}

pub mod png;
pub mod tiff;
pub mod traits;

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

    use core::{BitDepth, Channels};

    #[test]
    fn test_parse_extension() {
        assert_eq!(parse_extension(&"img.tiff".to_owned()), Some(Format::Tiff));
        assert_eq!(parse_extension(&"img.png".to_owned()), Some(Format::Png));
        assert_eq!(parse_extension(&"img.TIFF".to_owned()), Some(Format::Tiff));
    }

    #[test]
    fn test_open_png() {
        let img_luma_u8 = open("./test_data/io/png/grayscale_8bit.png").unwrap();
        assert_eq!(img_luma_u8.image_type(), (Channels::Luma, BitDepth::_8));
        assert!(img_luma_u8.is_luma());
        assert!(img_luma_u8.as_luma_u8().is_ok());
        let img_luma_u16 = open("./test_data/io/png/grayscale_16bit.png").unwrap();
        assert_eq!(img_luma_u16.image_type(), (Channels::Luma, BitDepth::_16));
        assert!(img_luma_u16.is_luma());
        assert!(img_luma_u16.as_luma_u16().is_ok());
        let img_luma_alpha_u8 = open("./test_data/io/png/grayscale_alpha_8bit.png").unwrap();
        assert_eq!(
            img_luma_alpha_u8.image_type(),
            (Channels::LumaA, BitDepth::_8)
        );
        assert!(img_luma_alpha_u8.is_luma_alpha());
        assert!(img_luma_alpha_u8.as_luma_alpha_u8().is_ok());
        let img_luma_alpha_u16 = open("./test_data/io/png/grayscale_alpha_16bit.png").unwrap();
        assert_eq!(
            img_luma_alpha_u16.image_type(),
            (Channels::LumaA, BitDepth::_16)
        );
        assert!(img_luma_alpha_u16.is_luma_alpha());
        assert!(img_luma_alpha_u16.as_luma_alpha_u16().is_ok());
        let img_rgb_u8 = open("./test_data/io/png/rgb_8bit.png").unwrap();
        assert_eq!(img_rgb_u8.image_type(), (Channels::Rgb, BitDepth::_8));
        assert!(img_rgb_u8.is_rgb());
        assert!(img_rgb_u8.as_rgb_u8().is_ok());
        let img_rgb_u16 = open("./test_data/io/png/rgb_16bit.png").unwrap();
        assert_eq!(img_rgb_u16.image_type(), (Channels::Rgb, BitDepth::_16));
        assert!(img_rgb_u16.is_rgb());
        assert!(img_rgb_u16.as_rgb_u16().is_ok());
        let img_rgb_alpha_u8 = open("./test_data/io/png/rgba_8bit.png").unwrap();
        assert_eq!(
            img_rgb_alpha_u8.image_type(),
            (Channels::RgbA, BitDepth::_8)
        );
        assert!(img_rgb_alpha_u8.is_rgb_alpha());
        assert!(img_rgb_alpha_u8.as_rgb_alpha_u8().is_ok());
        let img_rgb_alpha_u16 = open("./test_data/io/png/rgba_16bit.png").unwrap();
        assert_eq!(
            img_rgb_alpha_u16.image_type(),
            (Channels::RgbA, BitDepth::_16)
        );
        assert!(img_rgb_alpha_u16.is_rgb_alpha());
        assert!(img_rgb_alpha_u16.as_rgb_alpha_u16().is_ok());
    }

    #[test]
    fn test_open_tiff() {
        let img_luma_u8 = open("./test_data/io/tiff/grayscale_8bit.tiff").unwrap();
        assert_eq!(img_luma_u8.image_type(), (Channels::Luma, BitDepth::_8));
        assert!(img_luma_u8.is_luma());
        assert!(img_luma_u8.as_luma_u8().is_ok());
        let img_luma_u16 = open("./test_data/io/tiff/grayscale_16bit.tiff").unwrap();
        assert_eq!(img_luma_u16.image_type(), (Channels::Luma, BitDepth::_16));
        assert!(img_luma_u16.is_luma());
        assert!(img_luma_u16.as_luma_u16().is_ok());
        //let img_luma_alpha_u8 = open("./test_data/io/tiff/grayscale_alpha_8bit.tiff").unwrap();
        //assert_eq!(img_luma_alpha_u8.image_type(), (Channels::LumaA, BitDepth::_8));
        //assert!(img_luma_alpha_u8.is_luma_alpha());
        //assert!(img_luma_alpha_u8.as_luma_alpha_u8().is_ok());
        //let img_luma_alpha_u16 = open("./test_data/io/tiff/grayscale_alpha_16bit.tiff").unwrap();
        //assert_eq!(img_luma_alpha_u16.image_type(), (Channels::LumaA, BitDepth::_16));
        //assert!(img_luma_alpha_u16.is_luma_alpha());
        //assert!(img_luma_alpha_u16.as_luma_alpha_u16().is_ok());
        let img_rgb_u8 = open("./test_data/io/tiff/rgb_8bit.tiff").unwrap();
        assert_eq!(img_rgb_u8.image_type(), (Channels::Rgb, BitDepth::_8));
        assert!(img_rgb_u8.is_rgb());
        assert!(img_rgb_u8.as_rgb_u8().is_ok());
        let img_rgb_u16 = open("./test_data/io/tiff/rgb_16bit.tiff").unwrap();
        assert_eq!(img_rgb_u16.image_type(), (Channels::Rgb, BitDepth::_16));
        assert!(img_rgb_u16.is_rgb());
        assert!(img_rgb_u16.as_rgb_u16().is_ok());
        let img_rgb_alpha_u8 = open("./test_data/io/tiff/rgba_8bit.tiff").unwrap();
        assert_eq!(
            img_rgb_alpha_u8.image_type(),
            (Channels::RgbA, BitDepth::_8)
        );
        assert!(img_rgb_alpha_u8.is_rgb_alpha());
        assert!(img_rgb_alpha_u8.as_rgb_alpha_u8().is_ok());
        let img_rgb_alpha_u16 = open("./test_data/io/tiff/rgba_16bit.tiff").unwrap();
        assert_eq!(
            img_rgb_alpha_u16.image_type(),
            (Channels::RgbA, BitDepth::_16)
        );
        assert!(img_rgb_alpha_u16.is_rgb_alpha());
        assert!(img_rgb_alpha_u16.as_rgb_alpha_u16().is_ok());
    }
}
<|endoftext|>


<commit_before>// Simple example how to use the API.
extern crate differential_evolution;

use differential_evolution::Population;
use std::f32::consts::PI;
use std::env;

fn rastrigin(pos: &[f32]) -> f32 {
    10.0 * (pos.len() as f32) +
    pos.iter().fold(0.0, |sum, x| sum + x * x - 10.0 * (2.0 * PI * x).cos())
}

fn main() {
    let args: Vec<String> = env::args().collect();

    // problem dimension
    let dim = args[1].parse::<usize>().unwrap();

    // number of cost evaluations
    let num_cost_evaluations = args[2].parse::<usize>().unwrap();

    // initial search space for each dimension
    let initial_min_max = vec![(-5.12, 5.12); dim];

    // perform optimization
    let mut pop = Population::new(initial_min_max, rastrigin);
    pop.nth(num_cost_evaluations);

    // see what we've found
    println!("{} evaluations done", num_cost_evaluations);

    let (cost, pos) = pop.best().unwrap();
    println!("{} best cost", cost);
    println!("{:?} best position", pos);
}<commit_msg>minor rastrigin refactoring<commit_after>// Simple example how to use the API.
extern crate differential_evolution;

use differential_evolution::Population;
use std::f32::consts::PI;
use std::env;

fn rastrigin(pos: &[f32]) -> f32 {
    pos.iter().fold(0.0, |sum, x|
        sum + x * x - 10.0 * (2.0 * PI * x).cos() + 10.0)
}

fn main() {
    let args: Vec<String> = env::args().collect();

    // problem dimension
    let dim = args[1].parse::<usize>().unwrap();

    // number of cost evaluations
    let num_cost_evaluations = args[2].parse::<usize>().unwrap();

    // initial search space for each dimension
    let initial_min_max = vec![(-5.12, 5.12); dim];

    // perform optimization
    let mut pop = Population::new(initial_min_max, rastrigin);
    pop.nth(num_cost_evaluations);

    // see what we've found
    println!("{} evaluations done", num_cost_evaluations);

    let (cost, pos) = pop.best().unwrap();
    println!("{} best cost", cost);
    println!("{:?} best position", pos);
}<|endoftext|>