<commit_before>#![allow(nonstandard_style)]

use libc::{c_int, c_void, uintptr_t};

#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum _Unwind_Reason_Code {
    _URC_NO_REASON = 0,
    _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
    _URC_FATAL_PHASE2_ERROR = 2,
    _URC_FATAL_PHASE1_ERROR = 3,
    _URC_NORMAL_STOP = 4,
    _URC_END_OF_STACK = 5,
    _URC_HANDLER_FOUND = 6,
    _URC_INSTALL_CONTEXT = 7,
    _URC_CONTINUE_UNWIND = 8,
    _URC_FAILURE = 9, // used only by ARM EHABI
}
pub use _Unwind_Reason_Code::*;

pub type _Unwind_Exception_Class = u64;
pub type _Unwind_Word = uintptr_t;
pub type _Unwind_Ptr = uintptr_t;
pub type _Unwind_Trace_Fn =
    extern "C" fn(ctx: *mut _Unwind_Context, arg: *mut c_void) -> _Unwind_Reason_Code;

#[cfg(target_arch = "x86")]
pub const unwinder_private_data_size: usize = 5;

#[cfg(target_arch = "x86_64")]
pub const unwinder_private_data_size: usize = 6;

#[cfg(all(target_arch = "arm", not(target_os = "ios")))]
pub const unwinder_private_data_size: usize = 20;

#[cfg(all(target_arch = "arm", target_os = "ios"))]
pub const unwinder_private_data_size: usize = 5;

#[cfg(target_arch = "aarch64")]
pub const unwinder_private_data_size: usize = 2;

#[cfg(target_arch = "mips")]
pub const unwinder_private_data_size: usize = 2;

#[cfg(target_arch = "mips64")]
pub const unwinder_private_data_size: usize = 2;

#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
pub const unwinder_private_data_size: usize = 2;

#[cfg(target_arch = "s390x")]
pub const unwinder_private_data_size: usize = 2;

#[cfg(any(target_arch = "sparc", target_arch = "sparc64"))]
pub const unwinder_private_data_size: usize = 2;

#[cfg(any(target_arch = "riscv64", target_arch = "riscv32"))]
pub const unwinder_private_data_size: usize = 2;

#[cfg(target_os = "emscripten")]
pub const unwinder_private_data_size: usize = 20;

#[cfg(all(target_arch = "hexagon", target_os = "linux"))]
pub const unwinder_private_data_size: usize = 35;

#[repr(C)]
pub struct _Unwind_Exception {
    pub exception_class: _Unwind_Exception_Class,
    pub exception_cleanup: _Unwind_Exception_Cleanup_Fn,
    pub private: [_Unwind_Word; unwinder_private_data_size],
}

pub enum _Unwind_Context {}

pub type _Unwind_Exception_Cleanup_Fn =
    extern "C" fn(unwind_code: _Unwind_Reason_Code, exception: *mut _Unwind_Exception);
#[cfg_attr(
    all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")),
    link(name = "unwind", kind = "static")
)]
extern "C" {
    #[unwind(allowed)]
    pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !;
    pub fn _Unwind_DeleteException(exception: *mut _Unwind_Exception);
    pub fn _Unwind_GetLanguageSpecificData(ctx: *mut _Unwind_Context) -> *mut c_void;
    pub fn _Unwind_GetRegionStart(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
    pub fn _Unwind_GetTextRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
    pub fn _Unwind_GetDataRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
}

cfg_if::cfg_if! {
if #[cfg(any(target_os = "ios", target_os = "netbsd", not(target_arch = "arm")))] {
    // Not ARM EHABI
    #[repr(C)]
    #[derive(Copy, Clone, PartialEq)]
    pub enum _Unwind_Action {
        _UA_SEARCH_PHASE = 1,
        _UA_CLEANUP_PHASE = 2,
        _UA_HANDLER_FRAME = 4,
        _UA_FORCE_UNWIND = 8,
        _UA_END_OF_STACK = 16,
    }
    pub use _Unwind_Action::*;

    #[cfg_attr(all(feature = "llvm-libunwind",
                   any(target_os = "fuchsia", target_os = "linux")),
               link(name = "unwind", kind = "static"))]
    extern "C" {
        pub fn _Unwind_GetGR(ctx: *mut _Unwind_Context, reg_index: c_int) -> _Unwind_Word;
        pub fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: c_int, value: _Unwind_Word);
        pub fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> _Unwind_Word;
        pub fn _Unwind_SetIP(ctx: *mut _Unwind_Context, value: _Unwind_Word);
        pub fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context, ip_before_insn: *mut c_int)
                                 -> _Unwind_Word;
        pub fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void;
    }

} else {
    // ARM EHABI
    #[repr(C)]
    #[derive(Copy, Clone, PartialEq)]
    pub enum _Unwind_State {
        _US_VIRTUAL_UNWIND_FRAME = 0,
        _US_UNWIND_FRAME_STARTING = 1,
        _US_UNWIND_FRAME_RESUME = 2,
        _US_ACTION_MASK = 3,
        _US_FORCE_UNWIND = 8,
        _US_END_OF_STACK = 16,
    }
    pub use _Unwind_State::*;

    #[repr(C)]
    enum _Unwind_VRS_Result {
        _UVRSR_OK = 0,
        _UVRSR_NOT_IMPLEMENTED = 1,
        _UVRSR_FAILED = 2,
    }
    #[repr(C)]
    enum _Unwind_VRS_RegClass {
        _UVRSC_CORE = 0,
        _UVRSC_VFP = 1,
        _UVRSC_FPA = 2,
        _UVRSC_WMMXD = 3,
        _UVRSC_WMMXC = 4,
    }
    use _Unwind_VRS_RegClass::*;
    #[repr(C)]
    enum _Unwind_VRS_DataRepresentation {
        _UVRSD_UINT32 = 0,
        _UVRSD_VFPX = 1,
        _UVRSD_FPAX = 2,
        _UVRSD_UINT64 = 3,
        _UVRSD_FLOAT = 4,
        _UVRSD_DOUBLE = 5,
    }
    use _Unwind_VRS_DataRepresentation::*;

    pub const UNWIND_POINTER_REG: c_int = 12;
    pub const UNWIND_SP_REG: c_int = 13;
    pub const UNWIND_IP_REG: c_int = 15;

    #[cfg_attr(all(feature = "llvm-libunwind",
                   any(target_os = "fuchsia", target_os = "linux")),
               link(name = "unwind", kind = "static"))]
    extern "C" {
        fn _Unwind_VRS_Get(ctx: *mut _Unwind_Context,
                           regclass: _Unwind_VRS_RegClass,
                           regno: _Unwind_Word,
                           repr: _Unwind_VRS_DataRepresentation,
                           data: *mut c_void)
                           -> _Unwind_VRS_Result;

        fn _Unwind_VRS_Set(ctx: *mut _Unwind_Context,
                           regclass: _Unwind_VRS_RegClass,
                           regno: _Unwind_Word,
                           repr: _Unwind_VRS_DataRepresentation,
                           data: *mut c_void)
                           -> _Unwind_VRS_Result;
    }

    // On Android or ARM/Linux, these are implemented as macros:

    pub unsafe fn _Unwind_GetGR(ctx: *mut _Unwind_Context, reg_index: c_int) -> _Unwind_Word {
        let mut val: _Unwind_Word = 0;
        _Unwind_VRS_Get(ctx, _UVRSC_CORE, reg_index as _Unwind_Word, _UVRSD_UINT32,
                        &mut val as *mut _ as *mut c_void);
        val
    }

    pub unsafe fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: c_int, value: _Unwind_Word) {
        let mut value = value;
        _Unwind_VRS_Set(ctx, _UVRSC_CORE, reg_index as _Unwind_Word, _UVRSD_UINT32,
                        &mut value as *mut _ as *mut c_void);
    }

    pub unsafe fn _Unwind_GetIP(ctx: *mut _Unwind_Context)
                                -> _Unwind_Word {
        let val = _Unwind_GetGR(ctx, UNWIND_IP_REG);
        (val & !1) as _Unwind_Word
    }

    pub unsafe fn _Unwind_SetIP(ctx: *mut _Unwind_Context,
                                value: _Unwind_Word) {
        // Propagate thumb bit to instruction pointer
        let thumb_state = _Unwind_GetGR(ctx, UNWIND_IP_REG) & 1;
        let value = value | thumb_state;
        _Unwind_SetGR(ctx, UNWIND_IP_REG, value);
    }

    pub unsafe fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context,
                                    ip_before_insn: *mut c_int)
                                    -> _Unwind_Word {
        *ip_before_insn = 0;
        _Unwind_GetIP(ctx)
    }

    // This function also doesn't exist on Android or ARM/Linux, so make it a no-op
    pub unsafe fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void {
        pc
    }
}
} // cfg_if!

cfg_if::cfg_if! {
if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] {
    // Not 32-bit iOS
    #[cfg_attr(all(feature = "llvm-libunwind",
                   any(target_os = "fuchsia", target_os = "linux")),
               link(name = "unwind", kind = "static"))]
    extern "C" {
        #[unwind(allowed)]
        pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
        pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
                                 trace_argument: *mut c_void)
                                 -> _Unwind_Reason_Code;
    }
} else {
    // 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace()
    #[cfg_attr(all(feature = "llvm-libunwind",
                   any(target_os = "fuchsia", target_os = "linux")),
               link(name = "unwind", kind = "static"))]
    extern "C" {
        #[unwind(allowed)]
        pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
    }

    #[inline]
    pub unsafe fn _Unwind_RaiseException(exc: *mut _Unwind_Exception) -> _Unwind_Reason_Code {
        _Unwind_SjLj_RaiseException(exc)
    }
}
} // cfg_if!

cfg_if::cfg_if! {
if #[cfg(all(windows, target_arch = "x86_64", target_env = "gnu"))] {
    // We declare these as opaque types. This is fine since you just need to
    // pass them to _GCC_specific_handler and forget about them.
    pub enum EXCEPTION_RECORD {}
    pub type LPVOID = *mut c_void;
    pub enum CONTEXT {}
    pub enum DISPATCHER_CONTEXT {}
    pub type EXCEPTION_DISPOSITION = c_int;
    type PersonalityFn = unsafe extern "C" fn(version: c_int,
                                              actions: _Unwind_Action,
                                              exception_class: _Unwind_Exception_Class,
                                              exception_object: *mut _Unwind_Exception,
                                              context: *mut _Unwind_Context)
                                              -> _Unwind_Reason_Code;

    extern "C" {
        pub fn _GCC_specific_handler(exceptionRecord: *mut EXCEPTION_RECORD,
                                establisherFrame: LPVOID,
                                contextRecord: *mut CONTEXT,
                                dispatcherContext: *mut DISPATCHER_CONTEXT,
                                personality: PersonalityFn)
                                -> EXCEPTION_DISPOSITION;
    }
}
} // cfg_if!
<commit_msg>Support AArch64 ILP32 in libunwind bindings<commit_after>#![allow(nonstandard_style)]

use libc::{c_int, c_void, uintptr_t};

#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum _Unwind_Reason_Code {
    _URC_NO_REASON = 0,
    _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
    _URC_FATAL_PHASE2_ERROR = 2,
    _URC_FATAL_PHASE1_ERROR = 3,
    _URC_NORMAL_STOP = 4,
    _URC_END_OF_STACK = 5,
    _URC_HANDLER_FOUND = 6,
    _URC_INSTALL_CONTEXT = 7,
    _URC_CONTINUE_UNWIND = 8,
    _URC_FAILURE = 9, // used only by ARM EHABI
}
pub use _Unwind_Reason_Code::*;

pub type _Unwind_Exception_Class = u64;
pub type _Unwind_Word = uintptr_t;
pub type _Unwind_Ptr = uintptr_t;
pub type _Unwind_Trace_Fn =
    extern "C" fn(ctx: *mut _Unwind_Context, arg: *mut c_void) -> _Unwind_Reason_Code;

#[cfg(target_arch = "x86")]
pub const unwinder_private_data_size: usize = 5;

#[cfg(target_arch = "x86_64")]
pub const unwinder_private_data_size: usize = 6;

#[cfg(all(target_arch = "arm", not(target_os = "ios")))]
pub const unwinder_private_data_size: usize = 20;

#[cfg(all(target_arch = "arm", target_os = "ios"))]
pub const unwinder_private_data_size: usize = 5;

#[cfg(all(target_arch = "aarch64", target_pointer_width = "64"))]
pub const unwinder_private_data_size: usize = 2;

#[cfg(all(target_arch = "aarch64", target_pointer_width = "32"))]
pub const unwinder_private_data_size: usize = 5;

#[cfg(target_arch = "mips")]
pub const unwinder_private_data_size: usize = 2;

#[cfg(target_arch = "mips64")]
pub const unwinder_private_data_size: usize = 2;

#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
pub const unwinder_private_data_size: usize = 2;

#[cfg(target_arch = "s390x")]
pub const unwinder_private_data_size: usize = 2;

#[cfg(any(target_arch = "sparc", target_arch = "sparc64"))]
pub const unwinder_private_data_size: usize = 2;

#[cfg(any(target_arch = "riscv64", target_arch = "riscv32"))]
pub const unwinder_private_data_size: usize = 2;

#[cfg(target_os = "emscripten")]
pub const unwinder_private_data_size: usize = 20;

#[cfg(all(target_arch = "hexagon", target_os = "linux"))]
pub const unwinder_private_data_size: usize = 35;

#[repr(C)]
pub struct _Unwind_Exception {
    pub exception_class: _Unwind_Exception_Class,
    pub exception_cleanup: _Unwind_Exception_Cleanup_Fn,
    pub private: [_Unwind_Word; unwinder_private_data_size],
}

pub enum _Unwind_Context {}

pub type _Unwind_Exception_Cleanup_Fn =
    extern "C" fn(unwind_code: _Unwind_Reason_Code, exception: *mut _Unwind_Exception);
#[cfg_attr(
    all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")),
    link(name = "unwind", kind = "static")
)]
extern "C" {
    #[unwind(allowed)]
    pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !;
    pub fn _Unwind_DeleteException(exception: *mut _Unwind_Exception);
    pub fn _Unwind_GetLanguageSpecificData(ctx: *mut _Unwind_Context) -> *mut c_void;
    pub fn _Unwind_GetRegionStart(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
    pub fn _Unwind_GetTextRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
    pub fn _Unwind_GetDataRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
}

cfg_if::cfg_if! {
if #[cfg(any(target_os = "ios", target_os = "netbsd", not(target_arch = "arm")))] {
    // Not ARM EHABI
    #[repr(C)]
    #[derive(Copy, Clone, PartialEq)]
    pub enum _Unwind_Action {
        _UA_SEARCH_PHASE = 1,
        _UA_CLEANUP_PHASE = 2,
        _UA_HANDLER_FRAME = 4,
        _UA_FORCE_UNWIND = 8,
        _UA_END_OF_STACK = 16,
    }
    pub use _Unwind_Action::*;

    #[cfg_attr(all(feature = "llvm-libunwind",
                   any(target_os = "fuchsia", target_os = "linux")),
               link(name = "unwind", kind = "static"))]
    extern "C" {
        pub fn _Unwind_GetGR(ctx: *mut _Unwind_Context, reg_index: c_int) -> _Unwind_Word;
        pub fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: c_int, value: _Unwind_Word);
        pub fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> _Unwind_Word;
        pub fn _Unwind_SetIP(ctx: *mut _Unwind_Context, value: _Unwind_Word);
        pub fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context, ip_before_insn: *mut c_int)
                                 -> _Unwind_Word;
        pub fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void;
    }

} else {
    // ARM EHABI
    #[repr(C)]
    #[derive(Copy, Clone, PartialEq)]
    pub enum _Unwind_State {
        _US_VIRTUAL_UNWIND_FRAME = 0,
        _US_UNWIND_FRAME_STARTING = 1,
        _US_UNWIND_FRAME_RESUME = 2,
        _US_ACTION_MASK = 3,
        _US_FORCE_UNWIND = 8,
        _US_END_OF_STACK = 16,
    }
    pub use _Unwind_State::*;

    #[repr(C)]
    enum _Unwind_VRS_Result {
        _UVRSR_OK = 0,
        _UVRSR_NOT_IMPLEMENTED = 1,
        _UVRSR_FAILED = 2,
    }
    #[repr(C)]
    enum _Unwind_VRS_RegClass {
        _UVRSC_CORE = 0,
        _UVRSC_VFP = 1,
        _UVRSC_FPA = 2,
        _UVRSC_WMMXD = 3,
        _UVRSC_WMMXC = 4,
    }
    use _Unwind_VRS_RegClass::*;
    #[repr(C)]
    enum _Unwind_VRS_DataRepresentation {
        _UVRSD_UINT32 = 0,
        _UVRSD_VFPX = 1,
        _UVRSD_FPAX = 2,
        _UVRSD_UINT64 = 3,
        _UVRSD_FLOAT = 4,
        _UVRSD_DOUBLE = 5,
    }
    use _Unwind_VRS_DataRepresentation::*;

    pub const UNWIND_POINTER_REG: c_int = 12;
    pub const UNWIND_SP_REG: c_int = 13;
    pub const UNWIND_IP_REG: c_int = 15;

    #[cfg_attr(all(feature = "llvm-libunwind",
                   any(target_os = "fuchsia", target_os = "linux")),
               link(name = "unwind", kind = "static"))]
    extern "C" {
        fn _Unwind_VRS_Get(ctx: *mut _Unwind_Context,
                           regclass: _Unwind_VRS_RegClass,
                           regno: _Unwind_Word,
                           repr: _Unwind_VRS_DataRepresentation,
                           data: *mut c_void)
                           -> _Unwind_VRS_Result;

        fn _Unwind_VRS_Set(ctx: *mut _Unwind_Context,
                           regclass: _Unwind_VRS_RegClass,
                           regno: _Unwind_Word,
                           repr: _Unwind_VRS_DataRepresentation,
                           data: *mut c_void)
                           -> _Unwind_VRS_Result;
    }

    // On Android or ARM/Linux, these are implemented as macros:

    pub unsafe fn _Unwind_GetGR(ctx: *mut _Unwind_Context, reg_index: c_int) -> _Unwind_Word {
        let mut val: _Unwind_Word = 0;
        _Unwind_VRS_Get(ctx, _UVRSC_CORE, reg_index as _Unwind_Word, _UVRSD_UINT32,
                        &mut val as *mut _ as *mut c_void);
        val
    }

    pub unsafe fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: c_int, value: _Unwind_Word) {
        let mut value = value;
        _Unwind_VRS_Set(ctx, _UVRSC_CORE, reg_index as _Unwind_Word, _UVRSD_UINT32,
                        &mut value as *mut _ as *mut c_void);
    }

    pub unsafe fn _Unwind_GetIP(ctx: *mut _Unwind_Context)
                                -> _Unwind_Word {
        let val = _Unwind_GetGR(ctx, UNWIND_IP_REG);
        (val & !1) as _Unwind_Word
    }

    pub unsafe fn _Unwind_SetIP(ctx: *mut _Unwind_Context,
                                value: _Unwind_Word) {
        // Propagate thumb bit to instruction pointer
        let thumb_state = _Unwind_GetGR(ctx, UNWIND_IP_REG) & 1;
        let value = value | thumb_state;
        _Unwind_SetGR(ctx, UNWIND_IP_REG, value);
    }

    pub unsafe fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context,
                                    ip_before_insn: *mut c_int)
                                    -> _Unwind_Word {
        *ip_before_insn = 0;
        _Unwind_GetIP(ctx)
    }

    // This function also doesn't exist on Android or ARM/Linux, so make it a no-op
    pub unsafe fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void {
        pc
    }
}
} // cfg_if!

cfg_if::cfg_if! {
if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] {
    // Not 32-bit iOS
    #[cfg_attr(all(feature = "llvm-libunwind",
                   any(target_os = "fuchsia", target_os = "linux")),
               link(name = "unwind", kind = "static"))]
    extern "C" {
        #[unwind(allowed)]
        pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
        pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
                                 trace_argument: *mut c_void)
                                 -> _Unwind_Reason_Code;
    }
} else {
    // 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace()
    #[cfg_attr(all(feature = "llvm-libunwind",
                   any(target_os = "fuchsia", target_os = "linux")),
               link(name = "unwind", kind = "static"))]
    extern "C" {
        #[unwind(allowed)]
        pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
    }

    #[inline]
    pub unsafe fn _Unwind_RaiseException(exc: *mut _Unwind_Exception) -> _Unwind_Reason_Code {
        _Unwind_SjLj_RaiseException(exc)
    }
}
} // cfg_if!

cfg_if::cfg_if! {
if #[cfg(all(windows, target_arch = "x86_64", target_env = "gnu"))] {
    // We declare these as opaque types. This is fine since you just need to
    // pass them to _GCC_specific_handler and forget about them.
    pub enum EXCEPTION_RECORD {}
    pub type LPVOID = *mut c_void;
    pub enum CONTEXT {}
    pub enum DISPATCHER_CONTEXT {}
    pub type EXCEPTION_DISPOSITION = c_int;
    type PersonalityFn = unsafe extern "C" fn(version: c_int,
                                              actions: _Unwind_Action,
                                              exception_class: _Unwind_Exception_Class,
                                              exception_object: *mut _Unwind_Exception,
                                              context: *mut _Unwind_Context)
                                              -> _Unwind_Reason_Code;

    extern "C" {
        pub fn _GCC_specific_handler(exceptionRecord: *mut EXCEPTION_RECORD,
                                establisherFrame: LPVOID,
                                contextRecord: *mut CONTEXT,
                                dispatcherContext: *mut DISPATCHER_CONTEXT,
                                personality: PersonalityFn)
                                -> EXCEPTION_DISPOSITION;
    }
}
} // cfg_if!
<|endoftext|>


<commit_before>use serde::Deserialize;
use serde::Serialize;
use serde_json;
use std::collections::BTreeMap;
use super::Result;

/// represents an general jira error response
#[derive(Deserialize, Debug)]
pub struct Errors {
    #[serde(rename = "errorMessages")]
    pub error_messages: Vec<String>,
    pub errors: BTreeMap<String, String>,
}

/// represents a single jira issue
#[derive(Deserialize, Debug)]
pub struct Issue {
    #[serde(rename = "self")]
    pub self_link: String,
    pub key: String,
    pub id: String,
    pub fields: BTreeMap<String, ::serde_json::Value>,
    pub changelog: Option<Changelog>,
}

impl Issue {
    /// resolves a typed field from an issues lists of arbitrary fields
    pub fn field<F>(&self, name: &str) -> Option<Result<F>>
    where
        for<'de> F: Deserialize<'de>,
    {
        self.fields.get(name).map(|value| {
            let decoded = try!(serde_json::value::from_value::<F>(value.clone()));
            Ok(decoded)
        })
    }

    fn user_field(&self, name: &str) -> Option<Result<User>> {
        self.field::<User>(name)
    }

    fn string_field(&self, name: &str) -> Option<Result<String>> {
        self.field::<String>(name)
    }

    /// user assigned to issue
    pub fn assignee(&self) -> Option<User> {
        self.user_field("assignee").and_then(|value| value.ok())
    }

    /// user that created the issue
    pub fn creator(&self) -> Option<User> {
        self.user_field("creator").and_then(|value| value.ok())
    }

    /// user that reported the issue
    pub fn reporter(&self) -> Option<User> {
        self.user_field("reporter").and_then(|value| value.ok())
    }

    /// the current status of the issue
    pub fn status(&self) -> Option<Status> {
        self.field::<Status>("status").and_then(|value| value.ok())
    }

    /// brief summary of the issue
    pub fn summary(&self) -> Option<String> {
        self.string_field("summary").and_then(|value| value.ok())
    }

    /// description of the issue
    pub fn description(&self) -> Option<String> {
        self.string_field("description").and_then(
            |value| value.ok(),
        )
    }

    /// updated timestamp
    pub fn updated(&self) -> Option<String> {
        self.string_field("updated").and_then(|value| value.ok())
    }

    /// created timestamp
    pub fn created(&self) -> Option<String> {
        self.string_field("created").and_then(|value| value.ok())
    }

    pub fn resolution_date(&self) -> Option<String> {
        self.string_field("resolution_date").and_then(
            |value| value.ok(),
        )
    }

    /// an issue type
    pub fn issue_type(&self) -> Option<IssueType> {
        self.field::<IssueType>("issuetype").and_then(
            |value| value.ok(),
        )
    }

    /// labels associated with the issue
    pub fn labels(&self) -> Vec<String> {
        self.field::<Vec<String>>("labels")
            .and_then(|value| value.ok())
            .unwrap_or(vec![])
    }

    /// list of versions associated with the issue
    pub fn fix_versions(&self) -> Vec<Version> {
        self.field::<Vec<Version>>("fixVersions")
            .and_then(|value| value.ok())
            .unwrap_or(vec![])
    }

    /// priority of the issue
    pub fn priority(&self) -> Option<Priority> {
        self.field::<Priority>("priority").and_then(
            |value| value.ok(),
        )
    }

    /// links to other issues
    pub fn links(&self) -> Option<Result<Vec<IssueLink>>> {
        self.field::<Vec<IssueLink>>("issuelinks") //.and_then(|value| value.ok()).unwrap_or(vec![])
    }

    pub fn project(&self) -> Option<Project> {
        self.field::<Project>("project").and_then(
            |value| value.ok(),
        )
    }

    pub fn resolution(&self) -> Option<Resolution> {
        self.field::<Resolution>("resolution").and_then(
            |value| value.ok(),
        )
    }
}

#[derive(Deserialize, Debug)]
pub struct Changelog {
    pub histories: Vec<History>,
}

#[derive(Deserialize, Debug)]
pub struct History {
    pub author: User,
    pub created: String,
    pub items: Vec<HistoryItem>,
}

#[derive(Deserialize, Debug)]
pub struct HistoryItem {
    pub field: String,
    pub from: Option<String>,
    #[serde(rename = "fromString")]
    pub from_string: Option<String>,
    pub to: Option<String>,
    #[serde(rename = "toString")]
    pub to_string: Option<String>,
}

#[derive(Deserialize, Debug)]
pub struct Project {
    pub id: String,
    pub key: String,
    pub name: String,
}

/// represents link relationship between issues
#[derive(Deserialize, Debug)]
pub struct IssueLink {
    pub id: String,
    #[serde(rename = "self")]
    pub self_link: String,
    #[serde(rename = "outwardIssue")]
    pub outward_issue: Option<Issue>,
    #[serde(rename = "inwardIssue")]
    pub inward_issue: Option<Issue>,
    #[serde(rename = "type")]
    pub link_type: LinkType,
}

/// represents type of issue relation
#[derive(Deserialize, Debug)]
pub struct LinkType {
    pub id: String,
    pub inward: String,
    pub name: String,
    pub outward: String,
    #[serde(rename = "self")]
    pub self_link: String,
}

#[derive(Deserialize, Debug)]
pub struct Version {
    pub archived: bool,
    pub id: String,
    pub name: String,
    pub released: bool,
    #[serde(rename = "self")]
    pub self_link: String,
}

#[derive(Deserialize, Debug)]
pub struct User {
    pub active: bool,
    #[serde(rename = "avatarUrls")]
    pub avatar_urls: BTreeMap<String, String>,
    #[serde(rename = "displayName")]
    pub display_name: String,
    #[serde(rename = "emailAddress")]
    pub email_address: String,
    pub key: Option<String>,
    pub name: String,
    #[serde(rename = "self")]
    pub self_link: String,
    #[serde(rename = "timeZone")]
    pub timezone: Option<String>,
}

#[derive(Deserialize, Debug)]
pub struct Status {
    pub description: String,
    #[serde(rename = "iconUrl")]
    pub icon_url: String,
    pub id: String,
    pub name: String,
    #[serde(rename = "self")]
    pub self_link: String,
}

#[derive(Deserialize, Debug)]
pub struct Priority {
    pub icon_url: String,
    pub id: String,
    pub name: String,
    #[serde(rename = "self")]
    pub self_link: String,
}

#[derive(Deserialize, Debug)]
pub struct IssueType {
    pub description: String,
    #[serde(rename = "iconUrl")]
    pub icon_url: String,
    pub id: String,
    pub name: String,
    #[serde(rename = "self")]
    pub self_link: String,
    pub subtask: bool,
}

#[derive(Deserialize, Debug)]
pub struct SearchResults {
    pub total: u64,
    #[serde(rename = "maxResults")]
    pub max_results: u64,
    #[serde(rename = "startAt")]
    pub start_at: u64,
    pub expand: String,
    pub issues: Vec<Issue>,
}

#[derive(Deserialize, Debug)]
pub struct TransitionOption {
    pub id: String,
    pub name: String,
    pub to: TransitionTo,
}

#[derive(Deserialize, Debug)]
pub struct TransitionTo {
    pub name: String,
    pub id: String,
}

/// contains list of options an issue can transitions through
#[derive(Deserialize, Debug)]
pub struct TransitionOptions {
    pub transitions: Vec<TransitionOption>,
}

#[derive(Serialize, Debug)]
pub struct TransitionTriggerOptions {
    pub transition: Transition,
    pub fields: BTreeMap<String, ::serde_json::Value>,
}

impl TransitionTriggerOptions {
    /// creates a new instance
    pub fn new<I>(id: I) -> TransitionTriggerOptions
    where
        I: Into<String>,
    {
        TransitionTriggerOptions {
            transition: Transition { id: id.into() },
            fields: BTreeMap::new(),
        }
    }

    pub fn builder<I>(id: I) -> TransitionTriggerOptionsBuilder
    where
        I: Into<String>,
    {
        TransitionTriggerOptionsBuilder::new(id)
    }
}

pub struct TransitionTriggerOptionsBuilder {
    pub transition: Transition,
    pub fields: BTreeMap<String, ::serde_json::Value>,
}

impl TransitionTriggerOptionsBuilder {
    /// creates a new instance
    pub fn new<I>(id: I) -> TransitionTriggerOptionsBuilder
    where
        I: Into<String>,
    {
        TransitionTriggerOptionsBuilder {
            transition: Transition { id: id.into() },
            fields: BTreeMap::new(),
        }
    }

    /// appends a field to update as part of transition
    pub fn field<N, V>(&mut self, name: N, value: V) -> &mut TransitionTriggerOptionsBuilder
    where
        N: Into<String>,
        V: Serialize,
    {
        self.fields.insert(
            name.into(),
            serde_json::to_value(value).expect("Value to serialize"),
        );
        self
    }

    /// updates resolution in transition
    pub fn resolution<R>(&mut self, name: R) -> &mut TransitionTriggerOptionsBuilder
    where
        R: Into<String>,
    {
        self.field("resolution", Resolution { name: name.into() });
        self
    }

    pub fn build(&self) -> TransitionTriggerOptions {
        TransitionTriggerOptions {
            transition: self.transition.clone(),
            fields: self.fields.clone(),
        }
    }
}

#[derive(Serialize, Debug, Deserialize)]
pub struct Resolution {
    name: String,
}

#[derive(Serialize, Clone, Debug)]
pub struct Transition {
    pub id: String,
}
<commit_msg>[feat] support attachments<commit_after>use serde::Deserialize;
use serde::Serialize;
use serde_json;
use std::collections::BTreeMap;
use super::Result;

/// represents an general jira error response
#[derive(Deserialize, Debug)]
pub struct Errors {
    #[serde(rename = "errorMessages")]
    pub error_messages: Vec<String>,
    pub errors: BTreeMap<String, String>,
}

/// represents a single jira issue
#[derive(Deserialize, Debug)]
pub struct Issue {
    #[serde(rename = "self")]
    pub self_link: String,
    pub key: String,
    pub id: String,
    pub fields: BTreeMap<String, ::serde_json::Value>,
    pub changelog: Option<Changelog>,
}

impl Issue {
    /// resolves a typed field from an issues lists of arbitrary fields
    pub fn field<F>(&self, name: &str) -> Option<Result<F>>
    where
        for<'de> F: Deserialize<'de>,
    {
        self.fields.get(name).map(|value| {
            let decoded = try!(serde_json::value::from_value::<F>(value.clone()));
            Ok(decoded)
        })
    }

    fn user_field(&self, name: &str) -> Option<Result<User>> {
        self.field::<User>(name)
    }

    fn string_field(&self, name: &str) -> Option<Result<String>> {
        self.field::<String>(name)
    }

    /// user assigned to issue
    pub fn assignee(&self) -> Option<User> {
        self.user_field("assignee").and_then(|value| value.ok())
    }

    /// user that created the issue
    pub fn creator(&self) -> Option<User> {
        self.user_field("creator").and_then(|value| value.ok())
    }

    /// user that reported the issue
    pub fn reporter(&self) -> Option<User> {
        self.user_field("reporter").and_then(|value| value.ok())
    }

    /// the current status of the issue
    pub fn status(&self) -> Option<Status> {
        self.field::<Status>("status").and_then(|value| value.ok())
    }

    /// brief summary of the issue
    pub fn summary(&self) -> Option<String> {
        self.string_field("summary").and_then(|value| value.ok())
    }

    /// description of the issue
    pub fn description(&self) -> Option<String> {
        self.string_field("description").and_then(
            |value| value.ok(),
        )
    }

    /// updated timestamp
    pub fn updated(&self) -> Option<String> {
        self.string_field("updated").and_then(|value| value.ok())
    }

    /// created timestamp
    pub fn created(&self) -> Option<String> {
        self.string_field("created").and_then(|value| value.ok())
    }

    pub fn resolution_date(&self) -> Option<String> {
        self.string_field("resolution_date").and_then(
            |value| value.ok(),
        )
    }

    /// an issue type
    pub fn issue_type(&self) -> Option<IssueType> {
        self.field::<IssueType>("issuetype").and_then(
            |value| value.ok(),
        )
    }

    /// labels associated with the issue
    pub fn labels(&self) -> Vec<String> {
        self.field::<Vec<String>>("labels")
            .and_then(|value| value.ok())
            .unwrap_or(vec![])
    }

    /// list of versions associated with the issue
    pub fn fix_versions(&self) -> Vec<Version> {
        self.field::<Vec<Version>>("fixVersions")
            .and_then(|value| value.ok())
            .unwrap_or(vec![])
    }

    /// priority of the issue
    pub fn priority(&self) -> Option<Priority> {
        self.field::<Priority>("priority").and_then(
            |value| value.ok(),
        )
    }

    /// links to other issues
    pub fn links(&self) -> Option<Result<Vec<IssueLink>>> {
        self.field::<Vec<IssueLink>>("issuelinks") //.and_then(|value| value.ok()).unwrap_or(vec![])
    }

    pub fn project(&self) -> Option<Project> {
        self.field::<Project>("project").and_then(
            |value| value.ok(),
        )
    }

    pub fn resolution(&self) -> Option<Resolution> {
        self.field::<Resolution>("resolution").and_then(
            |value| value.ok(),
        )
    }

    pub fn attachment(&self) -> Vec<Attachment> {
        self.field::<Vec<Attachment>>("attachment")
            .and_then(|value| value.ok())
            .unwrap_or(vec![])
    }
}

#[derive(Deserialize, Debug)]
pub struct Attachment {
  pub id: String,
  #[serde(rename = "self")]
  pub self_link: String,
  pub filename: String,
  pub author: User,
  pub created: String,
  pub size: u64,
  #[serde(rename = "mimeType")]
  pub mime_type: String,
  pub content: String,
  pub thumbnail: Option<String>,
}

#[derive(Deserialize, Debug)]
pub struct Changelog {
    pub histories: Vec<History>,
}

#[derive(Deserialize, Debug)]
pub struct History {
    pub author: User,
    pub created: String,
    pub items: Vec<HistoryItem>,
}

#[derive(Deserialize, Debug)]
pub struct HistoryItem {
    pub field: String,
    pub from: Option<String>,
    #[serde(rename = "fromString")]
    pub from_string: Option<String>,
    pub to: Option<String>,
    #[serde(rename = "toString")]
    pub to_string: Option<String>,
}

#[derive(Deserialize, Debug)]
pub struct Project {
    pub id: String,
    pub key: String,
    pub name: String,
}

/// represents link relationship between issues
#[derive(Deserialize, Debug)]
pub struct IssueLink {
    pub id: String,
    #[serde(rename = "self")]
    pub self_link: String,
    #[serde(rename = "outwardIssue")]
    pub outward_issue: Option<Issue>,
    #[serde(rename = "inwardIssue")]
    pub inward_issue: Option<Issue>,
    #[serde(rename = "type")]
    pub link_type: LinkType,
}

/// represents type of issue relation
#[derive(Deserialize, Debug)]
pub struct LinkType {
    pub id: String,
    pub inward: String,
    pub name: String,
    pub outward: String,
    #[serde(rename = "self")]
    pub self_link: String,
}

#[derive(Deserialize, Debug)]
pub struct Version {
    pub archived: bool,
    pub id: String,
    pub name: String,
    pub released: bool,
    #[serde(rename = "self")]
    pub self_link: String,
}

#[derive(Deserialize, Debug)]
pub struct User {
    pub active: bool,
    #[serde(rename = "avatarUrls")]
    pub avatar_urls: BTreeMap<String, String>,
    #[serde(rename = "displayName")]
    pub display_name: String,
    #[serde(rename = "emailAddress")]
    pub email_address: String,
    pub key: Option<String>,
    pub name: String,
    #[serde(rename = "self")]
    pub self_link: String,
    #[serde(rename = "timeZone")]
    pub timezone: Option<String>,
}

#[derive(Deserialize, Debug)]
pub struct Status {
    pub description: String,
    #[serde(rename = "iconUrl")]
    pub icon_url: String,
    pub id: String,
    pub name: String,
    #[serde(rename = "self")]
    pub self_link: String,
}

#[derive(Deserialize, Debug)]
pub struct Priority {
    pub icon_url: String,
    pub id: String,
    pub name: String,
    #[serde(rename = "self")]
    pub self_link: String,
}

#[derive(Deserialize, Debug)]
pub struct IssueType {
    pub description: String,
    #[serde(rename = "iconUrl")]
    pub icon_url: String,
    pub id: String,
    pub name: String,
    #[serde(rename = "self")]
    pub self_link: String,
    pub subtask: bool,
}

#[derive(Deserialize, Debug)]
pub struct SearchResults {
    pub total: u64,
    #[serde(rename = "maxResults")]
    pub max_results: u64,
    #[serde(rename = "startAt")]
    pub start_at: u64,
    pub expand: String,
    pub issues: Vec<Issue>,
}

#[derive(Deserialize, Debug)]
pub struct TransitionOption {
    pub id: String,
    pub name: String,
    pub to: TransitionTo,
}

#[derive(Deserialize, Debug)]
pub struct TransitionTo {
    pub name: String,
    pub id: String,
}

/// contains list of options an issue can transitions through
#[derive(Deserialize, Debug)]
pub struct TransitionOptions {
    pub transitions: Vec<TransitionOption>,
}

#[derive(Serialize, Debug)]
pub struct TransitionTriggerOptions {
    pub transition: Transition,
    pub fields: BTreeMap<String, ::serde_json::Value>,
}

impl TransitionTriggerOptions {
    /// creates a new instance
    pub fn new<I>(id: I) -> TransitionTriggerOptions
    where
        I: Into<String>,
    {
        TransitionTriggerOptions {
            transition: Transition { id: id.into() },
            fields: BTreeMap::new(),
        }
    }

    pub fn builder<I>(id: I) -> TransitionTriggerOptionsBuilder
    where
        I: Into<String>,
    {
        TransitionTriggerOptionsBuilder::new(id)
    }
}

pub struct TransitionTriggerOptionsBuilder {
    pub transition: Transition,
    pub fields: BTreeMap<String, ::serde_json::Value>,
}

impl TransitionTriggerOptionsBuilder {
    /// creates a new instance
    pub fn new<I>(id: I) -> TransitionTriggerOptionsBuilder
    where
        I: Into<String>,
    {
        TransitionTriggerOptionsBuilder {
            transition: Transition { id: id.into() },
            fields: BTreeMap::new(),
        }
    }

    /// appends a field to update as part of transition
    pub fn field<N, V>(&mut self, name: N, value: V) -> &mut TransitionTriggerOptionsBuilder
    where
        N: Into<String>,
        V: Serialize,
    {
        self.fields.insert(
            name.into(),
            serde_json::to_value(value).expect("Value to serialize"),
        );
        self
    }

    /// updates resolution in transition
    pub fn resolution<R>(&mut self, name: R) -> &mut TransitionTriggerOptionsBuilder
    where
        R: Into<String>,
    {
        self.field("resolution", Resolution { name: name.into() });
        self
    }

    pub fn build(&self) -> TransitionTriggerOptions {
        TransitionTriggerOptions {
            transition: self.transition.clone(),
            fields: self.fields.clone(),
        }
    }
}

#[derive(Serialize, Debug, Deserialize)]
pub struct Resolution {
    name: String,
}

#[derive(Serialize, Clone, Debug)]
pub struct Transition {
    pub id: String,
}
<|endoftext|>


<commit_before>use std::fmt;
use num::{Float, NumCast};
use channel::{ColorChannel, BoundedChannel, cast};
use approx;

use color;

#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord)]
pub struct Rgb<T> {
    r: BoundedChannel<T>,
    g: BoundedChannel<T>,
    b: BoundedChannel<T>,
}

impl<T: ColorChannel> Rgb<T> {
    #[inline]
    pub fn new() -> Self {
        Rgb{r: BoundedChannel::min(),
            g: BoundedChannel::min(),
            b: BoundedChannel::min()}
    }

    #[inline]
    pub fn from_channels(red: T, green: T, blue: T) -> Self {
        Rgb{r: BoundedChannel::new(red),
            g: BoundedChannel::new(green),
            b: BoundedChannel::new(blue)}
    }

    pub fn broadcast(value: T) -> Self {
        Rgb::from_channels(value.clone(), value.clone(), value.clone())
    }

    pub fn clamp(&self, val: T) -> Self {
        Rgb{
            r: self.r.clone().clamp(val.clone()),
            g: self.g.clone().clamp(val.clone()),
            b: self.b.clone().clamp(val.clone())}
    }

    pub fn invert(&self) -> Self {
        Rgb{
            r: self.r.clone().invert(),
            g: self.g.clone().invert(),
            b: self.b.clone().invert(),
        }
    }

    #[inline]
    pub fn red(&self) -> &T {
        &self.r.0
    }
    #[inline]
    pub fn green(&self) -> &T {
        &self.g.0
    }
    #[inline]
    pub fn blue(&self) -> &T {
        &self.b.0
    }
    #[inline]
    pub fn red_mut(&mut self) -> &mut T {
        &mut self.r.0
    }
    #[inline]
    pub fn green_mut(&mut self) -> &mut T {
        &mut self.g.0
    }
    #[inline]
    pub fn blue_mut(&mut self) -> &mut T {
        &mut self.b.0
    }
    #[inline]
    pub fn red_chan(&self) -> &BoundedChannel<T> {
        &self.r
    }
    #[inline]
    pub fn green_chan(&self) -> &BoundedChannel<T> {
        &self.g
    }
    #[inline]
    pub fn blue_chan(&self) -> &BoundedChannel<T> {
        &self.b
    }

    #[inline]
    pub fn lerp<P>(&self, right: &Self, pos: P) -> Self
            where P: Float + NumCast {
        assert!(pos <= cast(1.0).unwrap() && pos >= cast(0.0).unwrap());
        Rgb{
            r: self.r.lerp(right.r, pos),
            g: self.g.lerp(right.g, pos),
            b: self.b.lerp(right.b, pos)
        }
    }
}

impl<T: ColorChannel + Float + approx::ApproxEq> approx::ApproxEq for Rgb<T>
        where T::Epsilon: Clone {
    type Epsilon = T::Epsilon;

    fn default_epsilon() -> Self::Epsilon {
        T::default_epsilon()
    }

    fn default_max_relative() -> Self::Epsilon {
        T::default_max_relative()
    }

    fn default_max_ulps() -> u32 {
        T::default_max_ulps()
    }

    fn relative_eq(&self, other: &Self, epsilon: Self::Epsilon,
           max_relative: Self::Epsilon) -> bool {
        self.red().relative_eq(other.red(), epsilon.clone(), max_relative.clone())
        && self.green().relative_eq(other.green(), epsilon.clone(), max_relative.clone())
        && self.blue().relative_eq(other.blue(), epsilon, max_relative)
    }

    fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
        self.red().ulps_eq(other.red(), epsilon.clone(), max_ulps)
        && self.green().ulps_eq(other.green(), epsilon.clone(), max_ulps)
        && self.blue().ulps_eq(other.blue(), epsilon.clone(), max_ulps)
    }

}

impl<T: ColorChannel> color::Color3<T> for Rgb<T> {
    fn as_tuple(&self) -> (T, T, T) {
        (self.r.0, self.g.0, self.b.0)
    }

    fn as_array(&self) -> [T; 3] {
        [self.r.0, self.g.0, self.b.0]
    }
}

impl<T: ColorChannel + fmt::Display> fmt::Display for Rgb<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Rgb({}, {}, {})", self.r, self.g, self.b)
    }
}

#[cfg(test)]
mod test {
    use ::rgb::Rgb;
    use ::channel::ColorChannel;

    #[test]
    fn test_construct() {
        {
            let color = Rgb::from_channels(0u8, 0, 0);
            assert_eq!(*color.red(), 0u8);
            assert_eq!(*color.green(), 0u8);
            assert_eq!(*color.blue(), 0u8);

            let c2 = color.clone();
            assert_eq!(color, c2);
        }
        {
            let color: Rgb<u8> = Rgb::new();
            assert_eq!(*color.red(), 0u8);
            assert_eq!(*color.green(), 0u8);
            assert_eq!(*color.blue(), 0u8);
        }
        {
            let color = Rgb::broadcast(0.5_f32);
            assert_ulps_eq!(color, Rgb::from_channels(0.5_f32, 0.5, 0.5));
        }
    }

    #[test]
    fn test_lerp_int() {
        let c1 = Rgb::from_channels(100u8, 200u8, 0u8);
        let c2 = Rgb::from_channels(200u8, 0u8, 255u8);

        assert_eq!(c1.lerp(&c2, 0.5_f64), Rgb::from_channels(150u8, 100, 127));
        assert_eq!(c1.lerp(&c2, 0.0_f64), c1);
        assert_eq!(c1.lerp(&c2, 1.0_f64), c2);
    }

    #[test]
    fn test_lerp_float() {
        let c1 = Rgb::from_channels(0.2_f32, 0.5, 1.0);
        let c2 = Rgb::from_channels(0.8_f32, 0.5, 0.1);

        assert_ulps_eq!(c1.lerp(&c2, 0.5_f32), Rgb::from_channels(0.5_f32, 0.5, 0.55));
        assert_ulps_eq!(c1.lerp(&c2, 0.0_f64), Rgb::from_channels(0.2_f32, 0.5, 1.0));
        assert_ulps_eq!(c1.lerp(&c2, 1.0_f32), Rgb::from_channels(0.8_f32, 0.5, 0.1));
    }

    #[test]
    fn test_invert() {
        let c = Rgb::from_channels(200u8, 0, 255);
        let c2 = Rgb::from_channels(0.8_f32, 0.0, 0.25);

        assert_eq!(c.invert(), Rgb::from_channels(55u8, 255, 0));
        assert_ulps_eq!(c2.invert(), Rgb::from_channels(0.2_f32, 1.0, 0.75));
    }
}
<commit_msg>Added channel_labels method.<commit_after>use std::fmt;
use num::{Float, NumCast};
use channel::{ColorChannel, BoundedChannel, cast};
use approx;

use color;

#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord)]
pub struct Rgb<T> {
    r: BoundedChannel<T>,
    g: BoundedChannel<T>,
    b: BoundedChannel<T>,
}

impl<T: ColorChannel> Rgb<T> {
    #[inline]
    pub fn new() -> Self {
        Rgb{r: BoundedChannel::min(),
            g: BoundedChannel::min(),
            b: BoundedChannel::min()}
    }

    #[inline]
    pub fn from_channels(red: T, green: T, blue: T) -> Self {
        Rgb{r: BoundedChannel::new(red),
            g: BoundedChannel::new(green),
            b: BoundedChannel::new(blue)}
    }

    pub fn broadcast(value: T) -> Self {
        Rgb::from_channels(value.clone(), value.clone(), value.clone())
    }

    pub fn clamp(&self, val: T) -> Self {
        Rgb{
            r: self.r.clone().clamp(val.clone()),
            g: self.g.clone().clamp(val.clone()),
            b: self.b.clone().clamp(val.clone())}
    }

    pub fn invert(&self) -> Self {
        Rgb{
            r: self.r.clone().invert(),
            g: self.g.clone().invert(),
            b: self.b.clone().invert(),
        }
    }

    #[inline]
    pub fn red(&self) -> &T {
        &self.r.0
    }
    #[inline]
    pub fn green(&self) -> &T {
        &self.g.0
    }
    #[inline]
    pub fn blue(&self) -> &T {
        &self.b.0
    }
    #[inline]
    pub fn red_mut(&mut self) -> &mut T {
        &mut self.r.0
    }
    #[inline]
    pub fn green_mut(&mut self) -> &mut T {
        &mut self.g.0
    }
    #[inline]
    pub fn blue_mut(&mut self) -> &mut T {
        &mut self.b.0
    }
    #[inline]
    pub fn red_chan(&self) -> &BoundedChannel<T> {
        &self.r
    }
    #[inline]
    pub fn green_chan(&self) -> &BoundedChannel<T> {
        &self.g
    }
    #[inline]
    pub fn blue_chan(&self) -> &BoundedChannel<T> {
        &self.b
    }

    #[inline]
    pub fn lerp<P>(&self, right: &Self, pos: P) -> Self
            where P: Float + NumCast {
        assert!(pos <= cast(1.0).unwrap() && pos >= cast(0.0).unwrap());
        Rgb{
            r: self.r.lerp(right.r, pos),
            g: self.g.lerp(right.g, pos),
            b: self.b.lerp(right.b, pos)
        }
    }

    pub fn channel_labels(&self) -> &'static str {
        "rgb"
    }
}

impl<T: ColorChannel + Float + approx::ApproxEq> approx::ApproxEq for Rgb<T>
        where T::Epsilon: Clone {
    type Epsilon = T::Epsilon;

    fn default_epsilon() -> Self::Epsilon {
        T::default_epsilon()
    }

    fn default_max_relative() -> Self::Epsilon {
        T::default_max_relative()
    }

    fn default_max_ulps() -> u32 {
        T::default_max_ulps()
    }

    fn relative_eq(&self, other: &Self, epsilon: Self::Epsilon,
           max_relative: Self::Epsilon) -> bool {
        self.red().relative_eq(other.red(), epsilon.clone(), max_relative.clone())
        && self.green().relative_eq(other.green(), epsilon.clone(), max_relative.clone())
        && self.blue().relative_eq(other.blue(), epsilon, max_relative)
    }

    fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
        self.red().ulps_eq(other.red(), epsilon.clone(), max_ulps)
        && self.green().ulps_eq(other.green(), epsilon.clone(), max_ulps)
        && self.blue().ulps_eq(other.blue(), epsilon.clone(), max_ulps)
    }

}

impl<T: ColorChannel> color::Color3<T> for Rgb<T> {
    fn as_tuple(&self) -> (T, T, T) {
        (self.r.0, self.g.0, self.b.0)
    }

    fn as_array(&self) -> [T; 3] {
        [self.r.0, self.g.0, self.b.0]
    }
}

impl<T: ColorChannel + fmt::Display> fmt::Display for Rgb<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Rgb({}, {}, {})", self.r, self.g, self.b)
    }
}

#[cfg(test)]
mod test {
    use ::rgb::Rgb;
    use ::channel::ColorChannel;

    #[test]
    fn test_construct() {
        {
            let color = Rgb::from_channels(0u8, 0, 0);
            assert_eq!(*color.red(), 0u8);
            assert_eq!(*color.green(), 0u8);
            assert_eq!(*color.blue(), 0u8);

            let c2 = color.clone();
            assert_eq!(color, c2);
        }
        {
            let color: Rgb<u8> = Rgb::new();
            assert_eq!(*color.red(), 0u8);
            assert_eq!(*color.green(), 0u8);
            assert_eq!(*color.blue(), 0u8);
        }
        {
            let color = Rgb::broadcast(0.5_f32);
            assert_ulps_eq!(color, Rgb::from_channels(0.5_f32, 0.5, 0.5));
        }
    }

    #[test]
    fn test_lerp_int() {
        let c1 = Rgb::from_channels(100u8, 200u8, 0u8);
        let c2 = Rgb::from_channels(200u8, 0u8, 255u8);

        assert_eq!(c1.lerp(&c2, 0.5_f64), Rgb::from_channels(150u8, 100, 127));
        assert_eq!(c1.lerp(&c2, 0.0_f64), c1);
        assert_eq!(c1.lerp(&c2, 1.0_f64), c2);
    }

    #[test]
    fn test_lerp_float() {
        let c1 = Rgb::from_channels(0.2_f32, 0.5, 1.0);
        let c2 = Rgb::from_channels(0.8_f32, 0.5, 0.1);

        assert_ulps_eq!(c1.lerp(&c2, 0.5_f32), Rgb::from_channels(0.5_f32, 0.5, 0.55));
        assert_ulps_eq!(c1.lerp(&c2, 0.0_f64), Rgb::from_channels(0.2_f32, 0.5, 1.0));
        assert_ulps_eq!(c1.lerp(&c2, 1.0_f32), Rgb::from_channels(0.8_f32, 0.5, 0.1));
    }

    #[test]
    fn test_invert() {
        let c = Rgb::from_channels(200u8, 0, 255);
        let c2 = Rgb::from_channels(0.8_f32, 0.0, 0.25);

        assert_eq!(c.invert(), Rgb::from_channels(55u8, 255, 0));
        assert_ulps_eq!(c2.invert(), Rgb::from_channels(0.2_f32, 1.0, 0.75));
    }
}
<|endoftext|>


<commit_before>use crate::cli::{clear_screen, Args};
use crate::error::{Error, Result};
use crate::gitignore;
use crate::ignore;
use crate::notification_filter::NotificationFilter;
use crate::pathop::PathOp;
use crate::process::{self, Process};
use crate::signal::{self, Signal};
use crate::watcher::{Event, Watcher};
use std::{
    collections::HashMap,
    fs::canonicalize,
    io::Write,
    sync::{
        mpsc::{channel, Receiver},
        Arc, RwLock,
    },
    time::Duration,
};

fn init_logger(debug: bool) {
    let mut log_builder = env_logger::Builder::new();
    let level = if debug {
        log::LevelFilter::Debug
    } else {
        log::LevelFilter::Warn
    };

    log_builder
        .format(|buf, r| writeln!(buf, "*** {}", r.args()))
        .filter(None, level)
        .init();
}

pub trait Handler {
    /// Called through a manual request, such as an initial run.
    ///
    /// # Returns
    ///
    /// A `Result` which means:
    ///
    /// - `Err`: an error has occurred while processing, quit.
    /// - `Ok(true)`: everything is fine and the loop can continue.
    /// - `Ok(false)`: everything is fine but we should gracefully stop.
    fn on_manual(&self) -> Result<bool>;

    /// Called through a file-update request.
    ///
    /// # Parameters
    ///
    /// - `ops`: The list of events that triggered this update.
    ///
    /// # Returns
    ///
    /// A `Result` which means:
    ///
    /// - `Err`: an error has occurred while processing, quit.
    /// - `Ok(true)`: everything is fine and the loop can continue.
    /// - `Ok(false)`: everything is fine but we should gracefully stop.
    fn on_update(&self, ops: &[PathOp]) -> Result<bool>;

    /// Called once by `watch` at the very start.
    ///
    /// Not called again; any changes will never be picked up.
    ///
    /// The `Args` instance should be created using `ArgsBuilder` rather than direct initialisation
    /// to resist potential breaking changes (see semver policy on crate root).
    fn args(&self) -> Args;
}

/// Starts watching, and calls a handler when something happens.
///
/// Given an argument structure and a `Handler` type, starts the watcher loop, blocking until done.
pub fn watch<H>(handler: &H) -> Result<()>
where
    H: Handler,
{
    let args = handler.args();
    init_logger(args.debug);

    let mut paths = vec![];
    for path in &args.paths {
        paths.push(
            canonicalize(&path)
                .map_err(|e| Error::Canonicalization(path.to_string_lossy().into_owned(), e))?,
        );
    }

    let ignore = ignore::load(if args.no_ignore { &[] } else { &paths });
    let gitignore = gitignore::load(if args.no_vcs_ignore || args.no_ignore {
        &[]
    } else {
        &paths
    });
    let filter = NotificationFilter::new(&args.filters, &args.ignores, gitignore, ignore)?;

    let (tx, rx) = channel();
    let poll = args.poll;
    #[cfg(target_os = "linux")]
    let poll_interval = args.poll_interval;
    #[allow(clippy::redundant_clone)]
    let watcher = Watcher::new(tx.clone(), &paths, args.poll, args.poll_interval).or_else(|err| {
        if poll {
            return Err(err);
        }

        #[cfg(target_os = "linux")]
        {
            use nix::libc;
            let mut fallback = false;
            if let notify::Error::Io(ref e) = err {
                if e.raw_os_error() == Some(libc::ENOSPC) {
                    warn!("System notification limit is too small, falling back to polling mode. For better performance increase system limit:\n\tsysctl fs.inotify.max_user_watches=524288");
                    fallback = true;
                }
            }

            if fallback {
                return Watcher::new(tx, &paths, true, poll_interval);
            }
        }

        Err(err)
    })?;

    if watcher.is_polling() {
        warn!("Polling for changes every {} ms", args.poll_interval);
    }

    // Call handler initially, if necessary
    if args.run_initially && !handler.on_manual()? {
        return Ok(());
    }

    loop {
        debug!("Waiting for filesystem activity");
        let paths = wait_fs(&rx, &filter, args.debounce);
        debug!("Paths updated: {:?}", paths);

        if !handler.on_update(&paths)? {
            break;
        }
    }

    Ok(())
}

pub struct ExecHandler {
    args: Args,
    signal: Option<Signal>,
    child_process: Arc<RwLock<Option<Process>>>,
}

impl ExecHandler {
    pub fn new(args: Args) -> Result<Self> {
        let child_process: Arc<RwLock<Option<Process>>> = Arc::new(RwLock::new(None));
        let weak_child = Arc::downgrade(&child_process);

        // Convert signal string to the corresponding integer
        let signal = signal::new(args.signal.clone());

        signal::install_handler(move |sig: Signal| {
            if let Some(lock) = weak_child.upgrade() {
                let strong = lock.read().expect("poisoned lock in install_handler");
                if let Some(ref child) = *strong {
                    match sig {
                        Signal::SIGCHLD => child.reap(), // SIGCHLD is special, initiate reap()
                        _ => child.signal(sig),
                    }
                }
            }
        });

        Ok(Self {
            args,
            signal,
            child_process,
        })
    }

    fn spawn(&self, ops: &[PathOp]) -> Result<()> {
        if self.args.clear_screen {
            clear_screen();
        }

        debug!("Launching child process");
        let mut guard = self.child_process.write()?;
        *guard = Some(process::spawn(&self.args.cmd, ops, self.args.no_shell)?);

        Ok(())
    }

    pub fn has_running_process(&self) -> bool {
        let guard = self
            .child_process
            .read()
            .expect("poisoned lock in has_running_process");

        if let Some(ref _child) = *guard {
            return true;
        }

        false
    }
}

impl Handler for ExecHandler {
    fn args(&self) -> Args {
        self.args.clone()
    }

    // Only returns Err() on lock poisoning.
    fn on_manual(&self) -> Result<bool> {
        if self.args.once {
            return Ok(true);
        }

        self.spawn(&[])?;
        Ok(true)
    }

    // Only returns Err() on lock poisoning.
    fn on_update(&self, ops: &[PathOp]) -> Result<bool> {
        // We have four scenarios here:
        //
        // 1. Send a specified signal to the child, wait for it to exit, then run the command again
        // 2. Send SIGTERM to the child, wait for it to exit, then run the command again
        // 3. Just send a specified signal to the child, do nothing more
        // 4. Make sure the previous run was ended, then run the command again
        //
        let scenario = (
            self.args.restart,
            self.signal.is_some(),
            self.args.watch_when_idle,
        );
        let running_process = self.has_running_process();

        match scenario {
            // SIGHUP scenario: --signal was given, but --restart was not
            // Just send a signal (e.g. SIGHUP) to the child, do nothing more
            (false, true, _) => signal_process(&self.child_process, self.signal, false),

            // Spawn a process when there are no running processes in the background
            (_, _, true) => {
                if !running_process {
                    self.spawn(ops)?;
                }
            }

            // Custom restart behaviour (--restart was given, and --signal specified):
            // Send specified signal to the child, wait for it to exit, then run the command again
            (true, true, false) => {
                signal_process(&self.child_process, self.signal, true);
                self.spawn(ops)?;
            }

            // Default restart behaviour (--restart was given, but --signal wasn't specified):
            // Send SIGTERM to the child, wait for it to exit, then run the command again
            (true, false, false) => {
                let sigterm = signal::new(Some("SIGTERM".into()));

                signal_process(&self.child_process, sigterm, true);
                self.spawn(ops)?;
            }

            // Default behaviour (neither --signal nor --restart specified):
            // Make sure the previous run was ended, then run the command again
            (false, false, false) => {
                signal_process(&self.child_process, None, true);
                self.spawn(ops)?;
            }
        }

        // Handle once option for integration testing
        if self.args.once {
            signal_process(&self.child_process, self.signal, false);
            return Ok(false);
        }

        Ok(true)
    }
}

pub fn run(args: Args) -> Result<()> {
    watch(&ExecHandler::new(args)?)
}

fn wait_fs(rx: &Receiver<Event>, filter: &NotificationFilter, debounce: u64) -> Vec<PathOp> {
    let mut paths = Vec::new();
    let mut cache = HashMap::new();

    loop {
        let e = rx.recv().expect("error when reading event");

        if let Some(ref path) = e.path {
            let pathop = PathOp::new(path, e.op.ok(), e.cookie);
            // Ignore cache for the initial file. Otherwise, in
            // debug mode it's hard to track what's going on
            let excluded = filter.is_excluded(path);
            if !cache.contains_key(&pathop) {
                cache.insert(pathop.clone(), excluded);
            }

            if !excluded {
                paths.push(pathop);
                break;
            }
        }
    }

    // Wait for filesystem activity to cool off
    let timeout = Duration::from_millis(debounce);
    while let Ok(e) = rx.recv_timeout(timeout) {
        if let Some(ref path) = e.path {
            let pathop = PathOp::new(path, e.op.ok(), e.cookie);
            if cache.contains_key(&pathop) {
                continue;
            }

            let excluded = filter.is_excluded(path);

            cache.insert(pathop.clone(), excluded);

            if !excluded {
                paths.push(pathop);
            }
        }
    }

    paths
}

// signal_process sends signal to process. It waits for the process to exit if wait is true
fn signal_process(process: &RwLock<Option<Process>>, signal: Option<Signal>, wait: bool) {
    let guard = process.read().expect("poisoned lock in signal_process");

    if let Some(ref child) = *guard {
        if let Some(s) = signal {
            child.signal(s);
        }

        if wait {
            debug!("Waiting for process to exit...");
            child.wait();
        }
    }
}
<commit_msg>Adding missed details<commit_after>use crate::cli::{clear_screen, Args};
use crate::error::{Error, Result};
use crate::gitignore;
use crate::ignore;
use crate::notification_filter::NotificationFilter;
use crate::pathop::PathOp;
use crate::process::{self, Process};
use crate::signal::{self, Signal};
use crate::watcher::{Event, Watcher};
use std::{
    collections::HashMap,
    fs::canonicalize,
    io::Write,
    sync::{
        mpsc::{channel, Receiver},
        Arc, RwLock,
    },
    time::Duration,
};

fn init_logger(debug: bool) {
    let mut log_builder = env_logger::Builder::new();
    let level = if debug {
        log::LevelFilter::Debug
    } else {
        log::LevelFilter::Warn
    };

    log_builder
        .format(|buf, r| writeln!(buf, "*** {}", r.args()))
        .filter(None, level)
        .init();
}

pub trait Handler {
    /// Called through a manual request, such as an initial run.
    ///
    /// # Returns
    ///
    /// A `Result` which means:
    ///
    /// - `Err`: an error has occurred while processing, quit.
    /// - `Ok(true)`: everything is fine and the loop can continue.
    /// - `Ok(false)`: everything is fine but we should gracefully stop.
    fn on_manual(&self) -> Result<bool>;

    /// Called through a file-update request.
    ///
    /// # Parameters
    ///
    /// - `ops`: The list of events that triggered this update.
    ///
    /// # Returns
    ///
    /// A `Result` which means:
    ///
    /// - `Err`: an error has occurred while processing, quit.
    /// - `Ok(true)`: everything is fine and the loop can continue.
    /// - `Ok(false)`: everything is fine but we should gracefully stop.
    fn on_update(&self, ops: &[PathOp]) -> Result<bool>;

    /// Called once by `watch` at the very start.
    ///
    /// Not called again; any changes will never be picked up.
    ///
    /// The `Args` instance should be created using `ArgsBuilder` rather than direct initialisation
    /// to resist potential breaking changes (see semver policy on crate root).
    fn args(&self) -> Args;
}

/// Starts watching, and calls a handler when something happens.
///
/// Given an argument structure and a `Handler` type, starts the watcher loop, blocking until done.
pub fn watch<H>(handler: &H) -> Result<()>
where
    H: Handler,
{
    let args = handler.args();
    init_logger(args.debug);

    let mut paths = vec![];
    for path in &args.paths {
        paths.push(
            canonicalize(&path)
                .map_err(|e| Error::Canonicalization(path.to_string_lossy().into_owned(), e))?,
        );
    }

    let ignore = ignore::load(if args.no_ignore { &[] } else { &paths });
    let gitignore = gitignore::load(if args.no_vcs_ignore || args.no_ignore {
        &[]
    } else {
        &paths
    });
    let filter = NotificationFilter::new(&args.filters, &args.ignores, gitignore, ignore)?;

    let (tx, rx) = channel();
    let poll = args.poll;
    #[cfg(target_os = "linux")]
    let poll_interval = args.poll_interval;
    #[allow(clippy::redundant_clone)]
    let watcher = Watcher::new(tx.clone(), &paths, args.poll, args.poll_interval).or_else(|err| {
        if poll {
            return Err(err);
        }

        #[cfg(target_os = "linux")]
        {
            use nix::libc;
            let mut fallback = false;
            if let notify::Error::Io(ref e) = err {
                if e.raw_os_error() == Some(libc::ENOSPC) {
                    warn!("System notification limit is too small, falling back to polling mode. For better performance increase system limit:\n\tsysctl fs.inotify.max_user_watches=524288");
                    fallback = true;
                }
            }

            if fallback {
                return Watcher::new(tx, &paths, true, poll_interval);
            }
        }

        Err(err)
    })?;

    if watcher.is_polling() {
        warn!("Polling for changes every {} ms", args.poll_interval);
    }

    // Call handler initially, if necessary
    if args.run_initially && !handler.on_manual()? {
        return Ok(());
    }

    loop {
        debug!("Waiting for filesystem activity");
        let paths = wait_fs(&rx, &filter, args.debounce);
        debug!("Paths updated: {:?}", paths);

        if !handler.on_update(&paths)? {
            break;
        }
    }

    Ok(())
}

pub struct ExecHandler {
    args: Args,
    signal: Option<Signal>,
    child_process: Arc<RwLock<Option<Process>>>,
}

impl ExecHandler {
    pub fn new(args: Args) -> Result<Self> {
        let child_process: Arc<RwLock<Option<Process>>> = Arc::new(RwLock::new(None));
        let weak_child = Arc::downgrade(&child_process);

        // Convert signal string to the corresponding integer
        let signal = signal::new(args.signal.clone());

        signal::install_handler(move |sig: Signal| {
            if let Some(lock) = weak_child.upgrade() {
                let strong = lock.read().expect("poisoned lock in install_handler");
                if let Some(ref child) = *strong {
                    match sig {
                        Signal::SIGCHLD => child.reap(), // SIGCHLD is special, initiate reap()
                        _ => child.signal(sig),
                    }
                }
            }
        });

        Ok(Self {
            args,
            signal,
            child_process,
        })
    }

    fn spawn(&self, ops: &[PathOp]) -> Result<()> {
        if self.args.clear_screen {
            clear_screen();
        }

        debug!("Launching child process");
        let mut guard = self.child_process.write()?;
        *guard = Some(process::spawn(&self.args.cmd, ops, self.args.no_shell)?);

        Ok(())
    }

    pub fn has_running_process(&self) -> bool {
        let guard = self
            .child_process
            .read()
            .expect("poisoned lock in has_running_process");

        (*guard).is_some()
    }
}

impl Handler for ExecHandler {
    fn args(&self) -> Args {
        self.args.clone()
    }

    // Only returns Err() on lock poisoning.
    fn on_manual(&self) -> Result<bool> {
        if self.args.once {
            return Ok(true);
        }

        self.spawn(&[])?;
        Ok(true)
    }

    // Only returns Err() on lock poisoning.
    fn on_update(&self, ops: &[PathOp]) -> Result<bool> {
        // We have four scenarios here:
        //
        // 1. Just send a specified signal to the child, do nothing more
        // 2. Just spawn a process if there are no running processes in the background
        // 3. Send a specified signal to the child, wait for it to exit, then run the command again
        // 4. Send SIGTERM to the child, wait for it to exit, then run the command again
        // 5. Make sure the previous run was ended, then run the command again
        //
        let scenario = (
            self.args.restart,
            self.signal.is_some(),
            self.args.watch_when_idle,
        );
        let running_process = self.has_running_process();

        match scenario {
            // SIGHUP scenario: --signal was given, but --restart was not
            // Just send a signal (e.g. SIGHUP) to the child, do nothing more
            (false, true, _) => signal_process(&self.child_process, self.signal, false),

            // Spawn a process when there are no running processes in the background
            (_, _, true) => {
                if !running_process {
                    self.spawn(ops)?;
                }
            }

            // Custom restart behaviour (--restart was given, and --signal specified):
            // Send specified signal to the child, wait for it to exit, then run the command again
            (true, true, false) => {
                signal_process(&self.child_process, self.signal, true);
                self.spawn(ops)?;
            }

            // Default restart behaviour (--restart was given, but --signal wasn't specified):
            // Send SIGTERM to the child, wait for it to exit, then run the command again
            (true, false, false) => {
                let sigterm = signal::new(Some("SIGTERM".into()));

                signal_process(&self.child_process, sigterm, true);
                self.spawn(ops)?;
            }

            // Default behaviour (neither --signal nor --restart specified):
            // Make sure the previous run was ended, then run the command again
            (false, false, false) => {
                signal_process(&self.child_process, None, true);
                self.spawn(ops)?;
            }
        }

        // Handle once option for integration testing
        if self.args.once {
            signal_process(&self.child_process, self.signal, false);
            return Ok(false);
        }

        Ok(true)
    }
}

pub fn run(args: Args) -> Result<()> {
    watch(&ExecHandler::new(args)?)
}

fn wait_fs(rx: &Receiver<Event>, filter: &NotificationFilter, debounce: u64) -> Vec<PathOp> {
    let mut paths = Vec::new();
    let mut cache = HashMap::new();

    loop {
        let e = rx.recv().expect("error when reading event");

        if let Some(ref path) = e.path {
            let pathop = PathOp::new(path, e.op.ok(), e.cookie);
            // Ignore cache for the initial file. Otherwise, in
            // debug mode it's hard to track what's going on
            let excluded = filter.is_excluded(path);
            if !cache.contains_key(&pathop) {
                cache.insert(pathop.clone(), excluded);
            }

            if !excluded {
                paths.push(pathop);
                break;
            }
        }
    }

    // Wait for filesystem activity to cool off
    let timeout = Duration::from_millis(debounce);
    while let Ok(e) = rx.recv_timeout(timeout) {
        if let Some(ref path) = e.path {
            let pathop = PathOp::new(path, e.op.ok(), e.cookie);
            if cache.contains_key(&pathop) {
                continue;
            }

            let excluded = filter.is_excluded(path);

            cache.insert(pathop.clone(), excluded);

            if !excluded {
                paths.push(pathop);
            }
        }
    }

    paths
}

// signal_process sends signal to process. It waits for the process to exit if wait is true
fn signal_process(process: &RwLock<Option<Process>>, signal: Option<Signal>, wait: bool) {
    let guard = process.read().expect("poisoned lock in signal_process");

    if let Some(ref child) = *guard {
        if let Some(s) = signal {
            child.signal(s);
        }

        if wait {
            debug!("Waiting for process to exit...");
            child.wait();
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>min and max for f64 helpers<commit_after><|endoftext|>


<commit_before>//! Library to read and write protocol buffers data.

// TODO: add docs
//#![deny(missing_docs)]

#![cfg_attr(rustc_nightly, feature(specialization))]

#[cfg(feature = "bytes")]
extern crate bytes;
#[cfg(feature = "with-serde")]
extern crate serde;
#[macro_use]
#[cfg(feature = "with-serde")]

extern crate serde_derive;
pub use crate::clear::Clear;
pub use crate::core::parse_from_bytes;
#[cfg(feature = "bytes")]
pub use crate::core::parse_from_carllerche_bytes;
pub use crate::core::parse_from_reader;
pub use crate::core::Message;
pub use crate::enums::ProtobufEnum;
pub use crate::enums::ProtobufEnumOrUnknown;
pub use crate::oneof::Oneof;
pub use crate::repeated::RepeatedField;
pub use crate::singular::SingularField;
pub use crate::singular::SingularPtrField;
pub use crate::stream::CodedInputStream;
pub use crate::stream::CodedOutputStream;
pub use crate::unknown::UnknownFields;
pub use crate::unknown::UnknownFieldsIter;
pub use crate::unknown::UnknownValue;
pub use crate::unknown::UnknownValueRef;
pub use crate::unknown::UnknownValues;
pub use crate::unknown::UnknownValuesIter;
pub mod wire_format;
pub use cached_size::CachedSize;
#[cfg(feature = "bytes")]
pub use crate::chars::Chars;
pub use crate::error::ProtobufError;
pub use crate::error::ProtobufResult;

pub use crate::reflect::types;

// generated
pub mod descriptor;
// TODO: move plugin to mod codegen
pub mod plugin;
pub mod rustproto;

mod clear;
mod core;
mod enums;
pub mod error;
pub mod ext;
pub mod json;
mod lazy;
mod oneof;
pub mod prelude;
pub mod reflect;
mod repeated;
pub mod rt;
mod singular;
mod stream;
pub mod text_format;
pub mod well_known_types;

// used by test
#[cfg(test)]
#[path = "../../protobuf-test-common/src/hex.rs"]
mod hex;

mod cached_size;
mod chars;
mod paginate;
mod unknown;
mod varint;
mod zigzag;

mod misc;

mod buf_read_iter;
mod buf_read_or_reader;
<commit_msg>Make mod error private, ProtobufError is reexported anyway<commit_after>//! Library to read and write protocol buffers data.

// TODO: add docs
//#![deny(missing_docs)]

#![cfg_attr(rustc_nightly, feature(specialization))]

#[cfg(feature = "bytes")]
extern crate bytes;
#[cfg(feature = "with-serde")]
extern crate serde;
#[macro_use]
#[cfg(feature = "with-serde")]

extern crate serde_derive;
pub use crate::clear::Clear;
pub use crate::core::parse_from_bytes;
#[cfg(feature = "bytes")]
pub use crate::core::parse_from_carllerche_bytes;
pub use crate::core::parse_from_reader;
pub use crate::core::Message;
pub use crate::enums::ProtobufEnum;
pub use crate::enums::ProtobufEnumOrUnknown;
pub use crate::oneof::Oneof;
pub use crate::repeated::RepeatedField;
pub use crate::singular::SingularField;
pub use crate::singular::SingularPtrField;
pub use crate::stream::CodedInputStream;
pub use crate::stream::CodedOutputStream;
pub use crate::unknown::UnknownFields;
pub use crate::unknown::UnknownFieldsIter;
pub use crate::unknown::UnknownValue;
pub use crate::unknown::UnknownValueRef;
pub use crate::unknown::UnknownValues;
pub use crate::unknown::UnknownValuesIter;
pub mod wire_format;
pub use cached_size::CachedSize;
#[cfg(feature = "bytes")]
pub use crate::chars::Chars;
pub use crate::error::ProtobufError;
pub use crate::error::ProtobufResult;

pub use crate::reflect::types;

// generated
pub mod descriptor;
// TODO: move plugin to mod codegen
pub mod plugin;
pub mod rustproto;

mod clear;
mod core;
mod enums;
mod error;
pub mod ext;
pub mod json;
mod lazy;
mod oneof;
pub mod prelude;
pub mod reflect;
mod repeated;
pub mod rt;
mod singular;
mod stream;
pub mod text_format;
pub mod well_known_types;

// used by test
#[cfg(test)]
#[path = "../../protobuf-test-common/src/hex.rs"]
mod hex;

mod cached_size;
mod chars;
mod paginate;
mod unknown;
mod varint;
mod zigzag;

mod misc;

mod buf_read_iter;
mod buf_read_or_reader;
<|endoftext|>


<commit_before>#![cfg(test)]

/// Creates an instance or returns if initialization fails.
macro_rules! instance {
    () => ({
        use instance;

        let app = instance::ApplicationInfo {
            application_name: "vulkano tests", application_version: 1,
            engine_name: "vulkano tests", engine_version: 1
        };

        match instance::Instance::new(Some(&app), None) {
            Ok(i) => i,
            Err(_) => return
        }
    })
}

/// Creates a device and a queue for graphics operations.
macro_rules! gfx_dev_and_queue {
    () => ({
        use instance;
        use device::Device;

        let instance = instance!();

        let physical = instance::PhysicalDevice::enumerate(&instance)
                            .next().expect("no device available");

        let queue = physical.queue_families().find(|q| q.supports_graphics())
                                                .expect("couldn't find a graphical queue family");

        let (device, queues) = Device::new(&physical, physical.supported_features(),
                                                        [(queue, 0.5)].iter().cloned(), None)
                                                                .expect("failed to create device");
        (device, queues.into_iter().next().unwrap())
    })
}
<commit_msg>Ignore tests if failure to initialize<commit_after>#![cfg(test)]

/// Creates an instance or returns if initialization fails.
macro_rules! instance {
    () => ({
        use instance;

        let app = instance::ApplicationInfo {
            application_name: "vulkano tests", application_version: 1,
            engine_name: "vulkano tests", engine_version: 1
        };

        match instance::Instance::new(Some(&app), None) {
            Ok(i) => i,
            Err(_) => return
        }
    })
}

/// Creates a device and a queue for graphics operations.
macro_rules! gfx_dev_and_queue {
    () => ({
        use instance;
        use device::Device;

        let instance = instance!();

        let physical = match instance::PhysicalDevice::enumerate(&instance).next() {
            Some(p) => p,
            None => return
        };

        let queue = match physical.queue_families().find(|q| q.supports_graphics()) {
            Some(q) => q,
            None => return
        };

        let (device, queues) = match Device::new(&physical, physical.supported_features(),
                                                 [(queue, 0.5)].iter().cloned(), None)
        {
            Ok(r) => r,
            Err(_) => return
        };

        (device, queues.into_iter().next().unwrap())
    })
}
<|endoftext|>


<commit_before>
use ndarray::*;

use super::error::*;
use super::layout::*;
use impl2::LapackScalar;

pub trait SVD<U, S, VT> {
    fn svd(self, calc_u: bool, calc_vt: bool) -> Result<(Option<U>, S, Option<VT>)>;
}

impl<A, S, Su, Svt, Ss> SVD<ArrayBase<Su, Ix2>, ArrayBase<Ss, Ix1>, ArrayBase<Svt, Ix2>> for ArrayBase<S, Ix2>
    where A: LapackScalar,
          S: DataMut<Elem = A>,
          Su: DataOwned<Elem = A>,
          Svt: DataOwned<Elem = A>,
          Ss: DataOwned<Elem = A::Real>
{
    fn svd(mut self,
           calc_u: bool,
           calc_vt: bool)
           -> Result<(Option<ArrayBase<Su, Ix2>>, ArrayBase<Ss, Ix1>, Option<ArrayBase<Svt, Ix2>>)> {
        let l = self.layout()?;
        let svd_res = A::svd(l, calc_u, calc_vt, self.as_allocated_mut()?)?;
        let (n, m) = l.size();
        let u = svd_res.u.map(|u| reconstruct(l.resized(n, n), u).unwrap());
        let vt = svd_res.vt.map(|vt| reconstruct(l.resized(m, m), vt).unwrap());
        let s = ArrayBase::from_vec(svd_res.s);
        Ok((u, s, vt))
    }
}
<commit_msg>Add SVD impl for &ArrayBase, &mut ArrayBase<commit_after>
use ndarray::*;

use super::error::*;
use super::layout::*;
use impl2::LapackScalar;

pub trait SVD<U, S, VT> {
    fn svd(self, calc_u: bool, calc_vt: bool) -> Result<(Option<U>, S, Option<VT>)>;
}

impl<A, S, Su, Svt, Ss> SVD<ArrayBase<Su, Ix2>, ArrayBase<Ss, Ix1>, ArrayBase<Svt, Ix2>> for ArrayBase<S, Ix2>
    where A: LapackScalar,
          S: DataMut<Elem = A>,
          Su: DataOwned<Elem = A>,
          Svt: DataOwned<Elem = A>,
          Ss: DataOwned<Elem = A::Real>
{
    fn svd(mut self,
           calc_u: bool,
           calc_vt: bool)
           -> Result<(Option<ArrayBase<Su, Ix2>>, ArrayBase<Ss, Ix1>, Option<ArrayBase<Svt, Ix2>>)> {
        (&mut self).svd(calc_u, calc_vt)
    }
}

impl<'a, A, S, Su, Svt, Ss> SVD<ArrayBase<Su, Ix2>, ArrayBase<Ss, Ix1>, ArrayBase<Svt, Ix2>> for &'a ArrayBase<S, Ix2>
    where A: LapackScalar + Clone,
          S: Data<Elem = A>,
          Su: DataOwned<Elem = A>,
          Svt: DataOwned<Elem = A>,
          Ss: DataOwned<Elem = A::Real>
{
    fn svd(self,
           calc_u: bool,
           calc_vt: bool)
           -> Result<(Option<ArrayBase<Su, Ix2>>, ArrayBase<Ss, Ix1>, Option<ArrayBase<Svt, Ix2>>)> {
        let a = self.to_owned();
        a.svd(calc_u, calc_vt)
    }
}

impl<'a, A, S, Su, Svt, Ss> SVD<ArrayBase<Su, Ix2>, ArrayBase<Ss, Ix1>, ArrayBase<Svt, Ix2>>
    for &'a mut ArrayBase<S, Ix2>
    where A: LapackScalar,
          S: DataMut<Elem = A>,
          Su: DataOwned<Elem = A>,
          Svt: DataOwned<Elem = A>,
          Ss: DataOwned<Elem = A::Real>
{
    fn svd(mut self,
           calc_u: bool,
           calc_vt: bool)
           -> Result<(Option<ArrayBase<Su, Ix2>>, ArrayBase<Ss, Ix1>, Option<ArrayBase<Svt, Ix2>>)> {
        let l = self.layout()?;
        let svd_res = A::svd(l, calc_u, calc_vt, self.as_allocated_mut()?)?;
        let (n, m) = l.size();
        let u = svd_res.u.map(|u| reconstruct(l.resized(n, n), u).unwrap());
        let vt = svd_res.vt.map(|vt| reconstruct(l.resized(m, m), vt).unwrap());
        let s = ArrayBase::from_vec(svd_res.s);
        Ok((u, s, vt))
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2019 Miklos Vajna. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

extern crate reqwest;
extern crate serde_json;
extern crate url;

use std::io::Write;

type BoxResult<T> = Result<T, Box<std::error::Error>>;

#[derive(Debug)]
struct OsmifyError {
    details: String
}

impl OsmifyError {
    fn new(msg: &str) -> OsmifyError {
        OsmifyError{details: msg.to_string()}
    }
}

impl std::fmt::Display for OsmifyError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}", self.details)
    }
}

impl std::error::Error for OsmifyError {
    fn description(&self) -> &str {
        &self.details
    }
}

fn query_turbo(query: &str) -> BoxResult<String> {
    let url = "http://overpass-api.de/api/interpreter";

    let client = reqwest::Client::new();
    let body = String::from(query);
    let mut buf = client.post(url)
        .body(body)
        .send()?;
    Ok(buf.text()?)
}

fn query_nominatim(query: &str) -> BoxResult<String> {
    let prefix = "http://nominatim.openstreetmap.org/search.php?";
    let encoded: String = url::form_urlencoded::Serializer::new(String::new())
        .append_pair("q", query)
        .append_pair("format", "json")
        .finish();
    let url = format!("{}{}", prefix, encoded);

    let mut buf = reqwest::get(url.as_str())?;

    Ok(buf.text()?)
}

fn osmify(query: &str) -> BoxResult<String> {
    let nominatim = query_nominatim(query)?;
    let json: serde_json::Value = match serde_json::from_str(&nominatim) {
        Ok(value) => value,
        Err(error) => {
            return Err(Box::new(OsmifyError::new(&format!("Failed to parse JSON from nominatim: {:?}", error))));
        },
    };
    let mut elements = json.as_array().ok_or("option::NoneError")?.clone();
    if elements.is_empty() {
        return Err(Box::new(OsmifyError::new("No results from nominatim")));
    }

    if elements.len() > 1 {
        // There are multiple elements, prefer buildings if possible.
        let buildings: Vec<serde_json::Value> = elements.iter().filter(|i| {
            let i = match i.as_object() {
                Some(value) => value,
                None => return false,
            };
            let class = match i.get("class") {
                Some(value) => value.as_str(),
                None => return false,
            };
            match class {
                Some(value) => value == "building",
                None => false,
            }
        } ).map(|i| i.clone()).collect();

        if !buildings.is_empty() {
            elements = buildings;
        }
    }

    let element = elements[0].as_object().ok_or("option::NoneError")?;
    let lat = element["lat"].as_str().ok_or("option::NoneError")?;
    let lon = element["lon"].as_str().ok_or("option::NoneError")?;
    let object_type = element["osm_type"].as_str().ok_or("option::NoneError")?;
    let object_id = element["osm_id"].as_str().ok_or("option::NoneError")?;

    // Use overpass to get the properties of the object.
    let overpass_query = format!(r#"[out:json];
(
    {}({});
);
out body;"#, object_type, object_id);
    let turbo = query_turbo(&overpass_query)?;
    let json: serde_json::Value = match serde_json::from_str(&turbo) {
        Ok(value) => value,
        Err(error) => {
            return Err(Box::new(OsmifyError::new(&format!("Failed to parse JSON from overpass: {:?}", error))));
        },
    };
    let json = json.as_object().ok_or("option::NoneError")?;
    let elements = &json["elements"].as_array().ok_or("option::NoneError")?;
    if elements.is_empty() {
        return Err(Box::new(OsmifyError::new("No results from overpass")));
    }

    let element = &elements[0];
    let tags = element["tags"].as_object().ok_or("option::NoneError")?;
    let city = tags["addr:city"].as_str().ok_or("option::NoneError")?;
    let housenumber = tags["addr:housenumber"].as_str().ok_or("option::NoneError")?;
    let postcode = tags["addr:postcode"].as_str().ok_or("option::NoneError")?;
    let street = tags["addr:street"].as_str().ok_or("option::NoneError")?;
    let addr = format!("{} {}, {} {}", postcode, city, street, housenumber);

    // Print the result.
    Ok(String::from(format!("geo:{},{} ({})", lat, lon, addr)))
}

fn spinner(rx: std::sync::mpsc::Receiver<Result<String, String>>) -> BoxResult<()> {
    let spin_characters = vec!['\\', '|', '/', '-'];
    let mut spin_index = 0;
    loop {
        match rx.try_recv() {
            Ok(result) => {
                print!("\r");
                std::io::stdout().flush()?;
                let result = result?;
                println!("{}", result);
                return Ok(());
            },
            Err(_) => {
                print!("\r [{}] ", spin_characters[spin_index]);
                std::io::stdout().flush()?;
                spin_index = (spin_index + 1) % spin_characters.len();
                std::thread::sleep(std::time::Duration::from_millis(100));
            }
        }
    }
}

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

    if args.len() > 1 {
        let (tx, rx) = std::sync::mpsc::channel();
        std::thread::spawn(move || {
            let result = osmify(&args[1]);
            match result {
                Ok(value) => tx.send(Ok(value)),
                Err(error) => tx.send(Err(format!("Failed to osmify: {:?}", error))),
            }
        });
        spinner(rx)?;
    } else {
        println!("usage: addr-osmify <query>");
        println!("");
        println!("e.g. addr-osmify 'Mészáros utca 58/a, Budapest'");
    }

    Ok(())
}
<commit_msg>addr-osmify-rust: fix clippy lints<commit_after>/*
 * Copyright 2019 Miklos Vajna. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

extern crate reqwest;
extern crate serde_json;
extern crate url;

use std::io::Write;

type BoxResult<T> = Result<T, Box<std::error::Error>>;

#[derive(Debug)]
struct OsmifyError {
    details: String
}

impl OsmifyError {
    fn new(msg: &str) -> OsmifyError {
        OsmifyError{details: msg.to_string()}
    }
}

impl std::fmt::Display for OsmifyError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}", self.details)
    }
}

impl std::error::Error for OsmifyError {
    fn description(&self) -> &str {
        &self.details
    }
}

fn query_turbo(query: &str) -> BoxResult<String> {
    let url = "http://overpass-api.de/api/interpreter";

    let client = reqwest::Client::new();
    let body = String::from(query);
    let mut buf = client.post(url)
        .body(body)
        .send()?;
    Ok(buf.text()?)
}

fn query_nominatim(query: &str) -> BoxResult<String> {
    let prefix = "http://nominatim.openstreetmap.org/search.php?";
    let encoded: String = url::form_urlencoded::Serializer::new(String::new())
        .append_pair("q", query)
        .append_pair("format", "json")
        .finish();
    let url = format!("{}{}", prefix, encoded);

    let mut buf = reqwest::get(url.as_str())?;

    Ok(buf.text()?)
}

fn osmify(query: &str) -> BoxResult<String> {
    let nominatim = query_nominatim(query)?;
    let json: serde_json::Value = match serde_json::from_str(&nominatim) {
        Ok(value) => value,
        Err(error) => {
            return Err(Box::new(OsmifyError::new(&format!("Failed to parse JSON from nominatim: {:?}", error))));
        },
    };
    let mut elements = json.as_array().ok_or("option::NoneError")?.clone();
    if elements.is_empty() {
        return Err(Box::new(OsmifyError::new("No results from nominatim")));
    }

    if elements.len() > 1 {
        // There are multiple elements, prefer buildings if possible.
        let buildings: Vec<serde_json::Value> = elements.iter().filter(|i| {
            let i = match i.as_object() {
                Some(value) => value,
                None => return false,
            };
            let class = match i.get("class") {
                Some(value) => value.as_str(),
                None => return false,
            };
            match class {
                Some(value) => value == "building",
                None => false,
            }
        } ).cloned().collect();

        if !buildings.is_empty() {
            elements = buildings;
        }
    }

    let element = elements[0].as_object().ok_or("option::NoneError")?;
    let lat = element["lat"].as_str().ok_or("option::NoneError")?;
    let lon = element["lon"].as_str().ok_or("option::NoneError")?;
    let object_type = element["osm_type"].as_str().ok_or("option::NoneError")?;
    let object_id = element["osm_id"].as_str().ok_or("option::NoneError")?;

    // Use overpass to get the properties of the object.
    let overpass_query = format!(r#"[out:json];
(
    {}({});
);
out body;"#, object_type, object_id);
    let turbo = query_turbo(&overpass_query)?;
    let json: serde_json::Value = match serde_json::from_str(&turbo) {
        Ok(value) => value,
        Err(error) => {
            return Err(Box::new(OsmifyError::new(&format!("Failed to parse JSON from overpass: {:?}", error))));
        },
    };
    let json = json.as_object().ok_or("option::NoneError")?;
    let elements = &json["elements"].as_array().ok_or("option::NoneError")?;
    if elements.is_empty() {
        return Err(Box::new(OsmifyError::new("No results from overpass")));
    }

    let element = &elements[0];
    let tags = element["tags"].as_object().ok_or("option::NoneError")?;
    let city = tags["addr:city"].as_str().ok_or("option::NoneError")?;
    let housenumber = tags["addr:housenumber"].as_str().ok_or("option::NoneError")?;
    let postcode = tags["addr:postcode"].as_str().ok_or("option::NoneError")?;
    let street = tags["addr:street"].as_str().ok_or("option::NoneError")?;
    let addr = format!("{} {}, {} {}", postcode, city, street, housenumber);

    // Print the result.
    Ok(format!("geo:{},{} ({})", lat, lon, addr))
}

fn spinner(rx: &std::sync::mpsc::Receiver<Result<String, String>>) -> BoxResult<()> {
    let spin_characters = vec!['\\', '|', '/', '-'];
    let mut spin_index = 0;
    loop {
        match rx.try_recv() {
            Ok(result) => {
                print!("\r");
                std::io::stdout().flush()?;
                let result = result?;
                println!("{}", result);
                return Ok(());
            },
            Err(_) => {
                print!("\r [{}] ", spin_characters[spin_index]);
                std::io::stdout().flush()?;
                spin_index = (spin_index + 1) % spin_characters.len();
                std::thread::sleep(std::time::Duration::from_millis(100));
            }
        }
    }
}

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

    if args.len() > 1 {
        let (tx, rx) = std::sync::mpsc::channel();
        std::thread::spawn(move || {
            let result = osmify(&args[1]);
            match result {
                Ok(value) => tx.send(Ok(value)),
                Err(error) => tx.send(Err(format!("Failed to osmify: {:?}", error))),
            }
        });
        spinner(&rx)?;
    } else {
        println!("usage: addr-osmify <query>");
        println!();
        println!("e.g. addr-osmify 'Mészáros utca 58/a, Budapest'");
    }

    Ok(())
}
<|endoftext|>