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

//! Angle units for type-safe, self-documenting code.

use std::fmt;
use std::f64;
use std::ops::*;

use rand::{Rand, Rng};
use rand::distributions::range::SampleRange;

use rust_num::{Float, Zero};
use rust_num::traits::cast;

use approx::ApproxEq;
use num::BaseFloat;

/// An angle, in radians.
///
/// This type is marked as `#[repr(C, packed)]`.
#[repr(C, packed)]
#[derive(Copy, Clone, PartialEq, PartialOrd, RustcEncodable, RustcDecodable)]
pub struct Rad<S> { pub s: S }

/// An angle, in degrees.
///
/// This type is marked as `#[repr(C, packed)]`.
#[repr(C, packed)]
#[derive(Copy, Clone, PartialEq, PartialOrd, RustcEncodable, RustcDecodable)]
pub struct Deg<S> { pub s: S }

/// Create a new angle, in radians
#[inline] pub fn rad<S: BaseFloat>(s: S) -> Rad<S> { Rad { s: s } }
/// Create a new angle, in degrees
#[inline] pub fn deg<S: BaseFloat>(s: S) -> Deg<S> { Deg { s: s } }

impl<S> From<Rad<S>> for Deg<S> where S: BaseFloat {
    #[inline]
    fn from(r: Rad<S>) -> Deg<S> {
        Deg::new(r.s * cast(180.0 / f64::consts::PI).unwrap())
    }
}

impl<S> From<Deg<S>> for Rad<S> where S: BaseFloat {
    #[inline]
    fn from(d: Deg<S>) -> Rad<S> {
        Rad::new(d.s * cast(f64::consts::PI / 180.0).unwrap())
    }
}

/// Operations on angles.
pub trait Angle where
    Self: Copy + Clone,
    Self: PartialEq + PartialOrd,
    // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
    Self: ApproxEq<Epsilon = <Self as Angle>::Unitless>,

    Self: Neg<Output = Self>,
    Self: Add<Self, Output = Self>,
    Self: Sub<Self, Output = Self>,
    Self: Rem<Self, Output = Self>,
    Self: Mul<<Self as Angle>::Unitless, Output = Self>,
    Self: Div<Self, Output = <Self as Angle>::Unitless>,
    Self: Div<<Self as Angle>::Unitless, Output = Self>,
{
    type Unitless: BaseFloat;

    /// Return the angle, normalized to the range `[0, full_turn)`.
    #[inline]
    fn normalize(self) -> Self {
        let rem = self % Self::full_turn();
        if rem < Self::zero() { rem + Self::full_turn() } else { rem }
    }

    /// Return the angle rotated by half a turn
    #[inline]
    fn opposite(self) -> Self {
        Self::normalize(self + Self::turn_div_2())
    }

    /// Returns the interior bisector of the two angles
    #[inline]
    fn bisect(self, other: Self) -> Self {
        let half = cast(0.5f64).unwrap();
        Self::normalize((self - other) * half + self)
    }

    fn zero() -> Self;
    fn full_turn() -> Self;
    fn turn_div_2() -> Self;
    fn turn_div_3() -> Self;
    fn turn_div_4() -> Self;
    fn turn_div_6() -> Self;

    fn sin(self) -> Self::Unitless;
    fn cos(self) -> Self::Unitless;
    fn tan(self) -> Self::Unitless;
    fn sin_cos(self) -> (Self::Unitless, Self::Unitless);

    #[inline] fn cot(self) -> Self::Unitless { Self::tan(self).recip() }
    #[inline] fn sec(self) -> Self::Unitless { Self::cos(self).recip() }
    #[inline] fn csc(self) -> Self::Unitless { Self::sin(self).recip() }

    fn asin(a: Self::Unitless) -> Self;
    fn acos(a: Self::Unitless) -> Self;
    fn atan(a: Self::Unitless) -> Self;
    fn atan2(a: Self::Unitless, b: Self::Unitless) -> Self;
}

macro_rules! impl_angle {
    ($Angle:ident, $fmt:expr, $full_turn:expr, $hi:expr) => {
        impl<S: BaseFloat> $Angle<S> {
            #[inline]
            pub fn new(value: S) -> $Angle<S> {
                $Angle { s: value }
            }
        }

        impl<S: BaseFloat> Angle for $Angle<S> {
            type Unitless = S;

            #[inline]
            fn zero() -> $Angle<S> {
                $Angle::new(S::zero())
            }

            #[inline] fn full_turn() -> $Angle<S> { $Angle::new(cast($full_turn).unwrap()) }
            #[inline] fn turn_div_2() -> $Angle<S> { let factor: S = cast(2).unwrap(); $Angle::full_turn() / factor }
            #[inline] fn turn_div_3() -> $Angle<S> { let factor: S = cast(3).unwrap(); $Angle::full_turn() / factor }
            #[inline] fn turn_div_4() -> $Angle<S> { let factor: S = cast(4).unwrap(); $Angle::full_turn() / factor }
            #[inline] fn turn_div_6() -> $Angle<S> { let factor: S = cast(6).unwrap(); $Angle::full_turn() / factor }

            #[inline] fn sin(self) -> S { Rad::from(self).s.sin() }
            #[inline] fn cos(self) -> S { Rad::from(self).s.cos() }
            #[inline] fn tan(self) -> S { Rad::from(self).s.tan() }
            #[inline] fn sin_cos(self) -> (S, S) { Rad::from(self).s.sin_cos() }

            #[inline] fn asin(a: S) -> $Angle<S> { Rad::new(a.asin()).into() }
            #[inline] fn acos(a: S) -> $Angle<S> { Rad::new(a.acos()).into() }
            #[inline] fn atan(a: S) -> $Angle<S> { Rad::new(a.atan()).into() }
            #[inline] fn atan2(a: S, b: S) -> $Angle<S> { Rad::new(a.atan2(b)).into() }
        }

        impl<S: BaseFloat> Neg for $Angle<S> {
            type Output = $Angle<S>;

            #[inline]
            fn neg(self) -> $Angle<S> { $Angle::new(-self.s) }
        }

        impl<'a, S: BaseFloat> Neg for &'a $Angle<S> {
            type Output = $Angle<S>;

            #[inline]
            fn neg(self) -> $Angle<S> { $Angle::new(-self.s) }
        }

        impl_operator!(<S: BaseFloat> Add<$Angle<S> > for $Angle<S> {
            fn add(lhs, rhs) -> $Angle<S> { $Angle::new(lhs.s + rhs.s) }
        });
        impl_operator!(<S: BaseFloat> Sub<$Angle<S> > for $Angle<S> {
            fn sub(lhs, rhs) -> $Angle<S> { $Angle::new(lhs.s - rhs.s) }
        });
        impl_operator!(<S: BaseFloat> Div<$Angle<S> > for $Angle<S> {
            fn div(lhs, rhs) -> S { lhs.s / rhs.s }
        });
        impl_operator!(<S: BaseFloat> Rem<$Angle<S> > for $Angle<S> {
            fn rem(lhs, rhs) -> $Angle<S> { $Angle::new(lhs.s % rhs.s) }
        });
        impl_assignment_operator!(<S: BaseFloat> AddAssign<$Angle<S> > for $Angle<S> {
            fn add_assign(&mut self, other) { self.s + other.s; }
        });
        impl_assignment_operator!(<S: BaseFloat> SubAssign<$Angle<S> > for $Angle<S> {
            fn sub_assign(&mut self, other) { self.s - other.s; }
        });
        impl_assignment_operator!(<S: BaseFloat> RemAssign<$Angle<S> > for $Angle<S> {
            fn rem_assign(&mut self, other) { self.s % other.s; }
        });

        impl_operator!(<S: BaseFloat> Mul<S> for $Angle<S> {
            fn mul(lhs, scalar) -> $Angle<S> { $Angle::new(lhs.s * scalar) }
        });
        impl_operator!(<S: BaseFloat> Div<S> for $Angle<S> {
            fn div(lhs, scalar) -> $Angle<S> { $Angle::new(lhs.s / scalar) }
        });
        impl_assignment_operator!(<S: BaseFloat> MulAssign<S> for $Angle<S> {
            fn mul_assign(&mut self, scalar) { self.s * scalar; }
        });
        impl_assignment_operator!(<S: BaseFloat> DivAssign<S> for $Angle<S> {
            fn div_assign(&mut self, scalar) { self.s / scalar; }
        });

        impl<S: BaseFloat> ApproxEq for $Angle<S> {
            type Epsilon = S;

            #[inline]
            fn approx_eq_eps(&self, other: &$Angle<S>, epsilon: &S) -> bool {
                self.s.approx_eq_eps(&other.s, epsilon)
            }
        }

        impl<S: BaseFloat + SampleRange> Rand for $Angle<S> {
            #[inline]
            fn rand<R: Rng>(rng: &mut R) -> $Angle<S> {
                $Angle::new(rng.gen_range(cast(-$hi).unwrap(), cast($hi).unwrap()))
            }
        }

        impl<S: fmt::Debug> fmt::Debug for $Angle<S> {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, $fmt, self.s)
            }
        }
    }
}

impl_angle!(Rad, "{:?} rad", f64::consts::PI * 2.0, f64::consts::PI);
impl_angle!(Deg, "{:?}°", 360, 180);
<commit_msg>Improve the documentation for some angle methods<commit_after>// Copyright 2013-2014 The CGMath Developers. For a full listing of the authors,
// refer to the Cargo.toml file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Angle units for type-safe, self-documenting code.

use std::fmt;
use std::f64;
use std::ops::*;

use rand::{Rand, Rng};
use rand::distributions::range::SampleRange;

use rust_num::{Float, Zero};
use rust_num::traits::cast;

use approx::ApproxEq;
use num::BaseFloat;

/// An angle, in radians.
///
/// This type is marked as `#[repr(C, packed)]`.
#[repr(C, packed)]
#[derive(Copy, Clone, PartialEq, PartialOrd, RustcEncodable, RustcDecodable)]
pub struct Rad<S> { pub s: S }

/// An angle, in degrees.
///
/// This type is marked as `#[repr(C, packed)]`.
#[repr(C, packed)]
#[derive(Copy, Clone, PartialEq, PartialOrd, RustcEncodable, RustcDecodable)]
pub struct Deg<S> { pub s: S }

/// Create a new angle, in radians
#[inline] pub fn rad<S: BaseFloat>(s: S) -> Rad<S> { Rad { s: s } }
/// Create a new angle, in degrees
#[inline] pub fn deg<S: BaseFloat>(s: S) -> Deg<S> { Deg { s: s } }

impl<S> From<Rad<S>> for Deg<S> where S: BaseFloat {
    #[inline]
    fn from(r: Rad<S>) -> Deg<S> {
        Deg::new(r.s * cast(180.0 / f64::consts::PI).unwrap())
    }
}

impl<S> From<Deg<S>> for Rad<S> where S: BaseFloat {
    #[inline]
    fn from(d: Deg<S>) -> Rad<S> {
        Rad::new(d.s * cast(f64::consts::PI / 180.0).unwrap())
    }
}

/// Angles and their associated trigonometric functions.
///
/// Typed angles allow for the writing of self-documenting code that makes it
/// clear when semantic violations have occured - for example, adding degrees to
/// radians, or adding a number to an angle.
///
pub trait Angle where
    Self: Copy + Clone,
    Self: PartialEq + PartialOrd,
    // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
    Self: ApproxEq<Epsilon = <Self as Angle>::Unitless>,

    Self: Neg<Output = Self>,
    Self: Add<Self, Output = Self>,
    Self: Sub<Self, Output = Self>,
    Self: Rem<Self, Output = Self>,
    Self: Mul<<Self as Angle>::Unitless, Output = Self>,
    Self: Div<Self, Output = <Self as Angle>::Unitless>,
    Self: Div<<Self as Angle>::Unitless, Output = Self>,
{
    type Unitless: BaseFloat;

    /// Return the angle, normalized to the range `[0, full_turn)`.
    #[inline]
    fn normalize(self) -> Self {
        let rem = self % Self::full_turn();
        if rem < Self::zero() { rem + Self::full_turn() } else { rem }
    }

    /// Return the angle rotated by half a turn.
    #[inline]
    fn opposite(self) -> Self {
        Self::normalize(self + Self::turn_div_2())
    }

    /// Returns the interior bisector of the two angles.
    #[inline]
    fn bisect(self, other: Self) -> Self {
        let half = cast(0.5f64).unwrap();
        Self::normalize((self - other) * half + self)
    }

    /// The additive identity.
    ///
    /// Adding this to another angle has no affect.
    ///
    /// For example:
    ///
    /// ```rust
    /// use cgmath::prelude::*;
    /// use cgmath::Deg;
    ///
    /// let v = Deg::new(180.0);
    /// assert_eq!(v + Deg::zero(), v);
    /// ```
    fn zero() -> Self;

    /// A full rotation.
    fn full_turn() -> Self;

    /// Half of a full rotation.
    fn turn_div_2() -> Self;

    /// A third of a full rotation.
    fn turn_div_3() -> Self;

    /// A quarter of a full rotation.
    fn turn_div_4() -> Self;

    /// A sixth of a full rotation.
    fn turn_div_6() -> Self;

    /// Compute the sine of the angle, returning a unitless ratio.
    ///
    /// ```rust
    /// use cgmath::prelude::*;
    /// use cgmath::Rad;
    ///
    /// let angle = Rad::new(35.0);
    /// let ratio: f32 = Rad::sin(angle);
    /// ```
    fn sin(self) -> Self::Unitless;

    /// Compute the cosine of the angle, returning a unitless ratio.
    ///
    /// ```rust
    /// use cgmath::prelude::*;
    /// use cgmath::Rad;
    ///
    /// let angle = Rad::new(35.0);
    /// let ratio: f32 = Rad::cos(angle);
    /// ```
    fn cos(self) -> Self::Unitless;

    /// Compute the tangent of the angle, returning a unitless ratio.
    ///
    /// ```rust
    /// use cgmath::prelude::*;
    /// use cgmath::Rad;
    ///
    /// let angle = Rad::new(35.0);
    /// let ratio: f32 = Rad::tan(angle);
    /// ```
    fn tan(self) -> Self::Unitless;

    /// Compute the sine and cosine of the angle, returning the result as a
    /// pair.
    ///
    /// This does not have any performance benefits, but calculating both the
    /// sine and cosine of a single angle is a common operation.
    ///
    /// ```rust
    /// use cgmath::prelude::*;
    /// use cgmath::Rad;
    ///
    /// let angle = Rad::new(35.0);
    /// let (s, c) = Rad::sin_cos(angle);
    /// ```
    fn sin_cos(self) -> (Self::Unitless, Self::Unitless);

    /// Compute the cosecant of the angle.
    ///
    /// This is the same a computing the reciprocal of `Self::sin`.
    ///
    /// ```rust
    /// use cgmath::prelude::*;
    /// use cgmath::Rad;
    ///
    /// let angle = Rad::new(35.0);
    /// let ratio: f32 = Rad::csc(angle);
    /// ```
    #[inline]
    fn csc(self) -> Self::Unitless {
        Self::sin(self).recip()
    }

    /// Compute the secant of the angle.
    ///
    /// This is the same a computing the reciprocal of `Self::tan`.
    ///
    /// ```rust
    /// use cgmath::prelude::*;
    /// use cgmath::Rad;
    ///
    /// let angle = Rad::new(35.0);
    /// let ratio: f32 = Rad::cot(angle);
    /// ```
    #[inline]
    fn cot(self) -> Self::Unitless {
        Self::tan(self).recip()
    }

    /// Compute the cotatangent of the angle.
    ///
    /// This is the same a computing the reciprocal of `Self::cos`.
    ///
    /// ```rust
    /// use cgmath::prelude::*;
    /// use cgmath::Rad;
    ///
    /// let angle = Rad::new(35.0);
    /// let ratio: f32 = Rad::sec(angle);
    /// ```
    #[inline]
    fn sec(self) -> Self::Unitless {
        Self::cos(self).recip()
    }

    /// Compute the arcsine of the ratio, returning the resulting angle.
    ///
    /// ```rust
    /// use cgmath::prelude::*;
    /// use cgmath::Rad;
    ///
    /// let angle: Rad<f32> = Rad::asin(0.5);
    /// ```
    fn asin(ratio: Self::Unitless) -> Self;

    /// Compute the arccosine of the ratio, returning the resulting angle.
    ///
    /// ```rust
    /// use cgmath::prelude::*;
    /// use cgmath::Rad;
    ///
    /// let angle: Rad<f32> = Rad::acos(0.5);
    /// ```
    fn acos(ratio: Self::Unitless) -> Self;

    /// Compute the arctangent of the ratio, returning the resulting angle.
    ///
    /// ```rust
    /// use cgmath::prelude::*;
    /// use cgmath::Rad;
    ///
    /// let angle: Rad<f32> = Rad::atan(0.5);
    /// ```
    fn atan(ratio: Self::Unitless) -> Self;

    fn atan2(a: Self::Unitless, b: Self::Unitless) -> Self;
}

macro_rules! impl_angle {
    ($Angle:ident, $fmt:expr, $full_turn:expr, $hi:expr) => {
        impl<S: BaseFloat> $Angle<S> {
            #[inline]
            pub fn new(value: S) -> $Angle<S> {
                $Angle { s: value }
            }
        }

        impl<S: BaseFloat> Angle for $Angle<S> {
            type Unitless = S;

            #[inline]
            fn zero() -> $Angle<S> {
                $Angle::new(S::zero())
            }

            #[inline] fn full_turn() -> $Angle<S> { $Angle::new(cast($full_turn).unwrap()) }
            #[inline] fn turn_div_2() -> $Angle<S> { let factor: S = cast(2).unwrap(); $Angle::full_turn() / factor }
            #[inline] fn turn_div_3() -> $Angle<S> { let factor: S = cast(3).unwrap(); $Angle::full_turn() / factor }
            #[inline] fn turn_div_4() -> $Angle<S> { let factor: S = cast(4).unwrap(); $Angle::full_turn() / factor }
            #[inline] fn turn_div_6() -> $Angle<S> { let factor: S = cast(6).unwrap(); $Angle::full_turn() / factor }

            #[inline] fn sin(self) -> S { Rad::from(self).s.sin() }
            #[inline] fn cos(self) -> S { Rad::from(self).s.cos() }
            #[inline] fn tan(self) -> S { Rad::from(self).s.tan() }
            #[inline] fn sin_cos(self) -> (S, S) { Rad::from(self).s.sin_cos() }

            #[inline] fn asin(a: S) -> $Angle<S> { Rad::new(a.asin()).into() }
            #[inline] fn acos(a: S) -> $Angle<S> { Rad::new(a.acos()).into() }
            #[inline] fn atan(a: S) -> $Angle<S> { Rad::new(a.atan()).into() }
            #[inline] fn atan2(a: S, b: S) -> $Angle<S> { Rad::new(a.atan2(b)).into() }
        }

        impl<S: BaseFloat> Neg for $Angle<S> {
            type Output = $Angle<S>;

            #[inline]
            fn neg(self) -> $Angle<S> { $Angle::new(-self.s) }
        }

        impl<'a, S: BaseFloat> Neg for &'a $Angle<S> {
            type Output = $Angle<S>;

            #[inline]
            fn neg(self) -> $Angle<S> { $Angle::new(-self.s) }
        }

        impl_operator!(<S: BaseFloat> Add<$Angle<S> > for $Angle<S> {
            fn add(lhs, rhs) -> $Angle<S> { $Angle::new(lhs.s + rhs.s) }
        });
        impl_operator!(<S: BaseFloat> Sub<$Angle<S> > for $Angle<S> {
            fn sub(lhs, rhs) -> $Angle<S> { $Angle::new(lhs.s - rhs.s) }
        });
        impl_operator!(<S: BaseFloat> Div<$Angle<S> > for $Angle<S> {
            fn div(lhs, rhs) -> S { lhs.s / rhs.s }
        });
        impl_operator!(<S: BaseFloat> Rem<$Angle<S> > for $Angle<S> {
            fn rem(lhs, rhs) -> $Angle<S> { $Angle::new(lhs.s % rhs.s) }
        });
        impl_assignment_operator!(<S: BaseFloat> AddAssign<$Angle<S> > for $Angle<S> {
            fn add_assign(&mut self, other) { self.s + other.s; }
        });
        impl_assignment_operator!(<S: BaseFloat> SubAssign<$Angle<S> > for $Angle<S> {
            fn sub_assign(&mut self, other) { self.s - other.s; }
        });
        impl_assignment_operator!(<S: BaseFloat> RemAssign<$Angle<S> > for $Angle<S> {
            fn rem_assign(&mut self, other) { self.s % other.s; }
        });

        impl_operator!(<S: BaseFloat> Mul<S> for $Angle<S> {
            fn mul(lhs, scalar) -> $Angle<S> { $Angle::new(lhs.s * scalar) }
        });
        impl_operator!(<S: BaseFloat> Div<S> for $Angle<S> {
            fn div(lhs, scalar) -> $Angle<S> { $Angle::new(lhs.s / scalar) }
        });
        impl_assignment_operator!(<S: BaseFloat> MulAssign<S> for $Angle<S> {
            fn mul_assign(&mut self, scalar) { self.s * scalar; }
        });
        impl_assignment_operator!(<S: BaseFloat> DivAssign<S> for $Angle<S> {
            fn div_assign(&mut self, scalar) { self.s / scalar; }
        });

        impl<S: BaseFloat> ApproxEq for $Angle<S> {
            type Epsilon = S;

            #[inline]
            fn approx_eq_eps(&self, other: &$Angle<S>, epsilon: &S) -> bool {
                self.s.approx_eq_eps(&other.s, epsilon)
            }
        }

        impl<S: BaseFloat + SampleRange> Rand for $Angle<S> {
            #[inline]
            fn rand<R: Rng>(rng: &mut R) -> $Angle<S> {
                $Angle::new(rng.gen_range(cast(-$hi).unwrap(), cast($hi).unwrap()))
            }
        }

        impl<S: fmt::Debug> fmt::Debug for $Angle<S> {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, $fmt, self.s)
            }
        }
    }
}

impl_angle!(Rad, "{:?} rad", f64::consts::PI * 2.0, f64::consts::PI);
impl_angle!(Deg, "{:?}°", 360, 180);
<|endoftext|>


<commit_before>use krate::Crate;
use schema::badges;
use util::CargoResult;

use diesel::pg::{Pg, PgConnection};
use diesel::prelude::*;
use serde_json;
use std::collections::HashMap;

#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "kebab-case", tag = "badge_type", content = "attributes")]
pub enum Badge {
    TravisCi {
        repository: String,
        branch: Option<String>,
    },
    Appveyor {
        repository: String,
        branch: Option<String>,
        service: Option<String>,
    },
    #[serde(rename = "gitlab")]
    GitLab {
        repository: String,
        branch: Option<String>,
    },
    CircleCi {
        repository: String,
        branch: Option<String>,
    },
    IsItMaintainedIssueResolution { repository: String },
    IsItMaintainedOpenIssues { repository: String },
    Codecov {
        repository: String,
        branch: Option<String>,
        service: Option<String>,
    },
    Coveralls {
        repository: String,
        branch: Option<String>,
        service: Option<String>,
    },
    Maintenance { value: MaintenanceValue },
}

#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
#[serde(tag = "badge_type", content = "attributes")]
pub enum MaintenanceValue {
    #[serde(rename = "actively-developed")]
    ActivelyDeveloped,

    #[serde(rename = "passively-maintained")]
    PassivelyMaintained,

    #[serde(rename = "as-is")]
    AsIs,

    #[serde(rename = "none")]
    None,

    #[serde(rename = "experimental")]
    Experimental,

    #[serde(rename = "looking-for-maintainer")]
    LookingForMaintainer,

    #[serde(rename = "deprecated")]
    Deprecated,
}

#[derive(PartialEq, Debug, Serialize, Deserialize)]
pub struct EncodableBadge {
    pub badge_type: String,
    pub attributes: HashMap<String, Option<String>>,
}

impl Queryable<badges::SqlType, Pg> for Badge {
    type Row = (i32, String, serde_json::Value);

    fn build((_, badge_type, attributes): Self::Row) -> Self {
        let json = json!({"badge_type": badge_type, "attributes": attributes});
        serde_json::from_value(json).expect("Invalid CI badge in the database")
    }
}

impl Badge {
    pub fn encodable(self) -> EncodableBadge {
        serde_json::from_value(serde_json::to_value(self).unwrap()).unwrap()
    }

    pub fn update_crate<'a>(
        conn: &PgConnection,
        krate: &Crate,
        badges: Option<&'a HashMap<String, HashMap<String, String>>>,
    ) -> CargoResult<Vec<&'a str>> {
        use diesel::{insert, delete};

        #[derive(Insertable)]
        #[table_name = "badges"]
        struct NewBadge<'a> {
            crate_id: i32,
            badge_type: &'a str,
            attributes: serde_json::Value,
        }

        let mut invalid_badges = vec![];
        let mut new_badges = vec![];

        if let Some(badges) = badges {
            for (k, v) in badges {
                let attributes_json = serde_json::to_value(v).unwrap();

                let json = json!({"badge_type": k, "attributes": attributes_json});
                if serde_json::from_value::<Badge>(json).is_ok() {
                    new_badges.push(NewBadge {
                        crate_id: krate.id,
                        badge_type: &**k,
                        attributes: attributes_json,
                    });
                } else {
                    invalid_badges.push(&**k);
                }
            }
        }

        conn.transaction(|| {
            delete(badges::table.filter(badges::crate_id.eq(krate.id)))
                .execute(conn)?;
            insert(&new_badges).into(badges::table).execute(conn)?;
            Ok(invalid_badges)
        })
    }
}
<commit_msg>Remove a serde annotation that doesn't apply<commit_after>use krate::Crate;
use schema::badges;
use util::CargoResult;

use diesel::pg::{Pg, PgConnection};
use diesel::prelude::*;
use serde_json;
use std::collections::HashMap;

#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "kebab-case", tag = "badge_type", content = "attributes")]
pub enum Badge {
    TravisCi {
        repository: String,
        branch: Option<String>,
    },
    Appveyor {
        repository: String,
        branch: Option<String>,
        service: Option<String>,
    },
    #[serde(rename = "gitlab")]
    GitLab {
        repository: String,
        branch: Option<String>,
    },
    CircleCi {
        repository: String,
        branch: Option<String>,
    },
    IsItMaintainedIssueResolution { repository: String },
    IsItMaintainedOpenIssues { repository: String },
    Codecov {
        repository: String,
        branch: Option<String>,
        service: Option<String>,
    },
    Coveralls {
        repository: String,
        branch: Option<String>,
        service: Option<String>,
    },
    Maintenance { value: MaintenanceValue },
}

#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
pub enum MaintenanceValue {
    #[serde(rename = "actively-developed")]
    ActivelyDeveloped,

    #[serde(rename = "passively-maintained")]
    PassivelyMaintained,

    #[serde(rename = "as-is")]
    AsIs,

    #[serde(rename = "none")]
    None,

    #[serde(rename = "experimental")]
    Experimental,

    #[serde(rename = "looking-for-maintainer")]
    LookingForMaintainer,

    #[serde(rename = "deprecated")]
    Deprecated,
}

#[derive(PartialEq, Debug, Serialize, Deserialize)]
pub struct EncodableBadge {
    pub badge_type: String,
    pub attributes: HashMap<String, Option<String>>,
}

impl Queryable<badges::SqlType, Pg> for Badge {
    type Row = (i32, String, serde_json::Value);

    fn build((_, badge_type, attributes): Self::Row) -> Self {
        let json = json!({"badge_type": badge_type, "attributes": attributes});
        serde_json::from_value(json).expect("Invalid CI badge in the database")
    }
}

impl Badge {
    pub fn encodable(self) -> EncodableBadge {
        serde_json::from_value(serde_json::to_value(self).unwrap()).unwrap()
    }

    pub fn update_crate<'a>(
        conn: &PgConnection,
        krate: &Crate,
        badges: Option<&'a HashMap<String, HashMap<String, String>>>,
    ) -> CargoResult<Vec<&'a str>> {
        use diesel::{insert, delete};

        #[derive(Insertable)]
        #[table_name = "badges"]
        struct NewBadge<'a> {
            crate_id: i32,
            badge_type: &'a str,
            attributes: serde_json::Value,
        }

        let mut invalid_badges = vec![];
        let mut new_badges = vec![];

        if let Some(badges) = badges {
            for (k, v) in badges {
                let attributes_json = serde_json::to_value(v).unwrap();

                let json = json!({"badge_type": k, "attributes": attributes_json});
                if serde_json::from_value::<Badge>(json).is_ok() {
                    new_badges.push(NewBadge {
                        crate_id: krate.id,
                        badge_type: &**k,
                        attributes: attributes_json,
                    });
                } else {
                    invalid_badges.push(&**k);
                }
            }
        }

        conn.transaction(|| {
            delete(badges::table.filter(badges::crate_id.eq(krate.id)))
                .execute(conn)?;
            insert(&new_badges).into(badges::table).execute(conn)?;
            Ok(invalid_badges)
        })
    }
}
<|endoftext|>


<commit_before>use std::default::Default;

pub struct Chip8 {
    // Clear Display (SDL - black screen)
    pub cls: bool,

    /*
     * 0x000-0x1FF - Chip 8 interpreter (contains font set in emu)
     * 0x050-0x0A0 - Used for the built in 4x5 pixel font set (0-F)
     * 0x200-0xFFF - Program ROM and work RAM
     */
    pub memory: [u8; 4096],

    /*
     * CPU registers: The Chip 8 has 15 8-bit general purpose registers
     * named V0,V1 up to VE. The 16th register is used  for the ‘carry flag’.
     */
    pub registers: [u8; 16],

    // Index register
    pub i: u16,

    // program counter
    pub pc: u16,

    // Screen - 64 x 32 pixels
    pub graphics: [u8; 64*32],

    // No timers, but 60hz counters
    pub delay_timer: u8,
    pub sound_timer: u8,

    // Stack needed to jump to certain addresses or call subroutines
    // The chip8 stack has 16 levels
    pub stack_pointer: u16,
    pub stack: [u16; 16],

    // Chip8 keypad had 16 keys - keep track of the kb state
    pub keypad: [u8; 16],
}

impl Default for Chip8 {
    #[inline]
    fn default() -> Chip8 {
        Chip8 {
            // Let's clear the screen at start
            cls: true,
            memory: [0u8; 4096],
            registers: [0u8; 16],
            i: 0u16,
            pc: 0x200u16,
            graphics: [0u8; 64*32],
            delay_timer: 0u8,
            sound_timer: 0u8,
            stack_pointer: 0u16,
            stack: [0u16; 16],
            keypad: [0u8; 16],
        }
    }
}

impl Chip8 {
   pub fn cycle(&mut self) {
        // fetch
        let highbits: u8 = self.memory[(self.pc as uint)];
        let lowbits: u8 = self.memory[(self.pc + 1) as uint];
        let mut opcode: u16 = highbits as u16;
        opcode = (opcode << 8) | lowbits as u16;

        // Decode
        // Execute
        // Increment the counter
        self.pc += 2;
        // Update timers
    }
}
<commit_msg>begin opcode matching with clear screen: 0x00e0<commit_after>use std::default::Default;

pub struct Chip8 {
    // Clear Display (SDL - black screen)
    pub cls: bool,

    /*
     * 0x000-0x1FF - Chip 8 interpreter (contains font set in emu)
     * 0x050-0x0A0 - Used for the built in 4x5 pixel font set (0-F)
     * 0x200-0xFFF - Program ROM and work RAM
     */
    pub memory: [u8; 4096],

    /*
     * CPU registers: The Chip 8 has 15 8-bit general purpose registers
     * named V0,V1 up to VE. The 16th register is used  for the ‘carry flag’.
     */
    pub registers: [u8; 16],

    // Index register
    pub i: u16,

    // program counter
    pub pc: u16,

    // Screen - 64 x 32 pixels
    pub graphics: [u8; 64*32],

    // No timers, but 60hz counters
    pub delay_timer: u8,
    pub sound_timer: u8,

    // Stack needed to jump to certain addresses or call subroutines
    // The chip8 stack has 16 levels
    pub stack_pointer: u16,
    pub stack: [u16; 16],

    // Chip8 keypad had 16 keys - keep track of the kb state
    pub keypad: [u8; 16],
}

impl Default for Chip8 {
    #[inline]
    fn default() -> Chip8 {
        Chip8 {
            // Let's clear the screen at start
            cls: true,
            memory: [0u8; 4096],
            registers: [0u8; 16],
            i: 0u16,
            pc: 0x200u16,
            graphics: [0u8; 64*32],
            delay_timer: 0u8,
            sound_timer: 0u8,
            stack_pointer: 0u16,
            stack: [0u16; 16],
            keypad: [0u8; 16],
        }
    }
}

impl Chip8 {
   pub fn cycle(&mut self) {
        // fetch
        let highbits: u8 = self.memory[(self.pc as uint)];
        let lowbits: u8 = self.memory[(self.pc + 1) as uint];
        let mut opcode: u16 = highbits as u16;
        opcode = (opcode << 8) | lowbits as u16;

        // Decode
        match opcode {
            // Clear screen
            0x00e0 => self.cls = true,
            op @ _ => println!("Unknown opcode: {:X}", op),
        }
        // Execute
        // Increment the counter
        self.pc += 2;
        // Update timers
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::mem;

const DATA: &'static str = include_str!("../data/input_18.txt");

pub fn main() -> Vec<String> {

    let mut life = Life::from_str(DATA);
    let lcount = life.nth(100).unwrap().lcount();
    vec![format!("{}", lcount)]
}

struct Life([[bool; 100]; 100]);

impl Life {
    fn new() -> Life {
        Life([[false; 100]; 100])
    }

    fn from_str(data: &str) -> Life {
        let mut life = Life::new();
        {
            let Life(ref mut arr) = life;

            for (l, c) in data.lines()
                              .enumerate()
                              .flat_map(move |(l, s)| {
                                  s.chars()
                                   .enumerate()
                                   .filter(|&(_, z)| z == '#')
                                   .map(move |(c, _)| (l, c))
                              }) {
                arr[l][c] = true;
            }
        }
        life
    }

    fn to_string(&self) -> String {
        let &Life(ref arr) = self;
        arr.iter()
           .map(|l| {
               l.iter()
                .map(|v| {
                    match *v {
                        true => '#',
                        false => '.',
                    }
                })
                .collect::<String>()
           })
           .collect::<Vec<String>>()
           .join("\n")
    }

    fn neighbors(x: usize, y: usize) -> Vec<(usize, usize)> {
        let mut n = Vec::new();
        if x != 0 {
            if y != 0 {
                n.push((x - 1, y - 1));
            }
            n.push((x - 1, y));
            if y != 99 {
                n.push((x - 1, y + 1));
            }
        }
        if y != 0 {
            n.push((x, y - 1));
        }
        if y != 99 {
            n.push((x, y + 1));
        }
        if x != 99 {
            if y != 0 {
                n.push((x + 1, y - 1));
            }
            n.push((x + 1, y));
            if y != 99 {
                n.push((x + 1, y + 1));
            }
        }
        n
    }

    fn lcount(&self) -> usize {
        let &Life(ref arr) = self;
        arr.iter()
           .flat_map(|x| x.iter().filter(|&&b| b == true))
           .count()
    }
}

impl Clone for Life {
    fn clone(&self) -> Life {
        let &Life(ref arr) = self;
        Life(*arr)
    }
}

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

impl Iterator for Life {
    type Item = Life;

    fn next(&mut self) -> Option<Life> {
        let &mut Life(ref mut arr) = self;
        let mut next = [[false; 100]; 100];

        for x in 0..100 {
            for y in 0..100 {
                let count = Life::neighbors(x, y)
                                .into_iter()
                                .map(|(x, y)| {
                                    let a = arr.get(x);
                                    let b = a.and_then(|a| a.get(y));
                                    b.unwrap_or(&false).to_owned()
                                })
                                .filter(|b| *b == true)
                                .count();
                match (arr[x][y], count) {
                    (true, 2) | (true, 3) => next[x][y] = true,
                    (true, _) => next[x][y] = false,
                    (false, 3) => next[x][y] = true,
                    (false, _) => next[x][y] = false,
                }
            }
        }
        // force corners on
        {
            next[0][0] = true;
            next[0][99] = true;
            next[99][0] = true;
            next[99][99] = true;
        }
        mem::swap(arr, &mut next);
        //mem::replace(arr, next);
        Some(Life(next))
    }
}
<commit_msg>day 18 cleaned up a touch<commit_after>use std::fmt;
use std::mem;

const DATA: &'static str = include_str!("../data/input_18.txt");

pub fn main() -> Vec<String> {
    let mut life = Life::from_str(DATA);
    let lcount = life.nth(100).unwrap().lcount();

    let mut life = Life::from_str(DATA);
    life.stick(0, 0);
    life.stick(0, 99);
    life.stick(99, 0);
    life.stick(99, 99);
    let lcount2 = life.nth(100).unwrap().lcount();

    vec![lcount.to_string(), lcount2.to_string()]
}

struct Life {
    arr: [[bool; 100]; 100],
    stuck: Vec<(usize, usize)>,
}

impl Life {
    fn new() -> Life {
        Life {
            arr: [[false; 100]; 100],
            stuck: Vec::new(),
        }
    }

    fn stick(&mut self, x: usize, y: usize) {
        self.stuck.push((x, y));
    }

    fn from_str(data: &str) -> Life {
        let mut life = Life::new();
        {
            for (l, c) in data.lines()
                              .enumerate()
                              .flat_map(move |(l, s)| {
                                  s.chars()
                                   .enumerate()
                                   .filter(|&(_, z)| z == '#')
                                   .map(move |(c, _)| (l, c))
                              }) {
                life.arr[l][c] = true;
            }
        }
        life
    }

    fn to_string(&self) -> String {
        self.arr
            .iter()
            .map(|l| {
                l.iter()
                 .map(|v| {
                     match *v {
                         true => '#',
                         false => '.',
                     }
                 })
                 .collect::<String>()
            })
            .collect::<Vec<String>>()
            .join("\n")
    }

    fn neighbors(x: usize, y: usize) -> Vec<(usize, usize)> {
        let mut n = Vec::new();
        if x != 0 {
            if y != 0 {
                n.push((x - 1, y - 1));
            }
            n.push((x - 1, y));
            if y != 99 {
                n.push((x - 1, y + 1));
            }
        }
        if y != 0 {
            n.push((x, y - 1));
        }
        if y != 99 {
            n.push((x, y + 1));
        }
        if x != 99 {
            if y != 0 {
                n.push((x + 1, y - 1));
            }
            n.push((x + 1, y));
            if y != 99 {
                n.push((x + 1, y + 1));
            }
        }
        n
    }

    fn lcount(&self) -> usize {
        self.arr
            .iter()
            .flat_map(|x| x.iter().filter(|&&b| b == true))
            .count()
    }
}

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

impl Iterator for Life {
    type Item = Life;

    fn next(&mut self) -> Option<Life> {
        let mut next = [[false; 100]; 100];

        for x in 0..100 {
            for y in 0..100 {
                let count = Life::neighbors(x, y)
                                .into_iter()
                                .map(|(x, y)| {
                                    let a = self.arr.get(x);
                                    let b = a.and_then(|a| a.get(y));
                                    b.unwrap_or(&false).to_owned()
                                })
                                .filter(|b| *b == true)
                                .count();
                match (self.arr[x][y], count) {
                    (true, 2) | (true, 3) => next[x][y] = true,
                    (true, _) => next[x][y] = false,
                    (false, 3) => next[x][y] = true,
                    (false, _) => next[x][y] = false,
                }
            }
        }
        for &(x, y) in self.stuck.iter() {
            next[x][y] = true;
        }

        mem::swap(&mut self.arr, &mut next);

        Some(Life {
            arr: next,
            stuck: self.stuck.clone(),
        })
    }
}
<|endoftext|>


<commit_before>use bytecodec;
use fibers::sync::oneshot::MonitorError;
use fibers_transport;
use std::io;
use std::sync::mpsc::SendError;
use stun_codec::rfc5389::attributes::ErrorCode;
use stun_codec::AttributeType;
use trackable::error::{self, ErrorKindExt, TrackableError};

/// This crate specific `Error` type.
#[derive(Debug, Clone, TrackableError)]
pub struct Error(TrackableError<ErrorKind>);
impl From<MonitorError<Error>> for Error {
    fn from(f: MonitorError<Error>) -> Self {
        f.unwrap_or_else(|| {
            ErrorKind::Other
                .cause("Monitor channel has disconnected")
                .into()
        })
    }
}
impl From<io::Error> for Error {
    fn from(f: io::Error) -> Self {
        ErrorKind::Other.cause(f).into()
    }
}
impl<T> From<SendError<T>> for Error {
    fn from(_: SendError<T>) -> Self {
        ErrorKind::Other.cause("Receiver has terminated").into()
    }
}
impl From<bytecodec::Error> for Error {
    fn from(f: bytecodec::Error) -> Self {
        let original_error_kind = *f.kind();
        let kind = match original_error_kind {
            bytecodec::ErrorKind::InvalidInput => ErrorKind::InvalidInput,
            _ => ErrorKind::Other,
        };
        track!(kind.takes_over(f); original_error_kind).into()
    }
}
impl From<MessageError> for Error {
    fn from(f: MessageError) -> Self {
        ErrorKind::InvalidMessage(f.kind().clone())
            .takes_over(f)
            .into()
    }
}
impl From<ErrorCode> for Error {
    fn from(f: ErrorCode) -> Self {
        ErrorKind::Other
            .cause(format!("STUN error response: {:?}", f))
            .into()
    }
}
impl From<fibers_transport::Error> for Error {
    fn from(f: fibers_transport::Error) -> Self {
        let original_error_kind = *f.kind();
        let kind = match original_error_kind {
            fibers_transport::ErrorKind::InvalidInput => ErrorKind::InvalidInput,
            _ => ErrorKind::Other,
        };
        track!(kind.takes_over(f); original_error_kind).into()
    }
}

/// Possible error kinds.
#[derive(Debug, Clone)]
pub enum ErrorKind {
    /// Input is invalid.
    InvalidInput,

    /// A message is invalid.
    ///
    /// This error does not affect the overall execution of a channel/client/server.
    InvalidMessage(MessageErrorKind),

    /// Other errors.
    Other,
}
impl error::ErrorKind for ErrorKind {}

/// Message level error.
#[derive(Debug, Clone)]
pub struct MessageError(TrackableError<MessageErrorKind>);
derive_traits_for_trackable_error_newtype!(MessageError, MessageErrorKind);
impl From<MonitorError<MessageError>> for MessageError {
    fn from(f: MonitorError<MessageError>) -> Self {
        f.unwrap_or_else(|| {
            MessageErrorKind::Other
                .cause("`Channel` instance has dropped")
                .into()
        })
    }
}
impl From<Error> for MessageError {
    fn from(f: Error) -> Self {
        let original_error_kind = f.kind().clone();
        track!(MessageErrorKind::Other.takes_over(f); original_error_kind).into()
    }
}
impl From<fibers_transport::Error> for MessageError {
    fn from(f: fibers_transport::Error) -> Self {
        let original_error_kind = *f.kind();
        let kind = match original_error_kind {
            fibers_transport::ErrorKind::InvalidInput => MessageErrorKind::InvalidInput,
            _ => MessageErrorKind::Other,
        };
        track!(kind.takes_over(f); original_error_kind).into()
    }
}

/// Possible error kinds.
#[derive(Debug, Clone)]
pub enum MessageErrorKind {
    /// Unexpected response message.
    UnexpectedResponse,

    /// There are some malformed attributes in a message.
    MalformedAttribute,

    /// There are unknown comprehension-required attributes.
    ///
    /// If a server receives a message that contains unknown comprehension-required attributes,
    /// it should reply an `ErrorResponse` message that has the [`UnknownAttribute`] error code and
    /// an [`UnknownAttributes`] attribute.
    ///
    /// [`UnknownAttribute`]: https://docs.rs/stun_codec/0.1/stun_codec/rfc5389/errors/struct.UnknownAttribute.html
    /// [`UnknownAttributes`]: https://docs.rs/stun_codec/0.1/stun_codec/rfc5389/attributes/struct.UnknownAttributes.html
    UnknownAttributes(Vec<AttributeType>),

    /// Input is invalid.
    InvalidInput,

    /// Operation timed out.
    Timeout,

    /// Other errors.
    Other,
}
impl error::ErrorKind for MessageErrorKind {}
<commit_msg>Stop using deprecated `derive_traits_for_trackable_error_newtype!` macro<commit_after>use bytecodec;
use fibers::sync::oneshot::MonitorError;
use fibers_transport;
use std::io;
use std::sync::mpsc::SendError;
use stun_codec::rfc5389::attributes::ErrorCode;
use stun_codec::AttributeType;
use trackable::error::{self, ErrorKindExt, TrackableError};

/// This crate specific `Error` type.
#[derive(Debug, Clone, TrackableError)]
pub struct Error(TrackableError<ErrorKind>);
impl From<MonitorError<Error>> for Error {
    fn from(f: MonitorError<Error>) -> Self {
        f.unwrap_or_else(|| {
            ErrorKind::Other
                .cause("Monitor channel has disconnected")
                .into()
        })
    }
}
impl From<io::Error> for Error {
    fn from(f: io::Error) -> Self {
        ErrorKind::Other.cause(f).into()
    }
}
impl<T> From<SendError<T>> for Error {
    fn from(_: SendError<T>) -> Self {
        ErrorKind::Other.cause("Receiver has terminated").into()
    }
}
impl From<bytecodec::Error> for Error {
    fn from(f: bytecodec::Error) -> Self {
        let original_error_kind = *f.kind();
        let kind = match original_error_kind {
            bytecodec::ErrorKind::InvalidInput => ErrorKind::InvalidInput,
            _ => ErrorKind::Other,
        };
        track!(kind.takes_over(f); original_error_kind).into()
    }
}
impl From<MessageError> for Error {
    fn from(f: MessageError) -> Self {
        ErrorKind::InvalidMessage(f.kind().clone())
            .takes_over(f)
            .into()
    }
}
impl From<ErrorCode> for Error {
    fn from(f: ErrorCode) -> Self {
        ErrorKind::Other
            .cause(format!("STUN error response: {:?}", f))
            .into()
    }
}
impl From<fibers_transport::Error> for Error {
    fn from(f: fibers_transport::Error) -> Self {
        let original_error_kind = *f.kind();
        let kind = match original_error_kind {
            fibers_transport::ErrorKind::InvalidInput => ErrorKind::InvalidInput,
            _ => ErrorKind::Other,
        };
        track!(kind.takes_over(f); original_error_kind).into()
    }
}

/// Possible error kinds.
#[derive(Debug, Clone)]
pub enum ErrorKind {
    /// Input is invalid.
    InvalidInput,

    /// A message is invalid.
    ///
    /// This error does not affect the overall execution of a channel/client/server.
    InvalidMessage(MessageErrorKind),

    /// Other errors.
    Other,
}
impl error::ErrorKind for ErrorKind {}

/// Message level error.
#[derive(Debug, Clone, TrackableError)]
#[trackable(error_kind = "MessageErrorKind")]
pub struct MessageError(TrackableError<MessageErrorKind>);
impl From<MonitorError<MessageError>> for MessageError {
    fn from(f: MonitorError<MessageError>) -> Self {
        f.unwrap_or_else(|| {
            MessageErrorKind::Other
                .cause("`Channel` instance has dropped")
                .into()
        })
    }
}
impl From<Error> for MessageError {
    fn from(f: Error) -> Self {
        let original_error_kind = f.kind().clone();
        track!(MessageErrorKind::Other.takes_over(f); original_error_kind).into()
    }
}
impl From<fibers_transport::Error> for MessageError {
    fn from(f: fibers_transport::Error) -> Self {
        let original_error_kind = *f.kind();
        let kind = match original_error_kind {
            fibers_transport::ErrorKind::InvalidInput => MessageErrorKind::InvalidInput,
            _ => MessageErrorKind::Other,
        };
        track!(kind.takes_over(f); original_error_kind).into()
    }
}

/// Possible error kinds.
#[derive(Debug, Clone)]
pub enum MessageErrorKind {
    /// Unexpected response message.
    UnexpectedResponse,

    /// There are some malformed attributes in a message.
    MalformedAttribute,

    /// There are unknown comprehension-required attributes.
    ///
    /// If a server receives a message that contains unknown comprehension-required attributes,
    /// it should reply an `ErrorResponse` message that has the [`UnknownAttribute`] error code and
    /// an [`UnknownAttributes`] attribute.
    ///
    /// [`UnknownAttribute`]: https://docs.rs/stun_codec/0.1/stun_codec/rfc5389/errors/struct.UnknownAttribute.html
    /// [`UnknownAttributes`]: https://docs.rs/stun_codec/0.1/stun_codec/rfc5389/attributes/struct.UnknownAttributes.html
    UnknownAttributes(Vec<AttributeType>),

    /// Input is invalid.
    InvalidInput,

    /// Operation timed out.
    Timeout,

    /// Other errors.
    Other,
}
impl error::ErrorKind for MessageErrorKind {}
<|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 GError; unlike g_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 a GError 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
    /// 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 src ; otherwise, moves src into *other . The error variable
    /// other.pointer points to must be NULL.
    ///
    /// Note that src is no longer valid after this call. If you want to keep using the same GError*, 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>Fix typos<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 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
    }
}
<|endoftext|>


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

/// Old name for `Error`. `SqliteError` is deprecated.
#[deprecated(since = "0.6.0", note = "Use Error instead")]
pub type SqliteError = Error;

/// Enum listing possible errors from rusqlite.
#[derive(Debug)]
#[allow(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<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 `c_int` is the column index, and
    /// the associated `i64` is the value returned by SQLite.
    IntegralValueOutOfRange(c_int, 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(c_int),

    /// 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(c_int, Type),

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

    /// Error returned by `functions::Context::get` when the function argument cannot be converted
    /// to the requested type.
    #[cfg(feature = "functions")]
    InvalidFunctionParameterType(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<error::Error + Send + Sync>),

    /// Error available for the implementors of the `FromSql` trait.
    Other(Box<error::Error + Send + Sync>),
}

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

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) => {
                write!(f,
                       "Conversion error from type {} at index: {}, {}",
                       t,
                       i,
                       err)
            }
            Error::IntegralValueOutOfRange(col, val) => {
                write!(f, "Integer {} out of range at index {}", val, col)
            }
            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 t) => {
                write!(f, "Invalid column type {} at index: {}", t, i)
            }
            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 = "functions")]
            Error::UserFunctionError(ref err) => err.fmt(f),
            Error::Other(ref err) => err.fmt(f),
        }
    }
}

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 = "functions")]
            Error::UserFunctionError(ref err) => err.description(),
            Error::Other(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::SqliteFailure(ref err, _) => Some(err),
            Error::FromSqlConversionFailure(_, _, 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(_) => None,

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

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

// 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)
}
<commit_msg>Rename Error::Other to Error::ToSqlConversionFailure<commit_after>use std::error;
use std::fmt;
use std::path::PathBuf;
use std::str;
use std::os::raw::c_int;
use {ffi, errmsg_to_string};
use types::Type;

/// Old name for `Error`. `SqliteError` is deprecated.
#[deprecated(since = "0.6.0", note = "Use Error instead")]
pub type SqliteError = Error;

/// Enum listing possible errors from rusqlite.
#[derive(Debug)]
#[allow(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<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 `c_int` is the column index, and
    /// the associated `i64` is the value returned by SQLite.
    IntegralValueOutOfRange(c_int, 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(c_int),

    /// 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(c_int, Type),

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

    /// Error returned by `functions::Context::get` when the function argument cannot be converted
    /// to the requested type.
    #[cfg(feature = "functions")]
    InvalidFunctionParameterType(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<error::Error + Send + Sync>),

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

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

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) => {
                write!(f,
                       "Conversion error from type {} at index: {}, {}",
                       t,
                       i,
                       err)
            }
            Error::IntegralValueOutOfRange(col, val) => {
                write!(f, "Integer {} out of range at index {}", val, col)
            }
            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 t) => {
                write!(f, "Invalid column type {} at index: {}", t, i)
            }
            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 = "functions")]
            Error::UserFunctionError(ref err) => err.fmt(f),
            Error::ToSqlConversionFailure(ref err) => err.fmt(f),
        }
    }
}

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 = "functions")]
            Error::UserFunctionError(ref err) => err.description(),
            Error::ToSqlConversionFailure(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::SqliteFailure(ref err, _) => Some(err),
            Error::FromSqlConversionFailure(_, _, 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(_) => None,

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

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

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


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

use std::fs::{self, File};
use std::path::{Path, PathBuf};
use std::result;
use std::time::{UNIX_EPOCH, SystemTime};
use std::fmt;

use serde::{Serialize, Serializer};
use serde::ser::SerializeStruct;
use serde_json;

/// Sample envelope JSON payload
/// {
///   "timestamp": "1479330000.13442404",
///   "version": 1,
///   "event": {
///     "name": "project-create",
///     "origin" : "myorigin"
///     "package" : "mypackage"
///     "account" : "133508078967455744"
///   }
/// }
pub const SCHEMA_VERSION: u32 = 1;

// Macros to help hooking in the event logger into an Iron chain,
// and calling into the chained event logger.
#[macro_export]
macro_rules! define_event_log {
    () => {
        pub struct EventLog;
        impl typemap::Key for EventLog {
            type Value = EventLogger;
        }
    }
}

#[macro_export]
macro_rules! log_event {
    ($req:ident, $evt:expr) => {{
        let el = ($req).get::<persistent::Read<EventLog>>().unwrap();
        el.record_event($evt)
    }};
}

#[derive(Debug, Clone)]
pub enum Event {
    ProjectCreate {
        origin: String,
        package: String,
        account: String,
    },
    PackageUpload {
        origin: String,
        package: String,
        version: String,
        release: String,
        target: String,
        account: String,
    },
    OriginKeyUpload {
        origin: String,
        version: String,
        account: String,
    },
    OriginSecretKeyUpload {
        origin: String,
        version: String,
        account: String,
    },
    OriginInvitationSend {
        origin: String,
        user: String,
        id: String,
        account: String,
    },
    OriginInvitationAccept { id: String, account: String },
    OriginInvitationIgnore { id: String, account: String },
    JobCreate { package: String, account: String },
    GithubAuthenticate { user: String, account: String },
}

impl fmt::Display for Event {
    // TODO fn: As of rustfmt 0.7.1 the following match block is not well understood. The tool puts
    // all match arms on the same line which blows over the 100-column max which then fails the
    // tool with a `"line exceeded maximum length"` error. This ignore should be removed when we
    // upgrade rustfmt and retry.
    #[cfg_attr(rustfmt, rustfmt_skip)]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let msg = match *self {
            Event::ProjectCreate { origin: _, package: _, account: _ } => "project-create",
            Event::PackageUpload { origin: _, package: _, version: _, release: _, target: _,
                account: _ } => {
                "package-upload"
            }
            Event::OriginKeyUpload { origin: _, version: _, account: _ } => "origin-key-upload",
            Event::OriginSecretKeyUpload { origin: _, version: _, account: _ } => {
                "origin-secret-key-upload"
            }
            Event::OriginInvitationSend { origin: _, user: _, id: _, account: _ } => {
                "origin-invitation-send"
            }
            Event::OriginInvitationAccept { id: _, account: _ } => "origin-invitation-accept",
            Event::OriginInvitationIgnore { id: _, account: _ } => "origin-invitation-ignore",
            Event::JobCreate { package: _, account: _ } => "job-create",
            Event::GithubAuthenticate { user: _, account: _ } => "github-authenticate",
        };

        write!(f, "{}", msg)
    }
}

impl Serialize for Event {
    fn serialize<S>(&self, serializer: S) -> result::Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let strukt = match *self {
            Event::ProjectCreate {
                origin: ref o,
                package: ref p,
                account: ref a,
            } => {
                let mut strukt = serializer.serialize_struct("event", 4)?;
                strukt.serialize_field("name", &self.to_string())?;
                strukt.serialize_field("origin", o)?;
                strukt.serialize_field("package", p)?;
                strukt.serialize_field("account", a)?;
                strukt
            }
            Event::PackageUpload {
                origin: ref o,
                package: ref p,
                version: ref v,
                release: ref r,
                target: ref t,
                account: ref a,
            } => {
                let mut strukt = serializer.serialize_struct("event", 6)?;
                strukt.serialize_field("name", &self.to_string())?;
                strukt.serialize_field("origin", o)?;
                strukt.serialize_field("package", p)?;
                strukt.serialize_field("version", v)?;
                strukt.serialize_field("release", r)?;
                strukt.serialize_field("target", t)?;
                strukt.serialize_field("account", a)?;
                strukt
            }
            Event::OriginInvitationSend {
                origin: ref o,
                user: ref u,
                id: ref i,
                account: ref a,
            } => {
                let mut strukt = serializer.serialize_struct("event", 5)?;
                strukt.serialize_field("name", &self.to_string())?;
                strukt.serialize_field("origin", o)?;
                strukt.serialize_field("user", u)?;
                strukt.serialize_field("id", i)?;
                strukt.serialize_field("account", a)?;
                strukt
            }
            Event::OriginInvitationAccept {
                id: ref i,
                account: ref a,
            } => {
                let mut strukt = serializer.serialize_struct("event", 3)?;
                strukt.serialize_field("name", &self.to_string())?;
                strukt.serialize_field("id", i)?;
                strukt.serialize_field("account", a)?;
                strukt
            }
            Event::OriginInvitationIgnore {
                id: ref i,
                account: ref a,
            } => {
                let mut strukt = serializer.serialize_struct("event", 3)?;
                strukt.serialize_field("name", &self.to_string())?;
                strukt.serialize_field("id", i)?;
                strukt.serialize_field("account", a)?;
                strukt
            }
            Event::JobCreate {
                package: ref p,
                account: ref a,
            } => {
                let mut strukt = serializer.serialize_struct("event", 3)?;
                strukt.serialize_field("name", &self.to_string())?;
                strukt.serialize_field("package", p)?;
                strukt.serialize_field("account", a)?;
                strukt
            }
            Event::GithubAuthenticate {
                user: ref u,
                account: ref a,
            } => {
                let mut strukt = serializer.serialize_struct("event", 3)?;
                strukt.serialize_field("name", &self.to_string())?;
                strukt.serialize_field("user", u)?;
                strukt.serialize_field("account", a)?;
                strukt
            }
            Event::OriginKeyUpload {
                origin: ref o,
                version: ref v,
                account: ref a,
            } => {
                let mut strukt = serializer.serialize_struct("event", 4)?;
                strukt.serialize_field("name", &self.to_string())?;
                strukt.serialize_field("origin", o)?;
                strukt.serialize_field("version", v)?;
                strukt.serialize_field("account", a)?;
                strukt
            }
            Event::OriginSecretKeyUpload {
                origin: ref o,
                version: ref v,
                account: ref a,
            } => {
                let mut strukt = serializer.serialize_struct("event", 4)?;
                strukt.serialize_field("name", &self.to_string())?;
                strukt.serialize_field("origin", o)?;
                strukt.serialize_field("version", v)?;
                strukt.serialize_field("account", a)?;
                strukt
            }
        };
        strukt.end()
    }
}

#[derive(Debug, Clone)]
pub struct Envelope {
    pub version: u32,
    pub timestamp: String,
    pub event: Event,
}

impl Envelope {
    pub fn new(event: &Event) -> Self {
        Envelope {
            version: SCHEMA_VERSION,
            timestamp: timestamp(),
            event: event.clone(),
        }
    }
}

impl Serialize for Envelope {
    fn serialize<S>(&self, serializer: S) -> result::Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut strukt = serializer.serialize_struct("envelope", 3)?;
        strukt.serialize_field("version", &self.version)?;
        strukt.serialize_field("timestamp", &self.timestamp)?;
        strukt.serialize_field("event", &self.event)?;
        strukt.end()
    }
}

fn write_file<T>(parent_dir: &Path, file_path: &Path, val: &T)
where
    T: Serialize + ?Sized,
{
    fs::create_dir_all(parent_dir).expect("Unable to create directory");
    let mut file = File::create(&file_path).expect("Unable to create file");
    serde_json::ser::to_writer(&mut file, val).expect("Unable to write file");
}

fn timestamp() -> String {
    let (secs, subsec_nanos) = match SystemTime::now().duration_since(UNIX_EPOCH) {
        Ok(duration) => (duration.as_secs(), duration.subsec_nanos()),
        Err(e) => {
            error!("Cannot generate system time: {}", e);
            return "0.0".to_string();
        }
    };
    format!("{}.{}", secs, subsec_nanos)
}

pub struct EventLogger {
    log_dir: PathBuf,
    enabled: bool,
}

impl EventLogger {
    pub fn new<T: Into<PathBuf>>(log_dir: T, enabled: bool) -> Self {
        EventLogger {
            log_dir: log_dir.into(),
            enabled: enabled,
        }
    }

    pub fn record_event(&self, event: Event) {
        if self.enabled {
            let envelope = Envelope::new(&event);
            let file_path = self.log_dir.join(
                format!("event-{}.json", &envelope.timestamp),
            );
            write_file(&self.log_dir, &file_path, &envelope);
        }
    }
}

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

    #[test]
    fn event_logger_path() {
        let event_logger: EventLogger = EventLogger::new("/hab/svc/foo/var", true);
        let expected = r#"foo"#;
        match event_logger.log_dir.to_str() {
            Some(s) => assert!(s.contains(expected)),
            None => assert!(false),
        }
    }
}
<commit_msg>Rename Event OriginSecretKeyUpload to OriginSigningKeyUpload<commit_after>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::fs::{self, File};
use std::path::{Path, PathBuf};
use std::result;
use std::time::{SystemTime, UNIX_EPOCH};
use std::fmt;

use serde::{Serialize, Serializer};
use serde::ser::SerializeStruct;
use serde_json;

/// Sample envelope JSON payload
/// {
///   "timestamp": "1479330000.13442404",
///   "version": 1,
///   "event": {
///     "name": "project-create",
///     "origin" : "myorigin"
///     "package" : "mypackage"
///     "account" : "133508078967455744"
///   }
/// }
pub const SCHEMA_VERSION: u32 = 1;

// Macros to help hooking in the event logger into an Iron chain,
// and calling into the chained event logger.
#[macro_export]
macro_rules! define_event_log {
    () => {
        pub struct EventLog;
        impl typemap::Key for EventLog {
            type Value = EventLogger;
        }
    }
}

#[macro_export]
macro_rules! log_event {
    ($req:ident, $evt:expr) => {{
        let el = ($req).get::<persistent::Read<EventLog>>().unwrap();
        el.record_event($evt)
    }};
}

#[derive(Debug, Clone)]
pub enum Event {
    ProjectCreate {
        origin: String,
        package: String,
        account: String,
    },
    PackageUpload {
        origin: String,
        package: String,
        version: String,
        release: String,
        target: String,
        account: String,
    },
    OriginKeyUpload {
        origin: String,
        version: String,
        account: String,
    },
    OriginSigningKeyUpload {
        origin: String,
        version: String,
        account: String,
    },
    OriginInvitationSend {
        origin: String,
        user: String,
        id: String,
        account: String,
    },
    OriginInvitationAccept { id: String, account: String },
    OriginInvitationIgnore { id: String, account: String },
    JobCreate { package: String, account: String },
    GithubAuthenticate { user: String, account: String },
}

impl fmt::Display for Event {
    // TODO fn: As of rustfmt 0.7.1 the following match block is not well understood. The tool puts
    // all match arms on the same line which blows over the 100-column max which then fails the
    // tool with a `"line exceeded maximum length"` error. This ignore should be removed when we
    // upgrade rustfmt and retry.
    #[cfg_attr(rustfmt, rustfmt_skip)]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let msg = match *self {
            Event::ProjectCreate { origin: _, package: _, account: _ } => "project-create",
            Event::PackageUpload { origin: _, package: _, version: _, release: _, target: _,
                account: _ } => {
                "package-upload"
            }
            Event::OriginKeyUpload { origin: _, version: _, account: _ } => "origin-key-upload",
            Event::OriginSigningKeyUpload { origin: _, version: _, account: _ } => {
                "origin-secret-key-upload"
            }
            Event::OriginInvitationSend { origin: _, user: _, id: _, account: _ } => {
                "origin-invitation-send"
            }
            Event::OriginInvitationAccept { id: _, account: _ } => "origin-invitation-accept",
            Event::OriginInvitationIgnore { id: _, account: _ } => "origin-invitation-ignore",
            Event::JobCreate { package: _, account: _ } => "job-create",
            Event::GithubAuthenticate { user: _, account: _ } => "github-authenticate",
        };

        write!(f, "{}", msg)
    }
}

impl Serialize for Event {
    fn serialize<S>(&self, serializer: S) -> result::Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let strukt = match *self {
            Event::ProjectCreate {
                origin: ref o,
                package: ref p,
                account: ref a,
            } => {
                let mut strukt = serializer.serialize_struct("event", 4)?;
                strukt.serialize_field("name", &self.to_string())?;
                strukt.serialize_field("origin", o)?;
                strukt.serialize_field("package", p)?;
                strukt.serialize_field("account", a)?;
                strukt
            }
            Event::PackageUpload {
                origin: ref o,
                package: ref p,
                version: ref v,
                release: ref r,
                target: ref t,
                account: ref a,
            } => {
                let mut strukt = serializer.serialize_struct("event", 6)?;
                strukt.serialize_field("name", &self.to_string())?;
                strukt.serialize_field("origin", o)?;
                strukt.serialize_field("package", p)?;
                strukt.serialize_field("version", v)?;
                strukt.serialize_field("release", r)?;
                strukt.serialize_field("target", t)?;
                strukt.serialize_field("account", a)?;
                strukt
            }
            Event::OriginInvitationSend {
                origin: ref o,
                user: ref u,
                id: ref i,
                account: ref a,
            } => {
                let mut strukt = serializer.serialize_struct("event", 5)?;
                strukt.serialize_field("name", &self.to_string())?;
                strukt.serialize_field("origin", o)?;
                strukt.serialize_field("user", u)?;
                strukt.serialize_field("id", i)?;
                strukt.serialize_field("account", a)?;
                strukt
            }
            Event::OriginInvitationAccept {
                id: ref i,
                account: ref a,
            } => {
                let mut strukt = serializer.serialize_struct("event", 3)?;
                strukt.serialize_field("name", &self.to_string())?;
                strukt.serialize_field("id", i)?;
                strukt.serialize_field("account", a)?;
                strukt
            }
            Event::OriginInvitationIgnore {
                id: ref i,
                account: ref a,
            } => {
                let mut strukt = serializer.serialize_struct("event", 3)?;
                strukt.serialize_field("name", &self.to_string())?;
                strukt.serialize_field("id", i)?;
                strukt.serialize_field("account", a)?;
                strukt
            }
            Event::JobCreate {
                package: ref p,
                account: ref a,
            } => {
                let mut strukt = serializer.serialize_struct("event", 3)?;
                strukt.serialize_field("name", &self.to_string())?;
                strukt.serialize_field("package", p)?;
                strukt.serialize_field("account", a)?;
                strukt
            }
            Event::GithubAuthenticate {
                user: ref u,
                account: ref a,
            } => {
                let mut strukt = serializer.serialize_struct("event", 3)?;
                strukt.serialize_field("name", &self.to_string())?;
                strukt.serialize_field("user", u)?;
                strukt.serialize_field("account", a)?;
                strukt
            }
            Event::OriginKeyUpload {
                origin: ref o,
                version: ref v,
                account: ref a,
            } => {
                let mut strukt = serializer.serialize_struct("event", 4)?;
                strukt.serialize_field("name", &self.to_string())?;
                strukt.serialize_field("origin", o)?;
                strukt.serialize_field("version", v)?;
                strukt.serialize_field("account", a)?;
                strukt
            }
            Event::OriginSigningKeyUpload {
                origin: ref o,
                version: ref v,
                account: ref a,
            } => {
                let mut strukt = serializer.serialize_struct("event", 4)?;
                strukt.serialize_field("name", &self.to_string())?;
                strukt.serialize_field("origin", o)?;
                strukt.serialize_field("version", v)?;
                strukt.serialize_field("account", a)?;
                strukt
            }
        };
        strukt.end()
    }
}

#[derive(Debug, Clone)]
pub struct Envelope {
    pub version: u32,
    pub timestamp: String,
    pub event: Event,
}

impl Envelope {
    pub fn new(event: &Event) -> Self {
        Envelope {
            version: SCHEMA_VERSION,
            timestamp: timestamp(),
            event: event.clone(),
        }
    }
}

impl Serialize for Envelope {
    fn serialize<S>(&self, serializer: S) -> result::Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut strukt = serializer.serialize_struct("envelope", 3)?;
        strukt.serialize_field("version", &self.version)?;
        strukt.serialize_field("timestamp", &self.timestamp)?;
        strukt.serialize_field("event", &self.event)?;
        strukt.end()
    }
}

fn write_file<T>(parent_dir: &Path, file_path: &Path, val: &T)
where
    T: Serialize + ?Sized,
{
    fs::create_dir_all(parent_dir).expect("Unable to create directory");
    let mut file = File::create(&file_path).expect("Unable to create file");
    serde_json::ser::to_writer(&mut file, val).expect("Unable to write file");
}

fn timestamp() -> String {
    let (secs, subsec_nanos) = match SystemTime::now().duration_since(UNIX_EPOCH) {
        Ok(duration) => (duration.as_secs(), duration.subsec_nanos()),
        Err(e) => {
            error!("Cannot generate system time: {}", e);
            return "0.0".to_string();
        }
    };
    format!("{}.{}", secs, subsec_nanos)
}

pub struct EventLogger {
    log_dir: PathBuf,
    enabled: bool,
}

impl EventLogger {
    pub fn new<T: Into<PathBuf>>(log_dir: T, enabled: bool) -> Self {
        EventLogger {
            log_dir: log_dir.into(),
            enabled: enabled,
        }
    }

    pub fn record_event(&self, event: Event) {
        if self.enabled {
            let envelope = Envelope::new(&event);
            let file_path = self.log_dir.join(
                format!("event-{}.json", &envelope.timestamp),
            );
            write_file(&self.log_dir, &file_path, &envelope);
        }
    }
}

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

    #[test]
    fn event_logger_path() {
        let event_logger: EventLogger = EventLogger::new("/hab/svc/foo/var", true);
        let expected = r#"foo"#;
        match event_logger.log_dir.to_str() {
            Some(s) => assert!(s.contains(expected)),
            None => assert!(false),
        }
    }
}
<|endoftext|>