<commit_before>use rustc::lint::Context;
use rustc::middle::const_eval::lookup_const_by_id;
use syntax::ast::*;
use syntax::ptr::P;

/// a Lit_-like enum to fold constant `Expr`s into
#[derive(PartialEq, Eq, Debug, Clone)]
pub enum Constant {
    ConstantStr(&'static str, StrStyle),
    ConstantBinary(Rc<Vec<u8>>),
    ConstantByte(u8),
    ConstantChar(char),
    ConstantInt(u64, LitIntType),
    ConstantFloat(Cow<'static, str>, FloatTy),
    ConstantFloatUnsuffixed(Cow<'static, str>),
    ConstantBool(bool),
    ConstantVec(Vec<Constant>),
    ConstantTuple(Vec<Constant>),
}

/// simple constant folding
pub fn constant(cx: &Context, e: &Expr) -> Option<Constant> {
    match e {
        &ExprParen(ref inner) => constant(cx, inner),
        &ExprPath(_, _) => fetch_path(cx, e),
        &ExprBlock(ref block) => constant_block(cx, inner),
        &ExprIf(ref cond, ref then, ref otherwise) =>
            match constant(cx, cond) {
                Some(ConstantBool(true)) => constant(cx, then),
                Some(ConstantBool(false)) => constant(cx, otherwise),
                _ => None,
            },
        &ExprLit(ref lit) => Some(lit_to_constant(lit)),
        &ExprVec(ref vec) => constant_vec(cx, vec),
        &ExprTup(ref tup) => constant_tup(cx, tup),
        &ExprUnary(op, ref operand) => constant(cx, operand).and_then(
            |o| match op {
                UnNot =>
                    if let ConstantBool(b) = o {
                        Some(ConstantBool(!b))
                    } else { None },
                UnNeg =>
                    match o {
                        &ConstantInt(value, ty) =>
                            Some(ConstantInt(value, match ty {
                                SignedIntLit(ity, sign) =>
                                    SignedIntLit(ity, neg_sign(sign)),
                                UnsuffixedIntLit(sign) =>
                                    UnsuffixedIntLit(neg_sign(sign)),
                                _ => { return None; },
                            })),
                        &LitFloat(ref is, ref ty) =>
                            Some(ConstantFloat(neg_float_str(is), ty)),
                        &LitFloatUnsuffixed(ref is) =>
                            Some(ConstantFloatUnsuffixed(neg_float_str(is))),
                        _ => None,
                    },
                UnUniq | UnDeref => o,
            }),
        //TODO: add other expressions
        _ => None,
    }
}

fn lit_to_constant(lit: &Lit_) -> Constant {
    match lit {
        &LitStr(ref is, style) => ConstantStr(&*is, style),
        &LitBinary(ref blob) => ConstantBinary(blob.clone()),
        &LitByte(b) => ConstantByte(b),
        &LitChar(c) => ConstantChar(c),
        &LitInt(value, ty) => ConstantInt(value, ty),
        &LitFloat(ref is, ty) => ConstantFloat(Cow::Borrowed(&*is), ty),
        &LitFloatUnsuffixed(InternedString) =>
            ConstantFloatUnsuffixed(Cow::Borrowed(&*is)),
        &LitBool(b) => ConstantBool(b),
    }
}

/// create `Some(ConstantVec(..))` of all constants, unless there is any
/// non-constant part
fn constant_vec(cx: &Context, vec: &[&Expr]) -> Option<Constant> {
    Vec<Constant> parts = Vec::new();
    for opt_part in vec {
        match constant(cx, opt_part) {
            Some(ref p) => parts.push(p),
            None => { return None; },
        }
    }
    Some(ConstantVec(parts))
}

fn constant_tup(cx, &Context, tup: &[&Expr]) -> Option<Constant> {
    Vec<Constant> parts = Vec::new();
    for opt_part in vec {
        match constant(cx, opt_part) {
            Some(ref p) => parts.push(p),
            None => { return None; },
        }
    }
    Some(ConstantTuple(parts))
}

/// lookup a possibly constant expression from a ExprPath
fn fetch_path(cx: &Context, e: &Expr) -> Option<Constant> {
    if let Some(&PathResolution { base_def: DefConst(id), ..}) =
            cx.tcx.def_map.borrow().get(&e.id) {
        lookup_const_by_id(cx.tcx, id, None).map(|l| constant(cx, l))
    } else { None }
}

/// A block can only yield a constant if it only has one constant expression
fn constant_block(cx: &Context, block: &Block) -> Option<Constant> {
    if block.stmts.is_empty() {
        block.expr.map(|b| constant(cx, b))
    } else { None }
}

fn neg_sign(s: Sign) -> Sign {
    match s:
        Sign::Plus => Sign::Minus,
        Sign::Minus => Sign::Plus,
    }
}

fn neg_float_str(s: &InternedString) -> Cow<'static, str> {
    if s.startsWith('-') {
        Cow::Borrowed(s[1..])
    } else {
        Cow::Owned(format!("-{}", &*s))
    }
}
<commit_msg>added follow flag<commit_after>use rustc::lint::Context;
use rustc::middle::const_eval::lookup_const_by_id;
use syntax::ast::*;
use syntax::ptr::P;

pub enum FloatWidth {
    Fw32,
    Fw64,
    FwAny
}

impl From<FloatTy> for FloatWidth {
    fn from(ty: FloatTy) -> FloatWidth {
        match ty {
            TyF32 => Fw32,
            TyF64 => Fw64,
        }
    }
}

/// a Lit_-like enum to fold constant `Expr`s into
#[derive(PartialEq, Eq, Debug, Clone)]
pub enum Constant {
    /// a String "abc"
    ConstantStr(&'static str, StrStyle),
    /// a Binary String b"abc"
    ConstantBinary(Rc<Vec<u8>>),
    /// a single byte b'a'
    ConstantByte(u8),
    /// a single char 'a'
    ConstantChar(char),
    /// an integer
    ConstantInt(u64, LitIntType),
    /// a float with given type
    ConstantFloat(Cow<'static, str>, FloatWidth),
    /// true or false
    ConstantBool(bool),
    /// an array of constants
    ConstantVec(Vec<Constant>),
    /// also an array, but with only one constant, repeated N times
    ConstantRepeat(Constant, usize),
    /// a tuple of constants
    ConstantTuple(Vec<Constant>),
}

/// simple constant folding
pub fn constant(cx: &Context, e: &Expr, follow: bool) -> Option<Constant> {
    match e {
        &ExprParen(ref inner) => constant(cx, inner, follow),
        &ExprPath(_, _) => if follow { fetch_path(cx, e) } else { None },
        &ExprBlock(ref block) => constant_block(cx, inner, follow),
        &ExprIf(ref cond, ref then, ref otherwise) =>
            match constant(cx, cond) {
                Some(ConstantBool(true)) => constant(cx, then, follow),
                Some(ConstantBool(false)) => constant(cx, otherwise, follow),
                _ => None,
            },
        &ExprLit(ref lit) => Some(lit_to_constant(lit)),
        &ExprVec(ref vec) => constant_vec(cx, vec, follow),
        &ExprTup(ref tup) => constant_tup(cx, tup, follow),
        &ExprRepeat(ref value, ref number) =>
            constant_binop_apply(cx, value, number,|v, n| ConstantRepeat(v, n)),
        &ExprUnary(op, ref operand) => constant(cx, operand, follow).and_then(
            |o| match op {
                UnNot =>
                    if let ConstantBool(b) = o {
                        Some(ConstantBool(!b))
                    } else { None },
                UnNeg => constant_negate(o),
                UnUniq | UnDeref => o,
            }),
        &ExprBinary(op, ref left, ref right) =>
            constant_binop(cx, op, left, right, follow),
        //TODO: add other expressions
        _ => None,
    }
}

fn lit_to_constant(lit: &Lit_) -> Constant {
    match lit {
        &LitStr(ref is, style) => ConstantStr(&*is, style),
        &LitBinary(ref blob) => ConstantBinary(blob.clone()),
        &LitByte(b) => ConstantByte(b),
        &LitChar(c) => ConstantChar(c),
        &LitInt(value, ty) => ConstantInt(value, ty),
        &LitFloat(ref is, ty) => ConstantFloat(Cow::Borrowed(&*is), ty.into()),
        &LitFloatUnsuffixed(InternedString) =>
                ConstantFloat(Cow::Borrowed(&*is), FwAny),
        &LitBool(b) => ConstantBool(b),
    }
}

/// create `Some(ConstantVec(..))` of all constants, unless there is any
/// non-constant part
fn constant_vec(cx: &Context, vec: &[&Expr], follow: bool) -> Option<Constant> {
    parts = Vec::new();
    for opt_part in vec {
        match constant(cx, opt_part, follow) {
            Some(ref p) => parts.push(p),
            None => { return None; },
        }
    }
    Some(ConstantVec(parts))
}

fn constant_tup(cx: &Context, tup: &[&Expr], follow: bool) -> Option<Constant> {
    parts = Vec::new();
    for opt_part in vec {
        match constant(cx, opt_part, follow) {
            Some(ref p) => parts.push(p),
            None => { return None; },
        }
    }
    Some(ConstantTuple(parts))
}

/// lookup a possibly constant expression from a ExprPath
fn fetch_path(cx: &Context, e: &Expr) -> Option<Constant> {
    if let Some(&PathResolution { base_def: DefConst(id), ..}) =
            cx.tcx.def_map.borrow().get(&e.id) {
        lookup_const_by_id(cx.tcx, id, None).map(|l| constant(cx, l))
    } else { None }
}

/// A block can only yield a constant if it only has one constant expression
fn constant_block(cx: &Context, block: &Block, follow: bool) -> Option<Constant> {
    if block.stmts.is_empty() {
        block.expr.map(|b| constant(cx, b, follow))
    } else { None }
}

fn constant_negate(o: Constant) -> Option<Constant> {
    match o {
        &ConstantInt(value, ty) =>
            Some(ConstantInt(value, match ty {
                SignedIntLit(ity, sign) => SignedIntLit(ity, neg_sign(sign)),
                UnsuffixedIntLit(sign) => UnsuffixedIntLit(neg_sign(sign)),
                _ => { return None; },
            })),
        &LitFloat(ref is, ref ty) => Some(ConstantFloat(neg_float_str(is), ty)),
        _ => None,
    }
}

fn neg_sign(s: Sign) -> Sign {
    match s {
        Sign::Plus => Sign::Minus,
        Sign::Minus => Sign::Plus,
    }
}

fn neg_float_str(s: &InternedString) -> Cow<'static, str> {
    if s.startsWith('-') {
        Cow::Borrowed(s[1..])
    } else {
        Cow::Owned(format!("-{}", &*s))
    }
}

fn constant_binop(cx: &Context, op: BinOp, left: &Expr, right: &Expr,
        follow: bool) -> Option<Constant> {
    match op.node {
        //BiAdd,
        //BiSub,
        //BiMul,
        //BiDiv,
        //BiRem,
        BiAnd => constant_short_circuit(cx, left, right, false, follow),
        BiOr => constant_short_circuit(cx, left, right, true, follow),
        //BiBitXor,
        //BiBitAnd,
        //BiBitOr,
        //BiShl,
        //BiShr,
        //BiEq,
        //BiLt,
        //BiLe,
        //BiNe,
        //BiGe,
        //BiGt,
        _ => None,
    }
}

fn constant_binop_apply<F>(cx: &Context, left: &Expr, right: &Expr, op: F,
        follow: bool) -> Option<Constant>
where F: FnMut(Constant, Constant) -> Option<Constant> {
    constant(cx, left, follow).and_then(|l| constant(cx, right, follow)
        .and_then(|r| op(l, r)))
}

fn constant_short_circuit(cx: &Context, left: &Expr, right: &Expr, b: bool,
        follow: bool) -> Option<Constant> {
    if let ConstantBool(lbool) = constant(cx, left, follow) {
        if l == b {
            Some(ConstantBool(b))
        } else {
            if let ConstantBool(rbool) = constant(cx, right, follow) {
                Some(ConstantBool(rbool))
            } else { None }
        }
    } else { None }
}
<|endoftext|>


<commit_before>fn is_odd(n: u32) -> bool {
    n % 2 == 1
}

fn main() {
    println!("Find the sum of all the squared odd numbers under 1000");
    let upper = 1000;

    // 命令式方式（imperative approach）
    // 声明累加器变量
    let mut acc = 0;
    // 重复：0，1, 2, ... 到无穷大
    for n in 0.. {
        // 数字的平方
        let n_squared = n * n;

        if n_squared >= upper {
            // 若大于上限（upper limit）则退出循环
            break;
        } else if is_odd(n_squared) {
            // 如果是奇数就累加值
            acc += n_squared;
        }
    }
    println!("imperative style: {}", acc);

    // 函数式方式（functional approach）
    let sum_of_squared_odd_numbers: u32 =
        (0..).map(|n| n * n)             // 所有自然数的平方
             .take_while(|&n| n < upper) // 小于上限
             .filter(|n| is_odd(*n))     // 为奇数
             .fold(0, |sum, i| sum + i); // 最后其后
    println!("functional style: {}", sum_of_squared_odd_numbers);
}
<commit_msg>fn/hof: destructure in `filter` like `take_while`<commit_after>fn is_odd(n: u32) -> bool {
    n % 2 == 1
}

fn main() {
    println!("Find the sum of all the squared odd numbers under 1000");
    let upper = 1000;

    // 命令式方式（imperative approach）
    // 声明累加器变量
    let mut acc = 0;
    // 重复：0，1, 2, ... 到无穷大
    for n in 0.. {
        // 数字的平方
        let n_squared = n * n;

        if n_squared >= upper {
            // 若大于上限（upper limit）则退出循环
            break;
        } else if is_odd(n_squared) {
            // 如果是奇数就累加值
            acc += n_squared;
        }
    }
    println!("imperative style: {}", acc);

    // 函数式方式（functional approach）
    let sum_of_squared_odd_numbers: u32 =
        (0..).map(|n| n * n)             // 所有自然数的平方
             .take_while(|&n| n < upper) // 小于上限
             .filter(|&n| is_odd(n))     // 为奇数
             .fold(0, |sum, i| sum + i); // 最后其后
    println!("functional style: {}", sum_of_squared_odd_numbers);
}
<|endoftext|>


<commit_before>use std::{fmt, old_io, result};
use std::error::FromError;
use std::fmt::Formatter;

/// An enum of all error kinds.
#[derive(PartialEq, Eq, Clone, Show)]
pub enum FerrumError {
    /// Failed to decode a file.
    DecodingError(String),
    /// The configuration file is improperly formatted.
    InvalidConfigError,
    /// A Document is improperly formatted.
    InvalidDocumentError(String),
    /// An IO error was encountered.
    IoError(old_io::IoError),
    /// A rust-mustache rendering error.
    MustacheError,
    /// Failed to parse a string with the parser.
    ParserError(String),
}

/// Application generic result type.
pub type FerrumResult<T> = ::std::result::Result<T, self::FerrumError>;

impl FromError<old_io::IoError> for FerrumError {
    fn from_error(e: old_io::IoError) -> FerrumError {
        FerrumError::IoError(e)
    }
}

impl fmt::Display for FerrumError {
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), fmt::Error> {
        match *self {
            FerrumError::DecodingError(ref s) => s.fmt(formatter),
            FerrumError::InvalidConfigError => "Invalid configuration".fmt(formatter),
            FerrumError::InvalidDocumentError(ref s) => s.fmt(formatter),
            FerrumError::IoError(ref e) => e.fmt(formatter),
            FerrumError::MustacheError => "Mustache error".fmt(formatter),
            FerrumError::ParserError(ref s) => s.fmt(formatter),
        }
    }
}

impl fmt::Debug for FerrumError {
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), fmt::Error> {
        match *self {
            FerrumError::DecodingError(ref s) => s.fmt(formatter),
            FerrumError::InvalidConfigError => "Invalid configuration".fmt(formatter),
            FerrumError::InvalidDocumentError(ref s) => s.fmt(formatter),
            FerrumError::IoError(ref e) => e.fmt(formatter),
            FerrumError::MustacheError => "Mustache error".fmt(formatter),
            FerrumError::ParserError(ref s) => s.fmt(formatter),
        }
    }
}
<commit_msg>Remove Show derive<commit_after>use std::{fmt, old_io, result};
use std::error::FromError;
use std::fmt::Formatter;

/// An enum of all error kinds.
#[derive(PartialEq, Eq, Clone)]
pub enum FerrumError {
    /// Failed to decode a file.
    DecodingError(String),
    /// The configuration file is improperly formatted.
    InvalidConfigError,
    /// A Document is improperly formatted.
    InvalidDocumentError(String),
    /// An IO error was encountered.
    IoError(old_io::IoError),
    /// A rust-mustache rendering error.
    MustacheError,
    /// Failed to parse a string with the parser.
    ParserError(String),
}

/// Application generic result type.
pub type FerrumResult<T> = ::std::result::Result<T, self::FerrumError>;

impl FromError<old_io::IoError> for FerrumError {
    fn from_error(e: old_io::IoError) -> FerrumError {
        FerrumError::IoError(e)
    }
}

impl fmt::Display for FerrumError {
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), fmt::Error> {
        match *self {
            FerrumError::DecodingError(ref s) => s.fmt(formatter),
            FerrumError::InvalidConfigError => "Invalid configuration".fmt(formatter),
            FerrumError::InvalidDocumentError(ref s) => s.fmt(formatter),
            FerrumError::IoError(ref e) => e.fmt(formatter),
            FerrumError::MustacheError => "Mustache error".fmt(formatter),
            FerrumError::ParserError(ref s) => s.fmt(formatter),
        }
    }
}

impl fmt::Debug for FerrumError {
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), fmt::Error> {
        match *self {
            FerrumError::DecodingError(ref s) => s.fmt(formatter),
            FerrumError::InvalidConfigError => "Invalid configuration".fmt(formatter),
            FerrumError::InvalidDocumentError(ref s) => s.fmt(formatter),
            FerrumError::IoError(ref e) => e.fmt(formatter),
            FerrumError::MustacheError => "Mustache error".fmt(formatter),
            FerrumError::ParserError(ref s) => s.fmt(formatter),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2013-2015, The Rust-GNOME Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use ffi::{self, GQuark};
use glib_container::GlibContainer;
use translate::ToGlibPtr;

/// The Error structure contains information about an error that has occurred.
pub struct Error {
    pointer: *mut ffi::GError
}

impl Error {
    /// Creates a new Error; unlike Error::new(), message is not a printf()-style format string.
    /// Use this function if message contains text you don't have control over, that could include
    /// printf() escape sequences.
    pub fn new_literal(domain: GQuark, code: i32, message: &str) -> Option<Error> {
        let tmp_pointer = unsafe {
            ffi::g_error_new_literal(domain, code, message.to_glib_none().0)
        };

        if tmp_pointer.is_null() {
            None
        } else {
            Some(Error{pointer: tmp_pointer})
        }
    }

    /// Frees an Error struct and associated resources.
    pub fn release(&mut self) -> () {
        if !self.pointer.is_null() {
            unsafe { ffi::g_error_free(self.pointer) };
            self.pointer = ::std::ptr::null_mut();
        }
    }

    /// Returns true if error matches domain and code , false otherwise. In particular, when error.pointer
    /// is NULL, false will be returned.
    ///
    /// If domain contains a FAILED (or otherwise generic) error code, you should generally not check
    /// for it explicitly, but should instead treat any not-explicitly-recognized error code as being
    /// equivalent to the FAILED code. This way, if the domain is extended in the future to provide a
    /// more specific error code for a certain case, your code will still work.
    pub fn matches(&self, domain: GQuark, code: i32) -> bool {
        match unsafe { ffi::g_error_matches(self.pointer, domain, code) } {
            ffi::GFALSE => false,
            _ => true
        }
    }

    /// Does nothing if self.pointer is NULL; if self.pointer is non-NULL, then *self.pointer must be NULL.
    /// A new GError is created and assigned to *self.pointer .
    pub fn set(&mut self, domain: GQuark, code: i32, message: &str) -> () {
        unsafe {
            ffi::g_set_error_literal(&mut self.pointer, domain, code, message.to_glib_none().0)
        }
    }

    /// If other.pointer is NULL, free self ; otherwise, moves self into other. The error variable
    /// other.pointer points to must be NULL.
    ///
    /// Note that self is no longer valid after this call. If you want to keep using the same Error
    /// struct, you need to set it to NULL after calling this function on it.
    pub fn propagate(&mut self, other: &Error) -> () {
        unsafe { ffi::g_propagate_error(&mut self.pointer, other.pointer) }
    }
}

impl Clone for Error {
    fn clone(&self) -> Error {
        let tmp_pointer = unsafe { ffi::g_error_copy(self.pointer) };

        if tmp_pointer.is_null() {
            Error {
                pointer: ::std::ptr::null_mut()
            }
        } else {
            GlibContainer::wrap(tmp_pointer)
        }
    }
}

impl Drop for Error {
    fn drop(&mut self) {
        self.release();
    }
}

impl GlibContainer<*mut ffi::GError> for Error {
    fn wrap(pointer: *mut ffi::GError) -> Error {
        Error {
            pointer: pointer
        }
    }

    fn unwrap(&self) -> *mut ffi::GError {
        self.pointer
    }
}
<commit_msg>Implemented Debug, Display, and Error for glib::Error<commit_after>// Copyright 2013-2015, The Rust-GNOME Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use std::str;
use std::ffi::CStr;
use std::fmt::{self, Formatter, Debug, Display};
use std::error;
use ffi::{self, GQuark};
use glib_container::GlibContainer;
use translate::ToGlibPtr;

/// The Error structure contains information about an error that has occurred.
pub struct Error {
    pointer: *mut ffi::GError
}

impl Error {
    /// Creates a new Error; unlike Error::new(), message is not a printf()-style format string.
    /// Use this function if message contains text you don't have control over, that could include
    /// printf() escape sequences.
    pub fn new_literal(domain: GQuark, code: i32, message: &str) -> Option<Error> {
        let tmp_pointer = unsafe {
            ffi::g_error_new_literal(domain, code, message.to_glib_none().0)
        };

        if tmp_pointer.is_null() {
            None
        } else {
            Some(Error{pointer: tmp_pointer})
        }
    }

    /// Frees an Error struct and associated resources.
    pub fn release(&mut self) -> () {
        if !self.pointer.is_null() {
            unsafe { ffi::g_error_free(self.pointer) };
            self.pointer = ::std::ptr::null_mut();
        }
    }

    /// Returns true if error matches domain and code , false otherwise. In particular, when error.pointer
    /// is NULL, false will be returned.
    ///
    /// If domain contains a FAILED (or otherwise generic) error code, you should generally not check
    /// for it explicitly, but should instead treat any not-explicitly-recognized error code as being
    /// equivalent to the FAILED code. This way, if the domain is extended in the future to provide a
    /// more specific error code for a certain case, your code will still work.
    pub fn matches(&self, domain: GQuark, code: i32) -> bool {
        match unsafe { ffi::g_error_matches(self.pointer, domain, code) } {
            ffi::GFALSE => false,
            _ => true
        }
    }

    /// Does nothing if self.pointer is NULL; if self.pointer is non-NULL, then *self.pointer must be NULL.
    /// A new GError is created and assigned to *self.pointer .
    pub fn set(&mut self, domain: GQuark, code: i32, message: &str) -> () {
        unsafe {
            ffi::g_set_error_literal(&mut self.pointer, domain, code, message.to_glib_none().0)
        }
    }

    /// If other.pointer is NULL, free self ; otherwise, moves self into other. The error variable
    /// other.pointer points to must be NULL.
    ///
    /// Note that self is no longer valid after this call. If you want to keep using the same Error
    /// struct, you need to set it to NULL after calling this function on it.
    pub fn propagate(&mut self, other: &Error) -> () {
        unsafe { ffi::g_propagate_error(&mut self.pointer, other.pointer) }
    }

    /// Returns the error message stored in the wrapped GError
    pub fn message(&self) -> &str {
        let c_str = unsafe { CStr::from_ptr((*self.pointer).message) };
        str::from_utf8(c_str.to_bytes()).unwrap()
    }
}

impl Clone for Error {
    fn clone(&self) -> Error {
        let tmp_pointer = unsafe { ffi::g_error_copy(self.pointer) };

        if tmp_pointer.is_null() {
            Error {
                pointer: ::std::ptr::null_mut()
            }
        } else {
            GlibContainer::wrap(tmp_pointer)
        }
    }
}

impl Debug for Error {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}", self.message())
    }
}

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

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

impl Drop for Error {
    fn drop(&mut self) {
        self.release();
    }
}

impl GlibContainer<*mut ffi::GError> for Error {
    fn wrap(pointer: *mut ffi::GError) -> Error {
        Error {
            pointer: pointer
        }
    }

    fn unwrap(&self) -> *mut ffi::GError {
        self.pointer
    }
}
<|endoftext|>


<commit_before>//! Defines error types used by this library.

use Value;

use xml::reader::Error as XmlError;
use xml::common::TextPosition;

use std::{error, io};
use std::fmt::{self, Formatter, Display};
use std::collections::BTreeMap;

/// Error that can occur when trying to perform an XML-RPC request.
///
/// This can be a lower-level error (for example, the HTTP request failed), a problem with the
/// server (maybe it's not implementing XML-RPC correctly), or just a failure to execute the
/// operation.
#[derive(Debug)]
pub struct Error(RequestErrorKind);

impl Error {
    /// If this `RequestError` was caused by the server responding with a `<fault>` response,
    /// returns the `Fault` in question.
    pub fn fault(&self) -> Option<&Fault> {
        match self.0 {
            RequestErrorKind::Fault(ref fault) => Some(fault),
            _ => None,
        }
    }
}

#[doc(hidden)]  // hide internal impl
impl From<RequestErrorKind> for Error {
    fn from(kind: RequestErrorKind) -> Self {
        Error(kind)
    }
}

impl Display for Error {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        self.0.fmt(fmt)
    }
}

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

    fn cause(&self) -> Option<&error::Error> {
        self.0.cause()
    }
}

#[derive(Debug)]
pub enum RequestErrorKind {
    /// The response could not be parsed. This can happen when the server doesn't correctly
    /// implement the XML-RPC spec.
    ParseError(ParseError),

    /// A communication error originating from the transport used to perform the request.
    TransportError(Box<error::Error + 'static>),

    /// The server returned a `<fault>` response, indicating that the execution of the call
    /// encountered a problem (for example, an invalid (number of) arguments was passed).
    Fault(Fault),
}

impl From<ParseError> for RequestErrorKind {
    fn from(e: ParseError) -> Self {
        RequestErrorKind::ParseError(e)
    }
}

impl From<Fault> for RequestErrorKind {
    fn from(f: Fault) -> Self {
        RequestErrorKind::Fault(f)
    }
}

impl Display for RequestErrorKind {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        match *self {
            RequestErrorKind::ParseError(ref err) => write!(fmt, "parse error: {}", err),
            RequestErrorKind::TransportError(ref err) => write!(fmt, "transport error: {}", err),
            RequestErrorKind::Fault(ref err) => write!(fmt, "{}", err),
        }
    }
}

impl error::Error for RequestErrorKind {
    fn description(&self) -> &str {
        match *self {
            RequestErrorKind::ParseError(_) => "parse error",
            RequestErrorKind::TransportError(_) => "transport error",
            RequestErrorKind::Fault(_) => "server returned a fault",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            RequestErrorKind::ParseError(ref err) => Some(err),
            RequestErrorKind::TransportError(ref err) => Some(err.as_ref()),
            RequestErrorKind::Fault(ref err) => Some(err),
        }
    }
}

/// Describes possible error that can occur when parsing a `Response`.
#[derive(Debug, PartialEq)]
pub enum ParseError {
    /// Error while parsing (malformed?) XML.
    XmlError(XmlError),

    /// Could not parse the given CDATA as XML-RPC value.
    ///
    /// For example, `<value><int>AAA</int></value>` describes an invalid value.
    InvalidValue {
        /// The type for which an invalid value was supplied (eg. `int` or `dateTime.iso8601`).
        for_type: &'static str,
        /// The value we encountered, as a string.
        found: String,
        /// The position of the invalid value inside the XML document.
        position: TextPosition,
    },

    /// Found an unexpected tag, attribute, etc.
    UnexpectedXml {
        /// A short description of the kind of data that was expected.
        expected: String,
        found: Option<String>,
        /// The position of the unexpected data inside the XML document.
        position: TextPosition,
    }
}

impl From<XmlError> for ParseError {
    fn from(e: XmlError) -> Self {
        ParseError::XmlError(e)
    }
}

impl From<io::Error> for ParseError {
    fn from(e: io::Error) -> Self {
        ParseError::XmlError(XmlError::from(e))
    }
}

impl Display for ParseError {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        match *self {
            ParseError::XmlError(ref err) => write!(fmt, "malformed XML: {}", err),
            ParseError::InvalidValue {
                for_type,
                ref found,
                ref position,
            } => write!(fmt, "invalid value for type '{}' at {}: {}", for_type, position, found),
            ParseError::UnexpectedXml {
                ref expected,
                ref position,
                found: None,
            } => {
                write!(fmt, "unexpected XML at {} (expected {})", position, expected)
            }
            ParseError::UnexpectedXml {
                ref expected,
                ref position,
                found: Some(ref found),
            } => {
                write!(fmt, "unexpected XML at {} (expected {}, found {})", position, expected, found)
            }
        }
    }
}

impl error::Error for ParseError {
    fn description(&self) -> &str {
        match *self {
            ParseError::XmlError(ref err) => err.description(),
            ParseError::InvalidValue { .. } => "invalid value for type",
            ParseError::UnexpectedXml { .. } => "unexpected XML content",
        }
    }
}

/// A `<fault>` response, indicating that a request failed.
///
/// The XML-RPC specification requires that a `<faultCode>` and `<faultString>` is returned in the
/// `<fault>` case, further describing the error.
#[derive(Debug, PartialEq, Eq)]
pub struct Fault {
    pub fault_code: i32,
    pub fault_string: String,
}

impl Fault {
    /// Creates a `Fault` from a `Value`.
    ///
    /// The `Value` must be a `Value::Struct` with a `faultCode` and `faultString` field (and no
    /// other fields).
    ///
    /// Returns `None` if the value isn't a valid `Fault`.
    pub fn from_value(value: &Value) -> Option<Self> {
        match *value {
            Value::Struct(ref map) => {
                if map.len() != 2 {
                    // incorrect field count
                    return None;
                }

                match (map.get("faultCode"), map.get("faultString")) {
                    (Some(&Value::Int(fault_code)), Some(&Value::String(ref fault_string))) => {
                        Some(Fault {
                            fault_code,
                            fault_string: fault_string.to_string(),
                        })
                    }
                    _ => None
                }
            }
            _ => None
        }
    }

    /// Turns this `Fault` into an equivalent `Value`.
    ///
    /// The returned value can be parsed back into a `Fault` using `Fault::from_value` or returned
    /// as a `<fault>` error response by serializing it into a `<fault></fault>` tag.
    pub fn to_value(&self) -> Value {
        let mut map = BTreeMap::new();
        map.insert("faultCode".to_string(), Value::from(self.fault_code));
        map.insert("faultString".to_string(), Value::from(self.fault_string.as_ref()));

        Value::Struct(map)
    }
}

impl Display for Fault {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{} ({})", self.fault_string, self.fault_code)
    }
}

impl error::Error for Fault {
    fn description(&self) -> &str {
        &self.fault_string
    }
}

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

    use std::error;

    #[test]
    fn fault_roundtrip() {
        let input = Fault {
            fault_code: -123456,
            fault_string: "The Bald Lazy House Jumps Over The Hyperactive Kitten".to_string()
        };

        assert_eq!(Fault::from_value(&input.to_value()), Some(input));
    }

    #[test]
    fn error_impls_error() {
        fn assert_error<T: error::Error>() {}

        assert_error::<Error>();
    }
}
<commit_msg>Fix typo in `Error` docs<commit_after>//! Defines error types used by this library.

use Value;

use xml::reader::Error as XmlError;
use xml::common::TextPosition;

use std::{error, io};
use std::fmt::{self, Formatter, Display};
use std::collections::BTreeMap;

/// Errors that can occur when trying to perform an XML-RPC request.
///
/// This can be a lower-level error (for example, the HTTP request failed), a problem with the
/// server (maybe it's not implementing XML-RPC correctly), or just a failure to execute the
/// operation.
#[derive(Debug)]
pub struct Error(RequestErrorKind);

impl Error {
    /// If this `RequestError` was caused by the server responding with a `<fault>` response,
    /// returns the `Fault` in question.
    pub fn fault(&self) -> Option<&Fault> {
        match self.0 {
            RequestErrorKind::Fault(ref fault) => Some(fault),
            _ => None,
        }
    }
}

#[doc(hidden)]  // hide internal impl
impl From<RequestErrorKind> for Error {
    fn from(kind: RequestErrorKind) -> Self {
        Error(kind)
    }
}

impl Display for Error {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        self.0.fmt(fmt)
    }
}

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

    fn cause(&self) -> Option<&error::Error> {
        self.0.cause()
    }
}

#[derive(Debug)]
pub enum RequestErrorKind {
    /// The response could not be parsed. This can happen when the server doesn't correctly
    /// implement the XML-RPC spec.
    ParseError(ParseError),

    /// A communication error originating from the transport used to perform the request.
    TransportError(Box<error::Error + 'static>),

    /// The server returned a `<fault>` response, indicating that the execution of the call
    /// encountered a problem (for example, an invalid (number of) arguments was passed).
    Fault(Fault),
}

impl From<ParseError> for RequestErrorKind {
    fn from(e: ParseError) -> Self {
        RequestErrorKind::ParseError(e)
    }
}

impl From<Fault> for RequestErrorKind {
    fn from(f: Fault) -> Self {
        RequestErrorKind::Fault(f)
    }
}

impl Display for RequestErrorKind {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        match *self {
            RequestErrorKind::ParseError(ref err) => write!(fmt, "parse error: {}", err),
            RequestErrorKind::TransportError(ref err) => write!(fmt, "transport error: {}", err),
            RequestErrorKind::Fault(ref err) => write!(fmt, "{}", err),
        }
    }
}

impl error::Error for RequestErrorKind {
    fn description(&self) -> &str {
        match *self {
            RequestErrorKind::ParseError(_) => "parse error",
            RequestErrorKind::TransportError(_) => "transport error",
            RequestErrorKind::Fault(_) => "server returned a fault",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            RequestErrorKind::ParseError(ref err) => Some(err),
            RequestErrorKind::TransportError(ref err) => Some(err.as_ref()),
            RequestErrorKind::Fault(ref err) => Some(err),
        }
    }
}

/// Describes possible error that can occur when parsing a `Response`.
#[derive(Debug, PartialEq)]
pub enum ParseError {
    /// Error while parsing (malformed?) XML.
    XmlError(XmlError),

    /// Could not parse the given CDATA as XML-RPC value.
    ///
    /// For example, `<value><int>AAA</int></value>` describes an invalid value.
    InvalidValue {
        /// The type for which an invalid value was supplied (eg. `int` or `dateTime.iso8601`).
        for_type: &'static str,
        /// The value we encountered, as a string.
        found: String,
        /// The position of the invalid value inside the XML document.
        position: TextPosition,
    },

    /// Found an unexpected tag, attribute, etc.
    UnexpectedXml {
        /// A short description of the kind of data that was expected.
        expected: String,
        found: Option<String>,
        /// The position of the unexpected data inside the XML document.
        position: TextPosition,
    }
}

impl From<XmlError> for ParseError {
    fn from(e: XmlError) -> Self {
        ParseError::XmlError(e)
    }
}

impl From<io::Error> for ParseError {
    fn from(e: io::Error) -> Self {
        ParseError::XmlError(XmlError::from(e))
    }
}

impl Display for ParseError {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        match *self {
            ParseError::XmlError(ref err) => write!(fmt, "malformed XML: {}", err),
            ParseError::InvalidValue {
                for_type,
                ref found,
                ref position,
            } => write!(fmt, "invalid value for type '{}' at {}: {}", for_type, position, found),
            ParseError::UnexpectedXml {
                ref expected,
                ref position,
                found: None,
            } => {
                write!(fmt, "unexpected XML at {} (expected {})", position, expected)
            }
            ParseError::UnexpectedXml {
                ref expected,
                ref position,
                found: Some(ref found),
            } => {
                write!(fmt, "unexpected XML at {} (expected {}, found {})", position, expected, found)
            }
        }
    }
}

impl error::Error for ParseError {
    fn description(&self) -> &str {
        match *self {
            ParseError::XmlError(ref err) => err.description(),
            ParseError::InvalidValue { .. } => "invalid value for type",
            ParseError::UnexpectedXml { .. } => "unexpected XML content",
        }
    }
}

/// A `<fault>` response, indicating that a request failed.
///
/// The XML-RPC specification requires that a `<faultCode>` and `<faultString>` is returned in the
/// `<fault>` case, further describing the error.
#[derive(Debug, PartialEq, Eq)]
pub struct Fault {
    pub fault_code: i32,
    pub fault_string: String,
}

impl Fault {
    /// Creates a `Fault` from a `Value`.
    ///
    /// The `Value` must be a `Value::Struct` with a `faultCode` and `faultString` field (and no
    /// other fields).
    ///
    /// Returns `None` if the value isn't a valid `Fault`.
    pub fn from_value(value: &Value) -> Option<Self> {
        match *value {
            Value::Struct(ref map) => {
                if map.len() != 2 {
                    // incorrect field count
                    return None;
                }

                match (map.get("faultCode"), map.get("faultString")) {
                    (Some(&Value::Int(fault_code)), Some(&Value::String(ref fault_string))) => {
                        Some(Fault {
                            fault_code,
                            fault_string: fault_string.to_string(),
                        })
                    }
                    _ => None
                }
            }
            _ => None
        }
    }

    /// Turns this `Fault` into an equivalent `Value`.
    ///
    /// The returned value can be parsed back into a `Fault` using `Fault::from_value` or returned
    /// as a `<fault>` error response by serializing it into a `<fault></fault>` tag.
    pub fn to_value(&self) -> Value {
        let mut map = BTreeMap::new();
        map.insert("faultCode".to_string(), Value::from(self.fault_code));
        map.insert("faultString".to_string(), Value::from(self.fault_string.as_ref()));

        Value::Struct(map)
    }
}

impl Display for Fault {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{} ({})", self.fault_string, self.fault_code)
    }
}

impl error::Error for Fault {
    fn description(&self) -> &str {
        &self.fault_string
    }
}

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

    use std::error;

    #[test]
    fn fault_roundtrip() {
        let input = Fault {
            fault_code: -123456,
            fault_string: "The Bald Lazy House Jumps Over The Hyperactive Kitten".to_string()
        };

        assert_eq!(Fault::from_value(&input.to_value()), Some(input));
    }

    #[test]
    fn error_impls_error() {
        fn assert_error<T: error::Error>() {}

        assert_error::<Error>();
    }
}
<|endoftext|>


<commit_before>//! jsonrpc errors
use serde::{Serialize, Serializer};
use super::Value;

#[derive(Debug, PartialEq)]
pub enum ErrorCode {
	/// Invalid JSON was received by the server.
	/// An error occurred on the server while parsing the JSON text.
	ParseError,
	/// The JSON sent is not a valid Request object.
	InvalidRequest,
	/// The method does not exist / is not available.
	MethodNotFound,
	/// Invalid method parameter(s).
	InvalidParams,
	/// Internal JSON-RPC error.
	InternalError,
	/// Reserved for implementation-defined server-errors.
	ServerError(i64)
}

impl ErrorCode {
	pub fn code(&self) -> i64 {
		match *self {
			ErrorCode::ParseError => -32700,
			ErrorCode::InvalidRequest => -32600,
			ErrorCode::MethodNotFound => -32601,
			ErrorCode::InvalidParams => -32602,
			ErrorCode::InternalError => -32603,
			ErrorCode::ServerError(code) => code
		}
	}

	pub fn description(&self) -> String {
		let desc = match *self {
			ErrorCode::ParseError => "Parse error.",
			ErrorCode::InvalidRequest => "Invalid request.",
			ErrorCode::MethodNotFound => "Method not found.",
			ErrorCode::InvalidParams => "Invalid params.",
			ErrorCode::InternalError => "Internal error.",
			ErrorCode::ServerError(_) => "Server error.",
		};
		desc.to_string()
	}
}

impl Serialize for ErrorCode {
	fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
	where S: Serializer {
		serializer.visit_i64(self.code())
	}
}

#[derive(Debug, PartialEq, Serialize)]
pub struct Error {
	pub code: ErrorCode,
	pub message: String,
	pub data: Option<Value>
}

impl Error {
	pub fn new(code: ErrorCode) -> Error {
		Error {
			message: code.description(),
			code: code,
			data: None
		}
	}
}
<commit_msg>error constructors<commit_after>//! jsonrpc errors
use serde::{Serialize, Serializer};
use super::Value;

#[derive(Debug, PartialEq)]
pub enum ErrorCode {
	/// Invalid JSON was received by the server.
	/// An error occurred on the server while parsing the JSON text.
	ParseError,
	/// The JSON sent is not a valid Request object.
	InvalidRequest,
	/// The method does not exist / is not available.
	MethodNotFound,
	/// Invalid method parameter(s).
	InvalidParams,
	/// Internal JSON-RPC error.
	InternalError,
	/// Reserved for implementation-defined server-errors.
	ServerError(i64)
}

impl ErrorCode {
	pub fn code(&self) -> i64 {
		match *self {
			ErrorCode::ParseError => -32700,
			ErrorCode::InvalidRequest => -32600,
			ErrorCode::MethodNotFound => -32601,
			ErrorCode::InvalidParams => -32602,
			ErrorCode::InternalError => -32603,
			ErrorCode::ServerError(code) => code
		}
	}

	pub fn description(&self) -> String {
		let desc = match *self {
			ErrorCode::ParseError => "Parse error.",
			ErrorCode::InvalidRequest => "Invalid request.",
			ErrorCode::MethodNotFound => "Method not found.",
			ErrorCode::InvalidParams => "Invalid params.",
			ErrorCode::InternalError => "Internal error.",
			ErrorCode::ServerError(_) => "Server error.",
		};
		desc.to_string()
	}
}

impl Serialize for ErrorCode {
	fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
	where S: Serializer {
		serializer.visit_i64(self.code())
	}
}

#[derive(Debug, PartialEq, Serialize)]
pub struct Error {
	pub code: ErrorCode,
	pub message: String,
	pub data: Option<Value>
}

impl Error {
	pub fn new(code: ErrorCode) -> Self {
		Error {
			message: code.description(),
			code: code,
			data: None
		}
	}

	pub fn parse_error() -> Self {
		Self::new(ErrorCode::ParseError)
	}

	pub fn invalid_request() -> Self {
		Self::new(ErrorCode::InvalidRequest)
	}

	pub fn method_not_found() -> Self {
		Self::new(ErrorCode::MethodNotFound)
	}

	pub fn invalid_params() -> Self {
		Self::new(ErrorCode::InvalidParams)
	}

	pub fn internal_error() -> Self {
		Self::new(ErrorCode::InternalError)
	}
}
<|endoftext|>


<commit_before>use crate::types::FromSqlError;
use crate::types::Type;
use crate::{errmsg_to_string, ffi};
use std::error;
use std::fmt;
use std::os::raw::c_int;
use std::path::PathBuf;
use std::str;

/// Enum listing possible errors from rusqlite.
#[derive(Debug)]
#[allow(clippy::enum_variant_names)]
pub enum Error {
    /// An error from an underlying SQLite call.
    SqliteFailure(ffi::Error, Option<String>),

    /// Error reported when attempting to open a connection when SQLite was
    /// configured to allow single-threaded use only.
    SqliteSingleThreadedMode,

    /// Error when the value of a particular column is requested, but it cannot
    /// be converted to the requested Rust type.
    FromSqlConversionFailure(usize, Type, Box<dyn error::Error + Send + Sync>),

    /// Error when SQLite gives us an integral value outside the range of the
    /// requested type (e.g., trying to get the value 1000 into a `u8`).
    /// The associated `usize` is the column index,
    /// and the associated `i64` is the value returned by SQLite.
    IntegralValueOutOfRange(usize, i64),

    /// Error converting a string to UTF-8.
    Utf8Error(str::Utf8Error),

    /// Error converting a string to a C-compatible string because it contained
    /// an embedded nul.
    NulError(::std::ffi::NulError),

    /// Error when using SQL named parameters and passing a parameter name not
    /// present in the SQL.
    InvalidParameterName(String),

    /// Error converting a file path to a string.
    InvalidPath(PathBuf),

    /// Error returned when an `execute` call returns rows.
    ExecuteReturnedResults,

    /// Error when a query that was expected to return at least one row (e.g.,
    /// for `query_row`) did not return any.
    QueryReturnedNoRows,

    /// Error when the value of a particular column is requested, but the index
    /// is out of range for the statement.
    InvalidColumnIndex(usize),

    /// Error when the value of a named column is requested, but no column
    /// matches the name for the statement.
    InvalidColumnName(String),

    /// Error when the value of a particular column is requested, but the type
    /// of the result in that column cannot be converted to the requested
    /// Rust type.
    InvalidColumnType(usize, String, Type),

    /// Error when a query that was expected to insert one row did not insert
    /// any or insert many.
    StatementChangedRows(usize),

    /// Error returned by `functions::Context::get` when the function argument
    /// cannot be converted to the requested type.
    #[cfg(feature = "functions")]
    InvalidFunctionParameterType(usize, Type),
    /// Error returned by `vtab::Values::get` when the filter argument cannot
    /// be converted to the requested type.
    #[cfg(feature = "vtab")]
    InvalidFilterParameterType(usize, Type),

    /// An error case available for implementors of custom user functions (e.g.,
    /// `create_scalar_function`).
    #[cfg(feature = "functions")]
    #[allow(dead_code)]
    UserFunctionError(Box<dyn error::Error + Send + Sync>),

    /// Error available for the implementors of the `ToSql` trait.
    ToSqlConversionFailure(Box<dyn error::Error + Send + Sync>),

    /// Error when the SQL is not a `SELECT`, is not read-only.
    InvalidQuery,

    /// An error case available for implementors of custom modules (e.g.,
    /// `create_module`).
    #[cfg(feature = "vtab")]
    #[allow(dead_code)]
    ModuleError(String),

    #[cfg(feature = "functions")]
    UnwindingPanic,

    /// An error returned when `Context::get_aux` attempts to retrieve data
    /// of a different type than what had been stored using `Context::set_aux`.
    #[cfg(feature = "functions")]
    GetAuxWrongType,
}

impl PartialEq for Error {
    fn eq(&self, other: &Error) -> bool {
        match (self, other) {
            (Error::SqliteFailure(e1, s1), Error::SqliteFailure(e2, s2)) => e1 == e2 && s1 == s2,
            (Error::SqliteSingleThreadedMode, Error::SqliteSingleThreadedMode) => true,
            (Error::IntegralValueOutOfRange(i1, n1), Error::IntegralValueOutOfRange(i2, n2)) => {
                i1 == i2 && n1 == n2
            }
            (Error::Utf8Error(e1), Error::Utf8Error(e2)) => e1 == e2,
            (Error::NulError(e1), Error::NulError(e2)) => e1 == e2,
            (Error::InvalidParameterName(n1), Error::InvalidParameterName(n2)) => n1 == n2,
            (Error::InvalidPath(p1), Error::InvalidPath(p2)) => p1 == p2,
            (Error::ExecuteReturnedResults, Error::ExecuteReturnedResults) => true,
            (Error::QueryReturnedNoRows, Error::QueryReturnedNoRows) => true,
            (Error::InvalidColumnIndex(i1), Error::InvalidColumnIndex(i2)) => i1 == i2,
            (Error::InvalidColumnName(n1), Error::InvalidColumnName(n2)) => n1 == n2,
            (Error::InvalidColumnType(i1, n1, t1), Error::InvalidColumnType(i2, n2, t2)) => {
                i1 == i2 && t1 == t2 && n1 == n2
            }
            (Error::StatementChangedRows(n1), Error::StatementChangedRows(n2)) => n1 == n2,
            #[cfg(feature = "functions")]
            (
                Error::InvalidFunctionParameterType(i1, t1),
                Error::InvalidFunctionParameterType(i2, t2),
            ) => i1 == i2 && t1 == t2,
            #[cfg(feature = "vtab")]
            (
                Error::InvalidFilterParameterType(i1, t1),
                Error::InvalidFilterParameterType(i2, t2),
            ) => i1 == i2 && t1 == t2,
            (Error::InvalidQuery, Error::InvalidQuery) => true,
            #[cfg(feature = "vtab")]
            (Error::ModuleError(s1), Error::ModuleError(s2)) => s1 == s2,
            #[cfg(feature = "functions")]
            (Error::UnwindingPanic, Error::UnwindingPanic) => true,
            #[cfg(feature = "functions")]
            (Error::GetAuxWrongType, Error::GetAuxWrongType) => true,
            (_, _) => false,
        }
    }
}

impl From<str::Utf8Error> for Error {
    fn from(err: str::Utf8Error) -> Error {
        Error::Utf8Error(err)
    }
}

impl From<::std::ffi::NulError> for Error {
    fn from(err: ::std::ffi::NulError) -> Error {
        Error::NulError(err)
    }
}

const UNKNOWN_COLUMN: usize = std::usize::MAX;

/// The conversion isn't precise, but it's convenient to have it
/// to allow use of `get_raw(…).as_…()?` in callbacks that take `Error`.
impl From<FromSqlError> for Error {
    fn from(err: FromSqlError) -> Error {
        // The error type requires index and type fields, but they aren't known in this
        // context.
        match err {
            FromSqlError::OutOfRange(val) => Error::IntegralValueOutOfRange(UNKNOWN_COLUMN, val),
            #[cfg(feature = "i128_blob")]
            FromSqlError::InvalidI128Size(s) => {
                Error::FromSqlConversionFailure(UNKNOWN_COLUMN, Type::Blob, Box::new(err))
            }
            #[cfg(feature = "uuid")]
            FromSqlError::InvalidUuidSize(s) => {
                Error::FromSqlConversionFailure(UNKNOWN_COLUMN, Type::Blob, Box::new(err))
            }
            FromSqlError::Other(source) => {
                Error::FromSqlConversionFailure(UNKNOWN_COLUMN, Type::Null, source)
            }
            _ => Error::FromSqlConversionFailure(UNKNOWN_COLUMN, Type::Null, Box::new(err)),
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            Error::SqliteFailure(ref err, None) => err.fmt(f),
            Error::SqliteFailure(_, Some(ref s)) => write!(f, "{}", s),
            Error::SqliteSingleThreadedMode => write!(
                f,
                "SQLite was compiled or configured for single-threaded use only"
            ),
            Error::FromSqlConversionFailure(i, ref t, ref err) => {
                if i != UNKNOWN_COLUMN {
                    write!(
                        f,
                        "Conversion error from type {} at index: {}, {}",
                        t, i, err
                    )
                } else {
                    err.fmt(f)
                }
            }
            Error::IntegralValueOutOfRange(col, val) => {
                if col != UNKNOWN_COLUMN {
                    write!(f, "Integer {} out of range at index {}", val, col)
                } else {
                    write!(f, "Integer {} out of range", val)
                }
            }
            Error::Utf8Error(ref err) => err.fmt(f),
            Error::NulError(ref err) => err.fmt(f),
            Error::InvalidParameterName(ref name) => write!(f, "Invalid parameter name: {}", name),
            Error::InvalidPath(ref p) => write!(f, "Invalid path: {}", p.to_string_lossy()),
            Error::ExecuteReturnedResults => {
                write!(f, "Execute returned results - did you mean to call query?")
            }
            Error::QueryReturnedNoRows => write!(f, "Query returned no rows"),
            Error::InvalidColumnIndex(i) => write!(f, "Invalid column index: {}", i),
            Error::InvalidColumnName(ref name) => write!(f, "Invalid column name: {}", name),
            Error::InvalidColumnType(i, ref name, ref t) => write!(
                f,
                "Invalid column type {} at index: {}, name: {}",
                t, i, name
            ),
            Error::StatementChangedRows(i) => write!(f, "Query changed {} rows", i),

            #[cfg(feature = "functions")]
            Error::InvalidFunctionParameterType(i, ref t) => {
                write!(f, "Invalid function parameter type {} at index {}", t, i)
            }
            #[cfg(feature = "vtab")]
            Error::InvalidFilterParameterType(i, ref t) => {
                write!(f, "Invalid filter parameter type {} at index {}", t, i)
            }
            #[cfg(feature = "functions")]
            Error::UserFunctionError(ref err) => err.fmt(f),
            Error::ToSqlConversionFailure(ref err) => err.fmt(f),
            Error::InvalidQuery => write!(f, "Query is not read-only"),
            #[cfg(feature = "vtab")]
            Error::ModuleError(ref desc) => write!(f, "{}", desc),
            #[cfg(feature = "functions")]
            Error::UnwindingPanic => write!(f, "unwinding panic"),
            #[cfg(feature = "functions")]
            Error::GetAuxWrongType => write!(f, "get_aux called with wrong type"),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::SqliteFailure(ref err, None) => err.description(),
            Error::SqliteFailure(_, Some(ref s)) => s,
            Error::SqliteSingleThreadedMode => {
                "SQLite was compiled or configured for single-threaded use only"
            }
            Error::FromSqlConversionFailure(_, _, ref err) => err.description(),
            Error::IntegralValueOutOfRange(_, _) => "integral value out of range of requested type",
            Error::Utf8Error(ref err) => err.description(),
            Error::InvalidParameterName(_) => "invalid parameter name",
            Error::NulError(ref err) => err.description(),
            Error::InvalidPath(_) => "invalid path",
            Error::ExecuteReturnedResults => {
                "execute returned results - did you mean to call query?"
            }
            Error::QueryReturnedNoRows => "query returned no rows",
            Error::InvalidColumnIndex(_) => "invalid column index",
            Error::InvalidColumnName(_) => "invalid column name",
            Error::InvalidColumnType(_, _, _) => "invalid column type",
            Error::StatementChangedRows(_) => "query inserted zero or more than one row",

            #[cfg(feature = "functions")]
            Error::InvalidFunctionParameterType(_, _) => "invalid function parameter type",
            #[cfg(feature = "vtab")]
            Error::InvalidFilterParameterType(_, _) => "invalid filter parameter type",
            #[cfg(feature = "functions")]
            Error::UserFunctionError(ref err) => err.description(),
            Error::ToSqlConversionFailure(ref err) => err.description(),
            Error::InvalidQuery => "query is not read-only",
            #[cfg(feature = "vtab")]
            Error::ModuleError(ref desc) => desc,
            #[cfg(feature = "functions")]
            Error::UnwindingPanic => "unwinding panic",
            #[cfg(feature = "functions")]
            Error::GetAuxWrongType => "get_aux called with wrong type",
        }
    }

    fn cause(&self) -> Option<&dyn error::Error> {
        match *self {
            Error::SqliteFailure(ref err, _) => Some(err),
            Error::Utf8Error(ref err) => Some(err),
            Error::NulError(ref err) => Some(err),

            Error::IntegralValueOutOfRange(_, _)
            | Error::SqliteSingleThreadedMode
            | Error::InvalidParameterName(_)
            | Error::ExecuteReturnedResults
            | Error::QueryReturnedNoRows
            | Error::InvalidColumnIndex(_)
            | Error::InvalidColumnName(_)
            | Error::InvalidColumnType(_, _, _)
            | Error::InvalidPath(_)
            | Error::StatementChangedRows(_)
            | Error::InvalidQuery => None,

            #[cfg(feature = "functions")]
            Error::InvalidFunctionParameterType(_, _) => None,
            #[cfg(feature = "vtab")]
            Error::InvalidFilterParameterType(_, _) => None,

            #[cfg(feature = "functions")]
            Error::UserFunctionError(ref err) => Some(&**err),

            Error::FromSqlConversionFailure(_, _, ref err)
            | Error::ToSqlConversionFailure(ref err) => Some(&**err),

            #[cfg(feature = "vtab")]
            Error::ModuleError(_) => None,

            #[cfg(feature = "functions")]
            Error::UnwindingPanic => None,

            #[cfg(feature = "functions")]
            Error::GetAuxWrongType => None,
        }
    }
}

// These are public but not re-exported by lib.rs, so only visible within crate.

pub fn error_from_sqlite_code(code: c_int, message: Option<String>) -> Error {
    Error::SqliteFailure(ffi::Error::new(code), message)
}

pub fn error_from_handle(db: *mut ffi::sqlite3, code: c_int) -> Error {
    let message = if db.is_null() {
        None
    } else {
        Some(unsafe { errmsg_to_string(ffi::sqlite3_errmsg(db)) })
    };
    error_from_sqlite_code(code, message)
}

macro_rules! check {
    ($funcall:expr) => {{
        let rc = $funcall;
        if rc != crate::ffi::SQLITE_OK {
            return Err(crate::error::error_from_sqlite_code(rc, None).into());
        }
    }};
}
<commit_msg>Fix warnings<commit_after>use crate::types::FromSqlError;
use crate::types::Type;
use crate::{errmsg_to_string, ffi};
use std::error;
use std::fmt;
use std::os::raw::c_int;
use std::path::PathBuf;
use std::str;

/// Enum listing possible errors from rusqlite.
#[derive(Debug)]
#[allow(clippy::enum_variant_names)]
pub enum Error {
    /// An error from an underlying SQLite call.
    SqliteFailure(ffi::Error, Option<String>),

    /// Error reported when attempting to open a connection when SQLite was
    /// configured to allow single-threaded use only.
    SqliteSingleThreadedMode,

    /// Error when the value of a particular column is requested, but it cannot
    /// be converted to the requested Rust type.
    FromSqlConversionFailure(usize, Type, Box<dyn error::Error + Send + Sync>),

    /// Error when SQLite gives us an integral value outside the range of the
    /// requested type (e.g., trying to get the value 1000 into a `u8`).
    /// The associated `usize` is the column index,
    /// and the associated `i64` is the value returned by SQLite.
    IntegralValueOutOfRange(usize, i64),

    /// Error converting a string to UTF-8.
    Utf8Error(str::Utf8Error),

    /// Error converting a string to a C-compatible string because it contained
    /// an embedded nul.
    NulError(::std::ffi::NulError),

    /// Error when using SQL named parameters and passing a parameter name not
    /// present in the SQL.
    InvalidParameterName(String),

    /// Error converting a file path to a string.
    InvalidPath(PathBuf),

    /// Error returned when an `execute` call returns rows.
    ExecuteReturnedResults,

    /// Error when a query that was expected to return at least one row (e.g.,
    /// for `query_row`) did not return any.
    QueryReturnedNoRows,

    /// Error when the value of a particular column is requested, but the index
    /// is out of range for the statement.
    InvalidColumnIndex(usize),

    /// Error when the value of a named column is requested, but no column
    /// matches the name for the statement.
    InvalidColumnName(String),

    /// Error when the value of a particular column is requested, but the type
    /// of the result in that column cannot be converted to the requested
    /// Rust type.
    InvalidColumnType(usize, String, Type),

    /// Error when a query that was expected to insert one row did not insert
    /// any or insert many.
    StatementChangedRows(usize),

    /// Error returned by `functions::Context::get` when the function argument
    /// cannot be converted to the requested type.
    #[cfg(feature = "functions")]
    InvalidFunctionParameterType(usize, Type),
    /// Error returned by `vtab::Values::get` when the filter argument cannot
    /// be converted to the requested type.
    #[cfg(feature = "vtab")]
    InvalidFilterParameterType(usize, Type),

    /// An error case available for implementors of custom user functions (e.g.,
    /// `create_scalar_function`).
    #[cfg(feature = "functions")]
    #[allow(dead_code)]
    UserFunctionError(Box<dyn error::Error + Send + Sync>),

    /// Error available for the implementors of the `ToSql` trait.
    ToSqlConversionFailure(Box<dyn error::Error + Send + Sync>),

    /// Error when the SQL is not a `SELECT`, is not read-only.
    InvalidQuery,

    /// An error case available for implementors of custom modules (e.g.,
    /// `create_module`).
    #[cfg(feature = "vtab")]
    #[allow(dead_code)]
    ModuleError(String),

    #[cfg(feature = "functions")]
    UnwindingPanic,

    /// An error returned when `Context::get_aux` attempts to retrieve data
    /// of a different type than what had been stored using `Context::set_aux`.
    #[cfg(feature = "functions")]
    GetAuxWrongType,
}

impl PartialEq for Error {
    fn eq(&self, other: &Error) -> bool {
        match (self, other) {
            (Error::SqliteFailure(e1, s1), Error::SqliteFailure(e2, s2)) => e1 == e2 && s1 == s2,
            (Error::SqliteSingleThreadedMode, Error::SqliteSingleThreadedMode) => true,
            (Error::IntegralValueOutOfRange(i1, n1), Error::IntegralValueOutOfRange(i2, n2)) => {
                i1 == i2 && n1 == n2
            }
            (Error::Utf8Error(e1), Error::Utf8Error(e2)) => e1 == e2,
            (Error::NulError(e1), Error::NulError(e2)) => e1 == e2,
            (Error::InvalidParameterName(n1), Error::InvalidParameterName(n2)) => n1 == n2,
            (Error::InvalidPath(p1), Error::InvalidPath(p2)) => p1 == p2,
            (Error::ExecuteReturnedResults, Error::ExecuteReturnedResults) => true,
            (Error::QueryReturnedNoRows, Error::QueryReturnedNoRows) => true,
            (Error::InvalidColumnIndex(i1), Error::InvalidColumnIndex(i2)) => i1 == i2,
            (Error::InvalidColumnName(n1), Error::InvalidColumnName(n2)) => n1 == n2,
            (Error::InvalidColumnType(i1, n1, t1), Error::InvalidColumnType(i2, n2, t2)) => {
                i1 == i2 && t1 == t2 && n1 == n2
            }
            (Error::StatementChangedRows(n1), Error::StatementChangedRows(n2)) => n1 == n2,
            #[cfg(feature = "functions")]
            (
                Error::InvalidFunctionParameterType(i1, t1),
                Error::InvalidFunctionParameterType(i2, t2),
            ) => i1 == i2 && t1 == t2,
            #[cfg(feature = "vtab")]
            (
                Error::InvalidFilterParameterType(i1, t1),
                Error::InvalidFilterParameterType(i2, t2),
            ) => i1 == i2 && t1 == t2,
            (Error::InvalidQuery, Error::InvalidQuery) => true,
            #[cfg(feature = "vtab")]
            (Error::ModuleError(s1), Error::ModuleError(s2)) => s1 == s2,
            #[cfg(feature = "functions")]
            (Error::UnwindingPanic, Error::UnwindingPanic) => true,
            #[cfg(feature = "functions")]
            (Error::GetAuxWrongType, Error::GetAuxWrongType) => true,
            (_, _) => false,
        }
    }
}

impl From<str::Utf8Error> for Error {
    fn from(err: str::Utf8Error) -> Error {
        Error::Utf8Error(err)
    }
}

impl From<::std::ffi::NulError> for Error {
    fn from(err: ::std::ffi::NulError) -> Error {
        Error::NulError(err)
    }
}

const UNKNOWN_COLUMN: usize = std::usize::MAX;

/// The conversion isn't precise, but it's convenient to have it
/// to allow use of `get_raw(…).as_…()?` in callbacks that take `Error`.
impl From<FromSqlError> for Error {
    fn from(err: FromSqlError) -> Error {
        // The error type requires index and type fields, but they aren't known in this
        // context.
        match err {
            FromSqlError::OutOfRange(val) => Error::IntegralValueOutOfRange(UNKNOWN_COLUMN, val),
            #[cfg(feature = "i128_blob")]
            FromSqlError::InvalidI128Size(_) => {
                Error::FromSqlConversionFailure(UNKNOWN_COLUMN, Type::Blob, Box::new(err))
            }
            #[cfg(feature = "uuid")]
            FromSqlError::InvalidUuidSize(_) => {
                Error::FromSqlConversionFailure(UNKNOWN_COLUMN, Type::Blob, Box::new(err))
            }
            FromSqlError::Other(source) => {
                Error::FromSqlConversionFailure(UNKNOWN_COLUMN, Type::Null, source)
            }
            _ => Error::FromSqlConversionFailure(UNKNOWN_COLUMN, Type::Null, Box::new(err)),
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            Error::SqliteFailure(ref err, None) => err.fmt(f),
            Error::SqliteFailure(_, Some(ref s)) => write!(f, "{}", s),
            Error::SqliteSingleThreadedMode => write!(
                f,
                "SQLite was compiled or configured for single-threaded use only"
            ),
            Error::FromSqlConversionFailure(i, ref t, ref err) => {
                if i != UNKNOWN_COLUMN {
                    write!(
                        f,
                        "Conversion error from type {} at index: {}, {}",
                        t, i, err
                    )
                } else {
                    err.fmt(f)
                }
            }
            Error::IntegralValueOutOfRange(col, val) => {
                if col != UNKNOWN_COLUMN {
                    write!(f, "Integer {} out of range at index {}", val, col)
                } else {
                    write!(f, "Integer {} out of range", val)
                }
            }
            Error::Utf8Error(ref err) => err.fmt(f),
            Error::NulError(ref err) => err.fmt(f),
            Error::InvalidParameterName(ref name) => write!(f, "Invalid parameter name: {}", name),
            Error::InvalidPath(ref p) => write!(f, "Invalid path: {}", p.to_string_lossy()),
            Error::ExecuteReturnedResults => {
                write!(f, "Execute returned results - did you mean to call query?")
            }
            Error::QueryReturnedNoRows => write!(f, "Query returned no rows"),
            Error::InvalidColumnIndex(i) => write!(f, "Invalid column index: {}", i),
            Error::InvalidColumnName(ref name) => write!(f, "Invalid column name: {}", name),
            Error::InvalidColumnType(i, ref name, ref t) => write!(
                f,
                "Invalid column type {} at index: {}, name: {}",
                t, i, name
            ),
            Error::StatementChangedRows(i) => write!(f, "Query changed {} rows", i),

            #[cfg(feature = "functions")]
            Error::InvalidFunctionParameterType(i, ref t) => {
                write!(f, "Invalid function parameter type {} at index {}", t, i)
            }
            #[cfg(feature = "vtab")]
            Error::InvalidFilterParameterType(i, ref t) => {
                write!(f, "Invalid filter parameter type {} at index {}", t, i)
            }
            #[cfg(feature = "functions")]
            Error::UserFunctionError(ref err) => err.fmt(f),
            Error::ToSqlConversionFailure(ref err) => err.fmt(f),
            Error::InvalidQuery => write!(f, "Query is not read-only"),
            #[cfg(feature = "vtab")]
            Error::ModuleError(ref desc) => write!(f, "{}", desc),
            #[cfg(feature = "functions")]
            Error::UnwindingPanic => write!(f, "unwinding panic"),
            #[cfg(feature = "functions")]
            Error::GetAuxWrongType => write!(f, "get_aux called with wrong type"),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::SqliteFailure(ref err, None) => err.description(),
            Error::SqliteFailure(_, Some(ref s)) => s,
            Error::SqliteSingleThreadedMode => {
                "SQLite was compiled or configured for single-threaded use only"
            }
            Error::FromSqlConversionFailure(_, _, ref err) => err.description(),
            Error::IntegralValueOutOfRange(_, _) => "integral value out of range of requested type",
            Error::Utf8Error(ref err) => err.description(),
            Error::InvalidParameterName(_) => "invalid parameter name",
            Error::NulError(ref err) => err.description(),
            Error::InvalidPath(_) => "invalid path",
            Error::ExecuteReturnedResults => {
                "execute returned results - did you mean to call query?"
            }
            Error::QueryReturnedNoRows => "query returned no rows",
            Error::InvalidColumnIndex(_) => "invalid column index",
            Error::InvalidColumnName(_) => "invalid column name",
            Error::InvalidColumnType(_, _, _) => "invalid column type",
            Error::StatementChangedRows(_) => "query inserted zero or more than one row",

            #[cfg(feature = "functions")]
            Error::InvalidFunctionParameterType(_, _) => "invalid function parameter type",
            #[cfg(feature = "vtab")]
            Error::InvalidFilterParameterType(_, _) => "invalid filter parameter type",
            #[cfg(feature = "functions")]
            Error::UserFunctionError(ref err) => err.description(),
            Error::ToSqlConversionFailure(ref err) => err.description(),
            Error::InvalidQuery => "query is not read-only",
            #[cfg(feature = "vtab")]
            Error::ModuleError(ref desc) => desc,
            #[cfg(feature = "functions")]
            Error::UnwindingPanic => "unwinding panic",
            #[cfg(feature = "functions")]
            Error::GetAuxWrongType => "get_aux called with wrong type",
        }
    }

    fn cause(&self) -> Option<&dyn error::Error> {
        match *self {
            Error::SqliteFailure(ref err, _) => Some(err),
            Error::Utf8Error(ref err) => Some(err),
            Error::NulError(ref err) => Some(err),

            Error::IntegralValueOutOfRange(_, _)
            | Error::SqliteSingleThreadedMode
            | Error::InvalidParameterName(_)
            | Error::ExecuteReturnedResults
            | Error::QueryReturnedNoRows
            | Error::InvalidColumnIndex(_)
            | Error::InvalidColumnName(_)
            | Error::InvalidColumnType(_, _, _)
            | Error::InvalidPath(_)
            | Error::StatementChangedRows(_)
            | Error::InvalidQuery => None,

            #[cfg(feature = "functions")]
            Error::InvalidFunctionParameterType(_, _) => None,
            #[cfg(feature = "vtab")]
            Error::InvalidFilterParameterType(_, _) => None,

            #[cfg(feature = "functions")]
            Error::UserFunctionError(ref err) => Some(&**err),

            Error::FromSqlConversionFailure(_, _, ref err)
            | Error::ToSqlConversionFailure(ref err) => Some(&**err),

            #[cfg(feature = "vtab")]
            Error::ModuleError(_) => None,

            #[cfg(feature = "functions")]
            Error::UnwindingPanic => None,

            #[cfg(feature = "functions")]
            Error::GetAuxWrongType => None,
        }
    }
}

// These are public but not re-exported by lib.rs, so only visible within crate.

pub fn error_from_sqlite_code(code: c_int, message: Option<String>) -> Error {
    Error::SqliteFailure(ffi::Error::new(code), message)
}

pub fn error_from_handle(db: *mut ffi::sqlite3, code: c_int) -> Error {
    let message = if db.is_null() {
        None
    } else {
        Some(unsafe { errmsg_to_string(ffi::sqlite3_errmsg(db)) })
    };
    error_from_sqlite_code(code, message)
}

macro_rules! check {
    ($funcall:expr) => {{
        let rc = $funcall;
        if rc != crate::ffi::SQLITE_OK {
            return Err(crate::error::error_from_sqlite_code(rc, None).into());
        }
    }};
}
<|endoftext|>


<commit_before>//! Provides a standardized error type for oxcable.

use std::error;
use std::fmt;
use std::io;
use std::result;

use byteorder;
use portaudio::pa;
use portmidi;

/// A global error type for all oxcable operations.
///
/// Many of the errors simply wrap the errors provided by our supporting
/// libraries.
#[derive(Debug)]
pub enum Error {
    /// No audio resources can be opened.
    NoAudioDevices,
    /// No MIDI resources can be opened.
    NoMidiDevices,
    /// A file is not formatted properly.
    InvalidFile,
    /// A requested index is out of range.
    ///
    /// The string argument specifies which index was out of range.
    OutOfRange(&'static str),
    /// The requested operation would create a graph cycle.
    CreatesCycle,
    /// A feature isn't supported.
    ///
    /// The string argument describes what feature.
    Unsupported(&'static str),
    /// A std::io operation failed.
    Io(io::Error),
    /// A portaudio operation failed.
    PortAudio(pa::Error),
    /// A portmidi operation failed.
    PortMidi(portmidi::PortMidiError),
}
use self::Error::*;

impl From<byteorder::Error> for Error {
    fn from(e: byteorder::Error) -> Self {
        match e {
            byteorder::Error::UnexpectedEOF => Error::InvalidFile,
            byteorder::Error::Io(e) => Error::Io(e),
        }
    }
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Error::Io(e)
    }
}

impl From<pa::Error> for Error {
    fn from(e: pa::Error) -> Self {
        Error::PortAudio(e)
    }
}

impl From<portmidi::PortMidiError> for Error {
    fn from(e: portmidi::PortMidiError) -> Self {
        Error::PortMidi(e)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self)
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match self {
            &NoAudioDevices => "No audio devices found.",
            &NoMidiDevices => "No midi devices found.",
            &InvalidFile => "The provided was not valid.",
            &OutOfRange(_) => "Index was out of range.",
            &CreatesCycle => "The requested action creates a graph cycle.",
            &Unsupported(_) => "Unsupported feature.",
            &Io(_) => "std::io error",
            &PortAudio(_) => "PortAudio error",
            &PortMidi(_) => "PortMidi error",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match self {
            &Io(ref e) => Some(e),
            &PortAudio(ref e) => Some(e),
            &PortMidi(ref e) => Some(e),
            _ => None,
        }
    }
}

/// A specialized Result for oxcable.
pub type Result<T> = result::Result<T, Error>;
<commit_msg>Strip punctuation from Error description<commit_after>//! Provides a standardized error type for oxcable.

use std::error;
use std::fmt;
use std::io;
use std::result;

use byteorder;
use portaudio::pa;
use portmidi;

/// A global error type for all oxcable operations.
///
/// Many of the errors simply wrap the errors provided by our supporting
/// libraries.
#[derive(Debug)]
pub enum Error {
    /// No audio resources can be opened.
    NoAudioDevices,
    /// No MIDI resources can be opened.
    NoMidiDevices,
    /// A file is not formatted properly.
    InvalidFile,
    /// A requested index is out of range.
    ///
    /// The string argument specifies which index was out of range.
    OutOfRange(&'static str),
    /// The requested operation would create a graph cycle.
    CreatesCycle,
    /// A feature isn't supported.
    ///
    /// The string argument describes what feature.
    Unsupported(&'static str),
    /// A std::io operation failed.
    Io(io::Error),
    /// A portaudio operation failed.
    PortAudio(pa::Error),
    /// A portmidi operation failed.
    PortMidi(portmidi::PortMidiError),
}
use self::Error::*;

impl From<byteorder::Error> for Error {
    fn from(e: byteorder::Error) -> Self {
        match e {
            byteorder::Error::UnexpectedEOF => Error::InvalidFile,
            byteorder::Error::Io(e) => Error::Io(e),
        }
    }
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Error::Io(e)
    }
}

impl From<pa::Error> for Error {
    fn from(e: pa::Error) -> Self {
        Error::PortAudio(e)
    }
}

impl From<portmidi::PortMidiError> for Error {
    fn from(e: portmidi::PortMidiError) -> Self {
        Error::PortMidi(e)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self)
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match self {
            &NoAudioDevices => "No audio devices found",
            &NoMidiDevices => "No midi devices found",
            &InvalidFile => "The provided was not valid",
            &OutOfRange(_) => "Index was out of range",
            &CreatesCycle => "The requested action creates a graph cycle",
            &Unsupported(_) => "Unsupported feature",
            &Io(_) => "std::io error",
            &PortAudio(_) => "PortAudio error",
            &PortMidi(_) => "PortMidi error",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match self {
            &Io(ref e) => Some(e),
            &PortAudio(ref e) => Some(e),
            &PortMidi(ref e) => Some(e),
            _ => None,
        }
    }
}

/// A specialized Result for oxcable.
pub type Result<T> = result::Result<T, Error>;
<|endoftext|>


<commit_before>use crate::logcat::LoggerEntry;

pub enum Event {
    Command(String),
    KeyCode(i32),
    LoggerEntry(LoggerEntry),
}
<commit_msg>Make Event derive Debug, Eq, PartialEq<commit_after>use crate::logcat::LoggerEntry;

#[derive(Debug, Eq, PartialEq)]
pub enum Event {
    Command(String),
    KeyCode(i32),
    LoggerEntry(LoggerEntry),
}
<|endoftext|>


<commit_before>use core_foundation::base::{CFRelease, CFRetain, CFTypeID, CFTypeRef, TCFType};
use geometry::CGPoint;
use event_source::{CGEventSource,CGEventSourceRef};

use libc;
use std::mem;
use std::ptr;

pub type CGKeyCode = libc::uint16_t;

/// Flags for events
///
/// [Ref](http://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-700/IOHIDSystem/IOKit/hidsystem/IOLLEvent.h)
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGEventFlags {
  // Device-independent modifier key bits.
  AlphaShift = 0x00010000,
  Shift = 0x00020000,
  Control = 0x00040000,
  Alternate = 0x00080000,
  Command = 0x00100000,

  // Special key identifiers.
  Help = 0x00400000,
  SecondaryFn = 0x00800000,

  // Identifies key events from numeric keypad area on extended keyboards.
  NumericPad = 0x00200000,

  // Indicates if mouse/pen movement events are not being coalesced
  NonCoalesced = 0x00000100,
}

/// Constants that specify the different types of input events.
///
/// [Ref](http://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-700/IOHIDSystem/IOKit/hidsystem/IOLLEvent.h)
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGEventType {
    Null = 0,

    // Mouse events.
    LeftMouseDown = 1,
    LeftMouseUp = 2,
    RightMouseDown = 3,
    RightMouseUp = 4,
    MouseMoved = 5,
    LeftMouseDragged = 6,
    RightMouseDragged = 7,

    // Keyboard events.
    KeyDown = 10,
    KeyUp = 11,
    FlagsChanged = 12,

    // Specialized control devices.
    ScrollWheel = 22,
    TabletPointer = 23,
    TabletProximity = 24,
    OtherMouseDown = 25,
    OtherMouseUp = 26,
    OtherMouseDragged = 27,

    // Out of band event types. These are delivered to the event tap callback
    // to notify it of unusual conditions that disable the event tap.
    TapDisabledByTimeout = 0xFFFFFFFE,
    TapDisabledByUserInput = 0xFFFFFFFF,
}

// Constants that specify buttons on a one, two, or three-button mouse.
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGMouseButton {
    Left,
    Right,
    Center,
}

/// Possible tapping points for events.
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGEventTapLocation {
    HID,
    Session,
    AnnotatedSession,
}

#[repr(C)]
pub struct __CGEvent;

pub type CGEventRef = *const __CGEvent;

pub struct CGEvent {
    obj: CGEventRef,
}

impl Clone for CGEvent {
    #[inline]
    fn clone(&self) -> CGEvent {
        unsafe {
            TCFType::wrap_under_get_rule(self.obj)
        }
    }
}

impl Drop for CGEvent {
    fn drop(&mut self) {
        unsafe {
            let ptr = self.as_CFTypeRef();
            assert!(ptr != ptr::null());
            CFRelease(ptr);
        }
    }
}

impl TCFType<CGEventRef> for CGEvent {
    #[inline]
    fn as_concrete_TypeRef(&self) -> CGEventRef {
        self.obj
    }

    #[inline]
    unsafe fn wrap_under_get_rule(reference: CGEventRef) -> CGEvent {
        let reference: CGEventRef = mem::transmute(CFRetain(mem::transmute(reference)));
        TCFType::wrap_under_create_rule(reference)
    }

    #[inline]
    fn as_CFTypeRef(&self) -> CFTypeRef {
        unsafe {
            mem::transmute(self.as_concrete_TypeRef())
        }
    }

    #[inline]
    unsafe fn wrap_under_create_rule(obj: CGEventRef) -> CGEvent {
        CGEvent {
            obj: obj,
        }
    }

    #[inline]
    fn type_id() -> CFTypeID {
        unsafe {
            CGEventGetTypeID()
        }
    }
}

impl CGEvent {
    pub fn new(source: CGEventSource) -> Result<CGEvent, ()> {
        unsafe {
            let event_ref = CGEventCreate(source.as_concrete_TypeRef());
            if event_ref != ptr::null() {
                Ok(TCFType::wrap_under_create_rule(event_ref))
            } else {
                Err(())
            }
        }
    }

    pub fn new_keyboard_event(
        source: CGEventSource,
        keycode: CGKeyCode,
        keydown: bool
    ) -> Result<CGEvent, ()> {
        unsafe {
            let event_ref = CGEventCreateKeyboardEvent(source.as_concrete_TypeRef(), keycode, keydown);
            if event_ref != ptr::null() {
                Ok(TCFType::wrap_under_create_rule(event_ref))
            } else {
                Err(())
            }
        }
    }

    pub fn new_mouse_event(
        source: CGEventSource,
        mouse_type: CGEventType,
        mouse_cursor_position: CGPoint,
        mouse_button: CGMouseButton
    ) -> Result<CGEvent, ()> {
        unsafe {
            let event_ref = CGEventCreateMouseEvent(source.as_concrete_TypeRef(), mouse_type,
                mouse_cursor_position, mouse_button);
            if event_ref != ptr::null() {
                Ok(TCFType::wrap_under_create_rule(event_ref))
            } else {
                Err(())
            }
        }
    }

    pub fn post(&self, tap_location: CGEventTapLocation) {
        unsafe {
            CGEventPost(tap_location, self.as_concrete_TypeRef());
        }
    }

    pub fn location(&self) -> CGPoint {
        unsafe {
            CGEventGetLocation(self.as_concrete_TypeRef())
        }
    }

    #[cfg(feature = "elcapitan")]
    pub fn post_to_pid(&self, pid: libc::pid_t) {
        unsafe {
            CGEventPostToPid(pid, self.as_concrete_TypeRef());
        }
    }

    pub fn set_flags(&self, flags: CGEventFlags) {
        unsafe {
            CGEventSetFlags(self.as_concrete_TypeRef(), flags);
        }
    }

    pub fn get_flags(&self) -> CGEventFlags {
        unsafe {
            CGEventGetFlags(self.as_concrete_TypeRef())
        }
    }
}

#[link(name = "ApplicationServices", kind = "framework")]
extern {
    /// Return the type identifier for the opaque type `CGEventRef'.
    fn CGEventGetTypeID() -> CFTypeID;

    /// Return a new event using the event source `source'. If `source' is NULL,
    /// the default source is used.
    fn CGEventCreate(source: CGEventSourceRef) -> CGEventRef;

    /// Return a new keyboard event.
    ///
    /// The event source may be taken from another event, or may be NULL. Based
    /// on the virtual key code values entered, the appropriate key down, key up,
    /// or flags changed events are generated.
    ///
    /// All keystrokes needed to generate a character must be entered, including
    /// SHIFT, CONTROL, OPTION, and COMMAND keys. For example, to produce a 'Z',
    /// the SHIFT key must be down, the 'z' key must go down, and then the SHIFT
    /// and 'z' key must be released:
    fn CGEventCreateKeyboardEvent(source: CGEventSourceRef, keycode: CGKeyCode,
        keydown: bool) -> CGEventRef;

    /// Return a new mouse event.
    ///
    /// The event source may be taken from another event, or may be NULL.
    /// `mouseType' should be one of the mouse event types. `mouseCursorPosition'
    /// should be the position of the mouse cursor in global coordinates.
    /// `mouseButton' should be the button that's changing state; `mouseButton'
    /// is ignored unless `mouseType' is one of `kCGEventOtherMouseDown',
    /// `kCGEventOtherMouseDragged', or `kCGEventOtherMouseUp'.
    ///
    /// The current implemementation of the event system supports a maximum of
    /// thirty-two buttons. Mouse button 0 is the primary button on the mouse.
    /// Mouse button 1 is the secondary mouse button (right). Mouse button 2 is
    /// the center button, and the remaining buttons are in USB device order.
    fn CGEventCreateMouseEvent(source: CGEventSourceRef, mouseType: CGEventType,
        mouseCursorPosition: CGPoint, mouseButton: CGMouseButton) -> CGEventRef;

    /// Post an event into the event stream at a specified location.
    ///
    /// This function posts the specified event immediately before any event taps
    /// instantiated for that location, and the event passes through any such
    /// taps.
    fn CGEventPost(tapLocation: CGEventTapLocation, event: CGEventRef);

    #[cfg(feature = "elcapitan")]
    /// Post an event to a specified process ID
    fn CGEventPostToPid(pid: libc::pid_t, event: CGEventRef);

    /// Set the event flags of an event.
    fn CGEventSetFlags(event: CGEventRef, flags: CGEventFlags);

    /// Return the event flags of an event.
    fn CGEventGetFlags(event: CGEventRef) -> CGEventFlags;

    /// Return the location of an event in global display coordinates.
    /// CGPointZero is returned if event is not a valid CGEventRef.
    fn CGEventGetLocation(event: CGEventRef) -> CGPoint;
}
<commit_msg>Allow applying multiple bitmask flags to events<commit_after>use core_foundation::base::{CFRelease, CFRetain, CFTypeID, CFTypeRef, TCFType};
use geometry::CGPoint;
use event_source::{CGEventSource,CGEventSourceRef};

use libc;
use std::mem;
use std::ptr;

pub type CGKeyCode = libc::uint16_t;
pub type CGEventFlagMask = libc::uint64_t;

/// Flags for events
///
/// [Ref](http://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-700/IOHIDSystem/IOKit/hidsystem/IOLLEvent.h)
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGEventFlags {
  // Device-independent modifier key bits.
  AlphaShift = 0x00010000,
  Shift = 0x00020000,
  Control = 0x00040000,
  Alternate = 0x00080000,
  Command = 0x00100000,

  // Special key identifiers.
  Help = 0x00400000,
  SecondaryFn = 0x00800000,

  // Identifies key events from numeric keypad area on extended keyboards.
  NumericPad = 0x00200000,

  // Indicates if mouse/pen movement events are not being coalesced
  NonCoalesced = 0x00000100,
}

/// Constants that specify the different types of input events.
///
/// [Ref](http://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-700/IOHIDSystem/IOKit/hidsystem/IOLLEvent.h)
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGEventType {
    Null = 0,

    // Mouse events.
    LeftMouseDown = 1,
    LeftMouseUp = 2,
    RightMouseDown = 3,
    RightMouseUp = 4,
    MouseMoved = 5,
    LeftMouseDragged = 6,
    RightMouseDragged = 7,

    // Keyboard events.
    KeyDown = 10,
    KeyUp = 11,
    FlagsChanged = 12,

    // Specialized control devices.
    ScrollWheel = 22,
    TabletPointer = 23,
    TabletProximity = 24,
    OtherMouseDown = 25,
    OtherMouseUp = 26,
    OtherMouseDragged = 27,

    // Out of band event types. These are delivered to the event tap callback
    // to notify it of unusual conditions that disable the event tap.
    TapDisabledByTimeout = 0xFFFFFFFE,
    TapDisabledByUserInput = 0xFFFFFFFF,
}

// Constants that specify buttons on a one, two, or three-button mouse.
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGMouseButton {
    Left,
    Right,
    Center,
}

/// Possible tapping points for events.
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGEventTapLocation {
    HID,
    Session,
    AnnotatedSession,
}

#[repr(C)]
pub struct __CGEvent;

pub type CGEventRef = *const __CGEvent;

pub struct CGEvent {
    obj: CGEventRef,
}

impl Clone for CGEvent {
    #[inline]
    fn clone(&self) -> CGEvent {
        unsafe {
            TCFType::wrap_under_get_rule(self.obj)
        }
    }
}

impl Drop for CGEvent {
    fn drop(&mut self) {
        unsafe {
            let ptr = self.as_CFTypeRef();
            assert!(ptr != ptr::null());
            CFRelease(ptr);
        }
    }
}

impl TCFType<CGEventRef> for CGEvent {
    #[inline]
    fn as_concrete_TypeRef(&self) -> CGEventRef {
        self.obj
    }

    #[inline]
    unsafe fn wrap_under_get_rule(reference: CGEventRef) -> CGEvent {
        let reference: CGEventRef = mem::transmute(CFRetain(mem::transmute(reference)));
        TCFType::wrap_under_create_rule(reference)
    }

    #[inline]
    fn as_CFTypeRef(&self) -> CFTypeRef {
        unsafe {
            mem::transmute(self.as_concrete_TypeRef())
        }
    }

    #[inline]
    unsafe fn wrap_under_create_rule(obj: CGEventRef) -> CGEvent {
        CGEvent {
            obj: obj,
        }
    }

    #[inline]
    fn type_id() -> CFTypeID {
        unsafe {
            CGEventGetTypeID()
        }
    }
}

impl CGEvent {
    pub fn new(source: CGEventSource) -> Result<CGEvent, ()> {
        unsafe {
            let event_ref = CGEventCreate(source.as_concrete_TypeRef());
            if event_ref != ptr::null() {
                Ok(TCFType::wrap_under_create_rule(event_ref))
            } else {
                Err(())
            }
        }
    }

    pub fn new_keyboard_event(
        source: CGEventSource,
        keycode: CGKeyCode,
        keydown: bool
    ) -> Result<CGEvent, ()> {
        unsafe {
            let event_ref = CGEventCreateKeyboardEvent(source.as_concrete_TypeRef(), keycode, keydown);
            if event_ref != ptr::null() {
                Ok(TCFType::wrap_under_create_rule(event_ref))
            } else {
                Err(())
            }
        }
    }

    pub fn new_mouse_event(
        source: CGEventSource,
        mouse_type: CGEventType,
        mouse_cursor_position: CGPoint,
        mouse_button: CGMouseButton
    ) -> Result<CGEvent, ()> {
        unsafe {
            let event_ref = CGEventCreateMouseEvent(source.as_concrete_TypeRef(), mouse_type,
                mouse_cursor_position, mouse_button);
            if event_ref != ptr::null() {
                Ok(TCFType::wrap_under_create_rule(event_ref))
            } else {
                Err(())
            }
        }
    }

    pub fn post(&self, tap_location: CGEventTapLocation) {
        unsafe {
            CGEventPost(tap_location, self.as_concrete_TypeRef());
        }
    }

    pub fn location(&self) -> CGPoint {
        unsafe {
            CGEventGetLocation(self.as_concrete_TypeRef())
        }
    }

    #[cfg(feature = "elcapitan")]
    pub fn post_to_pid(&self, pid: libc::pid_t) {
        unsafe {
            CGEventPostToPid(pid, self.as_concrete_TypeRef());
        }
    }

    pub fn set_flags(&self, flags: CGEventFlagMask) {
        unsafe {
            CGEventSetFlags(self.as_concrete_TypeRef(), flags);
        }
    }

    pub fn get_flags(&self) -> CGEventFlagMask {
        unsafe {
            CGEventGetFlags(self.as_concrete_TypeRef())
        }
    }
}

#[link(name = "ApplicationServices", kind = "framework")]
extern {
    /// Return the type identifier for the opaque type `CGEventRef'.
    fn CGEventGetTypeID() -> CFTypeID;

    /// Return a new event using the event source `source'. If `source' is NULL,
    /// the default source is used.
    fn CGEventCreate(source: CGEventSourceRef) -> CGEventRef;

    /// Return a new keyboard event.
    ///
    /// The event source may be taken from another event, or may be NULL. Based
    /// on the virtual key code values entered, the appropriate key down, key up,
    /// or flags changed events are generated.
    ///
    /// All keystrokes needed to generate a character must be entered, including
    /// SHIFT, CONTROL, OPTION, and COMMAND keys. For example, to produce a 'Z',
    /// the SHIFT key must be down, the 'z' key must go down, and then the SHIFT
    /// and 'z' key must be released:
    fn CGEventCreateKeyboardEvent(source: CGEventSourceRef, keycode: CGKeyCode,
        keydown: bool) -> CGEventRef;

    /// Return a new mouse event.
    ///
    /// The event source may be taken from another event, or may be NULL.
    /// `mouseType' should be one of the mouse event types. `mouseCursorPosition'
    /// should be the position of the mouse cursor in global coordinates.
    /// `mouseButton' should be the button that's changing state; `mouseButton'
    /// is ignored unless `mouseType' is one of `kCGEventOtherMouseDown',
    /// `kCGEventOtherMouseDragged', or `kCGEventOtherMouseUp'.
    ///
    /// The current implemementation of the event system supports a maximum of
    /// thirty-two buttons. Mouse button 0 is the primary button on the mouse.
    /// Mouse button 1 is the secondary mouse button (right). Mouse button 2 is
    /// the center button, and the remaining buttons are in USB device order.
    fn CGEventCreateMouseEvent(source: CGEventSourceRef, mouseType: CGEventType,
        mouseCursorPosition: CGPoint, mouseButton: CGMouseButton) -> CGEventRef;

    /// Post an event into the event stream at a specified location.
    ///
    /// This function posts the specified event immediately before any event taps
    /// instantiated for that location, and the event passes through any such
    /// taps.
    fn CGEventPost(tapLocation: CGEventTapLocation, event: CGEventRef);

    #[cfg(feature = "elcapitan")]
    /// Post an event to a specified process ID
    fn CGEventPostToPid(pid: libc::pid_t, event: CGEventRef);

    /// Set the event flags of an event.
    fn CGEventSetFlags(event: CGEventRef, flags: CGEventFlagMask);

    /// Return the event flags of an event.
    fn CGEventGetFlags(event: CGEventRef) -> CGEventFlagMask;

    /// Return the location of an event in global display coordinates.
    /// CGPointZero is returned if event is not a valid CGEventRef.
    fn CGEventGetLocation(event: CGEventRef) -> CGPoint;
}
<|endoftext|>