<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))
        )
    }

    /// Maps a global to a specific memory location.
    unsafe fn add_global_mapping<T>(&'b self, global: &'a Value, addr: *const T)
    {
      engine::LLVMAddGlobalMapping(self.into(), global.into(), mem::transmute(addr));
    }
}

/// 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}
<commit_msg>Add ExecutionEngine::get_function_raw for raw function pointer.<commit_after>use libc::{c_int, c_void, 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))
        )
    }

    /// Maps a global to a specific memory location.
    unsafe fn add_global_mapping<T>(&'b self, global: &'a Value, addr: *const T)
    {
      engine::LLVMAddGlobalMapping(self.into(), global.into(), mem::transmute(addr));
    }
}

/// 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)
    }

    /// Returns a pointer to the machine code for the raw function poionter.
    ///
    /// This is marked as unsafe because the defined function signature and
    /// return could be different from their internal representation.
    pub unsafe fn get_function_raw(&self, function: &'b Function) -> Option<*const ()> {
        let ptr:&u8 = self.get_global(function);
        Some(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>#![allow(unused_doc_comment)] // should be removed in next error-chain release
error_chain! {
    errors {
        AlreadySubscribed

        NotSubscribed

        EOF {
            description("unexpected EOF")
        }

        TooManyRedirects {
            description("too many redirects")
        }

        EmptyFeed {
            description("feed is empty or not valid")
        }

        Http(code: u32) {
            description("unexpected HTTP response code")
            display("HTTP {} ({})", code, response_code(*code).unwrap_or("Unknown"))
        }

        DatabaseOpen(path: String) {
            description("failed to open database")
            display("failed to open database: '{}'", path)
        }

        DatabaseSave(path: String) {
            description("failed to save database")
            display("failed to save database: '{}'", path)
        }

        DatabaseFormat {
            description("illegal database format")
        }
    }
    links {
        Xml(::quick_xml::errors::Error, ::quick_xml::errors::ErrorKind);
    }
    foreign_links {
        Curl(::tokio_curl::PerformError);
        Utf8(::std::str::Utf8Error);
    }
}

fn response_code(code: u32) -> Option<&'static str> {
    match code {
        100 => Some("Continue"),
        101 => Some("Switching Protocols"),
        102 => Some("Processing"),
        200 => Some("OK"),
        201 => Some("Created"),
        202 => Some("Accepted"),
        203 => Some("Non-Authoritative Information"),
        204 => Some("No Content"),
        205 => Some("Reset Content"),
        206 => Some("Partial Content"),
        207 => Some("Multi-Status"),
        208 => Some("Already Reported"),
        226 => Some("IM Used"),
        300 => Some("Multiple Choices"),
        301 => Some("Moved Permanently"),
        302 => Some("Found"),
        303 => Some("See Other"),
        304 => Some("Not Modified"),
        305 => Some("Use Proxy"),
        306 => Some("Switch Proxy"),
        307 => Some("Temporary Redirect"),
        308 => Some("Permanent Redirect"),
        400 => Some("Bad Request"),
        401 => Some("Unauthorized"),
        402 => Some("Payment Required"),
        403 => Some("Forbidden"),
        404 => Some("Not Found"),
        405 => Some("Method Not Allowed"),
        406 => Some("Not Acceptable"),
        407 => Some("Proxy Authentication Required"),
        408 => Some("Request Timeout"),
        409 => Some("Conflict"),
        410 => Some("Gone"),
        411 => Some("Length Required"),
        412 => Some("Precondition Failed"),
        413 => Some("Payload Too Large"),
        414 => Some("URI Too Long"),
        415 => Some("Unsupported Media Type"),
        416 => Some("Range Not Satisfiable"),
        417 => Some("Expectation Failed"),
        418 => Some("I'm a teapot"),
        421 => Some("Misdirected Request"),
        422 => Some("Unprocessable Entity"),
        423 => Some("Locked"),
        424 => Some("Failed Dependency"),
        426 => Some("Upgrade Required"),
        428 => Some("Precondition Required"),
        429 => Some("Too Many Requests"),
        431 => Some("Request Header Fields Too Large"),
        451 => Some("Unavailable For Legal Reasons"),
        500 => Some("Internal Server Error"),
        501 => Some("Not Implemented"),
        502 => Some("Bad Gateway"),
        503 => Some("Service Unavailable"),
        504 => Some("Gateway Timeout"),
        505 => Some("HTTP Version Not Supported"),
        506 => Some("Variant Also Negotiates"),
        507 => Some("Insufficient Storage"),
        508 => Some("Loop Detected"),
        510 => Some("Not Extended"),
        511 => Some("Network Authentication Required"),
        // nginx
        444 => Some("No Response"),
        495 => Some("SSL Certificate Error"),
        496 => Some("SSL Certificate Required"),
        497 => Some("HTTP Request Sent to HTTPS Port"),
        499 => Some("Client Closed Request"),
        // CloudFlare
        520 => Some("Unknown Error"),
        521 => Some("Web Server Is Down"),
        522 => Some("Connection Timed Out"),
        523 => Some("Origin Is Unreachable"),
        524 => Some("A Timeout Occurred"),
        525 => Some("SSL Handshake Failed"),
        526 => Some("Invalid SSL Certificate"),
        _ => None,
    }
}
<commit_msg>Remove unused lint<commit_after>error_chain! {
    errors {
        AlreadySubscribed

        NotSubscribed

        EOF {
            description("unexpected EOF")
        }

        TooManyRedirects {
            description("too many redirects")
        }

        EmptyFeed {
            description("feed is empty or not valid")
        }

        Http(code: u32) {
            description("unexpected HTTP response code")
            display("HTTP {} ({})", code, response_code(*code).unwrap_or("Unknown"))
        }

        DatabaseOpen(path: String) {
            description("failed to open database")
            display("failed to open database: '{}'", path)
        }

        DatabaseSave(path: String) {
            description("failed to save database")
            display("failed to save database: '{}'", path)
        }

        DatabaseFormat {
            description("illegal database format")
        }
    }
    links {
        Xml(::quick_xml::errors::Error, ::quick_xml::errors::ErrorKind);
    }
    foreign_links {
        Curl(::tokio_curl::PerformError);
        Utf8(::std::str::Utf8Error);
    }
}

fn response_code(code: u32) -> Option<&'static str> {
    match code {
        100 => Some("Continue"),
        101 => Some("Switching Protocols"),
        102 => Some("Processing"),
        200 => Some("OK"),
        201 => Some("Created"),
        202 => Some("Accepted"),
        203 => Some("Non-Authoritative Information"),
        204 => Some("No Content"),
        205 => Some("Reset Content"),
        206 => Some("Partial Content"),
        207 => Some("Multi-Status"),
        208 => Some("Already Reported"),
        226 => Some("IM Used"),
        300 => Some("Multiple Choices"),
        301 => Some("Moved Permanently"),
        302 => Some("Found"),
        303 => Some("See Other"),
        304 => Some("Not Modified"),
        305 => Some("Use Proxy"),
        306 => Some("Switch Proxy"),
        307 => Some("Temporary Redirect"),
        308 => Some("Permanent Redirect"),
        400 => Some("Bad Request"),
        401 => Some("Unauthorized"),
        402 => Some("Payment Required"),
        403 => Some("Forbidden"),
        404 => Some("Not Found"),
        405 => Some("Method Not Allowed"),
        406 => Some("Not Acceptable"),
        407 => Some("Proxy Authentication Required"),
        408 => Some("Request Timeout"),
        409 => Some("Conflict"),
        410 => Some("Gone"),
        411 => Some("Length Required"),
        412 => Some("Precondition Failed"),
        413 => Some("Payload Too Large"),
        414 => Some("URI Too Long"),
        415 => Some("Unsupported Media Type"),
        416 => Some("Range Not Satisfiable"),
        417 => Some("Expectation Failed"),
        418 => Some("I'm a teapot"),
        421 => Some("Misdirected Request"),
        422 => Some("Unprocessable Entity"),
        423 => Some("Locked"),
        424 => Some("Failed Dependency"),
        426 => Some("Upgrade Required"),
        428 => Some("Precondition Required"),
        429 => Some("Too Many Requests"),
        431 => Some("Request Header Fields Too Large"),
        451 => Some("Unavailable For Legal Reasons"),
        500 => Some("Internal Server Error"),
        501 => Some("Not Implemented"),
        502 => Some("Bad Gateway"),
        503 => Some("Service Unavailable"),
        504 => Some("Gateway Timeout"),
        505 => Some("HTTP Version Not Supported"),
        506 => Some("Variant Also Negotiates"),
        507 => Some("Insufficient Storage"),
        508 => Some("Loop Detected"),
        510 => Some("Not Extended"),
        511 => Some("Network Authentication Required"),
        // nginx
        444 => Some("No Response"),
        495 => Some("SSL Certificate Error"),
        496 => Some("SSL Certificate Required"),
        497 => Some("HTTP Request Sent to HTTPS Port"),
        499 => Some("Client Closed Request"),
        // CloudFlare
        520 => Some("Unknown Error"),
        521 => Some("Web Server Is Down"),
        522 => Some("Connection Timed Out"),
        523 => Some("Origin Is Unreachable"),
        524 => Some("A Timeout Occurred"),
        525 => Some("SSL Handshake Failed"),
        526 => Some("Invalid SSL Certificate"),
        _ => None,
    }
}
<|endoftext|>


<commit_before>use error_chain::{
    error_chain, error_chain_processing, impl_error_chain_kind, impl_error_chain_processed,
    impl_extract_backtrace,
};

error_chain! {
    errors {
        // TODO: fill with our own stuff
    }
}
<commit_msg>errors: remove now unused error_chain imports<commit_after>use error_chain::error_chain;

error_chain! {
    errors {
        // TODO: fill with our own stuff
    }
}
<|endoftext|>


<commit_before>//! Manage xml character escapes

use std::borrow::Cow;
use errors::Result;
use errors::ErrorKind::Escape;
use memchr;

// UTF-8 ranges and tags for encoding characters
const TAG_CONT: u8 = 0b1000_0000;
const TAG_TWO_B: u8 = 0b1100_0000;
const TAG_THREE_B: u8 = 0b1110_0000;
const TAG_FOUR_B: u8 = 0b1111_0000;
const MAX_ONE_B: u32 = 0x80;
const MAX_TWO_B: u32 = 0x800;
const MAX_THREE_B: u32 = 0x10000;

enum ByteOrChar {
    Byte(u8),
    Char(u32),
}

/// helper function to escape a `&[u8]` and replace all
/// xml special characters (<, >, &, ', ") with their corresponding
/// xml escaped value.
pub fn escape(raw: &[u8]) -> Cow<[u8]> {
    let mut escapes: Vec<(usize, &'static [u8])> = Vec::new();
    let mut bytes = raw.iter();
    fn to_escape(b: u8) -> bool {
        match b {
            b'<' | b'>' | b'\'' | b'&' | b'"' => true,
            _ => false,
        }
    }

    let mut loc = 0;
    while let Some(i) = bytes.position(|&b| to_escape(b)) {
        loc += i;
        match raw[loc] {
            b'<' => escapes.push((loc, b"<")),
            b'>' => escapes.push((loc, b">")),
            b'\'' => escapes.push((loc, b"'")),
            b'&' => escapes.push((loc, b"&")),
            b'"' => escapes.push((loc, b""")),
            _ => unreachable!("Only '<', '>','\', '&' and '\"' are escaped"),
        }
        loc += 1;
    }

    if escapes.is_empty() {
        Cow::Borrowed(raw)
    } else {
        let len = raw.len();
        let mut v = Vec::with_capacity(len);
        let mut start = 0;
        for (i, r) in escapes {
            v.extend_from_slice(&raw[start..i]);
            v.extend_from_slice(r);
            start = i + 1;
        }

        if start < len {
            v.extend_from_slice(&raw[start..]);
        }
        Cow::Owned(v)
    }
}

/// helper function to unescape a `&[u8]` and replace all
/// xml escaped characters ('&...;') into their corresponding value
pub fn unescape(raw: &[u8]) -> Result<Cow<[u8]>> {
    let mut escapes = Vec::new();

    let mut start = 0;
    while let Some(i) = memchr::memchr(b'&', &raw[start..]) {
        start += i + 1;
        if let Some(j) = memchr::memchr(b';', &raw[start..]) {
            let end = start + j;
            // search for character correctness
            let b_o_c = match &raw[start..end] {
                b"lt" => ByteOrChar::Byte(b'<'),
                b"gt" => ByteOrChar::Byte(b'>'),
                b"amp" => ByteOrChar::Byte(b'&'),
                b"apos" => ByteOrChar::Byte(b'\''),
                b"quot" => ByteOrChar::Byte(b'\"'),
                b"#x0" | b"#0" => bail!(Escape(
                    "Null character entity not allowed".to_string(),
                    start..end
                )),
                bytes if bytes.starts_with(b"#x") => {
                    ByteOrChar::Char(parse_hexadecimal(&bytes[2..])?)
                }
                bytes if bytes.starts_with(b"#") => ByteOrChar::Char(parse_decimal(&bytes[1..])?),
                bytes => bail!(Escape(
                    format!(
                        "Unrecognized escape symbol: {:?}",
                        ::std::str::from_utf8(bytes)
                    ),
                    start..end
                )),
            };
            escapes.push((start - 1..end, b_o_c));
            start = end + 1;
        } else {
            bail!(Escape(
                "Cannot find ';' after '&'".to_string(),
                start..raw.len()
            ));
        }
    }
    if escapes.is_empty() {
        Ok(Cow::Borrowed(raw))
    } else {
        let len = raw.len();
        let mut v = Vec::with_capacity(len);
        let mut start = 0;
        for (r, b) in escapes {
            v.extend_from_slice(&raw[start..r.start]);
            match b {
                ByteOrChar::Byte(b) => v.push(b),
                ByteOrChar::Char(c) => push_utf8(&mut v, c),
            }
            start = r.end + 1;
        }
        if start < raw.len() {
            v.extend_from_slice(&raw[start..]);
        }
        Ok(Cow::Owned(v))
    }
}

fn push_utf8(buf: &mut Vec<u8>, code: u32) {
    if code < MAX_ONE_B {
        buf.push(code as u8);
    } else if code < MAX_TWO_B {
        buf.push((code >> 6 & 0x1F) as u8 | TAG_TWO_B);
        buf.push((code & 0x3F) as u8 | TAG_CONT);
    } else if code < MAX_THREE_B {
        buf.push((code >> 12 & 0x0F) as u8 | TAG_THREE_B);
        buf.push((code >> 6 & 0x3F) as u8 | TAG_CONT);
        buf.push((code & 0x3F) as u8 | TAG_CONT);
    } else {
        buf.push((code >> 18 & 0x07) as u8 | TAG_FOUR_B);
        buf.push((code >> 12 & 0x3F) as u8 | TAG_CONT);
        buf.push((code >> 6 & 0x3F) as u8 | TAG_CONT);
        buf.push((code & 0x3F) as u8 | TAG_CONT);
    }
}

fn parse_hexadecimal(bytes: &[u8]) -> Result<u32> {
    let mut code = 0;
    for &b in bytes {
        code <<= 4;
        code += match b {
            b'0'...b'9' => b - b'0',
            b'a'...b'f' => b - b'a' + 10,
            b'A'...b'F' => b - b'A' + 10,
            b => bail!("'{}' is not a valid hexadecimal character", b as char),
        } as u32;
    }
    Ok(code)
}

fn parse_decimal(bytes: &[u8]) -> Result<u32> {
    let mut code = 0;
    for &b in bytes {
        code *= 10;
        code += match b {
            b'0'...b'9' => b - b'0',
            b => bail!("'{}' is not a valid decimal character", b as char),
        } as u32;
    }
    Ok(code)
}

#[test]
fn test_unescape() {
    assert_eq!(&*unescape(b"test").unwrap(), b"test");
    assert_eq!(&*unescape(b"<test>").unwrap(), b"<test>");
    assert_eq!(&*unescape(b"0").unwrap(), b"0");
    assert_eq!(&*unescape(b"0").unwrap(), b"0");
}

#[test]
fn test_escape() {
    assert_eq!(&*escape(b"test"), b"test");
    assert_eq!(&*escape(b"<test>"), b"<test>");
    assert_eq!(&*escape(b"\"a\"bc"), b""a"bc");
    assert_eq!(&*escape(b"\"a\"b&c"), b""a"b&c");
    assert_eq!(
        &*escape(b"prefix_\"a\"b&<>c"),
        "prefix_"a"b&<>c".as_bytes()
    );
}
<commit_msg>add bound checks for utf8 conversion<commit_after>//! Manage xml character escapes

use std::borrow::Cow;
use errors::Result;
use errors::ErrorKind::Escape;
use memchr;

// UTF-8 ranges and tags for encoding characters
const TAG_CONT: u8 = 0b1000_0000;
const TAG_TWO_B: u8 = 0b1100_0000;
const TAG_THREE_B: u8 = 0b1110_0000;
const TAG_FOUR_B: u8 = 0b1111_0000;
const MAX_ONE_B: u32 = 0x80;
const MAX_TWO_B: u32 = 0x800;
const MAX_THREE_B: u32 = 0x10000;

enum ByteOrChar {
    Byte(u8),
    Char(u32),
}

/// helper function to escape a `&[u8]` and replace all
/// xml special characters (<, >, &, ', ") with their corresponding
/// xml escaped value.
pub fn escape(raw: &[u8]) -> Cow<[u8]> {
    let mut escapes: Vec<(usize, &'static [u8])> = Vec::new();
    let mut bytes = raw.iter();
    fn to_escape(b: u8) -> bool {
        match b {
            b'<' | b'>' | b'\'' | b'&' | b'"' => true,
            _ => false,
        }
    }

    let mut loc = 0;
    while let Some(i) = bytes.position(|&b| to_escape(b)) {
        loc += i;
        match raw[loc] {
            b'<' => escapes.push((loc, b"<")),
            b'>' => escapes.push((loc, b">")),
            b'\'' => escapes.push((loc, b"'")),
            b'&' => escapes.push((loc, b"&")),
            b'"' => escapes.push((loc, b""")),
            _ => unreachable!("Only '<', '>','\', '&' and '\"' are escaped"),
        }
        loc += 1;
    }

    if escapes.is_empty() {
        Cow::Borrowed(raw)
    } else {
        let len = raw.len();
        let mut v = Vec::with_capacity(len);
        let mut start = 0;
        for (i, r) in escapes {
            v.extend_from_slice(&raw[start..i]);
            v.extend_from_slice(r);
            start = i + 1;
        }

        if start < len {
            v.extend_from_slice(&raw[start..]);
        }
        Cow::Owned(v)
    }
}

/// helper function to unescape a `&[u8]` and replace all
/// xml escaped characters ('&...;') into their corresponding value
pub fn unescape(raw: &[u8]) -> Result<Cow<[u8]>> {
    let mut escapes = Vec::new();

    let mut start = 0;
    while let Some(i) = memchr::memchr(b'&', &raw[start..]) {
        start += i + 1;
        if let Some(j) = memchr::memchr(b';', &raw[start..]) {
            let end = start + j;
            // search for character correctness
            let b_o_c = match &raw[start..end] {
                b"lt" => ByteOrChar::Byte(b'<'),
                b"gt" => ByteOrChar::Byte(b'>'),
                b"amp" => ByteOrChar::Byte(b'&'),
                b"apos" => ByteOrChar::Byte(b'\''),
                b"quot" => ByteOrChar::Byte(b'\"'),
                b"#x0" | b"#0" => bail!(Escape(
                    "Null character entity not allowed".to_string(),
                    start..end
                )),
                bytes if bytes.starts_with(b"#x") => {
                    ByteOrChar::Char(parse_hexadecimal(&bytes[2..])?)
                }
                bytes if bytes.starts_with(b"#") => ByteOrChar::Char(parse_decimal(&bytes[1..])?),
                bytes => bail!(Escape(
                    format!(
                        "Unrecognized escape symbol: {:?}",
                        ::std::str::from_utf8(bytes)
                    ),
                    start..end
                )),
            };
            escapes.push((start - 1..end, b_o_c));
            start = end + 1;
        } else {
            bail!(Escape(
                "Cannot find ';' after '&'".to_string(),
                start..raw.len()
            ));
        }
    }
    if escapes.is_empty() {
        Ok(Cow::Borrowed(raw))
    } else {
        let len = raw.len();
        let mut v = Vec::with_capacity(len);
        let mut start = 0;
        for (r, b) in escapes {
            v.extend_from_slice(&raw[start..r.start]);
            match b {
                ByteOrChar::Byte(b) => v.push(b),
                ByteOrChar::Char(c) => push_utf8(&mut v, c),
            }
            start = r.end + 1;
        }
        if start < raw.len() {
            v.extend_from_slice(&raw[start..]);
        }
        Ok(Cow::Owned(v))
    }
}

fn push_utf8(buf: &mut Vec<u8>, code: u32) {
    if code < MAX_ONE_B {
        buf.push(code as u8);
    } else if code < MAX_TWO_B {
        buf.push((code >> 6 & 0x1F) as u8 | TAG_TWO_B);
        buf.push((code & 0x3F) as u8 | TAG_CONT);
    } else if code < MAX_THREE_B {
        buf.push((code >> 12 & 0x0F) as u8 | TAG_THREE_B);
        buf.push((code >> 6 & 0x3F) as u8 | TAG_CONT);
        buf.push((code & 0x3F) as u8 | TAG_CONT);
    } else {
        buf.push((code >> 18 & 0x07) as u8 | TAG_FOUR_B);
        buf.push((code >> 12 & 0x3F) as u8 | TAG_CONT);
        buf.push((code >> 6 & 0x3F) as u8 | TAG_CONT);
        buf.push((code & 0x3F) as u8 | TAG_CONT);
    }
}

fn parse_hexadecimal(bytes: &[u8]) -> Result<u32> {
    // maximum code is character is 0x10FFFF => 6 characters
    if bytes.len() > 6 {
        bail!("Cannot convert hexadecimal to utf8");
    }
    let mut code = 0;
    for &b in bytes {
        code <<= 4;
        code += match b {
            b'0'...b'9' => b - b'0',
            b'a'...b'f' => b - b'a' + 10,
            b'A'...b'F' => b - b'A' + 10,
            b => bail!("'{}' is not a valid hexadecimal character", b as char),
        } as u32;
    }
    Ok(code)
}

fn parse_decimal(bytes: &[u8]) -> Result<u32> {
    // maximum code is character is 0x10FFFF = 1114111 => 7 characters
    if bytes.len() > 7 {
        bail!("Cannot convert decimal to utf8");
    }
    let mut code = 0;
    for &b in bytes {
        code *= 10;
        code += match b {
            b'0'...b'9' => b - b'0',
            b => bail!("'{}' is not a valid decimal character", b as char),
        } as u32;
    }
    Ok(code)
}

#[test]
fn test_unescape() {
    assert_eq!(&*unescape(b"test").unwrap(), b"test");
    assert_eq!(&*unescape(b"<test>").unwrap(), b"<test>");
    assert_eq!(&*unescape(b"0").unwrap(), b"0");
    assert_eq!(&*unescape(b"0").unwrap(), b"0");
}

#[test]
fn test_escape() {
    assert_eq!(&*escape(b"test"), b"test");
    assert_eq!(&*escape(b"<test>"), b"<test>");
    assert_eq!(&*escape(b"\"a\"bc"), b""a"bc");
    assert_eq!(&*escape(b"\"a\"b&c"), b""a"b&c");
    assert_eq!(
        &*escape(b"prefix_\"a\"b&<>c"),
        "prefix_"a"b&<>c".as_bytes()
    );
}
<|endoftext|>


<commit_before>use model::{DotFile, DotFileType};
use std::path::Path;
use std::path::PathBuf;
use slog::Logger;
use std::fs;
use std::env;
use std::error::Error;
use regex::Regex;
use errors::DotcopterError;

pub fn scan_dir(log: &Logger, dir: &str) -> Vec<DotFile> {
  let path = Path::new(dir);
  if path.is_dir() {
    match get_dot_files(log, &path) {
      Ok(links) => links,
      Err(e) => {
        error!(log, "Failed to get symlinks"; "error" => e.description());
        Vec::new()
      }
    }
  } else {
    error!(log, "Parameter is not a directory");
    Vec::new()
  }
}

fn get_dot_files(log: &Logger, dir: &Path) -> Result<Vec<DotFile>, DotcopterError> {
  let current_dir = env::current_dir().expect("Expected current directory to be available");
  let links = try!(get_links(log, dir));
  let mut dot_files: Vec<DotFile> = Vec::new();
  for link in links {
    let log = log.new(o!("link" => format!("{}", link.display())));
    if link.exists() {
      debug!(log, "Analyzing link");
      if try!(link_points_into_dir(&log, &link, &current_dir)) {
        info!(log, "Found dotfile");
        if let Ok(target) = link.clone().into_os_string().into_string() {
          let source_path = try!(link_target_to_relative_path(&link, &current_dir));
          if let Ok(source) = source_path.into_os_string().into_string() {
            let dot_file = DotFile {
              source: source,
              target: try!(replace_home_with_tilde(&log, &target)),
              dot_file_type: DotFileType::LINK,
            };
            dot_files.push(dot_file);
          }
        }
      } else {
        debug!(log, "Skip link")
      }
    } else {
      warn!(log, "Link broken");
    }
  }
  Ok(dot_files)
}

fn replace_home_with_tilde(log: &Logger, path: &str) -> Result<String, DotcopterError> {
  if let Some(home_dir) = env::home_dir() {
    replace_path_with_tilde(path, home_dir)
  } else {
    warn!(log, "Home dir not set");
    Ok(path.to_string())
  }
}

fn replace_path_with_tilde(path: &str, path_to_replace: PathBuf) -> Result<String, DotcopterError> {
  let replace_string = path_to_replace.into_os_string().into_string().expect("path should be a valid string");
  let mut pattern: String = "^".to_string();
  pattern.push_str(&replace_string);
  let regex = try!(Regex::new(&pattern));
  Ok(regex.replace_all(&path, "~").into_owned())
}

fn link_target_to_relative_path(link: &Path, current_dir: &Path) -> Result<PathBuf, DotcopterError> {
  let canonicalized_link = try!(link.canonicalize());
  Ok(canonicalized_link
       .strip_prefix(current_dir)
       .expect("Should be checked already")
       .to_path_buf())
}

fn link_points_into_dir(log: &Logger, link: &Path, dir: &Path) -> Result<bool, DotcopterError> {
  let canonicalized_link = try!(link.canonicalize());
  debug!(log, "Check if link points to dir";
         "canonicalized_link" => format!("{}", canonicalized_link.display()),
         "dir_to_check" => format!("{}", dir.display()));
  Ok(canonicalized_link.starts_with(dir))
}

fn get_links(log: &Logger, path: &Path) -> Result<Vec<PathBuf>, DotcopterError> {
  let mut symlinks: Vec<PathBuf> = Vec::new();
  let entries = try!(fs::read_dir(path));
  for dir_entry_result in entries {
    let dir_entry: fs::DirEntry = try!(dir_entry_result);
    let entry_path = dir_entry.path();
    debug!(log, "Analyzing"; "dir_entry" => format!("{}", entry_path.display()));
    let metadata: fs::Metadata = try!(entry_path.symlink_metadata());
    if metadata.file_type().is_symlink() {
      symlinks.push(entry_path.to_path_buf());
    }
  }
  debug!(log, format!("Found {} symlinks", symlinks.len()));
  Ok(symlinks)
}

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

  #[test]
  fn test_replace_path_with_tilde() {
    let home_dir = Path::new("/home/blubb").to_path_buf();

    let replaced_string = replace_path_with_tilde("/home/blubb/moep/home/blubb/test.txt", home_dir).expect("should succeed");
    assert_that(&replaced_string).is_equal_to("~/moep/home/blubb/test.txt".to_string());

  }
}
<commit_msg>don't unwrap cwd error<commit_after>use model::{DotFile, DotFileType};
use std::path::Path;
use std::path::PathBuf;
use slog::Logger;
use std::fs;
use std::env;
use std::error::Error;
use regex::Regex;
use errors::DotcopterError;

pub fn scan_dir(log: &Logger, dir: &str) -> Vec<DotFile> {
  let path = Path::new(dir);
  if path.is_dir() {
    match get_dot_files(log, &path) {
      Ok(links) => links,
      Err(e) => {
        error!(log, "Failed to get symlinks"; "error" => e.description());
        Vec::new()
      }
    }
  } else {
    error!(log, "Parameter is not a directory");
    Vec::new()
  }
}

fn get_dot_files(log: &Logger, dir: &Path) -> Result<Vec<DotFile>, DotcopterError> {
  let current_dir = try!(env::current_dir());
  let links = try!(get_links(log, dir));
  let mut dot_files: Vec<DotFile> = Vec::new();
  for link in links {
    let log = log.new(o!("link" => format!("{}", link.display())));
    if link.exists() {
      debug!(log, "Analyzing link");
      if try!(link_points_into_dir(&log, &link, &current_dir)) {
        info!(log, "Found dotfile");
        if let Ok(target) = link.clone().into_os_string().into_string() {
          let source_path = try!(link_target_to_relative_path(&link, &current_dir));
          if let Ok(source) = source_path.into_os_string().into_string() {
            let dot_file = DotFile {
              source: source,
              target: try!(replace_home_with_tilde(&log, &target)),
              dot_file_type: DotFileType::LINK,
            };
            dot_files.push(dot_file);
          }
        }
      } else {
        debug!(log, "Skip link")
      }
    } else {
      warn!(log, "Link broken");
    }
  }
  Ok(dot_files)
}

fn replace_home_with_tilde(log: &Logger, path: &str) -> Result<String, DotcopterError> {
  if let Some(home_dir) = env::home_dir() {
    replace_path_with_tilde(path, home_dir)
  } else {
    warn!(log, "Home dir not set");
    Ok(path.to_string())
  }
}

fn replace_path_with_tilde(path: &str, path_to_replace: PathBuf) -> Result<String, DotcopterError> {
  let replace_string = path_to_replace.into_os_string().into_string().expect("path should be a valid string");
  let mut pattern: String = "^".to_string();
  pattern.push_str(&replace_string);
  let regex = try!(Regex::new(&pattern));
  Ok(regex.replace_all(&path, "~").into_owned())
}

fn link_target_to_relative_path(link: &Path, current_dir: &Path) -> Result<PathBuf, DotcopterError> {
  let canonicalized_link = try!(link.canonicalize());
  Ok(canonicalized_link
       .strip_prefix(current_dir)
       .expect("Should be checked already")
       .to_path_buf())
}

fn link_points_into_dir(log: &Logger, link: &Path, dir: &Path) -> Result<bool, DotcopterError> {
  let canonicalized_link = try!(link.canonicalize());
  debug!(log, "Check if link points to dir";
         "canonicalized_link" => format!("{}", canonicalized_link.display()),
         "dir_to_check" => format!("{}", dir.display()));
  Ok(canonicalized_link.starts_with(dir))
}

fn get_links(log: &Logger, path: &Path) -> Result<Vec<PathBuf>, DotcopterError> {
  let mut symlinks: Vec<PathBuf> = Vec::new();
  let entries = try!(fs::read_dir(path));
  for dir_entry_result in entries {
    let dir_entry: fs::DirEntry = try!(dir_entry_result);
    let entry_path = dir_entry.path();
    debug!(log, "Analyzing"; "dir_entry" => format!("{}", entry_path.display()));
    let metadata: fs::Metadata = try!(entry_path.symlink_metadata());
    if metadata.file_type().is_symlink() {
      symlinks.push(entry_path.to_path_buf());
    }
  }
  debug!(log, format!("Found {} symlinks", symlinks.len()));
  Ok(symlinks)
}

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

  #[test]
  fn test_replace_path_with_tilde() {
    let home_dir = Path::new("/home/blubb").to_path_buf();

    let replaced_string = replace_path_with_tilde("/home/blubb/moep/home/blubb/test.txt", home_dir).expect("should succeed");
    assert_that(&replaced_string).is_equal_to("~/moep/home/blubb/test.txt".to_string());

  }
}
<|endoftext|>


<commit_before>//! Input and output of images.

use crate::{error, ImageError, ImageResult};

mod reader;
pub(crate) mod free_functions;

pub use self::reader::Reader;

/// Set of supported strict limits for a decoder
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[allow(missing_copy_implementations)]
pub struct LimitSupport {
    _non_exhaustive: (),
}

impl Default for LimitSupport {
    fn default() -> LimitSupport {
        LimitSupport {
            _non_exhaustive: (),
        }
    }
}

/// Resource limits for decoding.
///
/// Limits can be either *strict* or *non-strict*. Non-strict limits are best-effort
/// limits where the library does not guarantee that limit wont be exceeded. Do note
/// that it is still considered a bug if a non-strict limit is exceeded, however as
/// some of the underlying decoders do not support not support such limits one cannot
/// rely on these limits being supported. For stric limits the library makes a stronger
/// guarantee that the limit will not be exceeded. Exceeding a strict limit is considered
/// a critical bug. If a decoder cannot guaranree that it will uphold a strict limit it
/// *must* fail with `image::error::LimitErrorKind::Unsupported`.
///
/// The limit check should only ever fail if a limit will be exceeded or an unsupported
/// strict limit is used.
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[allow(missing_copy_implementations)]
pub struct Limits {
    /// The maximum allowed image width. This limit is strict. The default is no limit.
    pub max_image_width: Option<u32>,
    /// The maximum allowed image height. This limit is strict. The default is no limit.
    pub max_image_height: Option<u32>,
    /// The maximum allowed amount of memory to be allocated by the
    /// decoder at any one time. This limit is non-strict and some
    /// decoders may ignore it. The default is 512MiB.
    pub max_alloc: Option<u64>,
    _non_exhaustive: (),
}

impl Default for Limits {
    fn default() -> Limits {
        Limits {
            max_image_width: None,
            max_image_height: None,
            max_alloc: Some(512*1024*1024),
            _non_exhaustive: (),
        }
    }
}

impl Limits {
    /// Disable all limits
    pub fn no_limits() -> Limits {
        Limits {
            max_image_width: None,
            max_image_height: None,
            max_alloc: None,
            _non_exhaustive: (),
        }
    }

    /// This function checks that all currently set strict limits are supported.
    pub fn check_support(&self, _supported: &LimitSupport) -> ImageResult<()> {
        Ok(())
    }

    /// This function checks the `max_image_width` and `max_image_height` limits given
    /// the image width and height.
    pub fn check_dimensions(&self, width: u32, height: u32) -> ImageResult<()> {
        if let Some(max_width) = self.max_image_width {
            if width > max_width {
                return Err(ImageError::Limits(error::LimitError::from_kind(
                    error::LimitErrorKind::DimensionError)))
            }
        }

        if let Some(max_height) = self.max_image_height {
            if height > max_height {
                return Err(ImageError::Limits(error::LimitError::from_kind(
                    error::LimitErrorKind::DimensionError)))
            }
        }

        Ok(())
    }

    /// This function checks that the current limit allows for reserving the set amount
    /// of bytes, it then reduces the limit accordingly.
    pub fn reserve(&mut self, amount: u64) -> ImageResult<()> {
        if let Some(max_alloc) = self.max_alloc.as_mut() {
            if *max_alloc < amount {
                return Err(ImageError::Limits(error::LimitError::from_kind(
                    error::LimitErrorKind::InsufficientMemory)))
            }

            *max_alloc -= amount;
        }

        Ok(())
    }

    /// This function increases the `max_alloc` limit with amount. Should only be used
    /// togheter with [`reserve`].
    ///
    /// [`reserve`]: #method.reserve
    pub fn free(&mut self, amount: u64) {
        if let Some(max_alloc) = self.max_alloc.as_mut() {
            *max_alloc -= std::cmp::min(*max_alloc, amount);
        }
    }
}
<commit_msg>Fix bug in `Limits::free`<commit_after>//! Input and output of images.

use crate::{error, ImageError, ImageResult};

mod reader;
pub(crate) mod free_functions;

pub use self::reader::Reader;

/// Set of supported strict limits for a decoder
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[allow(missing_copy_implementations)]
pub struct LimitSupport {
    _non_exhaustive: (),
}

impl Default for LimitSupport {
    fn default() -> LimitSupport {
        LimitSupport {
            _non_exhaustive: (),
        }
    }
}

/// Resource limits for decoding.
///
/// Limits can be either *strict* or *non-strict*. Non-strict limits are best-effort
/// limits where the library does not guarantee that limit wont be exceeded. Do note
/// that it is still considered a bug if a non-strict limit is exceeded, however as
/// some of the underlying decoders do not support not support such limits one cannot
/// rely on these limits being supported. For stric limits the library makes a stronger
/// guarantee that the limit will not be exceeded. Exceeding a strict limit is considered
/// a critical bug. If a decoder cannot guaranree that it will uphold a strict limit it
/// *must* fail with `image::error::LimitErrorKind::Unsupported`.
///
/// The limit check should only ever fail if a limit will be exceeded or an unsupported
/// strict limit is used.
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[allow(missing_copy_implementations)]
pub struct Limits {
    /// The maximum allowed image width. This limit is strict. The default is no limit.
    pub max_image_width: Option<u32>,
    /// The maximum allowed image height. This limit is strict. The default is no limit.
    pub max_image_height: Option<u32>,
    /// The maximum allowed amount of memory to be allocated by the
    /// decoder at any one time. This limit is non-strict and some
    /// decoders may ignore it. The default is 512MiB.
    pub max_alloc: Option<u64>,
    _non_exhaustive: (),
}

impl Default for Limits {
    fn default() -> Limits {
        Limits {
            max_image_width: None,
            max_image_height: None,
            max_alloc: Some(512*1024*1024),
            _non_exhaustive: (),
        }
    }
}

impl Limits {
    /// Disable all limits
    pub fn no_limits() -> Limits {
        Limits {
            max_image_width: None,
            max_image_height: None,
            max_alloc: None,
            _non_exhaustive: (),
        }
    }

    /// This function checks that all currently set strict limits are supported.
    pub fn check_support(&self, _supported: &LimitSupport) -> ImageResult<()> {
        Ok(())
    }

    /// This function checks the `max_image_width` and `max_image_height` limits given
    /// the image width and height.
    pub fn check_dimensions(&self, width: u32, height: u32) -> ImageResult<()> {
        if let Some(max_width) = self.max_image_width {
            if width > max_width {
                return Err(ImageError::Limits(error::LimitError::from_kind(
                    error::LimitErrorKind::DimensionError)))
            }
        }

        if let Some(max_height) = self.max_image_height {
            if height > max_height {
                return Err(ImageError::Limits(error::LimitError::from_kind(
                    error::LimitErrorKind::DimensionError)))
            }
        }

        Ok(())
    }

    /// This function checks that the current limit allows for reserving the set amount
    /// of bytes, it then reduces the limit accordingly.
    pub fn reserve(&mut self, amount: u64) -> ImageResult<()> {
        if let Some(max_alloc) = self.max_alloc.as_mut() {
            if *max_alloc < amount {
                return Err(ImageError::Limits(error::LimitError::from_kind(
                    error::LimitErrorKind::InsufficientMemory)))
            }

            *max_alloc -= amount;
        }

        Ok(())
    }

    /// This function increases the `max_alloc` limit with amount. Should only be used
    /// togheter with [`reserve`].
    ///
    /// [`reserve`]: #method.reserve
    pub fn free(&mut self, amount: u64) {
        if let Some(max_alloc) = self.max_alloc.as_mut() {
            *max_alloc = max_alloc.saturating_add(amount);
        }
    }
}
<|endoftext|>


<commit_before>
use ndarray::*;
use lapack::c;

use super::error::*;

pub type LDA = i32;
pub type Col = i32;
pub type Row = i32;

#[derive(Debug, Clone, Copy)]
pub enum Layout {
    C((Row, LDA)),
    F((Col, LDA)),
}

impl Layout {
    pub fn size(&self) -> (Row, Col) {
        match *self {
            Layout::C((row, lda)) => (row, lda),
            Layout::F((col, lda)) => (lda, col),
        }
    }

    pub fn row(&self) -> Row {
        self.size().0
    }

    pub fn col(&self) -> Col {
        self.size().1
    }

    pub fn lda(&self) -> LDA {
        match *self {
            Layout::C((_, lda)) => lda,
            Layout::F((_, lda)) => lda,
        }
    }

    pub fn lapacke_layout(&self) -> c::Layout {
        match *self {
            Layout::C(_) => c::Layout::RowMajor,
            Layout::F(_) => c::Layout::ColumnMajor,
        }
    }
}

pub trait AllocatedArray {
    type Scalar;
    fn layout(&self) -> Result<Layout>;
    fn square_layout(&self) -> Result<Layout>;
    fn as_allocated(&self) -> Result<&[Self::Scalar]>;
}

impl<A, S> AllocatedArray for ArrayBase<S, Ix2>
    where S: Data<Elem = A>
{
    type Scalar = A;

    fn layout(&self) -> Result<Layout> {
        let strides = self.strides();
        if ::std::cmp::min(strides[0], strides[1]) != 1 {
            return Err(StrideError::new(strides[0], strides[1]).into());
        }
        if strides[0] > strides[1] {
            Ok(Layout::C((self.rows() as i32, self.cols() as i32)))
        } else {
            Ok(Layout::F((self.cols() as i32, self.rows() as i32)))
        }
    }

    fn square_layout(&self) -> Result<Layout> {
        let l = self.layout()?;
        let (n, m) = l.size();
        if n == m {
            Ok(l)
        } else {
            Err(NotSquareError::new(n, m).into())
        }
    }

    fn as_allocated(&self) -> Result<&[A]> {
        let slice = self.as_slice_memory_order().ok_or(MemoryContError::new())?;
        Ok(slice)
    }
}
<commit_msg>Remove row/col<commit_after>
use ndarray::*;
use lapack::c;

use super::error::*;

pub type LDA = i32;
pub type Col = i32;
pub type Row = i32;

#[derive(Debug, Clone, Copy)]
pub enum Layout {
    C((Row, LDA)),
    F((Col, LDA)),
}

impl Layout {
    pub fn size(&self) -> (Row, Col) {
        match *self {
            Layout::C((row, lda)) => (row, lda),
            Layout::F((col, lda)) => (lda, col),
        }
    }

    pub fn lda(&self) -> LDA {
        match *self {
            Layout::C((_, lda)) => lda,
            Layout::F((_, lda)) => lda,
        }
    }

    pub fn lapacke_layout(&self) -> c::Layout {
        match *self {
            Layout::C(_) => c::Layout::RowMajor,
            Layout::F(_) => c::Layout::ColumnMajor,
        }
    }
}

pub trait AllocatedArray {
    type Scalar;
    fn layout(&self) -> Result<Layout>;
    fn square_layout(&self) -> Result<Layout>;
    fn as_allocated(&self) -> Result<&[Self::Scalar]>;
}

impl<A, S> AllocatedArray for ArrayBase<S, Ix2>
    where S: Data<Elem = A>
{
    type Scalar = A;

    fn layout(&self) -> Result<Layout> {
        let strides = self.strides();
        if ::std::cmp::min(strides[0], strides[1]) != 1 {
            return Err(StrideError::new(strides[0], strides[1]).into());
        }
        if strides[0] > strides[1] {
            Ok(Layout::C((self.rows() as i32, self.cols() as i32)))
        } else {
            Ok(Layout::F((self.cols() as i32, self.rows() as i32)))
        }
    }

    fn square_layout(&self) -> Result<Layout> {
        let l = self.layout()?;
        let (n, m) = l.size();
        if n == m {
            Ok(l)
        } else {
            Err(NotSquareError::new(n, m).into())
        }
    }

    fn as_allocated(&self) -> Result<&[A]> {
        let slice = self.as_slice_memory_order().ok_or(MemoryContError::new())?;
        Ok(slice)
    }
}
<|endoftext|>


<commit_before>#![allow(non_snake_case)]

//! A few linear algebra operations on two-dimensional arrays.

use libnum::{Num, zero, one, Zero, One};
use std::iter;
use std::num::Float;
#[cfg(not(nocomplex))]
use libnum::Complex;
use std::ops::{Add, Sub, Mul, Div};

use super::{Array, Ix};

/// Column vector.
pub type Col = Array;
/// Rectangular matrix.
pub type Mat = Array;

/// Trait union for a ring with 1.
pub trait Ring : Clone + Zero + Add<Output=Self> + Sub<Output=Self>
    + One + Mul<Output=Self> { }
impl<A: Clone + Zero + Add<Output=A> + Sub<Output=A> + One + Mul<Output=A>> Ring for A { }

/// Trait union for a field.
pub trait Field : Ring + Div<Output=Self> { }
impl<A: Ring + Div<Output=A>> Field for A { }

/// A real or complex number.
pub trait ComplexField : Copy + Field
{
    #[inline]
    fn conjugate(self) -> Self { self }
    fn sqrt_real(self) -> Self;
    #[inline]
    fn is_complex() -> bool { false }
}

impl ComplexField for f32
{
    #[inline]
    fn sqrt_real(self) -> f32 { self.sqrt() }
}

impl ComplexField for f64
{
    #[inline]
    fn sqrt_real(self) -> f64 { self.sqrt() }
}

#[cfg(not(nocomplex))]
impl ComplexField for Complex
{
    #[inline]
    fn conjugate(self) -> Complex { self.conj() }
    fn sqrt_real(self) -> Complex { Complex::new(self.re.sqrt(), zero()) }
    #[inline]
    fn is_complex() -> bool { true }
}

/// Return the identity matrix of dimension *n*.
pub fn eye(n: Ix) -> Mat
{
    let mut eye = Array::zeros((n, n));
    for a_ii in eye.diag_iter_mut() {
        *a_ii = one::();
    }
    eye
}

/*
/// Return the inverse matrix of square matrix `a`.
pub fn inverse(a: &Mat) -> Mat
{
    fail!()
}
*/

/// Solve *a x = b* with linear least squares approximation.
///
/// It is used to find the best fit for an overdetermined system,
/// i.e. the number of rows in *a* is larger than the number of
/// unknowns *x*.
///
/// Return best fit for *x*.
pub fn least_squares(a: &Mat, b: &Col) -> Col
{
    // Using transpose: a.T a x = a.T b;
    // a.T a being square gives naive solution
    // x_lstsq = inv(a.T a) a.T b
    //
    // Solve using cholesky decomposition
    // aT a x = aT b
    //
    // Factor aT a into L L.T
    //
    // L L.T x = aT b
    //
    // => L z = aT b
    //  fw subst for z
    // => L.T x = z
    //  bw subst for x estimate
    //
    let mut aT = a.clone();
    aT.swap_axes(0, 1);
    if ::is_complex() {
        // conjugate transpose
        for elt in aT.iter_mut() {
            *elt = elt.conjugate();
        }
    }

    let aT_a = aT.mat_mul(a);
    let mut L = cholesky(aT_a);
    let rhs = aT.mat_mul_col(b);

    // Solve L z = aT b
    let z = subst_fw(&L, &rhs);

    // Solve L.T x = z
    if ::is_complex() {
        // conjugate transpose
        // only elements below the diagonal have imag part
        let (m, _) = L.dim();
        for i in (1..m) {
            for j in (0..i) {
                let elt = &mut L[(i, j)];
                *elt = elt.conjugate();
            }
        }
    }
    L.swap_axes(0, 1);

    // => x_lstsq
    subst_bw(&L, &z)
}

/// Factor *a = L LT*.
///
/// *a* should be a square matrix, hermitian and positive definite.
///
/// https://en.wikipedia.org/wiki/Cholesky_decomposition
///
/// “The Cholesky decomposition is mainly used for the numerical solution of
/// linear equations Ax = b.
///
/// If A is symmetric and positive definite, then we can solve Ax = b by first
/// computing the Cholesky decomposition A = LL*, then solving Ly = b for y by
/// forward substitution, and finally solving L*x = y for x by back
/// substitution.”
///
/// Return L.
pub fn cholesky(a: Mat) -> Mat
{
    let z = zero::();
    let (m, n) = a.dim();
    assert!(m == n);
    // Perform the operation in-place on `a`
    let mut L = a;
    for i in (0..m) {
        // Entries 0 .. i before the diagonal
        for j in (0..i) {
            // A = (
            // L²_1,1
            // L_2,1 L_1,1  L²_2,1 + L²_2,2
            // L_3,1 L_1,1  L_3,1 L_2,1 + L_3,2 L_2,2  L²_3,1 + L²_3,2 + L²_3,3
            // .. )
            let mut lik_ljk_sum = z.clone();
            {
                // L_ik for k = 0 .. j
                // L_jk for k = 0 .. j
                let Lik = L.row_iter(i);
                let Ljk = L.row_iter(j);
                for (&lik, &ljk) in Lik.zip(Ljk).take(j as usize) {
                    lik_ljk_sum = lik_ljk_sum + lik * ljk.conjugate();
                }
            }

            // L_ij = [ A_ij - Sum(k = 1 .. j) L_ik L_jk ] / L_jj
            L[(i, j)] = (L[(i, j)] - lik_ljk_sum) / L[(j, j)];
        }

        // Diagonal where i == j
        // L_jj = Sqrt[ A_jj - Sum(k = 1 .. j) L_jk L_jk ]
        let j = i;
        let mut ljk_sum = z.clone();
        // L_jk for k = 0 .. j
        for &ljk in L.row_iter(j).take(j as usize) {
            ljk_sum = ljk_sum + ljk * ljk.conjugate();
        }
        L[(j, j)] = (L[(j, j)] - ljk_sum).sqrt_real();

        // After the diagonal
        // L_ij = 0 for j > i
        for j in (i + 1..n) {
            L[(i, j)] = z.clone();
        }
    }
    L
}

/// Solve *L x = b* where *L* is a lower triangular matrix.
pub fn subst_fw(l: &Mat, b: &Col) -> Col
{
    let (m, n) = l.dim();
    assert!(m == n);
    assert!(m == b.dim());
    let mut x: Vec<_> = iter::repeat(zero::()).take(m as usize).collect();
    for (i, bi) in b.indexed_iter() {
        // b_lx_sum = b[i] - Sum(for j = 0 .. i) L_ij x_j
        let mut b_lx_sum = bi.clone();
        for (lij, xj) in l.row_iter(i).zip(x.iter()).take(i as usize) {
            b_lx_sum = b_lx_sum - (*lij) * (*xj)
        }
        x.as_mut_slice()[i as usize] = b_lx_sum / l[(i, i)];
    }
    Array::from_vec(x)
}

/// Solve *U x = b* where *U* is an upper triangular matrix.
pub fn subst_bw(u: &Mat, b: &Col) -> Col
{
    let (m, n) = u.dim();
    assert!(m == n);
    assert!(m == b.dim());
    let mut x: Vec<_> = iter::repeat(zero::()).take(m as usize).collect();
    for i in (0..m).rev() {
        // b_ux_sum = b[i] - Sum(for j = i .. m) U_ij x_j
        let mut b_ux_sum = b[i].clone();
        for (uij, xj) in u.row_iter(i).rev().zip(x.iter().rev()).take((m - i - 1) as usize) {
            b_ux_sum = b_ux_sum - (*uij) * (*xj);
        }
        x.as_mut_slice()[i as usize] = b_ux_sum / u[(i, i)];
    }
    Array::from_vec(x)
}
<commit_msg>Use a function for vec from elem<commit_after>#![allow(non_snake_case)]

//! A few linear algebra operations on two-dimensional arrays.

use libnum::{Num, zero, one, Zero, One};
use std::num::Float;
#[cfg(not(nocomplex))]
use libnum::Complex;
use std::ops::{Add, Sub, Mul, Div};

use super::{Array, Ix};

/// Column vector.
pub type Col = Array;
/// Rectangular matrix.
pub type Mat = Array;

/// Trait union for a ring with 1.
pub trait Ring : Clone + Zero + Add<Output=Self> + Sub<Output=Self>
    + One + Mul<Output=Self> { }
impl<A: Clone + Zero + Add<Output=A> + Sub<Output=A> + One + Mul<Output=A>> Ring for A { }

/// Trait union for a field.
pub trait Field : Ring + Div<Output=Self> { }
impl<A: Ring + Div<Output=A>> Field for A { }

/// A real or complex number.
pub trait ComplexField : Copy + Field
{
    #[inline]
    fn conjugate(self) -> Self { self }
    fn sqrt_real(self) -> Self;
    #[inline]
    fn is_complex() -> bool { false }
}

impl ComplexField for f32
{
    #[inline]
    fn sqrt_real(self) -> f32 { self.sqrt() }
}

impl ComplexField for f64
{
    #[inline]
    fn sqrt_real(self) -> f64 { self.sqrt() }
}

#[cfg(not(nocomplex))]
impl ComplexField for Complex
{
    #[inline]
    fn conjugate(self) -> Complex { self.conj() }
    fn sqrt_real(self) -> Complex { Complex::new(self.re.sqrt(), zero()) }
    #[inline]
    fn is_complex() -> bool { true }
}

/// Return the identity matrix of dimension *n*.
pub fn eye(n: Ix) -> Mat
{
    let mut eye = Array::zeros((n, n));
    for a_ii in eye.diag_iter_mut() {
        *a_ii = one::();
    }
    eye
}

/*
/// Return the inverse matrix of square matrix `a`.
pub fn inverse(a: &Mat) -> Mat
{
    fail!()
}
*/

/// Solve *a x = b* with linear least squares approximation.
///
/// It is used to find the best fit for an overdetermined system,
/// i.e. the number of rows in *a* is larger than the number of
/// unknowns *x*.
///
/// Return best fit for *x*.
pub fn least_squares(a: &Mat, b: &Col) -> Col
{
    // Using transpose: a.T a x = a.T b;
    // a.T a being square gives naive solution
    // x_lstsq = inv(a.T a) a.T b
    //
    // Solve using cholesky decomposition
    // aT a x = aT b
    //
    // Factor aT a into L L.T
    //
    // L L.T x = aT b
    //
    // => L z = aT b
    //  fw subst for z
    // => L.T x = z
    //  bw subst for x estimate
    //
    let mut aT = a.clone();
    aT.swap_axes(0, 1);
    if ::is_complex() {
        // conjugate transpose
        for elt in aT.iter_mut() {
            *elt = elt.conjugate();
        }
    }

    let aT_a = aT.mat_mul(a);
    let mut L = cholesky(aT_a);
    let rhs = aT.mat_mul_col(b);

    // Solve L z = aT b
    let z = subst_fw(&L, &rhs);

    // Solve L.T x = z
    if ::is_complex() {
        // conjugate transpose
        // only elements below the diagonal have imag part
        let (m, _) = L.dim();
        for i in (1..m) {
            for j in (0..i) {
                let elt = &mut L[(i, j)];
                *elt = elt.conjugate();
            }
        }
    }
    L.swap_axes(0, 1);

    // => x_lstsq
    subst_bw(&L, &z)
}

/// Factor *a = L LT*.
///
/// *a* should be a square matrix, hermitian and positive definite.
///
/// https://en.wikipedia.org/wiki/Cholesky_decomposition
///
/// “The Cholesky decomposition is mainly used for the numerical solution of
/// linear equations Ax = b.
///
/// If A is symmetric and positive definite, then we can solve Ax = b by first
/// computing the Cholesky decomposition A = LL*, then solving Ly = b for y by
/// forward substitution, and finally solving L*x = y for x by back
/// substitution.”
///
/// Return L.
pub fn cholesky(a: Mat) -> Mat
{
    let z = zero::();
    let (m, n) = a.dim();
    assert!(m == n);
    // Perform the operation in-place on `a`
    let mut L = a;
    for i in (0..m) {
        // Entries 0 .. i before the diagonal
        for j in (0..i) {
            // A = (
            // L²_1,1
            // L_2,1 L_1,1  L²_2,1 + L²_2,2
            // L_3,1 L_1,1  L_3,1 L_2,1 + L_3,2 L_2,2  L²_3,1 + L²_3,2 + L²_3,3
            // .. )
            let mut lik_ljk_sum = z.clone();
            {
                // L_ik for k = 0 .. j
                // L_jk for k = 0 .. j
                let Lik = L.row_iter(i);
                let Ljk = L.row_iter(j);
                for (&lik, &ljk) in Lik.zip(Ljk).take(j as usize) {
                    lik_ljk_sum = lik_ljk_sum + lik * ljk.conjugate();
                }
            }

            // L_ij = [ A_ij - Sum(k = 1 .. j) L_ik L_jk ] / L_jj
            L[(i, j)] = (L[(i, j)] - lik_ljk_sum) / L[(j, j)];
        }

        // Diagonal where i == j
        // L_jj = Sqrt[ A_jj - Sum(k = 1 .. j) L_jk L_jk ]
        let j = i;
        let mut ljk_sum = z.clone();
        // L_jk for k = 0 .. j
        for &ljk in L.row_iter(j).take(j as usize) {
            ljk_sum = ljk_sum + ljk * ljk.conjugate();
        }
        L[(j, j)] = (L[(j, j)] - ljk_sum).sqrt_real();

        // After the diagonal
        // L_ij = 0 for j > i
        for j in (i + 1..n) {
            L[(i, j)] = z.clone();
        }
    }
    L
}

fn vec_elem(elt: A, n: usize) -> Vec
{
    let mut v = Vec::with_capacity(n);
    for _ in (0..n) {
        v.push(elt);
    }
    v
}

/// Solve *L x = b* where *L* is a lower triangular matrix.
pub fn subst_fw(l: &Mat, b: &Col) -> Col
{
    let (m, n) = l.dim();
    assert!(m == n);
    assert!(m == b.dim());
    let mut x = vec_elem(zero::(), m as usize);
    for (i, bi) in b.indexed_iter() {
        // b_lx_sum = b[i] - Sum(for j = 0 .. i) L_ij x_j
        let mut b_lx_sum = bi.clone();
        for (lij, xj) in l.row_iter(i).zip(x.iter()).take(i as usize) {
            b_lx_sum = b_lx_sum - (*lij) * (*xj)
        }
        x.as_mut_slice()[i as usize] = b_lx_sum / l[(i, i)];
    }
    Array::from_vec(x)
}

/// Solve *U x = b* where *U* is an upper triangular matrix.
pub fn subst_bw(u: &Mat, b: &Col) -> Col
{
    let (m, n) = u.dim();
    assert!(m == n);
    assert!(m == b.dim());
    let mut x = vec_elem(zero::(), m as usize);
    for i in (0..m).rev() {
        // b_ux_sum = b[i] - Sum(for j = i .. m) U_ij x_j
        let mut b_ux_sum = b[i].clone();
        for (uij, xj) in u.row_iter(i).rev().zip(x.iter().rev()).take((m - i - 1) as usize) {
            b_ux_sum = b_ux_sum - (*uij) * (*xj);
        }
        x.as_mut_slice()[i as usize] = b_ux_sum / u[(i, i)];
    }
    Array::from_vec(x)
}
<|endoftext|>


<commit_before>// Copyright 2017 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/// Creates a `Vec<Box<Transaction>>` from the given transactions.
///
/// Each transaction must have an `Into<Box<Transaction>>` implementation.
#[macro_export]
macro_rules! txvec {
    ($($x:expr),*) => (
        vec![$($x.into()),*]
    );
    ($($x:expr,)*) => (
        vec![$($x.into()),*]
    )
}
<commit_msg>Change `txvec!` doc description<commit_after>// Copyright 2017 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/// Creates a `Vec<Box<Transaction>>` from the given transactions, or other objects
/// implementing the `Into<Box<Transaction>>` trait.
#[macro_export]
macro_rules! txvec {
    ($($x:expr),*) => (
        vec![$($x.into()),*]
    );
    ($($x:expr,)*) => (
        vec![$($x.into()),*]
    )
}
<|endoftext|>


<commit_before>/// Errors related to matrix operations
#[deriving(Show)]
pub enum MatErr{
    EmptyMatrix,
    DimensionsMismatch,
}
<commit_msg>non square matrix error condition.<commit_after>/// Errors related to matrix operations
#[deriving(Show)]
pub enum MatErr{
    EmptyMatrix,
    DimensionsMismatch,
    NonSquareMatrix,
}
<|endoftext|>


<commit_before>use std::rand::Rng;
use std::rand;
use std::iter::range_inclusive;
use std::iter::range_step_inclusive;
use std::cell::Cell;
use std::path::Path;

pub struct Memory {
    mem: Vec<u8>
}

impl Memory {
    pub fn new(size: uint) -> Memory {
        return Memory{ mem: Vec::from_elem(size, 0)}
    }

    pub fn read_byte(&self, addr: u16) -> u8 {
        return self.mem[addr as uint];
    }

    pub fn read_word(&self, addr: u16) -> u16 {
        let high_byte = self.mem[(addr + 1) as uint];
        let low_byte = self.mem[addr as uint];
        return ((high_byte as u16) << 8) + (low_byte as u16);
    }

    pub fn write_byte(&mut self, addr: u16, data: u8) {
        *self.mem.get_mut(addr as uint) = data;
    }

    pub fn write_word(&mut self, addr: u16, data: u16) {
        *self.mem.get_mut(addr as uint) = low_byte(data);
        *self.mem.get_mut((addr + 1) as uint) = high_byte(data);
    }

    pub fn load_rom(&self, path: Path) {
    }
}

pub fn high_nibble(num: u8) -> u8 {
    return num >> 4;
}

pub fn low_nibble(num: u8) -> u8 {
    return num & 0x0F
}

pub fn low_byte(num: u16) -> u8 {
    return  (num & 0xFF) as u8;
}

pub fn high_byte(num: u16) -> u8 {
    return (num >> 8) as u8;
}

pub fn pack_u16(high: u8, low: u8) -> u16 {
    return (high as u16 << 4) + low as u16;
}

#[test]
fn test_high_nibble() {
    assert!(high_nibble(0xFA) == 0xF);
    assert!(high_nibble(0x0F) == 0x0);
}

#[test]
fn test_low_nibble() {
    assert!(low_nibble(0x0F) == 0xF);
    assert!(low_nibble(0xF0) == 0x0);
    assert!(low_nibble(0xAA) == 0xA);
}

#[test]
fn test_low_byte() {
    assert!(low_byte(0xFFEE) == 0xEE);
    assert!(low_byte(0xFF00) == 0x00);
    assert!(low_byte(0x00FF) == 0xFF);
}

#[test]
fn test_high_byte() {
    assert!(high_byte(0xAE00) == 0xAE);
    assert!(high_byte(0xF0F0) == 0xF0);
    assert!(high_byte(0x00FF) == 0x00);
}

#[test]
fn test_pack_u16() {
    assert!(pack_u16(0xA, 0xE) == 0xAE);
    assert!(pack_u16(0xF, 0x0) == 0xF0);
    assert!(pack_u16(0x0, 0xF) == 0x0F);
}

#[test]
fn test_Memory_write_byte() {
    let mut memory = Memory::new(65536);
    let mut rng = rand::task_rng();

    for n in range_inclusive(0, 0xFFFF)
    {
        let num = rng.gen::<u8>();
        memory.write_byte(n, num);
        assert!(memory.mem[n as uint] == num);
    }
}

#[test]
fn test_Memory_write_word() {
    let mut memory = Memory::new(65536);
    let mut rng = rand::task_rng();

    for n in range_step_inclusive(0, 0xFFFF, 2)
    {
        let num = rng.gen::<u16>();
        memory.write_word(n, num);
        assert!(memory.mem[n as uint] == low_byte(num));
        assert!(memory.mem[(n + 1) as uint] == high_byte(num));
    }
}

#[test]
fn test_Memory_read_byte() {
    let mut memory = Memory::new(65536);

    *memory.mem.get_mut(0) = 0xF1;
    assert!(memory.read_byte(0) == 0xF1);

    *memory.mem.get_mut(0xFFFF) = 0xAB;
    assert!(memory.read_byte(0xFFFF) == 0xAB);

    *memory.mem.get_mut(0xABAB) = 0xBB;
    assert!(memory.read_byte(0xABAB) == 0xBB);
}

#[test]
fn test_Memory_read_word() {
    let mut memory = Memory::new(65536);

    *memory.mem.get_mut(0) = 0xF1;
    *memory.mem.get_mut(1) = 0xEA;
    assert!(memory.read_word(0) == 0xEAF1);

    *memory.mem.get_mut(0xFFFE) = 0xBB;
    *memory.mem.get_mut(0xFFFF) = 0xAB;
    assert!(memory.read_word(0xFFFE) == 0xABBB);

    *memory.mem.get_mut(0xABAA) = 0x12;
    *memory.mem.get_mut(0xABAB) = 0xBA;
    assert!(memory.read_word(0xABAA) == 0xBA12);
}
<commit_msg>Fix bug in pack_u16<commit_after>use std::rand::Rng;
use std::rand;
use std::iter::range_inclusive;
use std::iter::range_step_inclusive;
use std::cell::Cell;
use std::path::Path;

pub struct Memory {
    mem: Vec<u8>
}

impl Memory {
    pub fn new(size: uint) -> Memory {
        return Memory{ mem: Vec::from_elem(size, 0)}
    }

    pub fn read_byte(&self, addr: u16) -> u8 {
        return self.mem[addr as uint];
    }

    pub fn read_word(&self, addr: u16) -> u16 {
        let high_byte = self.mem[(addr + 1) as uint];
        let low_byte = self.mem[addr as uint];
        return ((high_byte as u16) << 8) + (low_byte as u16);
    }

    pub fn write_byte(&mut self, addr: u16, data: u8) {
        *self.mem.get_mut(addr as uint) = data;
    }

    pub fn write_word(&mut self, addr: u16, data: u16) {
        *self.mem.get_mut(addr as uint) = low_byte(data);
        *self.mem.get_mut((addr + 1) as uint) = high_byte(data);
    }

    pub fn load_rom(&self, path: Path) {
    }
}

pub fn high_nibble(num: u8) -> u8 {
    return num >> 4;
}

pub fn low_nibble(num: u8) -> u8 {
    return num & 0x0F
}

pub fn low_byte(num: u16) -> u8 {
    return  (num & 0xFF) as u8;
}

pub fn high_byte(num: u16) -> u8 {
    return (num >> 8) as u8;
}

pub fn pack_u16(high: u8, low: u8) -> u16 {
    return (high as u16 << 8) + low as u16;
}

#[test]
fn test_high_nibble() {
    assert!(high_nibble(0xFA) == 0xF);
    assert!(high_nibble(0x0F) == 0x0);
}

#[test]
fn test_low_nibble() {
    assert!(low_nibble(0x0F) == 0xF);
    assert!(low_nibble(0xF0) == 0x0);
    assert!(low_nibble(0xAA) == 0xA);
}

#[test]
fn test_low_byte() {
    assert!(low_byte(0xFFEE) == 0xEE);
    assert!(low_byte(0xFF00) == 0x00);
    assert!(low_byte(0x00FF) == 0xFF);
}

#[test]
fn test_high_byte() {
    assert!(high_byte(0xAE00) == 0xAE);
    assert!(high_byte(0xF0F0) == 0xF0);
    assert!(high_byte(0x00FF) == 0x00);
}

#[test]
fn test_pack_u16() {
    assert!(pack_u16(0xAB, 0xEF)== 0xABEF);
    assert!(pack_u16(0xF, 0x01) == 0xF01);
    assert!(pack_u16(0x0, 0xF) == 0x0F);
}

#[test]
fn test_Memory_write_byte() {
    let mut memory = Memory::new(65536);
    let mut rng = rand::task_rng();

    for n in range_inclusive(0, 0xFFFF)
    {
        let num = rng.gen::<u8>();
        memory.write_byte(n, num);
        assert!(memory.mem[n as uint] == num);
    }
}

#[test]
fn test_Memory_write_word() {
    let mut memory = Memory::new(65536);
    let mut rng = rand::task_rng();

    for n in range_step_inclusive(0, 0xFFFF, 2)
    {
        let num = rng.gen::<u16>();
        memory.write_word(n, num);
        assert!(memory.mem[n as uint] == low_byte(num));
        assert!(memory.mem[(n + 1) as uint] == high_byte(num));
    }
}

#[test]
fn test_Memory_read_byte() {
    let mut memory = Memory::new(65536);

    *memory.mem.get_mut(0) = 0xF1;
    assert!(memory.read_byte(0) == 0xF1);

    *memory.mem.get_mut(0xFFFF) = 0xAB;
    assert!(memory.read_byte(0xFFFF) == 0xAB);

    *memory.mem.get_mut(0xABAB) = 0xBB;
    assert!(memory.read_byte(0xABAB) == 0xBB);
}

#[test]
fn test_Memory_read_word() {
    let mut memory = Memory::new(65536);

    *memory.mem.get_mut(0) = 0xF1;
    *memory.mem.get_mut(1) = 0xEA;
    assert!(memory.read_word(0) == 0xEAF1);

    *memory.mem.get_mut(0xFFFE) = 0xBB;
    *memory.mem.get_mut(0xFFFF) = 0xAB;
    assert!(memory.read_word(0xFFFE) == 0xABBB);

    *memory.mem.get_mut(0xABAA) = 0x12;
    *memory.mem.get_mut(0xABAB) = 0xBA;
    assert!(memory.read_word(0xABAA) == 0xBA12);
}
<|endoftext|>