<commit_before>use libc::{c_int, c_uint, c_ulonglong, size_t};
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 this 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 size_t, &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, size_t};
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 this 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 size_t, &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>error_chain!{
    errors {
        /// Failed to fetch crate from crates.io
        FetchVersionFailure {
            description("Failed to fetch crate version from crates.io")
        }
        /// Invalid JSON from crates.io response
        InvalidCratesIoJson {
            description("Invalid JSON (the crate may not exist)")
        }
        /// No versions available
        NoVersionsAvailable {
            description("No available versions exist. Either all were yanked \
                         or only prerelease versions exist. Trying with the \
                         --fetch-prereleases flag might solve the issue."
            )
        }
        /// Unable to parse external Cargo.toml
        ParseCargoToml {
            description("Unable to parse external Cargo.toml")
        }
        /// Cargo.toml could not be found.
        MissingManifest {
            description("Unable to find Cargo.toml")
        }
        /// Cargo.toml is valid toml, but doesn't contain the expected fields
        InvalidManifest {
            description("Cargo.toml missing expected `package` or `project` fields")
        }
        /// Found a workspace manifest when expecting a normal manifest
        UnexpectedRootManifest {
            description("Found virtual manifest, but this command requires running against an \
                         actual package in this workspace.")
        }
        /// The TOML table could not be found.
        NonExistentTable(table: String) {
            description("non existent table")
            display("The table `{}` could not be found.", table)
        }
        /// The dependency could not be found.
        NonExistentDependency(name: String, table: String) {
            description("non existent dependency")
            display("The dependency `{}` could not be found in `{}`.", name, table)
        }
    }
}
<commit_msg>fix prerelease error description<commit_after>error_chain!{
    errors {
        /// Failed to fetch crate from crates.io
        FetchVersionFailure {
            description("Failed to fetch crate version from crates.io")
        }
        /// Invalid JSON from crates.io response
        InvalidCratesIoJson {
            description("Invalid JSON (the crate may not exist)")
        }
        /// No versions available
        NoVersionsAvailable {
            description("No available versions exist. Either all were yanked \
                         or only prerelease versions exist. Trying with the \
                         --allow-prerelease flag might solve the issue."
            )
        }
        /// Unable to parse external Cargo.toml
        ParseCargoToml {
            description("Unable to parse external Cargo.toml")
        }
        /// Cargo.toml could not be found.
        MissingManifest {
            description("Unable to find Cargo.toml")
        }
        /// Cargo.toml is valid toml, but doesn't contain the expected fields
        InvalidManifest {
            description("Cargo.toml missing expected `package` or `project` fields")
        }
        /// Found a workspace manifest when expecting a normal manifest
        UnexpectedRootManifest {
            description("Found virtual manifest, but this command requires running against an \
                         actual package in this workspace.")
        }
        /// The TOML table could not be found.
        NonExistentTable(table: String) {
            description("non existent table")
            display("The table `{}` could not be found.", table)
        }
        /// The dependency could not be found.
        NonExistentDependency(name: String, table: String) {
            description("non existent dependency")
            display("The dependency `{}` could not be found in `{}`.", name, table)
        }
    }
}
<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use super::filespec::SBFileSpec;
use super::section::SBSection;
use super::stream::SBStream;
use super::symbolcontextlist::SBSymbolContextList;
use super::typelist::SBTypeList;
use super::{SymbolType, TypeClass};
use std::ffi::CString;
use std::fmt;
use sys;

/// An executable image and its associated object and symbol files.
pub struct SBModule {
    /// The underlying raw `SBModuleRef`.
    pub raw: sys::SBModuleRef,
}

impl SBModule {
    /// Construct a new `Some(SBModule)` or `None`.
    pub fn maybe_wrap(raw: sys::SBModuleRef) -> Option<SBModule> {
        if unsafe { sys::SBModuleIsValid(raw) } {
            Some(SBModule { raw })
        } else {
            None
        }
    }

    /// Check whether or not this is a valid `SBModule` value.
    pub fn is_valid(&self) -> bool {
        unsafe { sys::SBModuleIsValid(self.raw) }
    }

    /// The file for the module on the host system that is running LLDB.
    ///
    /// This can differ from the path on the platform since we might
    /// be doing remote debugging.
    pub fn filespec(&self) -> SBFileSpec {
        SBFileSpec::from(unsafe { sys::SBModuleGetFileSpec(self.raw) })
    }

    /// The file for the module as it is known on the remote system on
    /// which it is being debugged.
    ///
    /// For local debugging this is always the same as `SBModule::filespec`.
    /// But remote debugging might mention a file `/usr/lib/liba.dylib`
    /// which might be locally downloaded and cached. In this case the
    /// platform file could be something like:
    /// `/tmp/lldb/platform-cache/remote.host.computer/usr/lib/liba.dylib`
    /// The file could also be cached in a local developer kit directory.
    pub fn platform_filespec(&self) -> SBFileSpec {
        SBFileSpec::from(unsafe { sys::SBModuleGetPlatformFileSpec(self.raw) })
    }

    #[allow(missing_docs)]
    pub fn find_section(&self, name: &str) -> Option<SBSection> {
        let name = CString::new(name).unwrap();
        SBSection::maybe_wrap(unsafe { sys::SBModuleFindSection(self.raw, name.as_ptr()) })
    }

    /// Get an iterator over the [sections] known to this module instance.
    ///
    /// [sections]: struct.SBSection.html
    pub fn sections(&self) -> SBModuleSectionIter {
        SBModuleSectionIter {
            module: self,
            idx: 0,
        }
    }

    #[allow(missing_docs)]
    pub fn find_functions(&self, name: &str, name_type_mask: u32) -> SBSymbolContextList {
        let name = CString::new(name).unwrap();
        SBSymbolContextList::from(unsafe {
            sys::SBModuleFindFunctions(self.raw, name.as_ptr(), name_type_mask)
        })
    }

    #[allow(missing_docs)]
    pub fn find_symbols(&self, name: &str, symbol_type: SymbolType) -> SBSymbolContextList {
        let name = CString::new(name).unwrap();
        SBSymbolContextList::from(unsafe {
            sys::SBModuleFindSymbols(self.raw, name.as_ptr(), symbol_type)
        })
    }

    /// Get all types matching `type_mask` from the debug info in this
    /// module.
    ///
    /// `type_mask` is a bitfield consisting of one or more type classes.
    /// This allows you to request only structure types, or only class,
    /// structure, and union types. Passing in [`TypeClass::ANY`] will
    /// return all types found in the debug information for this module.
    pub fn types(&self, type_mask: TypeClass) -> SBTypeList {
        SBTypeList::from(unsafe { sys::SBModuleGetTypes(self.raw, type_mask.bits()) })
    }

}

/// Iterate over the [sections] in a [module].
///
/// [sections]: struct.SBSection.html
/// [module]: struct.SBModule.html
pub struct SBModuleSectionIter<'d> {
    module: &'d SBModule,
    idx: usize,
}

impl<'d> Iterator for SBModuleSectionIter<'d> {
    type Item = SBSection;

    fn next(&mut self) -> Option<SBSection> {
        if self.idx < unsafe { sys::SBModuleGetNumSections(self.module.raw) } {
            let r = Some(SBSection::from(unsafe {
                sys::SBModuleGetSectionAtIndex(self.module.raw, self.idx)
            }));
            self.idx += 1;
            r
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let sz = unsafe { sys::SBModuleGetNumSections(self.module.raw) };
        (sz - self.idx, Some(sz))
    }
}

impl<'d> ExactSizeIterator for SBModuleSectionIter<'d> {}

impl Clone for SBModule {
    fn clone(&self) -> SBModule {
        SBModule {
            raw: unsafe { sys::CloneSBModule(self.raw) },
        }
    }
}

impl fmt::Debug for SBModule {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let stream = SBStream::new();
        unsafe { sys::SBModuleGetDescription(self.raw, stream.raw) };
        write!(fmt, "SBModule {{ {} }}", stream.data())
    }
}

impl Drop for SBModule {
    fn drop(&mut self) {
        unsafe { sys::DisposeSBModule(self.raw) };
    }
}

impl From<sys::SBModuleRef> for SBModule {
    fn from(raw: sys::SBModuleRef) -> SBModule {
        SBModule { raw }
    }
}

unsafe impl Send for SBModule {}
unsafe impl Sync for SBModule {}

#[cfg(feature = "graphql")]
graphql_object!(SBModule: super::debugger::SBDebugger | &self | {
    field is_valid() -> bool {
        self.is_valid()
    }

    field filespec() -> SBFileSpec {
        self.filespec()
    }

    field platform_filespec() -> SBFileSpec {
        self.platform_filespec()
    }

    field sections() -> Vec<SBSection> {
        self.sections().collect()
    }
});
<commit_msg>Remove extra blank line.<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use super::filespec::SBFileSpec;
use super::section::SBSection;
use super::stream::SBStream;
use super::symbolcontextlist::SBSymbolContextList;
use super::typelist::SBTypeList;
use super::{SymbolType, TypeClass};
use std::ffi::CString;
use std::fmt;
use sys;

/// An executable image and its associated object and symbol files.
pub struct SBModule {
    /// The underlying raw `SBModuleRef`.
    pub raw: sys::SBModuleRef,
}

impl SBModule {
    /// Construct a new `Some(SBModule)` or `None`.
    pub fn maybe_wrap(raw: sys::SBModuleRef) -> Option<SBModule> {
        if unsafe { sys::SBModuleIsValid(raw) } {
            Some(SBModule { raw })
        } else {
            None
        }
    }

    /// Check whether or not this is a valid `SBModule` value.
    pub fn is_valid(&self) -> bool {
        unsafe { sys::SBModuleIsValid(self.raw) }
    }

    /// The file for the module on the host system that is running LLDB.
    ///
    /// This can differ from the path on the platform since we might
    /// be doing remote debugging.
    pub fn filespec(&self) -> SBFileSpec {
        SBFileSpec::from(unsafe { sys::SBModuleGetFileSpec(self.raw) })
    }

    /// The file for the module as it is known on the remote system on
    /// which it is being debugged.
    ///
    /// For local debugging this is always the same as `SBModule::filespec`.
    /// But remote debugging might mention a file `/usr/lib/liba.dylib`
    /// which might be locally downloaded and cached. In this case the
    /// platform file could be something like:
    /// `/tmp/lldb/platform-cache/remote.host.computer/usr/lib/liba.dylib`
    /// The file could also be cached in a local developer kit directory.
    pub fn platform_filespec(&self) -> SBFileSpec {
        SBFileSpec::from(unsafe { sys::SBModuleGetPlatformFileSpec(self.raw) })
    }

    #[allow(missing_docs)]
    pub fn find_section(&self, name: &str) -> Option<SBSection> {
        let name = CString::new(name).unwrap();
        SBSection::maybe_wrap(unsafe { sys::SBModuleFindSection(self.raw, name.as_ptr()) })
    }

    /// Get an iterator over the [sections] known to this module instance.
    ///
    /// [sections]: struct.SBSection.html
    pub fn sections(&self) -> SBModuleSectionIter {
        SBModuleSectionIter {
            module: self,
            idx: 0,
        }
    }

    #[allow(missing_docs)]
    pub fn find_functions(&self, name: &str, name_type_mask: u32) -> SBSymbolContextList {
        let name = CString::new(name).unwrap();
        SBSymbolContextList::from(unsafe {
            sys::SBModuleFindFunctions(self.raw, name.as_ptr(), name_type_mask)
        })
    }

    #[allow(missing_docs)]
    pub fn find_symbols(&self, name: &str, symbol_type: SymbolType) -> SBSymbolContextList {
        let name = CString::new(name).unwrap();
        SBSymbolContextList::from(unsafe {
            sys::SBModuleFindSymbols(self.raw, name.as_ptr(), symbol_type)
        })
    }

    /// Get all types matching `type_mask` from the debug info in this
    /// module.
    ///
    /// `type_mask` is a bitfield consisting of one or more type classes.
    /// This allows you to request only structure types, or only class,
    /// structure, and union types. Passing in [`TypeClass::ANY`] will
    /// return all types found in the debug information for this module.
    pub fn types(&self, type_mask: TypeClass) -> SBTypeList {
        SBTypeList::from(unsafe { sys::SBModuleGetTypes(self.raw, type_mask.bits()) })
    }
}

/// Iterate over the [sections] in a [module].
///
/// [sections]: struct.SBSection.html
/// [module]: struct.SBModule.html
pub struct SBModuleSectionIter<'d> {
    module: &'d SBModule,
    idx: usize,
}

impl<'d> Iterator for SBModuleSectionIter<'d> {
    type Item = SBSection;

    fn next(&mut self) -> Option<SBSection> {
        if self.idx < unsafe { sys::SBModuleGetNumSections(self.module.raw) } {
            let r = Some(SBSection::from(unsafe {
                sys::SBModuleGetSectionAtIndex(self.module.raw, self.idx)
            }));
            self.idx += 1;
            r
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let sz = unsafe { sys::SBModuleGetNumSections(self.module.raw) };
        (sz - self.idx, Some(sz))
    }
}

impl<'d> ExactSizeIterator for SBModuleSectionIter<'d> {}

impl Clone for SBModule {
    fn clone(&self) -> SBModule {
        SBModule {
            raw: unsafe { sys::CloneSBModule(self.raw) },
        }
    }
}

impl fmt::Debug for SBModule {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let stream = SBStream::new();
        unsafe { sys::SBModuleGetDescription(self.raw, stream.raw) };
        write!(fmt, "SBModule {{ {} }}", stream.data())
    }
}

impl Drop for SBModule {
    fn drop(&mut self) {
        unsafe { sys::DisposeSBModule(self.raw) };
    }
}

impl From<sys::SBModuleRef> for SBModule {
    fn from(raw: sys::SBModuleRef) -> SBModule {
        SBModule { raw }
    }
}

unsafe impl Send for SBModule {}
unsafe impl Sync for SBModule {}

#[cfg(feature = "graphql")]
graphql_object!(SBModule: super::debugger::SBDebugger | &self | {
    field is_valid() -> bool {
        self.is_valid()
    }

    field filespec() -> SBFileSpec {
        self.filespec()
    }

    field platform_filespec() -> SBFileSpec {
        self.platform_filespec()
    }

    field sections() -> Vec<SBSection> {
        self.sections().collect()
    }
});
<|endoftext|>


<commit_before>use rustc_serialize::json;
use rustc_serialize::json::Json;
use rustc_serialize::Encodable;
use time::Tm;
use std::io;
use retry;

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Record<T: Encodable> {
    tag: String,
    time: Tm,
    record: T,
}

pub enum FluentError {
    EncodeError(json::EncoderError),
    IOError(io::Error),
    RetryError(retry::RetryError),
}

impl From<io::Error> for FluentError {
    fn from(err: io::Error) -> FluentError {
        FluentError::IOError(err)
    }
}

impl From<json::EncoderError> for FluentError {
    fn from(err: json::EncoderError) -> FluentError {
        FluentError::EncodeError(err)
    }
}

impl From<retry::RetryError> for FluentError {
    fn from(err: retry::RetryError) -> FluentError {
        FluentError::RetryError(err)
    }
}

impl<T: Encodable> Record<T> {
    pub fn new(tag: String, time: Tm, record: T) -> Record<T> {
        Record {
            tag: tag,
            time: time,
            record: record,
        }
    }

    pub fn make_forwardable_json(self) -> Result<String, FluentError> {
        let tag = try!(json::encode(&self.tag));
        let record = try!(json::encode(&self.record));
        let option = Json::Null;
        let message = format!("[{},{},{},{}]",
                              tag,
                              self.time.to_timespec().sec,
                              record,
                              option);
        Ok(message)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use time;
    use std::collections::HashMap;
    use rustc_serialize::json;

    #[test]
    fn test_json_format() {
        let tag = "fruently".to_string();
        let time = time::now();
        let mut obj: HashMap<String, String> = HashMap::new();
        obj.insert("name".to_string(), "fruently".to_string());
        let record = Record::new(tag.clone(), time, obj.clone());
        let forwardable_json = record.make_forwardable_json().ok().unwrap();
        let json_tag = json::encode(&tag.clone()).ok().unwrap();
        let json_obj = json::encode(&obj.clone()).ok().unwrap();
        let expected = format!("[{},{},{},null]",
                               json_tag,
                               time.to_timespec().sec,
                               json_obj);
        assert_eq!(expected, forwardable_json);
    }
}
<commit_msg>Use Json::Null in test<commit_after>use rustc_serialize::json;
use rustc_serialize::json::Json;
use rustc_serialize::Encodable;
use time::Tm;
use std::io;
use retry;

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Record<T: Encodable> {
    tag: String,
    time: Tm,
    record: T,
}

pub enum FluentError {
    EncodeError(json::EncoderError),
    IOError(io::Error),
    RetryError(retry::RetryError),
}

impl From<io::Error> for FluentError {
    fn from(err: io::Error) -> FluentError {
        FluentError::IOError(err)
    }
}

impl From<json::EncoderError> for FluentError {
    fn from(err: json::EncoderError) -> FluentError {
        FluentError::EncodeError(err)
    }
}

impl From<retry::RetryError> for FluentError {
    fn from(err: retry::RetryError) -> FluentError {
        FluentError::RetryError(err)
    }
}

impl<T: Encodable> Record<T> {
    pub fn new(tag: String, time: Tm, record: T) -> Record<T> {
        Record {
            tag: tag,
            time: time,
            record: record,
        }
    }

    pub fn make_forwardable_json(self) -> Result<String, FluentError> {
        let tag = try!(json::encode(&self.tag));
        let record = try!(json::encode(&self.record));
        let option = Json::Null;
        let message = format!("[{},{},{},{}]",
                              tag,
                              self.time.to_timespec().sec,
                              record,
                              option);
        Ok(message)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use time;
    use std::collections::HashMap;
    use rustc_serialize::json;
    use rustc_serialize::json::Json;

    #[test]
    fn test_json_format() {
        let tag = "fruently".to_string();
        let time = time::now();
        let mut obj: HashMap<String, String> = HashMap::new();
        obj.insert("name".to_string(), "fruently".to_string());
        let record = Record::new(tag.clone(), time, obj.clone());
        let forwardable_json = record.make_forwardable_json().ok().unwrap();
        let json_tag = json::encode(&tag.clone()).ok().unwrap();
        let json_obj = json::encode(&obj.clone()).ok().unwrap();
        let expected = format!("[{},{},{},{}]",
                               json_tag,
                               time.to_timespec().sec,
                               json_obj,
                               Json::Null);
        assert_eq!(expected, forwardable_json);
    }
}
<|endoftext|>


<commit_before>//! Implement record manupulation mechanisms.

use rustc_serialize::json;
use rustc_serialize::{Encodable, Encoder};
use rmp_serialize::encode;
use time::Tm;
use std::io;
use std::fmt;
use std::fmt::Debug;
use retry;

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Record<T: Encodable> {
    tag: String,
    time: Tm,
    record: T,
}

#[derive(Debug)]
pub enum FluentError {
    JsonEncode(json::EncoderError),
    MsgpackEncode(encode::Error),
    IO(io::Error),
    Retry(retry::RetryError),
    #[doc(hidden)]
    Dummy(String),
}

impl From<io::Error> for FluentError {
    fn from(err: io::Error) -> FluentError {
        FluentError::IO(err)
    }
}

impl From<encode::Error> for FluentError {
    fn from(err: encode::Error) -> FluentError {
        FluentError::MsgpackEncode(err)
    }
}

impl From<retry::RetryError> for FluentError {
    fn from(err: retry::RetryError) -> FluentError {
        FluentError::Retry(err)
    }
}

impl From<json::EncoderError> for FluentError {
    fn from(err: json::EncoderError) -> FluentError {
        FluentError::JsonEncode(err)
    }
}

impl<T: Encodable + Debug> fmt::Display for Record<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} {:?} {:?}", self.tag, self.time.to_timespec().sec, self.record)
    }
}

impl<T: Encodable> Record<T> {
    pub fn new(tag: String, time: Tm, record: T) -> Record<T> {
        Record {
            tag: tag,
            time: time,
            record: record,
        }
    }

    pub fn make_forwardable_json(self) -> Result<String, FluentError> {
        let message = try!(json::encode(&self));
        Ok(message)
    }
}

/// Construct custom encoding json/msgpack style.
///
/// Because `Record` struct should map following style json/msgpack:
///
/// `[tag, unixtime/eventtime, record]`
///
/// ref: https://github.com/fluent/fluentd/wiki/Forward-Protocol-Specification-v0#message-mode
impl<T: Encodable> Encodable for Record<T> {
    fn encode<S: Encoder>(&self, encoder: &mut S) -> Result<(), S::Error> {
        match *self {
            Record { tag: ref p_tag, time: ref p_time, record: ref p_record } => {
                encoder.emit_tuple(4, |encoder| {
                    try!(encoder.emit_tuple_arg(0, |encoder| p_tag.encode(encoder)));
                    try!(encoder.emit_tuple_arg(1, |encoder| {
                        p_time.to_timespec().sec.encode(encoder)
                    }));
                    try!(encoder.emit_tuple_arg(2, |encoder| p_record.encode(encoder)));
                    // Put `None::<T>` as-is for now.
                    try!(encoder.emit_tuple_arg(3, |encoder| None::<T>.encode(encoder)));
                    Ok(())
                })
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use time;
    use std::collections::HashMap;
    use rustc_serialize::json;
    use rustc_serialize::json::Json;

    #[test]
    fn test_json_format() {
        let tag = "fruently".to_string();
        let time = time::now();
        let mut obj: HashMap<String, String> = HashMap::new();
        obj.insert("name".to_string(), "fruently".to_string());
        let record = Record::new(tag.clone(), time, obj.clone());
        let forwardable_json = record.make_forwardable_json().ok().unwrap();
        let json_tag = json::encode(&tag.clone()).ok().unwrap();
        let json_obj = json::encode(&obj.clone()).ok().unwrap();
        let expected = format!("[{},{},{},{}]",
                               json_tag,
                               time.to_timespec().sec,
                               json_obj,
                               Json::Null);
        assert_eq!(expected, forwardable_json);
    }
}
<commit_msg>record: Remove needless Display trait impl<commit_after>//! Implement record manupulation mechanisms.

use rustc_serialize::json;
use rustc_serialize::{Encodable, Encoder};
use rmp_serialize::encode;
use time::Tm;
use std::io;
use retry;

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Record<T: Encodable> {
    tag: String,
    time: Tm,
    record: T,
}

#[derive(Debug)]
pub enum FluentError {
    JsonEncode(json::EncoderError),
    MsgpackEncode(encode::Error),
    IO(io::Error),
    Retry(retry::RetryError),
    #[doc(hidden)]
    Dummy(String),
}

impl From<io::Error> for FluentError {
    fn from(err: io::Error) -> FluentError {
        FluentError::IO(err)
    }
}

impl From<encode::Error> for FluentError {
    fn from(err: encode::Error) -> FluentError {
        FluentError::MsgpackEncode(err)
    }
}

impl From<retry::RetryError> for FluentError {
    fn from(err: retry::RetryError) -> FluentError {
        FluentError::Retry(err)
    }
}

impl From<json::EncoderError> for FluentError {
    fn from(err: json::EncoderError) -> FluentError {
        FluentError::JsonEncode(err)
    }
}

impl<T: Encodable> Record<T> {
    pub fn new(tag: String, time: Tm, record: T) -> Record<T> {
        Record {
            tag: tag,
            time: time,
            record: record,
        }
    }

    pub fn make_forwardable_json(self) -> Result<String, FluentError> {
        let message = try!(json::encode(&self));
        Ok(message)
    }
}

/// Construct custom encoding json/msgpack style.
///
/// Because `Record` struct should map following style json/msgpack:
///
/// `[tag, unixtime/eventtime, record]`
///
/// ref: https://github.com/fluent/fluentd/wiki/Forward-Protocol-Specification-v0#message-mode
impl<T: Encodable> Encodable for Record<T> {
    fn encode<S: Encoder>(&self, encoder: &mut S) -> Result<(), S::Error> {
        match *self {
            Record { tag: ref p_tag, time: ref p_time, record: ref p_record } => {
                encoder.emit_tuple(4, |encoder| {
                    try!(encoder.emit_tuple_arg(0, |encoder| p_tag.encode(encoder)));
                    try!(encoder.emit_tuple_arg(1, |encoder| {
                        p_time.to_timespec().sec.encode(encoder)
                    }));
                    try!(encoder.emit_tuple_arg(2, |encoder| p_record.encode(encoder)));
                    // Put `None::<T>` as-is for now.
                    try!(encoder.emit_tuple_arg(3, |encoder| None::<T>.encode(encoder)));
                    Ok(())
                })
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use time;
    use std::collections::HashMap;
    use rustc_serialize::json;
    use rustc_serialize::json::Json;

    #[test]
    fn test_json_format() {
        let tag = "fruently".to_string();
        let time = time::now();
        let mut obj: HashMap<String, String> = HashMap::new();
        obj.insert("name".to_string(), "fruently".to_string());
        let record = Record::new(tag.clone(), time, obj.clone());
        let forwardable_json = record.make_forwardable_json().ok().unwrap();
        let json_tag = json::encode(&tag.clone()).ok().unwrap();
        let json_obj = json::encode(&obj.clone()).ok().unwrap();
        let expected = format!("[{},{},{},{}]",
                               json_tag,
                               time.to_timespec().sec,
                               json_obj,
                               Json::Null);
        assert_eq!(expected, forwardable_json);
    }
}
<|endoftext|>


<commit_before>use regex::{self, Captures, Regex};
use std::error;
use std::fmt;
use term::{self, color, Terminal};

#[derive(Debug)]
pub enum Error {
    Regex(regex::Error)
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Regex(ref err) => err.description()
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Regex(ref err) => Some(err)
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Regex(ref err) => write!(f, "Regex error: {}", err)
        }
    }
}

impl From<regex::Error> for Error {
    fn from(err: regex::Error) -> Error {
        Error::Regex(err)
    }
}

/// Returns an iterator for finding all matches of `pattern` in `subject`.
pub fn find_matches<'t>(pattern: &str, subject: &'t str) -> Result<Vec<Captures<'t>>, Error> {
    let regex = try!(Regex::new(&pattern));
    Ok(regex.captures_iter(subject).collect())
}

/// Finds all matches for the given pattern on the given subject and prints out
/// the subject with matches highlighted.
pub fn print_subject_highlighted<'t>(subject: &str, matches: &Vec<Captures<'t>>) {
    // Loop over each match in the subject and pretty-print the match as well as
    // any trailing, non-matching text preceding the match.
    let mut last_index = 0;

    for captures in matches.iter() {
        let positions = captures.pos(0).unwrap();

        print!("{}", &subject[last_index .. positions.0]);
        print_match(&subject, captures);

        last_index = positions.1;
    }

    // Print trailing unmatched text if there is any.
    if last_index < subject.len() {
        print!("{}", &subject[last_index ..]);
    }
    println!("");
}

/// Prints the matches in a list format.
pub fn print_match_list<'t>(subject: &str, matches: &Vec<Captures<'t>>) {
    let mut match_id = 1;

    for captures in matches.iter() {
        let positions = captures.pos(0).unwrap();

        print!("{:<4} {:<14} ", format!("{}.", match_id), format!("[{}-{}]", positions.0, positions.1));
        print_match(&subject, captures);
        println!("");
        match_id += 1;
    }
}

/// Prints out a match using color formatting.
///
/// The match is highlighted according to the captures that are matched. Each
/// capture is highlighted in a different color to distinguish it from other
/// captures. Because captures can be nested, this function uses a stack to keep
/// track of capture scope and display nested captures correctly.
///
/// The worst-case run time is O(2n), but the average run time should be more
/// like Θ(n + log(n)). The more nested the captures are, the worse the run time
/// is.
fn print_match(subject: &str, captures: &Captures) {
    let mut terminal = term::stdout().unwrap();
    let color_cycle = [color::BLUE, color::GREEN, color::MAGENTA, color::YELLOW];
    let mut color_index = 0;

    // To highlight the captures in a context-sensitive manner, set up a stack
    // to keep track of entering and exiting capture scopes. When examining a
    // capture, check if it fits inside the parent capture. If it doesn't, close
    // the scopes until we find a scope the capture does fit in.
    let mut stack: Vec<(usize, usize, u16)> = Vec::new();

    // Since we will print the captures as we go along, set up a cursor that
    // points to how much of the string we have printed out so far so we don't
    // accidentally print out the same regions of the strings more than once.
    let mut string_cursor = captures.pos(0).unwrap().0;

    // Loop over each capture and find the scope it belongs to. Optional capture
    // groups that are not matched are ignored.
    for i in 0..captures.len() {
        let pos = match captures.pos(i) {
            None => continue,
            Some(pos) => pos
        };

        // Unwind the stack until we find the correct parent.
        while !stack.is_empty() && pos.1 > stack.last().unwrap().1 {
            let scope = stack.pop().unwrap();

            terminal.bg(scope.2).unwrap();
            print!("{}", &subject[string_cursor .. scope.1]);
            string_cursor = scope.1;
        }

        // If the stack isn't empty, print out the head end of the parent scope
        // just before the current capture.
        if !stack.is_empty() {
            terminal.bg(stack.last().unwrap().2).unwrap();
            print!("{}", &subject[string_cursor .. pos.0]);
            string_cursor = pos.0;
        }

        // Push the current capture onto the stack with a color selected from
        // the color cycle.
        stack.push((pos.0, pos.1, color_cycle[color_index]));
        color_index = (color_index + 1) % color_cycle.len();
    }

    // Finally, print out the tail of the match. The stack will still have
    // captures in it for the very last capture and its ancestors, so unwind the
    // stack one last time and print out each capture's tail.
    while !stack.is_empty() {
        let scope = stack.pop().unwrap();
        terminal.bg(scope.2).unwrap();
        print!("{}", &subject[string_cursor .. scope.1]);
        string_cursor = scope.1;
    }

    // Reset coloring to normal.
    terminal.reset().unwrap();
}
<commit_msg>Fix some comments<commit_after>use regex::{self, Captures, Regex};
use std::error;
use std::fmt;
use term::{self, color, Terminal};

#[derive(Debug)]
pub enum Error {
    Regex(regex::Error)
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Regex(ref err) => err.description()
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Regex(ref err) => Some(err)
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Regex(ref err) => write!(f, "Regex error: {}", err)
        }
    }
}

impl From<regex::Error> for Error {
    fn from(err: regex::Error) -> Error {
        Error::Regex(err)
    }
}

/// Finds all matches for the given pattern on the given subject and returns
/// the matches and their captures.
pub fn find_matches<'t>(pattern: &str, subject: &'t str) -> Result<Vec<Captures<'t>>, Error> {
    let regex = try!(Regex::new(&pattern));
    Ok(regex.captures_iter(subject).collect())
}

/// Prints out the given subject string, with the regions in the given matches
/// highlighted.
pub fn print_subject_highlighted<'t>(subject: &str, matches: &Vec<Captures<'t>>) {
    // Loop over each match in the subject and pretty-print the match as well as
    // any trailing, non-matching text preceding the match.
    let mut last_index = 0;

    for captures in matches.iter() {
        let positions = captures.pos(0).unwrap();

        print!("{}", &subject[last_index .. positions.0]);
        print_match(&subject, captures);

        last_index = positions.1;
    }

    // Print trailing unmatched text if there is any.
    if last_index < subject.len() {
        print!("{}", &subject[last_index ..]);
    }
    println!("");
}

/// Prints the given matches in a formatted list.
pub fn print_match_list<'t>(subject: &str, matches: &Vec<Captures<'t>>) {
    let mut match_id = 1;

    for captures in matches.iter() {
        let positions = captures.pos(0).unwrap();

        print!("{:<4} {:<14} ", format!("{}.", match_id), format!("[{}-{}]", positions.0, positions.1));
        print_match(&subject, captures);
        println!("");
        match_id += 1;
    }
}

/// Prints out a match using color formatting.
///
/// The match is highlighted according to the captures that are matched. Each
/// capture is highlighted in a different color to distinguish it from other
/// captures. Because captures can be nested, this function uses a stack to keep
/// track of capture scope and display nested captures correctly.
///
/// The worst-case run time is O(2n log(n)), but the average run time should be
/// more like Θ(n + log(n)). The more nested the captures are, the worse the run
/// time is.
fn print_match(subject: &str, captures: &Captures) {
    let mut terminal = term::stdout().unwrap();
    let color_cycle = [color::BLUE, color::GREEN, color::MAGENTA, color::YELLOW];
    let mut color_index = 0;

    // To highlight the captures in a context-sensitive manner, set up a stack
    // to keep track of entering and exiting capture scopes. When examining a
    // capture, check if it fits inside the parent capture. If it doesn't, close
    // the scopes until we find a scope the capture does fit in.
    let mut stack: Vec<(usize, usize, u16)> = Vec::new();

    // Since we will print the captures as we go along, set up a cursor that
    // points to how much of the string we have printed out so far so we don't
    // accidentally print out the same regions of the strings more than once.
    let mut string_cursor = captures.pos(0).unwrap().0;

    // Loop over each capture and find the scope it belongs to. Optional capture
    // groups that are not matched are ignored.
    for i in 0..captures.len() {
        let pos = match captures.pos(i) {
            None => continue,
            Some(pos) => pos
        };

        // Unwind the stack until we find the correct parent.
        while !stack.is_empty() && pos.1 > stack.last().unwrap().1 {
            let scope = stack.pop().unwrap();

            terminal.bg(scope.2).unwrap();
            print!("{}", &subject[string_cursor .. scope.1]);
            string_cursor = scope.1;
        }

        // If the stack isn't empty, print out the head end of the parent scope
        // just before the current capture.
        if !stack.is_empty() {
            terminal.bg(stack.last().unwrap().2).unwrap();
            print!("{}", &subject[string_cursor .. pos.0]);
            string_cursor = pos.0;
        }

        // Push the current capture onto the stack with a color selected from
        // the color cycle.
        stack.push((pos.0, pos.1, color_cycle[color_index]));
        color_index = (color_index + 1) % color_cycle.len();
    }

    // Finally, print out the tail of the match. The stack will still have
    // captures in it for the very last capture and its ancestors, so unwind the
    // stack one last time and print out each capture's tail.
    while !stack.is_empty() {
        let scope = stack.pop().unwrap();
        terminal.bg(scope.2).unwrap();
        print!("{}", &subject[string_cursor .. scope.1]);
        string_cursor = scope.1;
    }

    // Reset coloring to normal.
    terminal.reset().unwrap();
}
<|endoftext|>


<commit_before>//!Router asigns handlers to paths and resolves them per request

#[cfg(test)]
use http::method;
use http::method::Method;
use regex::Regex;
use std::collections::hashmap::HashMap;
use request::Request;
use response::Response;

/// A Route is the basic data structure that stores both the path
/// and the handler that gets executed for the route.
/// The path can contain variable pattern such as `user/:userid/invoices`
struct Route {
    pub path: String,
    pub method: Method,
    pub handler: fn(request: &Request, response: &mut Response),
    pub variables: HashMap<String, uint>,
    matcher: Regex
}

impl Clone for Route {
    fn clone(&self) -> Route {
        Route {
            path: self.path.clone(),
            method: self.method.clone(),
            handler: self.handler,
            matcher: self.matcher.clone(),
            variables: self.variables.clone()
        }
    }
}

/// A RouteResult is what the router returns when `match_route` is called.
/// It contains the matched `route` and also a `params` property holding
/// a HashMap with the keys being the variable names and the value being the
/// evaluated string
struct RouteResult<'a> {
    pub route: &'a Route,
    pub params: HashMap<String, String>
}

/// The PathUtils collects some small helper methods that operate on the path
struct PathUtils;

static REGEX_VAR_SEQ: Regex                 = regex!(r":([a-zA-Z0-9_-]*)");
static VAR_SEQ:&'static str                 = "[a-zA-Z0-9_-]*";
static VAR_SEQ_WITH_SLASH:&'static str      = "[/a-zA-Z0-9_-]*";
static VAR_SEQ_WITH_CAPTURE:&'static str    = "([a-zA-Z0-9_-]*)";
static REGEX_START:&'static str             = "^";
static REGEX_END:&'static str               = "$";

impl PathUtils {
    fn create_regex (route_path: &str) -> Regex {

        let updated_path = route_path.to_string()
                                     // first mark all double wildcards for replacement. We can't directly replace them
                                     // since the replacement does contain the * symbol as well, which would get overwritten
                                     // with the next replace call
                                     .replace("**", "___DOUBLE_WILDCARD___")
                                     // then replace the regular wildcard symbols (*) with the appropriate regex
                                     .replace("*", VAR_SEQ)
                                     // now replace the previously marked double wild cards (**)
                                     .replace("___DOUBLE_WILDCARD___", VAR_SEQ_WITH_SLASH);

        // then replace the variable symbols (:variable) with the appropriate regex
        let result = REGEX_START.to_string()
                                .append(REGEX_VAR_SEQ.replace_all(updated_path.as_slice(), VAR_SEQ_WITH_CAPTURE).as_slice())
                                .append(REGEX_END);

        match Regex::new(result.as_slice()) {
            Ok(re) => re,
            Err(err) => fail!("{}", err)
        }
    }

    fn get_variable_info (route_path: &str) -> HashMap<String, uint> {
        REGEX_VAR_SEQ.captures_iter(route_path)
             .enumerate()
             .map(|(i, matched)| (matched.at(1).to_string(), i))
             .collect()
    }
}

/// The Router's job is it to hold routes and to resolve them later against
/// concrete URLs

#[deriving(Clone)]
pub struct Router{
    pub routes: Vec<Route>,
}

impl Router {
    pub fn new () -> Router {
        Router {
            routes: Vec::new()
        }
    }

    pub fn add_route (&mut self, method: Method, path: String, handler: fn(request: &Request, response: &mut Response)) -> () {
        let matcher = PathUtils::create_regex(path.as_slice());
        let variable_infos = PathUtils::get_variable_info(path.as_slice());
        let route = Route {
            path: path,
            method: method,
            matcher: matcher,
            handler: handler,
            variables: variable_infos
        };
        self.routes.push(route);
    }

    pub fn match_route<'a>(&'a self, method: Method, path: String) -> Option<RouteResult<'a>> {
        self.routes.iter().find(|item| item.method == method && item.matcher.is_match(path.as_slice()))
            .and_then(|route| {
                match route.matcher.captures(path.as_slice()) {
                    Some(captures) => {
                        let mut map = HashMap::new();
                        for (name, pos) in route.variables.iter() {
                            map.insert(name.to_string(), captures.at(pos + 1).to_string());
                        }
                        Some(RouteResult {
                            route: route,
                            params: map
                        })
                    },
                    None => Some(RouteResult{
                        route: route,
                        params: HashMap::new()
                    })
                }
            })
    }
}

#[test]
fn creates_map_with_var_variable_infos () {
    let map = PathUtils::get_variable_info("foo/:uid/bar/:groupid");

    assert_eq!(map.len(), 2);
    assert_eq!(map.get(&"uid".to_string()), &0);
    assert_eq!(map.get(&"groupid".to_string()), &1);
}

#[test]
fn creates_regex_with_captures () {
    let regex = PathUtils::create_regex("foo/:uid/bar/:groupid");
    let caps = regex.captures("foo/4711/bar/5490").unwrap();

    assert_eq!(caps.at(1), "4711");
    assert_eq!(caps.at(2), "5490");

    let regex = PathUtils::create_regex("foo/*/:uid/bar/:groupid");
    let caps = regex.captures("foo/test/4711/bar/5490").unwrap();

    assert_eq!(caps.at(1), "4711");
    assert_eq!(caps.at(2), "5490");

    let regex = PathUtils::create_regex("foo/**/:uid/bar/:groupid");
    let caps = regex.captures("foo/test/another/4711/bar/5490").unwrap();

    assert_eq!(caps.at(1), "4711");
    assert_eq!(caps.at(2), "5490");
}

#[test]
fn creates_valid_regex_for_routes () {
    let regex1 = PathUtils::create_regex("foo/:uid/bar/:groupid");
    let regex2 = PathUtils::create_regex("foo/*/bar");
    let regex3 = PathUtils::create_regex("foo/**/bar");

    assert_eq!(regex1.is_match("foo/4711/bar/5490"), true);
    assert_eq!(regex1.is_match("foo/4711/bar"), false);

    assert_eq!(regex2.is_match("foo/4711/bar"), true);
    assert_eq!(regex2.is_match("foo/4711/4712/bar"), false);

    assert_eq!(regex3.is_match("foo/4711/bar"), true);
    assert_eq!(regex3.is_match("foo/4711/4712/bar"), true);
}

#[test]
fn can_match_var_routes () {
    let route_store = &mut Router::new();

    fn handler (request: &Request, response: &mut Response) -> () {
        response.origin.write("hello from foo".as_bytes());
    };

    route_store.add_route(method::Get, "/foo/:userid".to_string(), handler);
    route_store.add_route(method::Get, "/bar".to_string(), handler);

    let route_result = route_store.match_route(method::Get, "/foo/4711".to_string()).unwrap();
    let route = route_result.route;

    assert_eq!(route_result.params.get(&"userid".to_string()), &"4711".to_string());

    //assert the route has identified the variable
    assert_eq!(route.variables.len(), 1);
    assert_eq!(route.variables.get(&"userid".to_string()), &0);

    let route_result = route_store.match_route(method::Get, "/bar/4711".to_string());

    let result = match route_result {
        Some(res) => true,
        None => false
    };

    assert_eq!(result, false);

    let route_result = route_store.match_route(method::Get, "/foo".to_string());

    let result = match route_result{
        Some(res) => true,
        None => false
    };

    assert_eq!(result, false);
}
<commit_msg>fix(tests): make compiler happy about unused variables<commit_after>//!Router asigns handlers to paths and resolves them per request

#[cfg(test)]
use http::method;
use http::method::Method;
use regex::Regex;
use std::collections::hashmap::HashMap;
use request::Request;
use response::Response;

/// A Route is the basic data structure that stores both the path
/// and the handler that gets executed for the route.
/// The path can contain variable pattern such as `user/:userid/invoices`
struct Route {
    pub path: String,
    pub method: Method,
    pub handler: fn(request: &Request, response: &mut Response),
    pub variables: HashMap<String, uint>,
    matcher: Regex
}

impl Clone for Route {
    fn clone(&self) -> Route {
        Route {
            path: self.path.clone(),
            method: self.method.clone(),
            handler: self.handler,
            matcher: self.matcher.clone(),
            variables: self.variables.clone()
        }
    }
}

/// A RouteResult is what the router returns when `match_route` is called.
/// It contains the matched `route` and also a `params` property holding
/// a HashMap with the keys being the variable names and the value being the
/// evaluated string
struct RouteResult<'a> {
    pub route: &'a Route,
    pub params: HashMap<String, String>
}

/// The PathUtils collects some small helper methods that operate on the path
struct PathUtils;

static REGEX_VAR_SEQ: Regex                 = regex!(r":([a-zA-Z0-9_-]*)");
static VAR_SEQ:&'static str                 = "[a-zA-Z0-9_-]*";
static VAR_SEQ_WITH_SLASH:&'static str      = "[/a-zA-Z0-9_-]*";
static VAR_SEQ_WITH_CAPTURE:&'static str    = "([a-zA-Z0-9_-]*)";
static REGEX_START:&'static str             = "^";
static REGEX_END:&'static str               = "$";

impl PathUtils {
    fn create_regex (route_path: &str) -> Regex {

        let updated_path = route_path.to_string()
                                     // first mark all double wildcards for replacement. We can't directly replace them
                                     // since the replacement does contain the * symbol as well, which would get overwritten
                                     // with the next replace call
                                     .replace("**", "___DOUBLE_WILDCARD___")
                                     // then replace the regular wildcard symbols (*) with the appropriate regex
                                     .replace("*", VAR_SEQ)
                                     // now replace the previously marked double wild cards (**)
                                     .replace("___DOUBLE_WILDCARD___", VAR_SEQ_WITH_SLASH);

        // then replace the variable symbols (:variable) with the appropriate regex
        let result = REGEX_START.to_string()
                                .append(REGEX_VAR_SEQ.replace_all(updated_path.as_slice(), VAR_SEQ_WITH_CAPTURE).as_slice())
                                .append(REGEX_END);

        match Regex::new(result.as_slice()) {
            Ok(re) => re,
            Err(err) => fail!("{}", err)
        }
    }

    fn get_variable_info (route_path: &str) -> HashMap<String, uint> {
        REGEX_VAR_SEQ.captures_iter(route_path)
             .enumerate()
             .map(|(i, matched)| (matched.at(1).to_string(), i))
             .collect()
    }
}

/// The Router's job is it to hold routes and to resolve them later against
/// concrete URLs

#[deriving(Clone)]
pub struct Router{
    pub routes: Vec<Route>,
}

impl Router {
    pub fn new () -> Router {
        Router {
            routes: Vec::new()
        }
    }

    pub fn add_route (&mut self, method: Method, path: String, handler: fn(request: &Request, response: &mut Response)) -> () {
        let matcher = PathUtils::create_regex(path.as_slice());
        let variable_infos = PathUtils::get_variable_info(path.as_slice());
        let route = Route {
            path: path,
            method: method,
            matcher: matcher,
            handler: handler,
            variables: variable_infos
        };
        self.routes.push(route);
    }

    pub fn match_route<'a>(&'a self, method: Method, path: String) -> Option<RouteResult<'a>> {
        self.routes.iter().find(|item| item.method == method && item.matcher.is_match(path.as_slice()))
            .and_then(|route| {
                match route.matcher.captures(path.as_slice()) {
                    Some(captures) => {
                        let mut map = HashMap::new();
                        for (name, pos) in route.variables.iter() {
                            map.insert(name.to_string(), captures.at(pos + 1).to_string());
                        }
                        Some(RouteResult {
                            route: route,
                            params: map
                        })
                    },
                    None => Some(RouteResult{
                        route: route,
                        params: HashMap::new()
                    })
                }
            })
    }
}

#[test]
fn creates_map_with_var_variable_infos () {
    let map = PathUtils::get_variable_info("foo/:uid/bar/:groupid");

    assert_eq!(map.len(), 2);
    assert_eq!(map.get(&"uid".to_string()), &0);
    assert_eq!(map.get(&"groupid".to_string()), &1);
}

#[test]
fn creates_regex_with_captures () {
    let regex = PathUtils::create_regex("foo/:uid/bar/:groupid");
    let caps = regex.captures("foo/4711/bar/5490").unwrap();

    assert_eq!(caps.at(1), "4711");
    assert_eq!(caps.at(2), "5490");

    let regex = PathUtils::create_regex("foo/*/:uid/bar/:groupid");
    let caps = regex.captures("foo/test/4711/bar/5490").unwrap();

    assert_eq!(caps.at(1), "4711");
    assert_eq!(caps.at(2), "5490");

    let regex = PathUtils::create_regex("foo/**/:uid/bar/:groupid");
    let caps = regex.captures("foo/test/another/4711/bar/5490").unwrap();

    assert_eq!(caps.at(1), "4711");
    assert_eq!(caps.at(2), "5490");
}

#[test]
fn creates_valid_regex_for_routes () {
    let regex1 = PathUtils::create_regex("foo/:uid/bar/:groupid");
    let regex2 = PathUtils::create_regex("foo/*/bar");
    let regex3 = PathUtils::create_regex("foo/**/bar");

    assert_eq!(regex1.is_match("foo/4711/bar/5490"), true);
    assert_eq!(regex1.is_match("foo/4711/bar"), false);

    assert_eq!(regex2.is_match("foo/4711/bar"), true);
    assert_eq!(regex2.is_match("foo/4711/4712/bar"), false);

    assert_eq!(regex3.is_match("foo/4711/bar"), true);
    assert_eq!(regex3.is_match("foo/4711/4712/bar"), true);
}

#[test]
fn can_match_var_routes () {
    let route_store = &mut Router::new();

    fn handler (_request: &Request, response: &mut Response) -> () {
        let _ = response.origin.write("hello from foo".as_bytes());
    };

    route_store.add_route(method::Get, "/foo/:userid".to_string(), handler);
    route_store.add_route(method::Get, "/bar".to_string(), handler);

    let route_result = route_store.match_route(method::Get, "/foo/4711".to_string()).unwrap();
    let route = route_result.route;

    assert_eq!(route_result.params.get(&"userid".to_string()), &"4711".to_string());

    //assert the route has identified the variable
    assert_eq!(route.variables.len(), 1);
    assert_eq!(route.variables.get(&"userid".to_string()), &0);

    let route_result = route_store.match_route(method::Get, "/bar/4711".to_string());

    let result = match route_result {
        Some(_res) => true,
        None => false
    };

    assert_eq!(result, false);

    let route_result = route_store.match_route(method::Get, "/foo".to_string());

    let result = match route_result{
        Some(_res) => true,
        None => false
    };

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


<commit_before>extern crate rustbox;

use std::error::Error;
use self::rustbox::{Color, RustBox, Key};
use self::rustbox::Event::KeyEvent;

// Error処理

// Screen Status
pub enum Status {
    Selected(usize),
    Escaped,
    Continue,
    Quit,
    Error,
}

trait PrintLine {
    fn print_line(&self, y: usize, item: &str, fg: Color, bg: Color);
}

impl PrintLine for RustBox {

    fn print_line(&self, y: usize, item: &str, fg: Color, bg: Color) {
        for x in 0..(self.width()) {
            let ch = item.chars().nth(x).unwrap_or(' ');
            self.print_char(x, y, rustbox::RB_NORMAL, fg, bg, ch);
        }
    }
}

pub struct Screen {
    lines: Vec<String>, // フィールドレベルのミュータビリティ
    // prompt: String,
    // y_offset: usize,
    // filtered: Vec<String>,
    // query: String,
    cursor: usize,
    // offset: usize,
    rustbox: RustBox
}

impl Screen {

    pub fn new() -> Screen {

        let rustbox = match RustBox::init(Default::default()) {
            Result::Ok(v) => v,
            Result::Err(e) => panic!("{}", e),
        };

        Screen {
            lines: vec!(),
            // prompt: "☰ ".to_owned(),
            // y_offset: 1,
            cursor: 0,
            // offset: 0,
            rustbox: rustbox
        }
    }

    pub fn update_lines(&mut self, lines: &Vec<String>) {
        self.lines = lines.to_owned()
    }

    pub fn select_line(&mut self) -> Status {

        loop {

            self.render_items();

            match self.rustbox.poll_event(false) {

                Err(err) => panic!("{:?}", err),
                Ok(event) => match self.handle_event(event) {
                    Ok(Status::Selected(s)) => return Status::Selected(s),
                    Ok(Status::Quit) => return Status::Quit,
                        _ => (),
                    }
            }
        }
    }

    pub fn poll_event(&self) -> Key {
        match self.rustbox.poll_event(false) {
            Ok(rustbox::Event::KeyEvent(key)) => key,
            Err(e) => panic!("{}", e.description()),
            _ => panic!("error")
        }
    }

    fn handle_event(&mut self, event: rustbox::Event) -> Result<Status, Box<Error>> {

        match event {
            KeyEvent(Key::Enter) => {
                Ok(Status::Selected(self.cursor))
            },
            KeyEvent(Key::Esc) => Ok(Status::Escaped),
            KeyEvent(Key::Up) | KeyEvent(Key::Ctrl('p')) => {
                self.cursor_up();
                Ok(Status::Continue)
            },
            KeyEvent(Key::Down) | KeyEvent(Key::Ctrl('n')) => {
                self.cursor_down();
                Ok(Status::Continue)
            },
            KeyEvent(Key::Char('q')) => {
                Ok(Status::Quit)
            },
            // KeyEvent(Key::Backspace) => self.remove_query().and(Ok(Continue)),
            // KeyEvent(Key::Char(c)) => self.append_query(c).and(Ok(Continue)),
            _ => Ok(Status::Continue),
        }
    }

    fn cursor_up(&mut self) {

        if self.cursor != 0 { self.cursor -= 1; }
    }

    fn cursor_down(&mut self) {

        self.cursor += 1;  // displayのサイズを考慮する必要がある
    }

    fn render_items(&self) {

        self.rustbox.clear();

        for(y, item) in self.lines.iter().enumerate() {
            if y == self.cursor {
                self.rustbox.print_line(y, &format!("[{0}]: {1}", y, &item), Color::Black, Color::Green);
            } else {
                self.rustbox.print_line(y, &format!("[{0}]: {1}", y, &item), Color::Blue, Color::Black);
            }
        }

        self.rustbox.present();
    }

    pub fn draw_help(&self) {
        self.rustbox.clear();
        self.rustbox.print_line(0, "☰ Hello! this is kinesis helper tool.", Color::Black, Color::Green);
        self.rustbox.print_line(1, "☰ Press 'l' to show kinesis streams.", Color::Blue, Color::Black);
        self.rustbox.print_line(2, "☰ Press 'q' to quit.", Color::Blue, Color::Black);
        self.rustbox.present();
    }

    pub fn draw_strem_names(&self, stream_names: &Vec<String>) {

        self.rustbox.clear();

        self.rustbox.print_line(0, "☰ Kinesis > Streams", Color::Black, Color::Green);

        self.rustbox.present();
    }

    pub fn draw_shards(&self, shards: &Vec<String>) {

        self.rustbox.clear();

        self.rustbox.print_line(0, "☰ Kinesis > Streams > Shards", Color::Black, Color::Green);

        for (num, shards) in shards.iter().enumerate() {
            self.rustbox.print_line(num + 1, &format!("[{0}]: {1}", num, &shards), Color::Blue, Color::Black);
        }

        self.rustbox.present();
    }

    pub fn draw_records(&self, records: &Vec<String>) {

        self.rustbox.clear();

        self.rustbox.print_line(0, "☰ Kinesis > Streams > Shards > Records", Color::Black, Color::Green);
        self.rustbox.print_line(1, "☰ Press 'n' to next page.", Color::Black, Color::Green);

        for (num, record) in records.iter().enumerate() {
            self.rustbox.print_line(num + 2, &format!("[{0}]: {1}", num, &record), Color::Blue, Color::Black);
        }

        self.rustbox.present();
    }

}

<commit_msg>Enable filter item<commit_after>extern crate rustbox;
extern crate regex;

use std::error::Error;
use self::rustbox::{Color, RustBox, Key};
use self::rustbox::Event::KeyEvent;
use self::regex::Regex;

// Error処理

// Screen Status
pub enum Status {
    Selected(usize),
    Escaped,
    Continue,
    Quit,
    Error,
}

trait PrintLine {
    fn print_line(&self, y: usize, item: &str, fg: Color, bg: Color);
}

impl PrintLine for RustBox {

    fn print_line(&self, y: usize, item: &str, fg: Color, bg: Color) {
        for x in 0..(self.width()) {
            let ch = item.chars().nth(x).unwrap_or(' ');
            self.print_char(x, y, rustbox::RB_NORMAL, fg, bg, ch);
        }
    }
}

pub struct Screen {
    lines: Vec<String>, // フィールドレベルのミュータビリティ
    prompt: String,
    // y_offset: usize,
    filtered: Vec<String>,
    query: String,
    cursor: usize,
    // offset: usize,
    rustbox: RustBox
}

impl Screen {

    pub fn new() -> Screen {

        let rustbox = match RustBox::init(Default::default()) {
            Result::Ok(v) => v,
            Result::Err(e) => panic!("{}", e),
        };

        Screen {
            lines: vec!(),
            filtered: vec!(),
            prompt: "☰ >".to_owned(),
            // y_offset: 1,
            query: String::new(),
            cursor: 0,
            // offset: 0,
            rustbox: rustbox
        }
    }

    pub fn update_lines(&mut self, lines: &Vec<String>) {
        self.cursor = 0;
        self.lines = lines.to_owned();
        self.filtered = self.lines.clone();
    }

    pub fn select_line(&mut self) -> Status {

        loop {

            self.render_items();

            match self.rustbox.poll_event(false) {

                Err(err) => panic!("{:?}", err),
                Ok(event) => match self.handle_event(event) {
                    Ok(Status::Selected(s)) => return Status::Selected(s),
                    Ok(Status::Quit) => return Status::Quit,
                    _ => (),
                }
            }
        }
    }

    pub fn poll_event(&self) -> Key {
        match self.rustbox.poll_event(false) {
            Ok(rustbox::Event::KeyEvent(key)) => key,
            Err(e) => panic!("{}", e.description()),
            _ => panic!("error")
        }
    }

    fn handle_event(&mut self, event: rustbox::Event) -> Result<Status, Box<Error>> {

        match event {
            KeyEvent(Key::Enter) => {
                Ok(Status::Selected(self.cursor))
            },
            KeyEvent(Key::Esc) => Ok(Status::Escaped),
            KeyEvent(Key::Up) | KeyEvent(Key::Ctrl('p')) => {
                self.cursor_up();
                Ok(Status::Continue)
            },
            KeyEvent(Key::Down) | KeyEvent(Key::Ctrl('n')) => {
                self.cursor_down();
                Ok(Status::Continue)
            },
            KeyEvent(Key::Char('q')) => {
                Ok(Status::Quit)
            },
            KeyEvent(Key::Backspace) => self.remove_query().and(Ok(Status::Continue)),
            KeyEvent(Key::Char(c)) => self.append_query(c).and(Ok(Status::Continue)),
            _ => Ok(Status::Continue),
        }
    }

    fn append_query(&mut self, c: char) -> Result<(), Box<Error>> {

        self.query.push(c);
        self.apply_filter()
    }

    fn remove_query(&mut self) -> Result<(), Box<Error>> {

        if self.query.is_empty() {
            return Ok(());
        }

        let idx = self.query.len() - 1;
        self.query.remove(idx);
        self.apply_filter()
    }

    fn apply_filter(&mut self) -> Result<(), Box<Error>> {
        self.filtered = if self.query.len() == 0 {
            self.lines.clone()
        } else {
            let re = try!(Regex::new(self.query.as_str()));
            self.lines.iter().filter(|&input| re.is_match(input)).cloned().collect()
        };

        self.cursor = 0;
        // self.offset = 0;

        Ok(())
    }

    fn cursor_up(&mut self) {

        if self.cursor != 0 { self.cursor -= 1; }
    }

    fn cursor_down(&mut self) {

        self.cursor += 1;  // displayのサイズを考慮する必要がある
    }

    fn render_items(&self) {

        self.rustbox.clear();

        for(y, item) in self.filtered.iter().enumerate() {
            if y == self.cursor {
                self.rustbox.print_line(y+1, &format!("[{0}]: {1}", y, &item), Color::Black, Color::Green);
            } else {
                self.rustbox.print_line(y+1, &format!("[{0}]: {1}", y, &item), Color::Blue, Color::Black);
            }
        }

        // print query line and move the cursor to end.
        let query_str = format!("{}{}", self.prompt, self.query);
        self.rustbox.print_line(0, &query_str, Color::White, Color::Black);
        self.rustbox.set_cursor(query_str.len() as isize, 0);

        self.rustbox.present();
    }

    pub fn draw_help(&self) {
        self.rustbox.clear();
        self.rustbox.print_line(0, "☰ Hello! this is kinesis helper tool.", Color::Black, Color::Green);
        self.rustbox.print_line(1, "☰ Press 'l' to show kinesis streams.", Color::Blue, Color::Black);
        self.rustbox.print_line(2, "☰ Press 'q' to quit.", Color::Blue, Color::Black);
        self.rustbox.present();
    }

    pub fn draw_strem_names(&self, stream_names: &Vec<String>) {

        self.rustbox.clear();

        self.rustbox.print_line(0, "☰ Kinesis > Streams", Color::Black, Color::Green);

        self.rustbox.present();
    }

    pub fn draw_shards(&self, shards: &Vec<String>) {

        self.rustbox.clear();

        self.rustbox.print_line(0, "☰ Kinesis > Streams > Shards", Color::Black, Color::Green);

        for (num, shards) in shards.iter().enumerate() {
            self.rustbox.print_line(num + 1, &format!("[{0}]: {1}", num, &shards), Color::Blue, Color::Black);
        }

        self.rustbox.present();
    }

    pub fn draw_records(&self, records: &Vec<String>) {

        self.rustbox.clear();

        self.rustbox.print_line(0, "☰ Kinesis > Streams > Shards > Records", Color::Black, Color::Green);
        self.rustbox.print_line(1, "☰ Press 'n' to next page.", Color::Black, Color::Green);

        for (num, record) in records.iter().enumerate() {
            self.rustbox.print_line(num + 2, &format!("[{0}]: {1}", num, &record), Color::Blue, Color::Black);
        }

        self.rustbox.present();
    }

}

<|endoftext|>