<commit_before>use std::fmt;
use std::num::Float;
use std::ops::Mul;

use numvec::Vec3f;

/// The type of matrix elements.
pub type Scalar = f32;

/// A 4x4 matrix type stored in column-major order for interoperability with
/// OpenGL.
///
/// Supports the creation of isometries and projections in homogenous
/// coordinates.  In terms of operations, only transposition and multiplication
/// are currently supported (and not super-efficiently implemented).
///
/// _Note:_ The 16 elements are stored in place, so copies are not cheap.
#[packed]
#[repr(C)]
#[derive(Copy)]
pub struct Mat4 {
    data: [Scalar; 16]
}

impl Mat4 {
    pub fn new(m00: Scalar, m01: Scalar, m02: Scalar, m03: Scalar,
               m10: Scalar, m11: Scalar, m12: Scalar, m13: Scalar,
               m20: Scalar, m21: Scalar, m22: Scalar, m23: Scalar,
               m30: Scalar, m31: Scalar, m32: Scalar, m33: Scalar) -> Mat4 {
        // In my mind vectors are columns, hence matrices need to be transposed
        // to the OpenGL memory order.
        Mat4 { data: [m00, m10, m20, m30, m01, m11, m21, m31,
                      m02, m12, m22, m32, m03, m13, m23, m33] }
    }

    pub fn new_identity() -> Mat4 {
        Mat4::new(1.0, 0.0, 0.0, 0.0,
                  0.0, 1.0, 0.0, 0.0,
                  0.0, 0.0, 1.0, 0.0,
                  0.0, 0.0, 0.0, 1.0)
    }

    /// Creates a perspective projection matrix from.
    ///
    /// The parameters are:
    /// * `fov_degrees`  - Horizontal field of view.
    /// * `aspect_ratio` - Ratio between width and height of the view.
    /// * `near`, `far`  - The Z coordinate of the near and far planes.
    pub fn new_perspective(fov_degrees: Scalar, aspect_ratio: Scalar,
                           near: Scalar, far: Scalar) -> Mat4 {
        let fov = (3.1415926538 * fov_degrees) / 180.0;
        let f = 1.0 / (fov * 0.5).tan();

        Mat4::new(
            f / aspect_ratio, 0.0, 0.0, 0.0,
            0.0, f, 0.0, 0.0,
            0.0, 0.0, (far + near) / (near - far), 2.0*far*near / (near - far),
            0.0, 0.0, -1.0, 0.0)
    }

    /// Creates a matrix which rotates points by `angle_radians` around `axis`.
    pub fn new_axis_rotation(axis: &Vec3f, angle_radians: Scalar) -> Mat4 {
        let ca = angle_radians.cos();
        let sa = angle_radians.sin();
        let nca = 1.0 - ca;
        let u = axis;
        Mat4::new(
            ca + u.x*u.x*nca, u.x*u.y*nca - u.z*sa, u.x*u.z*nca + u.y*sa, 0.0,
            u.y*u.x*nca + u.z*sa, ca + u.y*u.y*nca, u.y*u.z*nca - u.x*sa, 0.0,
            u.z*u.x*nca - u.y*sa, u.z*u.y*nca + u.x*sa, ca + u.z*u.z*nca, 0.0,
            0.0, 0.0, 0.0, 1.0
        )
    }

    /// Creates a rotation matrix from the three _Euler angles_.
    pub fn new_euler_rotation(yaw: f32, pitch: f32, roll: f32) -> Mat4 {
        let (ca, sa) = (yaw.cos(), yaw.sin());
        let (cb, sb) = (roll.cos(), roll.sin());
        let (cc, sc) = (pitch.cos(), pitch.sin());

        Mat4::new(
             ca*cb, sa*sc - ca*sb*cc,  ca*sb*sc + sa*cc, 0.0,
                sb,          cb * cc,          -cb * sc, 0.0,
            -sa*cb, sa*sb*cc + ca*sc, -sa*sb*sc + ca*cc, 0.0,
               0.0,              0.0,               0.0, 1.0,
        )
    }

    /// Creates a translation matrix which maps points `p` to `p + by`.
    pub fn new_translation(by: Vec3f) -> Mat4 {
        Mat4::new(1.0, 0.0, 0.0, by.x,
                  0.0, 1.0, 0.0, by.y,
                  0.0, 0.0, 1.0, by.z,
                  0.0, 0.0, 0.0,  1.0)
    }

    /// Returns the transpose of the matrix (columns swapped with rows).
    pub fn transposed(&self) -> Mat4 {
        let m = &self.data;
        // m is in column-major order, so calling with new in row-order will
        // transpose it.
        Mat4::new(m[0], m[1], m[2], m[3],
                  m[4], m[5], m[6], m[7],
                  m[8], m[9], m[10], m[11],
                  m[12], m[13], m[14], m[15])
    }

    pub fn get(&self, row: usize, column: usize) -> Scalar {
        self.data[column * 4 + row]
    }

    pub fn as_scalar_ptr(&self) -> *const Scalar {
        self.data.as_ptr()
    }
}

impl fmt::Debug for Mat4 {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter,
               "[{:10.3e} {:10.3e} {:10.3e} {:10.3e};\n \
                 {:10.3e} {:10.3e} {:10.3e} {:10.3e};\n \
                 {:10.3e} {:10.3e} {:10.3e} {:10.3e};\n \
                 {:10.3e} {:10.3e} {:10.3e} {:10.3e}]",
               self.get(0, 0), self.get(0, 1), self.get(0, 2), self.get(0, 3),
               self.get(1, 0), self.get(1, 1), self.get(1, 2), self.get(1, 3),
               self.get(2, 0), self.get(2, 1), self.get(2, 2), self.get(2, 3),
               self.get(3, 0), self.get(3, 1), self.get(3, 2), self.get(3, 3))
    }
}

impl Mul for Mat4 {
    type Output = Mat4;

    fn mul(self, rhs: Mat4) -> Mat4 {
        let l = &self.data;
        let r = &rhs.data;
        Mat4 { data:[
            l[ 0]*r[ 0] + l[ 4]*r[ 1] + l[ 8]*r[ 2] + l[12]*r[ 3],
            l[ 1]*r[ 0] + l[ 5]*r[ 1] + l[ 9]*r[ 2] + l[13]*r[ 3],
            l[ 2]*r[ 0] + l[ 6]*r[ 1] + l[10]*r[ 2] + l[14]*r[ 3],
            l[ 3]*r[ 0] + l[ 7]*r[ 1] + l[11]*r[ 2] + l[15]*r[ 3],

            l[ 0]*r[ 4] + l[ 4]*r[ 5] + l[ 8]*r[ 6] + l[12]*r[ 7],
            l[ 1]*r[ 4] + l[ 5]*r[ 5] + l[ 9]*r[ 6] + l[13]*r[ 7],
            l[ 2]*r[ 4] + l[ 6]*r[ 5] + l[10]*r[ 6] + l[14]*r[ 7],
            l[ 3]*r[ 4] + l[ 7]*r[ 5] + l[11]*r[ 6] + l[15]*r[ 7],

            l[ 0]*r[ 8] + l[ 4]*r[ 9] + l[ 8]*r[10] + l[12]*r[11],
            l[ 1]*r[ 8] + l[ 5]*r[ 9] + l[ 9]*r[10] + l[13]*r[11],
            l[ 2]*r[ 8] + l[ 6]*r[ 9] + l[10]*r[10] + l[14]*r[11],
            l[ 3]*r[ 8] + l[ 7]*r[ 9] + l[11]*r[10] + l[15]*r[11],

            l[ 0]*r[12] + l[ 4]*r[13] + l[ 8]*r[14] + l[12]*r[15],
            l[ 1]*r[12] + l[ 5]*r[13] + l[ 9]*r[14] + l[13]*r[15],
            l[ 2]*r[12] + l[ 6]*r[13] + l[10]*r[14] + l[14]*r[15],
            l[ 3]*r[12] + l[ 7]*r[13] + l[11]*r[14] + l[15]*r[15],
        ]}
    }
}

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

    #[test]
    fn test_mul() {
        use std::num::Float;
        let a = Mat4::new(4.0,    8.0,    1.0,    6.0,
                          9.0,    4.0,    2.0,    1.0,
                          4.0,    3.0,    9.0,    3.0,
                          2.0,    4.0,    9.0,    4.0);

        let b = Mat4::new(8.0,    6.0,    5.0,    7.0,
                          1.0,    7.0,    3.0,    2.0,
                          1.0,    6.0,    7.0,    4.0,
                          2.0,    5.0,    2.0,    6.0);

        let exp_ab = Mat4::new(53.0,   116.0,    63.0,    84.0,
                               80.0,    99.0,    73.0,    85.0,
                               50.0,   114.0,    98.0,    88.0,
                               37.0,   114.0,    93.0,    82.0);
        let ab = a * b;

        for i in range(0, 16) {
            if exp_ab.data[i] != ab.data[i] {
                panic!(
                    "They differ at {} ({}):\nexpected=\n{:?}\n\nactual=\n{:?}",
                    i, (a.data[i] - b.data[i]).abs(), exp_ab, ab);
            }
        }

    }
}
<commit_msg>Fixed mat test<commit_after>use std::fmt;
use std::num::Float;
use std::ops::Mul;

use numvec::Vec3f;

/// The type of matrix elements.
pub type Scalar = f32;

/// A 4x4 matrix type stored in column-major order for interoperability with
/// OpenGL.
///
/// Supports the creation of isometries and projections in homogenous
/// coordinates.  In terms of operations, only transposition and multiplication
/// are currently supported (and not super-efficiently implemented).
///
/// _Note:_ The 16 elements are stored in place, so copies are not cheap.
#[packed]
#[repr(C)]
#[derive(Copy)]
pub struct Mat4 {
    data: [Scalar; 16]
}

impl Mat4 {
    pub fn new(m00: Scalar, m01: Scalar, m02: Scalar, m03: Scalar,
               m10: Scalar, m11: Scalar, m12: Scalar, m13: Scalar,
               m20: Scalar, m21: Scalar, m22: Scalar, m23: Scalar,
               m30: Scalar, m31: Scalar, m32: Scalar, m33: Scalar) -> Mat4 {
        // In my mind vectors are columns, hence matrices need to be transposed
        // to the OpenGL memory order.
        Mat4 { data: [m00, m10, m20, m30, m01, m11, m21, m31,
                      m02, m12, m22, m32, m03, m13, m23, m33] }
    }

    pub fn new_identity() -> Mat4 {
        Mat4::new(1.0, 0.0, 0.0, 0.0,
                  0.0, 1.0, 0.0, 0.0,
                  0.0, 0.0, 1.0, 0.0,
                  0.0, 0.0, 0.0, 1.0)
    }

    /// Creates a perspective projection matrix from.
    ///
    /// The parameters are:
    /// * `fov_degrees`  - Horizontal field of view.
    /// * `aspect_ratio` - Ratio between width and height of the view.
    /// * `near`, `far`  - The Z coordinate of the near and far planes.
    pub fn new_perspective(fov_degrees: Scalar, aspect_ratio: Scalar,
                           near: Scalar, far: Scalar) -> Mat4 {
        let fov = (3.1415926538 * fov_degrees) / 180.0;
        let f = 1.0 / (fov * 0.5).tan();

        Mat4::new(
            f / aspect_ratio, 0.0, 0.0, 0.0,
            0.0, f, 0.0, 0.0,
            0.0, 0.0, (far + near) / (near - far), 2.0*far*near / (near - far),
            0.0, 0.0, -1.0, 0.0)
    }

    /// Creates a matrix which rotates points by `angle_radians` around `axis`.
    pub fn new_axis_rotation(axis: &Vec3f, angle_radians: Scalar) -> Mat4 {
        let ca = angle_radians.cos();
        let sa = angle_radians.sin();
        let nca = 1.0 - ca;
        let u = axis;
        Mat4::new(
            ca + u.x*u.x*nca, u.x*u.y*nca - u.z*sa, u.x*u.z*nca + u.y*sa, 0.0,
            u.y*u.x*nca + u.z*sa, ca + u.y*u.y*nca, u.y*u.z*nca - u.x*sa, 0.0,
            u.z*u.x*nca - u.y*sa, u.z*u.y*nca + u.x*sa, ca + u.z*u.z*nca, 0.0,
            0.0, 0.0, 0.0, 1.0
        )
    }

    /// Creates a rotation matrix from the three _Euler angles_.
    pub fn new_euler_rotation(yaw: f32, pitch: f32, roll: f32) -> Mat4 {
        let (ca, sa) = (yaw.cos(), yaw.sin());
        let (cb, sb) = (roll.cos(), roll.sin());
        let (cc, sc) = (pitch.cos(), pitch.sin());

        Mat4::new(
             ca*cb, sa*sc - ca*sb*cc,  ca*sb*sc + sa*cc, 0.0,
                sb,          cb * cc,          -cb * sc, 0.0,
            -sa*cb, sa*sb*cc + ca*sc, -sa*sb*sc + ca*cc, 0.0,
               0.0,              0.0,               0.0, 1.0,
        )
    }

    /// Creates a translation matrix which maps points `p` to `p + by`.
    pub fn new_translation(by: Vec3f) -> Mat4 {
        Mat4::new(1.0, 0.0, 0.0, by.x,
                  0.0, 1.0, 0.0, by.y,
                  0.0, 0.0, 1.0, by.z,
                  0.0, 0.0, 0.0,  1.0)
    }

    /// Returns the transpose of the matrix (columns swapped with rows).
    pub fn transposed(&self) -> Mat4 {
        let m = &self.data;
        // m is in column-major order, so calling with new in row-order will
        // transpose it.
        Mat4::new(m[0], m[1], m[2], m[3],
                  m[4], m[5], m[6], m[7],
                  m[8], m[9], m[10], m[11],
                  m[12], m[13], m[14], m[15])
    }

    pub fn get(&self, row: usize, column: usize) -> Scalar {
        self.data[column * 4 + row]
    }

    pub fn as_scalar_ptr(&self) -> *const Scalar {
        self.data.as_ptr()
    }
}

impl fmt::Debug for Mat4 {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter,
               "[{:10.3e} {:10.3e} {:10.3e} {:10.3e};\n \
                 {:10.3e} {:10.3e} {:10.3e} {:10.3e};\n \
                 {:10.3e} {:10.3e} {:10.3e} {:10.3e};\n \
                 {:10.3e} {:10.3e} {:10.3e} {:10.3e}]",
               self.get(0, 0), self.get(0, 1), self.get(0, 2), self.get(0, 3),
               self.get(1, 0), self.get(1, 1), self.get(1, 2), self.get(1, 3),
               self.get(2, 0), self.get(2, 1), self.get(2, 2), self.get(2, 3),
               self.get(3, 0), self.get(3, 1), self.get(3, 2), self.get(3, 3))
    }
}

impl Mul for Mat4 {
    type Output = Mat4;

    fn mul(self, rhs: Mat4) -> Mat4 {
        let l = &self.data;
        let r = &rhs.data;
        Mat4 { data:[
            l[ 0]*r[ 0] + l[ 4]*r[ 1] + l[ 8]*r[ 2] + l[12]*r[ 3],
            l[ 1]*r[ 0] + l[ 5]*r[ 1] + l[ 9]*r[ 2] + l[13]*r[ 3],
            l[ 2]*r[ 0] + l[ 6]*r[ 1] + l[10]*r[ 2] + l[14]*r[ 3],
            l[ 3]*r[ 0] + l[ 7]*r[ 1] + l[11]*r[ 2] + l[15]*r[ 3],

            l[ 0]*r[ 4] + l[ 4]*r[ 5] + l[ 8]*r[ 6] + l[12]*r[ 7],
            l[ 1]*r[ 4] + l[ 5]*r[ 5] + l[ 9]*r[ 6] + l[13]*r[ 7],
            l[ 2]*r[ 4] + l[ 6]*r[ 5] + l[10]*r[ 6] + l[14]*r[ 7],
            l[ 3]*r[ 4] + l[ 7]*r[ 5] + l[11]*r[ 6] + l[15]*r[ 7],

            l[ 0]*r[ 8] + l[ 4]*r[ 9] + l[ 8]*r[10] + l[12]*r[11],
            l[ 1]*r[ 8] + l[ 5]*r[ 9] + l[ 9]*r[10] + l[13]*r[11],
            l[ 2]*r[ 8] + l[ 6]*r[ 9] + l[10]*r[10] + l[14]*r[11],
            l[ 3]*r[ 8] + l[ 7]*r[ 9] + l[11]*r[10] + l[15]*r[11],

            l[ 0]*r[12] + l[ 4]*r[13] + l[ 8]*r[14] + l[12]*r[15],
            l[ 1]*r[12] + l[ 5]*r[13] + l[ 9]*r[14] + l[13]*r[15],
            l[ 2]*r[12] + l[ 6]*r[13] + l[10]*r[14] + l[14]*r[15],
            l[ 3]*r[12] + l[ 7]*r[13] + l[11]*r[14] + l[15]*r[15],
        ]}
    }
}

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

    #[test]
    fn test_mul() {
        use std::num::Float;
        let a = Mat4::new(4.0,    8.0,    1.0,    6.0,
                          9.0,    4.0,    2.0,    1.0,
                          4.0,    3.0,    9.0,    3.0,
                          2.0,    4.0,    9.0,    4.0);

        let b = Mat4::new(8.0,    6.0,    5.0,    7.0,
                          1.0,    7.0,    3.0,    2.0,
                          1.0,    6.0,    7.0,    4.0,
                          2.0,    5.0,    2.0,    6.0);

        let exp_ab = Mat4::new(53.0,   116.0,    63.0,    84.0,
                               80.0,    99.0,    73.0,    85.0,
                               50.0,   114.0,    98.0,    88.0,
                               37.0,   114.0,    93.0,    82.0);
        let ab = a * b;

        for i in 0..16 {
            if exp_ab.data[i] != ab.data[i] {
                panic!(
                    "They differ at {} ({}):\nexpected=\n{:?}\n\nactual=\n{:?}",
                    i, (a.data[i] - b.data[i]).abs(), exp_ab, ab);
            }
        }

    }
}
<|endoftext|>


<commit_before>#![allow(clippy::zero_sized_map_values)]

use indoc::indoc;
use serde::de::{Deserialize, SeqAccess, Visitor};
use serde_derive::Deserialize;
use serde_yaml::Deserializer;
use std::collections::BTreeMap;
use std::fmt::{self, Debug};

fn test_error<T>(yaml: &str, expected: &str)
where
    T: serde::de::DeserializeOwned + Debug,
{
    let result = serde_yaml::from_str::<T>(yaml);
    assert_eq!(expected, result.unwrap_err().to_string());
}

#[test]
fn test_incorrect_type() {
    let yaml = indoc! {"
        ---
        str
    "};
    let expected = "invalid type: string \"str\", expected i16 at line 2 column 1";
    test_error::<i16>(yaml, expected);
}

#[test]
fn test_incorrect_nested_type() {
    #[derive(Deserialize, Debug)]
    struct A {
        #[allow(dead_code)]
        b: Vec<B>,
    }
    #[derive(Deserialize, Debug)]
    enum B {
        C(C),
    }
    #[derive(Deserialize, Debug)]
    struct C {
        #[allow(dead_code)]
        d: bool,
    }
    let yaml = indoc! {"
        b:
          - !C
            d: fase
    "};
    let expected = "b[0].d: invalid type: string \"fase\", expected a boolean at line 3 column 8";
    test_error::<A>(yaml, expected);
}

#[test]
fn test_empty() {
    let expected = "EOF while parsing a value";
    test_error::<String>("", expected);
}

#[test]
fn test_missing_field() {
    #[derive(Deserialize, Debug)]
    struct Basic {
        #[allow(dead_code)]
        v: bool,
        #[allow(dead_code)]
        w: bool,
    }
    let yaml = indoc! {"
        ---
        v: true
    "};
    let expected = "missing field `w` at line 2 column 1";
    test_error::<Basic>(yaml, expected);
}

#[test]
fn test_unknown_anchor() {
    let yaml = indoc! {"
        ---
        *some
    "};
    let expected = "unknown anchor at line 2 column 1";
    test_error::<String>(yaml, expected);
}

#[test]
fn test_ignored_unknown_anchor() {
    #[derive(Deserialize, Debug)]
    struct Wrapper {
        #[allow(dead_code)]
        c: (),
    }
    let yaml = indoc! {"
        b: [*a]
        c: ~
    "};
    let expected = "unknown anchor at line 1 column 5";
    test_error::<Wrapper>(yaml, expected);
}

#[test]
fn test_two_documents() {
    let yaml = indoc! {"
        ---
        0
        ---
        1
    "};
    let expected = "deserializing from YAML containing more than one document is not supported";
    test_error::<usize>(yaml, expected);
}

#[test]
fn test_second_document_syntax_error() {
    let yaml = indoc! {"
        ---
        0
        ---
        ]
    "};

    let mut de = Deserializer::from_str(yaml);
    let first_doc = de.next().unwrap();
    let result = <usize as serde::Deserialize>::deserialize(first_doc);
    assert_eq!(0, result.unwrap());

    let second_doc = de.next().unwrap();
    let result = <usize as serde::Deserialize>::deserialize(second_doc);
    let expected = "did not find expected node content at line 4 column 1, while parsing a block node at line 4 column 1";
    assert_eq!(expected, result.unwrap_err().to_string());
}

#[test]
fn test_missing_enum_tag() {
    #[derive(Deserialize, Debug)]
    enum E {
        V(usize),
    }
    let yaml = indoc! {r#"
        "V": 16
        "other": 32
    "#};
    let expected = "invalid type: map, expected a YAML tag starting with '!' at position 0";
    test_error::<E>(yaml, expected);
}

#[test]
fn test_variant_not_a_seq() {
    #[derive(Deserialize, Debug)]
    enum E {
        V(usize),
    }
    let yaml = indoc! {r#"
        ---
        !V
        value: 0
    "#};
    let expected = "invalid type: map, expected usize at line 2 column 1";
    test_error::<E>(yaml, expected);
}

#[test]
fn test_bad_bool() {
    let yaml = indoc! {"
        ---
        !!bool str
    "};
    let expected = "invalid value: string \"str\", expected a boolean at line 2 column 1";
    test_error::<bool>(yaml, expected);
}

#[test]
fn test_bad_int() {
    let yaml = indoc! {"
        ---
        !!int str
    "};
    let expected = "invalid value: string \"str\", expected an integer at line 2 column 1";
    test_error::<i64>(yaml, expected);
}

#[test]
fn test_bad_float() {
    let yaml = indoc! {"
        ---
        !!float str
    "};
    let expected = "invalid value: string \"str\", expected a float at line 2 column 1";
    test_error::<f64>(yaml, expected);
}

#[test]
fn test_bad_null() {
    let yaml = indoc! {"
        ---
        !!null str
    "};
    let expected = "invalid value: string \"str\", expected null at line 2 column 1";
    test_error::<()>(yaml, expected);
}

#[test]
fn test_short_tuple() {
    let yaml = indoc! {"
        ---
        [0, 0]
    "};
    let expected = "invalid length 2, expected a tuple of size 3 at line 2 column 1";
    test_error::<(u8, u8, u8)>(yaml, expected);
}

#[test]
fn test_long_tuple() {
    let yaml = indoc! {"
        ---
        [0, 0, 0]
    "};
    let expected = "invalid length 3, expected sequence of 2 elements at line 2 column 1";
    test_error::<(u8, u8)>(yaml, expected);
}

#[test]
fn test_invalid_scalar_type() {
    #[derive(Deserialize, Debug)]
    struct S {
        #[allow(dead_code)]
        x: [(); 1],
    }

    let yaml = "x:\n";
    let expected = "x: invalid type: unit value, expected an array of length 1 at line 1 column 3";
    test_error::<S>(yaml, expected);
}

#[cfg(not(miri))]
#[test]
fn test_infinite_recursion_objects() {
    #[derive(Deserialize, Debug)]
    struct S {
        #[allow(dead_code)]
        x: Option<Box<S>>,
    }

    let yaml = "&a {'x': *a}";
    let expected = "recursion limit exceeded at position 0";
    test_error::<S>(yaml, expected);
}

#[cfg(not(miri))]
#[test]
fn test_infinite_recursion_arrays() {
    #[derive(Deserialize, Debug)]
    struct S(usize, Option<Box<S>>);

    let yaml = "&a [0, *a]";
    let expected = "recursion limit exceeded at position 0";
    test_error::<S>(yaml, expected);
}

#[cfg(not(miri))]
#[test]
fn test_infinite_recursion_newtype() {
    #[derive(Deserialize, Debug)]
    struct S(Option<Box<S>>);

    let yaml = "&a [*a]";
    let expected = "recursion limit exceeded at position 0";
    test_error::<S>(yaml, expected);
}

#[cfg(not(miri))]
#[test]
fn test_finite_recursion_objects() {
    #[derive(Deserialize, Debug)]
    struct S {
        #[allow(dead_code)]
        x: Option<Box<S>>,
    }

    let yaml = "{'x':".repeat(1_000) + &"}".repeat(1_000);
    let expected = "recursion limit exceeded at line 1 column 641";
    test_error::<S>(&yaml, expected);
}

#[cfg(not(miri))]
#[test]
fn test_finite_recursion_arrays() {
    #[derive(Deserialize, Debug)]
    struct S(usize, Option<Box<S>>);

    let yaml = "[0, ".repeat(1_000) + &"]".repeat(1_000);
    let expected = "recursion limit exceeded at line 1 column 513";
    test_error::<S>(&yaml, expected);
}

#[cfg(not(miri))]
#[test]
fn test_billion_laughs() {
    #[derive(Debug)]
    struct X;

    impl<'de> Deserialize<'de> for X {
        fn deserialize<D>(deserializer: D) -> Result<X, D::Error>
        where
            D: serde::Deserializer<'de>,
        {
            impl<'de> Visitor<'de> for X {
                type Value = X;

                fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                    formatter.write_str("exponential blowup")
                }

                fn visit_unit<E>(self) -> Result<X, E> {
                    Ok(X)
                }

                fn visit_seq<S>(self, mut seq: S) -> Result<X, S::Error>
                where
                    S: SeqAccess<'de>,
                {
                    while let Some(X) = seq.next_element()? {}
                    Ok(X)
                }
            }

            deserializer.deserialize_any(X)
        }
    }

    let yaml = indoc! {"
        a: &a ~
        b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]
        c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]
        d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]
        e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]
        f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]
        g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]
        h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]
        i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]
    "};
    let expected = "repetition limit exceeded";
    test_error::<BTreeMap<String, X>>(yaml, expected);
}
<commit_msg>Add test of struct deserialization from sequence<commit_after>#![allow(clippy::zero_sized_map_values)]

use indoc::indoc;
use serde::de::{Deserialize, SeqAccess, Visitor};
use serde_derive::Deserialize;
use serde_yaml::Deserializer;
use std::collections::BTreeMap;
use std::fmt::{self, Debug};

fn test_error<T>(yaml: &str, expected: &str)
where
    T: serde::de::DeserializeOwned + Debug,
{
    let result = serde_yaml::from_str::<T>(yaml);
    assert_eq!(expected, result.unwrap_err().to_string());
}

#[test]
fn test_incorrect_type() {
    let yaml = indoc! {"
        ---
        str
    "};
    let expected = "invalid type: string \"str\", expected i16 at line 2 column 1";
    test_error::<i16>(yaml, expected);
}

#[test]
fn test_incorrect_nested_type() {
    #[derive(Deserialize, Debug)]
    struct A {
        #[allow(dead_code)]
        b: Vec<B>,
    }
    #[derive(Deserialize, Debug)]
    enum B {
        C(C),
    }
    #[derive(Deserialize, Debug)]
    struct C {
        #[allow(dead_code)]
        d: bool,
    }
    let yaml = indoc! {"
        b:
          - !C
            d: fase
    "};
    let expected = "b[0].d: invalid type: string \"fase\", expected a boolean at line 3 column 8";
    test_error::<A>(yaml, expected);
}

#[test]
fn test_empty() {
    let expected = "EOF while parsing a value";
    test_error::<String>("", expected);
}

#[test]
fn test_missing_field() {
    #[derive(Deserialize, Debug)]
    struct Basic {
        #[allow(dead_code)]
        v: bool,
        #[allow(dead_code)]
        w: bool,
    }
    let yaml = indoc! {"
        ---
        v: true
    "};
    let expected = "missing field `w` at line 2 column 1";
    test_error::<Basic>(yaml, expected);
}

#[test]
fn test_unknown_anchor() {
    let yaml = indoc! {"
        ---
        *some
    "};
    let expected = "unknown anchor at line 2 column 1";
    test_error::<String>(yaml, expected);
}

#[test]
fn test_ignored_unknown_anchor() {
    #[derive(Deserialize, Debug)]
    struct Wrapper {
        #[allow(dead_code)]
        c: (),
    }
    let yaml = indoc! {"
        b: [*a]
        c: ~
    "};
    let expected = "unknown anchor at line 1 column 5";
    test_error::<Wrapper>(yaml, expected);
}

#[test]
fn test_two_documents() {
    let yaml = indoc! {"
        ---
        0
        ---
        1
    "};
    let expected = "deserializing from YAML containing more than one document is not supported";
    test_error::<usize>(yaml, expected);
}

#[test]
fn test_second_document_syntax_error() {
    let yaml = indoc! {"
        ---
        0
        ---
        ]
    "};

    let mut de = Deserializer::from_str(yaml);
    let first_doc = de.next().unwrap();
    let result = <usize as serde::Deserialize>::deserialize(first_doc);
    assert_eq!(0, result.unwrap());

    let second_doc = de.next().unwrap();
    let result = <usize as serde::Deserialize>::deserialize(second_doc);
    let expected = "did not find expected node content at line 4 column 1, while parsing a block node at line 4 column 1";
    assert_eq!(expected, result.unwrap_err().to_string());
}

#[test]
fn test_missing_enum_tag() {
    #[derive(Deserialize, Debug)]
    enum E {
        V(usize),
    }
    let yaml = indoc! {r#"
        "V": 16
        "other": 32
    "#};
    let expected = "invalid type: map, expected a YAML tag starting with '!' at position 0";
    test_error::<E>(yaml, expected);
}

#[test]
fn test_variant_not_a_seq() {
    #[derive(Deserialize, Debug)]
    enum E {
        V(usize),
    }
    let yaml = indoc! {r#"
        ---
        !V
        value: 0
    "#};
    let expected = "invalid type: map, expected usize at line 2 column 1";
    test_error::<E>(yaml, expected);
}

#[test]
fn test_struct_from_sequence() {
    #[allow(dead_code)]
    #[derive(Deserialize, Debug)]
    struct Struct {
        x: usize,
        y: usize,
    }
    let yaml = indoc! {"
        [0, 0]
    "};
    let expected = "invalid type: sequence, expected struct Struct at position 0";
    test_error::<Struct>(yaml, expected);
}

#[test]
fn test_bad_bool() {
    let yaml = indoc! {"
        ---
        !!bool str
    "};
    let expected = "invalid value: string \"str\", expected a boolean at line 2 column 1";
    test_error::<bool>(yaml, expected);
}

#[test]
fn test_bad_int() {
    let yaml = indoc! {"
        ---
        !!int str
    "};
    let expected = "invalid value: string \"str\", expected an integer at line 2 column 1";
    test_error::<i64>(yaml, expected);
}

#[test]
fn test_bad_float() {
    let yaml = indoc! {"
        ---
        !!float str
    "};
    let expected = "invalid value: string \"str\", expected a float at line 2 column 1";
    test_error::<f64>(yaml, expected);
}

#[test]
fn test_bad_null() {
    let yaml = indoc! {"
        ---
        !!null str
    "};
    let expected = "invalid value: string \"str\", expected null at line 2 column 1";
    test_error::<()>(yaml, expected);
}

#[test]
fn test_short_tuple() {
    let yaml = indoc! {"
        ---
        [0, 0]
    "};
    let expected = "invalid length 2, expected a tuple of size 3 at line 2 column 1";
    test_error::<(u8, u8, u8)>(yaml, expected);
}

#[test]
fn test_long_tuple() {
    let yaml = indoc! {"
        ---
        [0, 0, 0]
    "};
    let expected = "invalid length 3, expected sequence of 2 elements at line 2 column 1";
    test_error::<(u8, u8)>(yaml, expected);
}

#[test]
fn test_invalid_scalar_type() {
    #[derive(Deserialize, Debug)]
    struct S {
        #[allow(dead_code)]
        x: [(); 1],
    }

    let yaml = "x:\n";
    let expected = "x: invalid type: unit value, expected an array of length 1 at line 1 column 3";
    test_error::<S>(yaml, expected);
}

#[cfg(not(miri))]
#[test]
fn test_infinite_recursion_objects() {
    #[derive(Deserialize, Debug)]
    struct S {
        #[allow(dead_code)]
        x: Option<Box<S>>,
    }

    let yaml = "&a {'x': *a}";
    let expected = "recursion limit exceeded at position 0";
    test_error::<S>(yaml, expected);
}

#[cfg(not(miri))]
#[test]
fn test_infinite_recursion_arrays() {
    #[derive(Deserialize, Debug)]
    struct S(usize, Option<Box<S>>);

    let yaml = "&a [0, *a]";
    let expected = "recursion limit exceeded at position 0";
    test_error::<S>(yaml, expected);
}

#[cfg(not(miri))]
#[test]
fn test_infinite_recursion_newtype() {
    #[derive(Deserialize, Debug)]
    struct S(Option<Box<S>>);

    let yaml = "&a [*a]";
    let expected = "recursion limit exceeded at position 0";
    test_error::<S>(yaml, expected);
}

#[cfg(not(miri))]
#[test]
fn test_finite_recursion_objects() {
    #[derive(Deserialize, Debug)]
    struct S {
        #[allow(dead_code)]
        x: Option<Box<S>>,
    }

    let yaml = "{'x':".repeat(1_000) + &"}".repeat(1_000);
    let expected = "recursion limit exceeded at line 1 column 641";
    test_error::<S>(&yaml, expected);
}

#[cfg(not(miri))]
#[test]
fn test_finite_recursion_arrays() {
    #[derive(Deserialize, Debug)]
    struct S(usize, Option<Box<S>>);

    let yaml = "[0, ".repeat(1_000) + &"]".repeat(1_000);
    let expected = "recursion limit exceeded at line 1 column 513";
    test_error::<S>(&yaml, expected);
}

#[cfg(not(miri))]
#[test]
fn test_billion_laughs() {
    #[derive(Debug)]
    struct X;

    impl<'de> Deserialize<'de> for X {
        fn deserialize<D>(deserializer: D) -> Result<X, D::Error>
        where
            D: serde::Deserializer<'de>,
        {
            impl<'de> Visitor<'de> for X {
                type Value = X;

                fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                    formatter.write_str("exponential blowup")
                }

                fn visit_unit<E>(self) -> Result<X, E> {
                    Ok(X)
                }

                fn visit_seq<S>(self, mut seq: S) -> Result<X, S::Error>
                where
                    S: SeqAccess<'de>,
                {
                    while let Some(X) = seq.next_element()? {}
                    Ok(X)
                }
            }

            deserializer.deserialize_any(X)
        }
    }

    let yaml = indoc! {"
        a: &a ~
        b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]
        c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]
        d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]
        e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]
        f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]
        g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]
        h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]
        i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]
    "};
    let expected = "repetition limit exceeded";
    test_error::<BTreeMap<String, X>>(yaml, expected);
}
<|endoftext|>


<commit_before>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Andres Vahter (andres.vahter@gmail.com)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

use ffiliquid;
use num::complex::Complex;
use super::LiquidComplex32;
use std::mem::transmute;

pub struct MsresampCrcf {
     object: ffiliquid::msresamp_crcf,
}

impl MsresampCrcf {

    /// create multi-stage arbitrary resampler
    ///  _r      :   resampling rate [output/input]
    ///  _as     :   stop-band attenuation [dB]
    pub fn new(_r: f32, _as: f32) -> MsresampCrcf {
        let resampler: ffiliquid::msresamp_crcf = unsafe{ffiliquid::msresamp_crcf_create(_r, _as)};
        MsresampCrcf{object: resampler}
    }

    /// get filter delay (output samples)
    pub fn get_delay(&self) -> f32 {
        unsafe{ffiliquid::msresamp_crcf_get_delay(self.object)}
    }

    /// execute multi-stage resampler
    ///  `input`   :   input sample array
    ///  `output`  :   output sample array
    ///  returns how many samples were written to `output` buffer
    pub fn execute(&self, input: &mut [Complex<f32>], output: &mut [Complex<f32>]) -> u32 {
        let _nx = input.len() as u32;
        let x = unsafe {transmute::<*mut Complex<f32>, *mut LiquidComplex32>(input.as_mut_ptr())};
        let y = unsafe {transmute::<*mut Complex<f32>, *mut LiquidComplex32>(output.as_mut_ptr())};
        let mut output_sample_count = 0;

        //  _x      :   input sample array  [size: _nx x 1]
        //  _nx     :   input sample array size
        //  _y      :   output sample array [size: variable]
        //  _ny     :   number of samples written to _y
        unsafe{ffiliquid::msresamp_crcf_execute(self.object, x, _nx, y, &mut output_sample_count)};

        output_sample_count
    }
}

impl Drop for MsresampCrcf {
    fn drop(&mut self) {
        unsafe{ffiliquid::msresamp_crcf_destroy(self.object)};
    }
}
<commit_msg>make MsresampCrcf interface more Rust like<commit_after>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Andres Vahter (andres.vahter@gmail.com)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

use ffiliquid;
use num::complex::Complex;
use super::LiquidComplex32;
use std::mem::transmute;

pub struct MsresampCrcf {
     object: ffiliquid::msresamp_crcf,
     resample_rate: f32,
}

impl MsresampCrcf {

    /// Creates multi-stage arbitrary resampler where `resample_rate` is resampling rate expressed as (output/input).
    /// Filter stop-band `attenuation` is in dB.
    pub fn new(resample_rate: f32, attenuation: f32) -> MsresampCrcf {
        let resampler: ffiliquid::msresamp_crcf = unsafe{ffiliquid::msresamp_crcf_create(resample_rate, attenuation)};
        MsresampCrcf{object: resampler,
                     resample_rate: resample_rate
        }
    }

    /// Get filter delay (output samples).
    pub fn get_delay(&self) -> f32 {
        unsafe{ffiliquid::msresamp_crcf_get_delay(self.object)}
    }

    /// Creates Vec<Complex<f32>> that contains resampled original `input` signal.
    pub fn resample(&self, input: &mut [Complex<f32>]) -> Vec<Complex<f32>> {
        let output_len = (2f32 * input.len() as f32 * self.resample_rate) as u32;
        let mut output = vec![Complex::<f32>::new(0.0f32, 0.0f32); output_len as usize];

        let _nx = input.len() as u32;
        let x = unsafe {transmute::<*mut Complex<f32>, *mut LiquidComplex32>(input.as_mut_ptr())};
        let y = unsafe {transmute::<*mut Complex<f32>, *mut LiquidComplex32>(output.as_mut_ptr())};
        let mut output_sample_count = 0;

        // execute multi-stage resampler
        //  _x      :   input sample array  [size: _nx x 1]
        //  _nx     :   input sample array size
        //  _y      :   output sample array [size: variable]
        //  _ny     :   number of samples written to _y
        unsafe {ffiliquid::msresamp_crcf_execute(self.object, x, _nx, y, &mut output_sample_count)};
        output.truncate(output_sample_count as usize);
        output
    }
}

impl Drop for MsresampCrcf {
    fn drop(&mut self) {
        unsafe{ffiliquid::msresamp_crcf_destroy(self.object)};
    }
}
<|endoftext|>


<commit_before>//! Various definitions of types, constants, traint, ... related to network

use core::fmt::{
    Binary,
    Octal,
    LowerHex,
    UpperHex,
    Debug,
    Display,
    Formatter,
    Error
};

use num::PrimInt;

/// Network integer representation
///
/// This type stores an integer using network's endianness and let the user
/// manipulates it using host's endianness.
#[derive(Clone)]
#[repr(C, packed)]
pub struct Int<T: PrimInt + Clone>(T);

impl<T> Int<T> where T: PrimInt + Clone {
    /// Construct from an integer represented using network's endianness
    pub fn from_net(i: T) -> Self {
        Int(i)
    }

    /// Construct from an integer represented using host's endianness
    pub fn from_host(i: T) -> Self {
        Int(i.to_be())
    }

    /// Returns the contained integer using host's endianness
    pub fn as_host(&self) -> T {
        T::from_be(self.0.clone())
    }

    /// Returns the contained integer using network's endianness
    pub fn as_net(&self) -> T {
        self.0.clone()
    }
}

impl<T> Binary for Int<T> where T: PrimInt + Clone + Binary {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { self.as_host().fmt(f) }
}

impl<T> Octal for Int<T> where T: PrimInt + Clone + Octal {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { self.as_host().fmt(f) }
}

impl<T> LowerHex for Int<T> where T: PrimInt + Clone + LowerHex {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { self.as_host().fmt(f) }
}

impl<T> UpperHex for Int<T> where T: PrimInt + Clone + UpperHex {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { self.as_host().fmt(f) }
}

impl<T> Debug for Int<T> where T: PrimInt + Clone + Debug {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { self.as_host().fmt(f) }
}

impl<T> Display for Int<T> where T: PrimInt + Clone + Display {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { self.as_host().fmt(f) }
}

const COUNT_HWADDR_BYTES: usize = 6;

#[repr(C, packed)]
#[derive(Copy, Clone)]
/// A MAC address
pub struct HwAddr {
    bytes: [u8; COUNT_HWADDR_BYTES],
}

impl HwAddr {
    /// Create an empty hardware address (i.e., 00:00:00:00:00:00)
    pub fn empty() -> Self {
        HwAddr {
            bytes: [0; COUNT_HWADDR_BYTES],
        }
    }

    /// Create an hardware address from bytes.
    ///
    /// This method is unsafe because the slice *MUST* contain at least 6
    /// elements.
    pub unsafe fn from_bytes(bytes: &[u8]) -> Self {
        let mut ret = Self::empty();

        ret.bytes[0] = bytes[0];
        ret.bytes[1] = bytes[1];
        ret.bytes[2] = bytes[2];
        ret.bytes[3] = bytes[3];
        ret.bytes[4] = bytes[4];
        ret.bytes[5] = bytes[5];

        ret
    }

    fn format(&self, f: &mut Formatter) -> Result<(), Error> {
        f.write_fmt(format_args!("{:x}:{:x}:{:x}:{:x}:{:x}:{:x}", self.bytes[0],
                                 self.bytes[1], self.bytes[2], self.bytes[3],
                                 self.bytes[4], self.bytes[5]))
    }

    #[inline]
    /// Returns the internal representation of an hardware address
    pub fn as_bytes(&self) -> &[u8] {
        &self.bytes[..]
    }
}

impl PartialEq for HwAddr {
    fn eq(&self, rhs: &Self) -> bool {
        self.bytes[0] == rhs.bytes[0] &&
        self.bytes[1] == rhs.bytes[1] &&
        self.bytes[2] == rhs.bytes[2] &&
        self.bytes[3] == rhs.bytes[3] &&
        self.bytes[4] == rhs.bytes[4] &&
        self.bytes[5] == rhs.bytes[5]
    }
}

impl Debug for HwAddr {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        self.format(f)
    }
}

impl Display for HwAddr {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        self.format(f)
    }
}
<commit_msg>net: HwAddr does not implement Debug anymore<commit_after>//! Various definitions of types, constants, traint, ... related to network

use core::fmt::{
    Binary,
    Octal,
    LowerHex,
    UpperHex,
    Debug,
    Display,
    Formatter,
    Error
};

use num::PrimInt;

/// Network integer representation
///
/// This type stores an integer using network's endianness and let the user
/// manipulates it using host's endianness.
#[derive(Clone)]
#[repr(C, packed)]
pub struct Int<T: PrimInt + Clone>(T);

impl<T> Int<T> where T: PrimInt + Clone {
    /// Construct from an integer represented using network's endianness
    pub fn from_net(i: T) -> Self {
        Int(i)
    }

    /// Construct from an integer represented using host's endianness
    pub fn from_host(i: T) -> Self {
        Int(i.to_be())
    }

    /// Returns the contained integer using host's endianness
    pub fn as_host(&self) -> T {
        T::from_be(self.0.clone())
    }

    /// Returns the contained integer using network's endianness
    pub fn as_net(&self) -> T {
        self.0.clone()
    }
}

impl<T> Binary for Int<T> where T: PrimInt + Clone + Binary {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { self.as_host().fmt(f) }
}

impl<T> Octal for Int<T> where T: PrimInt + Clone + Octal {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { self.as_host().fmt(f) }
}

impl<T> LowerHex for Int<T> where T: PrimInt + Clone + LowerHex {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { self.as_host().fmt(f) }
}

impl<T> UpperHex for Int<T> where T: PrimInt + Clone + UpperHex {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { self.as_host().fmt(f) }
}

impl<T> Debug for Int<T> where T: PrimInt + Clone + Debug {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { self.as_host().fmt(f) }
}

impl<T> Display for Int<T> where T: PrimInt + Clone + Display {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { self.as_host().fmt(f) }
}

const COUNT_HWADDR_BYTES: usize = 6;

#[repr(C, packed)]
#[derive(Copy, Clone)]
/// A MAC address
pub struct HwAddr {
    bytes: [u8; COUNT_HWADDR_BYTES],
}

impl HwAddr {
    /// Create an empty hardware address (i.e., 00:00:00:00:00:00)
    pub fn empty() -> Self {
        HwAddr {
            bytes: [0; COUNT_HWADDR_BYTES],
        }
    }

    /// Create an hardware address from bytes.
    ///
    /// This method is unsafe because the slice *MUST* contain at least 6
    /// elements.
    pub unsafe fn from_bytes(bytes: &[u8]) -> Self {
        let mut ret = Self::empty();

        ret.bytes[0] = bytes[0];
        ret.bytes[1] = bytes[1];
        ret.bytes[2] = bytes[2];
        ret.bytes[3] = bytes[3];
        ret.bytes[4] = bytes[4];
        ret.bytes[5] = bytes[5];

        ret
    }

    #[inline]
    /// Returns the internal representation of an hardware address
    pub fn as_bytes(&self) -> &[u8] {
        &self.bytes[..]
    }
}

impl PartialEq for HwAddr {
    fn eq(&self, rhs: &Self) -> bool {
        self.bytes[0] == rhs.bytes[0] &&
        self.bytes[1] == rhs.bytes[1] &&
        self.bytes[2] == rhs.bytes[2] &&
        self.bytes[3] == rhs.bytes[3] &&
        self.bytes[4] == rhs.bytes[4] &&
        self.bytes[5] == rhs.bytes[5]
    }
}

impl Display for HwAddr {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        f.write_fmt(format_args!("{:x}:{:x}:{:x}:{:x}:{:x}:{:x}", self.bytes[0],
                                 self.bytes[1], self.bytes[2], self.bytes[3],
                                 self.bytes[4], self.bytes[5]))
    }
}
<|endoftext|>


<commit_before>use iced::{canvas, mouse, Canvas, Color, Element, Length, Point, Rectangle, Sandbox, Settings, Vector};
use oppai_field::field::{self, Field, Pos};
use oppai_field::player::Player;
use oppai_field::zobrist::Zobrist;
use rand::SeedableRng;
use rand_xorshift::XorShiftRng;

const SEED: [u8; 16] = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53];

const FIELD_WIDTH: u32 = 39;
const FIELD_HEIGHT: u32 = 32;

pub fn main() {
  Game::run(Settings {
    antialiasing: true,
    ..Settings::default()
  });
}

struct Game {
  player: Player,
  field: Field,
  captures: Vec<(Vec<Pos>, Player)>,
}

#[derive(Debug, Clone, Copy)]
enum Message {
  PutPoint(Pos),
}

impl Sandbox for Game {
  type Message = Message;

  fn new() -> Self {
    let mut rng = XorShiftRng::from_seed(SEED);
    let zobrist = Zobrist::new(field::length(FIELD_WIDTH, FIELD_HEIGHT) * 2, &mut rng);
    let field = Field::new(FIELD_WIDTH, FIELD_HEIGHT, std::sync::Arc::new(zobrist));
    Game {
      player: Player::Red,
      field,
      captures: Vec::new(),
    }
  }

  fn title(&self) -> String {
    "OpPAI".into()
  }

  fn update(&mut self, message: Self::Message) {
    let Message::PutPoint(pos) = message;
    if self.field.put_point(pos, self.player) {
      self.player = self.player.next();
      let last_chain = self.field.get_last_chain();
      if let Some(&pos) = last_chain.first() {
        let player = self.field.cell(pos).get_player();
        self.captures.push((last_chain, player));
      }
    }
  }

  fn view(&mut self) -> iced::Element<'_, Self::Message> {
    let canvas = Canvas::new(self).height(Length::Fill).width(Length::Fill);
    Element::<Pos>::from(canvas).map(Message::PutPoint)
  }
}

impl canvas::Program<Pos> for Game {
  fn update(&mut self, event: canvas::Event, bounds: Rectangle, cursor: canvas::Cursor) -> Option<Pos> {
    let cursor_position = cursor.position_in(&bounds)?;
    let canvas::Event::Mouse(mouse_event) = event;
    match mouse_event {
      mouse::Event::ButtonPressed(mouse::Button::Left) => {
        let field_width = self.field.width();
        let field_height = self.field.height();
        let width = bounds
          .width
          .min(bounds.height / field_height as f32 * field_width as f32);
        let height = bounds
          .height
          .min(bounds.width / field_width as f32 * field_height as f32);
        let step_x = width / field_width as f32;
        let step_y = height / field_height as f32;
        let shift = Vector::new(
          ((bounds.width - width) / 2.0).round() + step_x / 2.0,
          ((bounds.height - height) / 2.0).round() + step_y / 2.0,
        );

        let point = cursor_position - shift;
        let x = (point.x / step_x).round() as u32;
        let y = (point.y / step_y).round() as u32;
        Some(self.field.to_pos(x, y))
      }
      _ => None,
    }
  }

  fn draw(&self, bounds: Rectangle, _cursor: canvas::Cursor) -> Vec<canvas::Geometry> {
    let mut frame = canvas::Frame::new(bounds.size());

    let field_width = self.field.width();
    let field_height = self.field.height();
    let width = frame
      .width()
      .min(frame.height() / field_height as f32 * field_width as f32);
    let height = frame
      .height()
      .min(frame.width() / field_width as f32 * field_height as f32);
    let step_x = width / field_width as f32;
    let step_y = height / field_height as f32;
    let shift = Vector::new(
      ((frame.width() - width) / 2.0).round(),
      ((frame.height() - height) / 2.0).round(),
    );

    let grid = canvas::Path::new(|path| {
      for x in 0..field_width {
        let offset = (step_x * x as f32 + step_x / 2.0).round() + 0.5;
        path.move_to(Point::new(offset, 0.0) + shift);
        path.line_to(Point::new(offset, height) + shift);
      }
      for y in 0..field_height {
        let offset = (step_y * y as f32 + step_y / 2.0).round() + 0.5;
        path.move_to(Point::new(0.0, offset) + shift);
        path.line_to(Point::new(width, offset) + shift);
      }
    });

    frame.stroke(
      &grid,
      canvas::Stroke {
        width: 1.0,
        color: Color::BLACK,
        ..canvas::Stroke::default()
      },
    );

    fn color(player: Player) -> Color {
      match player {
        Player::Red => Color::from_rgb8(0xFF, 0x00, 0x00),
        Player::Black => Color::BLACK,
      }
    }

    for &player in &[Player::Red, Player::Black] {
      let points = canvas::Path::new(|path| {
        for &pos in self
          .field
          .points_seq()
          .iter()
          .filter(|&&pos| self.field.cell(pos).is_players_point(player))
        {
          let x = self.field.to_x(pos);
          let y = self.field.to_y(pos);

          let offset_x = (step_x * x as f32 + step_x / 2.0).round() + 0.5;
          let offset_y = (step_y * y as f32 + step_y / 2.0).round() + 0.5;
          path.circle(Point::new(offset_x, offset_y) + shift, 5.0)
        }
      });

      frame.fill(&points, color(player));
    }

    for (chain, player) in &self.captures {
      let path = canvas::Path::new(|path| {
        let pos = chain[0];
        let x = self.field.to_x(pos);
        let y = self.field.to_y(pos);

        let offset_x = (step_x * x as f32 + step_x / 2.0).round() + 0.5;
        let offset_y = (step_y * y as f32 + step_y / 2.0).round() + 0.5;
        path.move_to(Point::new(offset_x, offset_y) + shift);

        for &pos in chain.iter().skip(1) {
          let x = self.field.to_x(pos);
          let y = self.field.to_y(pos);

          let offset_x = (step_x * x as f32 + step_x / 2.0).round() + 0.5;
          let offset_y = (step_y * y as f32 + step_y / 2.0).round() + 0.5;
          path.line_to(Point::new(offset_x, offset_y) + shift);
        }
      });

      let mut color = color(*player);
      color.a = 0.5;

      frame.fill(&path, color);
    }

    vec![frame.into_geometry()]
  }
}
<commit_msg>Reduce code duplication.<commit_after>use iced::{canvas, mouse, Canvas, Color, Element, Length, Point, Rectangle, Sandbox, Settings, Vector};
use oppai_field::field::{self, Field, Pos};
use oppai_field::player::Player;
use oppai_field::zobrist::Zobrist;
use rand::SeedableRng;
use rand_xorshift::XorShiftRng;

const SEED: [u8; 16] = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53];

const FIELD_WIDTH: u32 = 39;
const FIELD_HEIGHT: u32 = 32;

pub fn main() {
  Game::run(Settings {
    antialiasing: true,
    ..Settings::default()
  });
}

struct Game {
  player: Player,
  field: Field,
  captures: Vec<(Vec<Pos>, Player)>,
}

#[derive(Debug, Clone, Copy)]
enum Message {
  PutPoint(Pos),
}

impl Sandbox for Game {
  type Message = Message;

  fn new() -> Self {
    let mut rng = XorShiftRng::from_seed(SEED);
    let zobrist = Zobrist::new(field::length(FIELD_WIDTH, FIELD_HEIGHT) * 2, &mut rng);
    let field = Field::new(FIELD_WIDTH, FIELD_HEIGHT, std::sync::Arc::new(zobrist));
    Game {
      player: Player::Red,
      field,
      captures: Vec::new(),
    }
  }

  fn title(&self) -> String {
    "OpPAI".into()
  }

  fn update(&mut self, message: Self::Message) {
    let Message::PutPoint(pos) = message;
    if self.field.put_point(pos, self.player) {
      self.player = self.player.next();
      let last_chain = self.field.get_last_chain();
      if let Some(&pos) = last_chain.first() {
        let player = self.field.cell(pos).get_player();
        self.captures.push((last_chain, player));
      }
    }
  }

  fn view(&mut self) -> iced::Element<'_, Self::Message> {
    let canvas = Canvas::new(self).height(Length::Fill).width(Length::Fill);
    Element::<Pos>::from(canvas).map(Message::PutPoint)
  }
}

impl canvas::Program<Pos> for Game {
  fn update(&mut self, event: canvas::Event, bounds: Rectangle, cursor: canvas::Cursor) -> Option<Pos> {
    let cursor_position = cursor.position_in(&bounds)?;
    let canvas::Event::Mouse(mouse_event) = event;
    match mouse_event {
      mouse::Event::ButtonPressed(mouse::Button::Left) => {
        let field_width = self.field.width();
        let field_height = self.field.height();
        let width = bounds
          .width
          .min(bounds.height / field_height as f32 * field_width as f32);
        let height = bounds
          .height
          .min(bounds.width / field_width as f32 * field_height as f32);
        let step_x = width / field_width as f32;
        let step_y = height / field_height as f32;
        let shift = Vector::new(
          ((bounds.width - width) / 2.0).round() + step_x / 2.0,
          ((bounds.height - height) / 2.0).round() + step_y / 2.0,
        );

        let point = cursor_position - shift;
        let x = (point.x / step_x).round() as u32;
        let y = (point.y / step_y).round() as u32;
        Some(self.field.to_pos(x, y))
      }
      _ => None,
    }
  }

  fn draw(&self, bounds: Rectangle, _cursor: canvas::Cursor) -> Vec<canvas::Geometry> {
    let mut frame = canvas::Frame::new(bounds.size());

    let field_width = self.field.width();
    let field_height = self.field.height();
    let width = frame
      .width()
      .min(frame.height() / field_height as f32 * field_width as f32);
    let height = frame
      .height()
      .min(frame.width() / field_width as f32 * field_height as f32);
    let step_x = width / field_width as f32;
    let step_y = height / field_height as f32;
    let shift = Vector::new(
      ((frame.width() - width) / 2.0).round(),
      ((frame.height() - height) / 2.0).round(),
    );

    let grid = canvas::Path::new(|path| {
      for x in 0..field_width {
        let offset = (step_x * x as f32 + step_x / 2.0).round() + 0.5;
        path.move_to(Point::new(offset, 0.0) + shift);
        path.line_to(Point::new(offset, height) + shift);
      }
      for y in 0..field_height {
        let offset = (step_y * y as f32 + step_y / 2.0).round() + 0.5;
        path.move_to(Point::new(0.0, offset) + shift);
        path.line_to(Point::new(width, offset) + shift);
      }
    });

    frame.stroke(
      &grid,
      canvas::Stroke {
        width: 1.0,
        color: Color::BLACK,
        ..canvas::Stroke::default()
      },
    );

    fn color(player: Player) -> Color {
      match player {
        Player::Red => Color::from_rgb8(0xFF, 0x00, 0x00),
        Player::Black => Color::BLACK,
      }
    }

    let pos_to_point = |pos: Pos| {
      let x = self.field.to_x(pos);
      let y = self.field.to_y(pos);
      let offset_x = (step_x * x as f32 + step_x / 2.0).round() + 0.5;
      let offset_y = (step_y * y as f32 + step_y / 2.0).round() + 0.5;
      Point::new(offset_x, offset_y) + shift
    };

    for &player in &[Player::Red, Player::Black] {
      let points = canvas::Path::new(|path| {
        for &pos in self
          .field
          .points_seq()
          .iter()
          .filter(|&&pos| self.field.cell(pos).is_players_point(player))
        {
          path.circle(pos_to_point(pos), 5.0)
        }
      });

      frame.fill(&points, color(player));
    }

    for (chain, player) in &self.captures {
      let path = canvas::Path::new(|path| {
        path.move_to(pos_to_point(chain[0]));
        for &pos in chain.iter().skip(1) {
          path.line_to(pos_to_point(pos));
        }
      });

      let mut color = color(*player);
      color.a = 0.5;

      frame.fill(&path, color);
    }

    vec![frame.into_geometry()]
  }
}
<|endoftext|>


<commit_before>#[crate_id(name = "md5sum", vers = "1.0.0", author = "Arcterus")];

#[feature(macro_rules)];

extern crate crypto = "rust-crypto";
extern crate getopts;

use std::io::fs::File;
use std::io::BufferedReader;
use std::os;
use crypto::digest::Digest;

#[path = "../common/util.rs"]
mod util;

static NAME: &'static str = "md5sum";
static VERSION: &'static str = "1.0.0";

fn main() {
    let args = os::args();

    let program = args[0].clone();

    let opts = [
        getopts::optflag("b", "binary", "read in binary mode"),
        getopts::optflag("c", "check", "read MD5 sums from the FILEs and check them"),
        getopts::optflag("", "tag", "create a BSD-style checksum"),
        getopts::optflag("t", "text", "read in text mode (default)"),
        getopts::optflag("q", "quiet", "don't print OK for each successfully verified file"),
        getopts::optflag("s", "status", "don't output anything, status code shows success"),
        getopts::optflag("", "strict", "exit non-zero for improperly formatted checksum lines"),
        getopts::optflag("w", "warn", "warn about improperly formatted checksum lines"),
        getopts::optflag("h", "help", "display this help and exit"),
        getopts::optflag("V", "version", "output version information and exit")
    ];

    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => crash!(1, "{}", f.to_err_msg())
    };

    if matches.opt_present("help") {
        println!("{} v{}", NAME, VERSION);
        println!("");
        println!("Usage:");
        println!("  {} [OPTION]... [FILE]...", program);
        println!("");
        print!("{}", getopts::usage("Compute and check MD5 message digests.", opts));
    } else if matches.opt_present("version") {
        println!("{} v{}", NAME, VERSION);
    } else {
        let binary = matches.opt_present("binary");
        let check = matches.opt_present("check");
        let tag = matches.opt_present("tag");
        let status = matches.opt_present("status");
        let quiet = matches.opt_present("quiet") || status;
        let strict = matches.opt_present("strict");
        let warn = matches.opt_present("warn") && !status;
        md5sum(matches.free, binary, check, tag, status, quiet, strict, warn);
    }
}

fn md5sum(files: Vec<~str>, binary: bool, check: bool, tag: bool, status: bool, quiet: bool, strict: bool, warn: bool) {
    let mut md5 = crypto::md5::Md5::new();
    let bytes = md5.output_bits() / 4;
    let mut bad_format = 0;
    let mut failed = 0;
    for filename in files.iter() {
        let filename: &str = *filename;
        let mut file = safe_unwrap!(File::open(&Path::new(filename)));
        if check {
            let mut buffer = BufferedReader::new(file);
            for (i, line) in buffer.lines().enumerate() {
                let line = safe_unwrap!(line);
                let (ck_filename, sum) = match from_gnu(line, bytes) {
                    Some(m) => m,
                    None => match from_bsd(line, bytes) {
                        Some(m) => m,
                        None => {
                            bad_format += 1;
                            if strict {
                                os::set_exit_status(1);
                            }
                            if warn {
                                show_warning!("{}: {}: improperly formatted MD5 checksum line", filename, i + 1);
                            }
                            continue;
                        }
                    }
                };
                let real_sum = calc_sum(&mut md5, &mut safe_unwrap!(File::open(&Path::new(ck_filename))), binary);
                if sum == real_sum {
                    if !quiet {
                        println!("{}: OK", ck_filename);
                    }
                } else {
                    if !status {
                        println!("{}: FAILED", ck_filename);
                    }
                    failed += 1;
                    os::set_exit_status(1);
                }
            }
        } else {
            let sum = calc_sum(&mut md5, &mut file, binary);
            if tag {
                println!("MD5 ({}) = {}", filename, sum);
            } else {
                println!("{}  {}", sum, filename);
            }
        }
    }
    if !status {
        if bad_format == 1 {
            show_warning!("{} line is improperly formatted", bad_format);
        } else if bad_format > 1 {
            show_warning!("{} lines are improperly formatted", bad_format);
        }
        if failed > 0 {
            show_warning!("{} computed checksum did NOT match", failed);
        }
    }
}

fn calc_sum(md5: &mut crypto::md5::Md5, file: &mut File, binary: bool) -> ~str {
    let data =
        if binary {
            safe_unwrap!(file.read_to_end())
        } else {
            let val = safe_unwrap!(file.read_to_str()).into_bytes();  // XXX: i don't know why the variable is necessary
            val
        };
    md5.reset();
    md5.input(data);
    md5.result_str()
}

fn from_gnu<'a>(line: &'a str, bytes: uint) -> Option<(&'a str, &'a str)> {
    let sum = line.slice_to(bytes);
    if sum.len() < bytes || line.slice(bytes, bytes + 2) != "  " {
        None
    } else {
        Some((line.slice(bytes + 2, line.len() - 1), sum))
    }
}

fn from_bsd<'a>(line: &'a str, bytes: uint) -> Option<(&'a str, &'a str)> {
    if line.slice(0, 5) == "MD5 (" {
        let rparen = match line.find(')') {
            Some(m) => m,
            None => return None
        };
        if rparen > 5 && line.slice(rparen + 1, rparen + 4) == " = " && line.len() - 1 == rparen + 4 + bytes {
            return Some((line.slice(5, rparen), line.slice(rparen + 4, line.len() - 1)));
        }
    }
    None
}<commit_msg>md5sum: remove unnecessary variable (thanks @huonw)<commit_after>#[crate_id(name = "md5sum", vers = "1.0.0", author = "Arcterus")];

#[feature(macro_rules)];

extern crate crypto = "rust-crypto";
extern crate getopts;

use std::io::fs::File;
use std::io::BufferedReader;
use std::os;
use crypto::digest::Digest;

#[path = "../common/util.rs"]
mod util;

static NAME: &'static str = "md5sum";
static VERSION: &'static str = "1.0.0";

fn main() {
    let args = os::args();

    let program = args[0].clone();

    let opts = [
        getopts::optflag("b", "binary", "read in binary mode"),
        getopts::optflag("c", "check", "read MD5 sums from the FILEs and check them"),
        getopts::optflag("", "tag", "create a BSD-style checksum"),
        getopts::optflag("t", "text", "read in text mode (default)"),
        getopts::optflag("q", "quiet", "don't print OK for each successfully verified file"),
        getopts::optflag("s", "status", "don't output anything, status code shows success"),
        getopts::optflag("", "strict", "exit non-zero for improperly formatted checksum lines"),
        getopts::optflag("w", "warn", "warn about improperly formatted checksum lines"),
        getopts::optflag("h", "help", "display this help and exit"),
        getopts::optflag("V", "version", "output version information and exit")
    ];

    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => crash!(1, "{}", f.to_err_msg())
    };

    if matches.opt_present("help") {
        println!("{} v{}", NAME, VERSION);
        println!("");
        println!("Usage:");
        println!("  {} [OPTION]... [FILE]...", program);
        println!("");
        print!("{}", getopts::usage("Compute and check MD5 message digests.", opts));
    } else if matches.opt_present("version") {
        println!("{} v{}", NAME, VERSION);
    } else {
        let binary = matches.opt_present("binary");
        let check = matches.opt_present("check");
        let tag = matches.opt_present("tag");
        let status = matches.opt_present("status");
        let quiet = matches.opt_present("quiet") || status;
        let strict = matches.opt_present("strict");
        let warn = matches.opt_present("warn") && !status;
        md5sum(matches.free, binary, check, tag, status, quiet, strict, warn);
    }
}

fn md5sum(files: Vec<~str>, binary: bool, check: bool, tag: bool, status: bool, quiet: bool, strict: bool, warn: bool) {
    let mut md5 = crypto::md5::Md5::new();
    let bytes = md5.output_bits() / 4;
    let mut bad_format = 0;
    let mut failed = 0;
    for filename in files.iter() {
        let filename: &str = *filename;
        let mut file = safe_unwrap!(File::open(&Path::new(filename)));
        if check {
            let mut buffer = BufferedReader::new(file);
            for (i, line) in buffer.lines().enumerate() {
                let line = safe_unwrap!(line);
                let (ck_filename, sum) = match from_gnu(line, bytes) {
                    Some(m) => m,
                    None => match from_bsd(line, bytes) {
                        Some(m) => m,
                        None => {
                            bad_format += 1;
                            if strict {
                                os::set_exit_status(1);
                            }
                            if warn {
                                show_warning!("{}: {}: improperly formatted MD5 checksum line", filename, i + 1);
                            }
                            continue;
                        }
                    }
                };
                let real_sum = calc_sum(&mut md5, &mut safe_unwrap!(File::open(&Path::new(ck_filename))), binary);
                if sum == real_sum {
                    if !quiet {
                        println!("{}: OK", ck_filename);
                    }
                } else {
                    if !status {
                        println!("{}: FAILED", ck_filename);
                    }
                    failed += 1;
                    os::set_exit_status(1);
                }
            }
        } else {
            let sum = calc_sum(&mut md5, &mut file, binary);
            if tag {
                println!("MD5 ({}) = {}", filename, sum);
            } else {
                println!("{}  {}", sum, filename);
            }
        }
    }
    if !status {
        if bad_format == 1 {
            show_warning!("{} line is improperly formatted", bad_format);
        } else if bad_format > 1 {
            show_warning!("{} lines are improperly formatted", bad_format);
        }
        if failed > 0 {
            show_warning!("{} computed checksum did NOT match", failed);
        }
    }
}

fn calc_sum(md5: &mut crypto::md5::Md5, file: &mut File, binary: bool) -> ~str {
    let data =
        if binary {
            safe_unwrap!(file.read_to_end())
        } else {
            (safe_unwrap!(file.read_to_str())).into_bytes()
        };
    md5.reset();
    md5.input(data);
    md5.result_str()
}

fn from_gnu<'a>(line: &'a str, bytes: uint) -> Option<(&'a str, &'a str)> {
    let sum = line.slice_to(bytes);
    if sum.len() < bytes || line.slice(bytes, bytes + 2) != "  " {
        None
    } else {
        Some((line.slice(bytes + 2, line.len() - 1), sum))
    }
}

fn from_bsd<'a>(line: &'a str, bytes: uint) -> Option<(&'a str, &'a str)> {
    if line.slice(0, 5) == "MD5 (" {
        let rparen = match line.find(')') {
            Some(m) => m,
            None => return None
        };
        if rparen > 5 && line.slice(rparen + 1, rparen + 4) == " = " && line.len() - 1 == rparen + 4 + bytes {
            return Some((line.slice(5, rparen), line.slice(rparen + 4, line.len() - 1)));
        }
    }
    None
}
<|endoftext|>


<commit_before>extern crate proc_macro;

use proc_macro::TokenStream;
use proc_macro2::{Span, TokenStream as TokenStream2};
use quote::{quote, ToTokens, TokenStreamExt};
use syn::{AttributeArgs, Ident, NestedMeta};

enum ResourceType {
    Async,
    Sync,
}

impl ToTokens for ResourceType {
    fn to_tokens(&self, stream: &mut TokenStream2) {
        let ident = match self {
            ResourceType::Async => "to",
            ResourceType::Sync => "to",
        };
        let ident = Ident::new(ident, Span::call_site());
        stream.append(ident);
    }
}

#[derive(PartialEq)]
pub enum GuardType {
    Get,
    Post,
    Put,
    Delete,
    Head,
    Connect,
    Options,
    Trace,
    Patch,
}

impl GuardType {
    fn as_str(&self) -> &'static str {
        match self {
            GuardType::Get => "Get",
            GuardType::Post => "Post",
            GuardType::Put => "Put",
            GuardType::Delete => "Delete",
            GuardType::Head => "Head",
            GuardType::Connect => "Connect",
            GuardType::Options => "Options",
            GuardType::Trace => "Trace",
            GuardType::Patch => "Patch",
        }
    }
}

impl ToTokens for GuardType {
    fn to_tokens(&self, stream: &mut TokenStream2) {
        let ident = self.as_str();
        let ident = Ident::new(ident, Span::call_site());
        stream.append(ident);
    }
}

struct Args {
    path: syn::LitStr,
    guards: Vec<Ident>,
}

impl Args {
    fn new(args: AttributeArgs) -> syn::Result<Self> {
        let mut path = None;
        let mut guards = Vec::new();
        for arg in args {
            match arg {
                NestedMeta::Lit(syn::Lit::Str(lit)) => match path {
                    None => {
                        path = Some(lit);
                    }
                    _ => {
                        return Err(syn::Error::new_spanned(
                            lit,
                            "Multiple paths specified! Should be only one!",
                        ));
                    }
                },
                NestedMeta::Meta(syn::Meta::NameValue(nv)) => {
                    if nv.path.is_ident("guard") {
                        if let syn::Lit::Str(lit) = nv.lit {
                            guards.push(Ident::new(&lit.value(), Span::call_site()));
                        } else {
                            return Err(syn::Error::new_spanned(
                                nv.lit,
                                "Attribute guard expects literal string!",
                            ));
                        }
                    } else {
                        return Err(syn::Error::new_spanned(
                            nv.path,
                            "Unknown attribute key is specified. Allowed: guard",
                        ));
                    }
                }
                arg => {
                    return Err(syn::Error::new_spanned(arg, "Unknown attribute"));
                }
            }
        }
        Ok(Args {
            path: path.unwrap(),
            guards,
        })
    }
}

pub struct Route {
    name: syn::Ident,
    args: Args,
    ast: syn::ItemFn,
    resource_type: ResourceType,
    guard: GuardType,
}

fn guess_resource_type(typ: &syn::Type) -> ResourceType {
    let mut guess = ResourceType::Sync;

    if let syn::Type::ImplTrait(typ) = typ {
        for bound in typ.bounds.iter() {
            if let syn::TypeParamBound::Trait(bound) = bound {
                for bound in bound.path.segments.iter() {
                    if bound.ident == "Future" {
                        guess = ResourceType::Async;
                        break;
                    } else if bound.ident == "Responder" {
                        guess = ResourceType::Sync;
                        break;
                    }
                }
            }
        }
    }

    guess
}

impl Route {
    pub fn new(
        args: AttributeArgs,
        input: TokenStream,
        guard: GuardType,
    ) -> syn::Result<Self> {
        if args.is_empty() {
            return Err(syn::Error::new(
                Span::call_site(),
                format!(
                    r#"invalid server definition, expected #[{}("<some path>")]"#,
                    guard.as_str().to_ascii_lowercase()
                ),
            ));
        }
        let ast: syn::ItemFn = syn::parse(input)?;
        let name = ast.sig.ident.clone();

        let args = Args::new(args)?;

        let resource_type = if ast.sig.asyncness.is_some() {
            ResourceType::Async
        } else {
            match ast.sig.output {
                syn::ReturnType::Default => {
                    return Err(syn::Error::new_spanned(
                        ast,
                        "Function has no return type. Cannot be used as handler",
                    ));
                }
                syn::ReturnType::Type(_, ref typ) => guess_resource_type(typ.as_ref()),
            }
        };

        Ok(Self {
            name,
            args,
            ast,
            resource_type,
            guard,
        })
    }

    pub fn generate(&self) -> TokenStream {
        let name = &self.name;
        let resource_name = name.to_string();
        let guard = &self.guard;
        let ast = &self.ast;
        let path = &self.args.path;
        let extra_guards = &self.args.guards;
        let resource_type = &self.resource_type;
        let stream = quote! {
            #[allow(non_camel_case_types)]
            pub struct #name;

            impl actix_web::dev::HttpServiceFactory for #name {
                fn register(self, __config: &mut actix_web::dev::AppService) {
                    #ast
                    let __resource = actix_web::Resource::new(#path)
                        .name(#resource_name)
                        .guard(actix_web::guard::#guard())
                        #(.guard(actix_web::guard::fn_guard(#extra_guards)))*
                        .#resource_type(#name);

                    actix_web::dev::HttpServiceFactory::register(__resource, __config)
                }
            }
        };
        stream.into()
    }
}
<commit_msg>Add missing_docs attribute to generated structs<commit_after>extern crate proc_macro;

use proc_macro::TokenStream;
use proc_macro2::{Span, TokenStream as TokenStream2};
use quote::{quote, ToTokens, TokenStreamExt};
use syn::{AttributeArgs, Ident, NestedMeta};

enum ResourceType {
    Async,
    Sync,
}

impl ToTokens for ResourceType {
    fn to_tokens(&self, stream: &mut TokenStream2) {
        let ident = match self {
            ResourceType::Async => "to",
            ResourceType::Sync => "to",
        };
        let ident = Ident::new(ident, Span::call_site());
        stream.append(ident);
    }
}

#[derive(PartialEq)]
pub enum GuardType {
    Get,
    Post,
    Put,
    Delete,
    Head,
    Connect,
    Options,
    Trace,
    Patch,
}

impl GuardType {
    fn as_str(&self) -> &'static str {
        match self {
            GuardType::Get => "Get",
            GuardType::Post => "Post",
            GuardType::Put => "Put",
            GuardType::Delete => "Delete",
            GuardType::Head => "Head",
            GuardType::Connect => "Connect",
            GuardType::Options => "Options",
            GuardType::Trace => "Trace",
            GuardType::Patch => "Patch",
        }
    }
}

impl ToTokens for GuardType {
    fn to_tokens(&self, stream: &mut TokenStream2) {
        let ident = self.as_str();
        let ident = Ident::new(ident, Span::call_site());
        stream.append(ident);
    }
}

struct Args {
    path: syn::LitStr,
    guards: Vec<Ident>,
}

impl Args {
    fn new(args: AttributeArgs) -> syn::Result<Self> {
        let mut path = None;
        let mut guards = Vec::new();
        for arg in args {
            match arg {
                NestedMeta::Lit(syn::Lit::Str(lit)) => match path {
                    None => {
                        path = Some(lit);
                    }
                    _ => {
                        return Err(syn::Error::new_spanned(
                            lit,
                            "Multiple paths specified! Should be only one!",
                        ));
                    }
                },
                NestedMeta::Meta(syn::Meta::NameValue(nv)) => {
                    if nv.path.is_ident("guard") {
                        if let syn::Lit::Str(lit) = nv.lit {
                            guards.push(Ident::new(&lit.value(), Span::call_site()));
                        } else {
                            return Err(syn::Error::new_spanned(
                                nv.lit,
                                "Attribute guard expects literal string!",
                            ));
                        }
                    } else {
                        return Err(syn::Error::new_spanned(
                            nv.path,
                            "Unknown attribute key is specified. Allowed: guard",
                        ));
                    }
                }
                arg => {
                    return Err(syn::Error::new_spanned(arg, "Unknown attribute"));
                }
            }
        }
        Ok(Args {
            path: path.unwrap(),
            guards,
        })
    }
}

pub struct Route {
    name: syn::Ident,
    args: Args,
    ast: syn::ItemFn,
    resource_type: ResourceType,
    guard: GuardType,
}

fn guess_resource_type(typ: &syn::Type) -> ResourceType {
    let mut guess = ResourceType::Sync;

    if let syn::Type::ImplTrait(typ) = typ {
        for bound in typ.bounds.iter() {
            if let syn::TypeParamBound::Trait(bound) = bound {
                for bound in bound.path.segments.iter() {
                    if bound.ident == "Future" {
                        guess = ResourceType::Async;
                        break;
                    } else if bound.ident == "Responder" {
                        guess = ResourceType::Sync;
                        break;
                    }
                }
            }
        }
    }

    guess
}

impl Route {
    pub fn new(
        args: AttributeArgs,
        input: TokenStream,
        guard: GuardType,
    ) -> syn::Result<Self> {
        if args.is_empty() {
            return Err(syn::Error::new(
                Span::call_site(),
                format!(
                    r#"invalid server definition, expected #[{}("<some path>")]"#,
                    guard.as_str().to_ascii_lowercase()
                ),
            ));
        }
        let ast: syn::ItemFn = syn::parse(input)?;
        let name = ast.sig.ident.clone();

        let args = Args::new(args)?;

        let resource_type = if ast.sig.asyncness.is_some() {
            ResourceType::Async
        } else {
            match ast.sig.output {
                syn::ReturnType::Default => {
                    return Err(syn::Error::new_spanned(
                        ast,
                        "Function has no return type. Cannot be used as handler",
                    ));
                }
                syn::ReturnType::Type(_, ref typ) => guess_resource_type(typ.as_ref()),
            }
        };

        Ok(Self {
            name,
            args,
            ast,
            resource_type,
            guard,
        })
    }

    pub fn generate(&self) -> TokenStream {
        let name = &self.name;
        let resource_name = name.to_string();
        let guard = &self.guard;
        let ast = &self.ast;
        let path = &self.args.path;
        let extra_guards = &self.args.guards;
        let resource_type = &self.resource_type;
        let stream = quote! {
            #[allow(non_camel_case_types, missing_docs)]
            pub struct #name;

            impl actix_web::dev::HttpServiceFactory for #name {
                fn register(self, __config: &mut actix_web::dev::AppService) {
                    #ast
                    let __resource = actix_web::Resource::new(#path)
                        .name(#resource_name)
                        .guard(actix_web::guard::#guard())
                        #(.guard(actix_web::guard::fn_guard(#extra_guards)))*
                        .#resource_type(#name);

                    actix_web::dev::HttpServiceFactory::register(__resource, __config)
                }
            }
        };
        stream.into()
    }
}
<|endoftext|>


<commit_before>use std::fs;
use std::io;
use std::path::Path;
use std::sync::Arc;

use memmap::{Mmap, Protection};

/// A read only view into a memory map.
///
/// Reading a memory map is unsafe because we cannot guarantee that its
/// underlying memory is not mutated by external processes. This read only
/// memory map guarantees that consumers can at least never modify the
/// underlying data.
///
/// It is principally useful for controlling which region of a file an `Fst`
/// reads. Taking a slice from it is still considered unsafe.
pub struct MmapReadOnly {
    map: Arc<Mmap>,
    offset: usize,
    len: usize,
}

impl MmapReadOnly {
    /// Create a new memory map from an existing file handle.
    pub fn open(file: &fs::File) -> io::Result<MmapReadOnly> {
        Ok(try!(Mmap::open(file, Protection::Read)).into())
    }

    /// Open a new memory map from the path given.
    pub fn open_path<P: AsRef<Path>>(path: P) -> io::Result<MmapReadOnly> {
        MmapReadOnly::open(&try!(fs::File::open(path)))
    }

    /// Returns the size in byte of the memory map.
    ///
    /// If it is a range, the size is the size of the range.
    pub fn len(&self,) -> usize {
        self.len
    }

    /// Slice this memory map to a new `offset` and `len`.
    ///
    /// If the new range is outside the bounds of `self`, then this method
    /// panics.
    pub fn range(&self, offset: usize, len: usize) -> MmapReadOnly {
        assert!(offset + len <= self.len);
        MmapReadOnly {
            map: self.map.clone(),
            offset: self.offset + offset,
            len: len,
        }
    }

    /// Read the memory map as a `&[u8]`.
    pub unsafe fn as_slice(&self) -> &[u8] {
        &self.map.as_slice()[self.offset..self.offset + self.len]
    }
}

impl Clone for MmapReadOnly {
    fn clone(&self) -> MmapReadOnly {
        MmapReadOnly{
            map: self.map.clone(),
            offset: self.offset,
            len: self.len,
        }
    }
}

impl From<Mmap> for MmapReadOnly {
    fn from(mmap: Mmap) -> MmapReadOnly {
        let len = mmap.len();
        MmapReadOnly {
            map: Arc::new(mmap),
            offset: 0,
            len: len,
        }
    }
}
<commit_msg>Added impl From<Arc<Mmap>> for MmapReadOnly<commit_after>use std::fs;
use std::io;
use std::path::Path;
use std::sync::Arc;

use memmap::{Mmap, Protection};

/// A read only view into a memory map.
///
/// Reading a memory map is unsafe because we cannot guarantee that its
/// underlying memory is not mutated by external processes. This read only
/// memory map guarantees that consumers can at least never modify the
/// underlying data.
///
/// It is principally useful for controlling which region of a file an `Fst`
/// reads. Taking a slice from it is still considered unsafe.
pub struct MmapReadOnly {
    map: Arc<Mmap>,
    offset: usize,
    len: usize,
}

impl MmapReadOnly {
    /// Create a new memory map from an existing file handle.
    pub fn open(file: &fs::File) -> io::Result<MmapReadOnly> {
        Ok(try!(Mmap::open(file, Protection::Read)).into())
    }

    /// Open a new memory map from the path given.
    pub fn open_path<P: AsRef<Path>>(path: P) -> io::Result<MmapReadOnly> {
        MmapReadOnly::open(&try!(fs::File::open(path)))
    }

    /// Returns the size in byte of the memory map.
    ///
    /// If it is a range, the size is the size of the range.
    pub fn len(&self,) -> usize {
        self.len
    }

    /// Slice this memory map to a new `offset` and `len`.
    ///
    /// If the new range is outside the bounds of `self`, then this method
    /// panics.
    pub fn range(&self, offset: usize, len: usize) -> MmapReadOnly {
        assert!(offset + len <= self.len);
        MmapReadOnly {
            map: self.map.clone(),
            offset: self.offset + offset,
            len: len,
        }
    }

    /// Read the memory map as a `&[u8]`.
    pub unsafe fn as_slice(&self) -> &[u8] {
        &self.map.as_slice()[self.offset..self.offset + self.len]
    }
}

impl Clone for MmapReadOnly {
    fn clone(&self) -> MmapReadOnly {
        MmapReadOnly{
            map: self.map.clone(),
            offset: self.offset,
            len: self.len,
        }
    }
}

impl From<Mmap> for MmapReadOnly {
    fn from(mmap: Mmap) -> MmapReadOnly {
        From::from(Arc::new(mmap))
    }
}

impl From<Arc<Mmap>> for MmapReadOnly {
    fn from(mmap_arc: Arc<Mmap>) -> MmapReadOnly {
        let len = mmap_arc.len();
        MmapReadOnly {
            map: mmap_arc,
            offset: 0,
            len: len,
        }
    }
}
<|endoftext|>


<commit_before>use std::ops::{Shl, Shr};
use std::cell::RefCell;

pub trait Subscriber {
    type Input;

    fn on_next(&mut self, t: Self::Input) -> bool;
    fn on_subscribe(&mut self, usize) {
        debug!("on_subscribe called");
    }
    fn on_error(&mut self, err: &str) {
        error!("on_error called: {:?}", err);
    }
    fn on_complete(&mut self, force: bool) {
        debug!("on_complete called");
    }
}

pub trait Publisher<'S> {
    type Output;
    fn subscribe<S>(&mut self, Box<S>) where S : Subscriber<Input=Self::Output>;

    fn next(&mut self) -> bool {
        panic!("Unimplemented fn, presumably run() or next() is being attempted on a processor, not a publisher");
    }

    fn run(&mut self) {
        loop {
            if ! self.next() {
                break
            }
        }
    }
}

pub trait Processor<'a> : Subscriber + Publisher<'a> { }

impl<'a, P> Processor<'a> for P
where P : Subscriber + Publisher<'a> { }
<commit_msg>more tweaks to publisher..<commit_after>use std::ops::{Shl, Shr};
use std::cell::RefCell;

pub trait Subscriber {
    type Input;

    fn on_next(&mut self, t: Self::Input) -> bool;
    fn on_subscribe(&mut self, usize) {
        debug!("on_subscribe called");
    }
    fn on_error(&mut self, err: &str) {
        error!("on_error called: {:?}", err);
    }
    fn on_complete(&mut self, force: bool) {
        debug!("on_complete called");
    }
}

pub trait Publisher<'a> {
    type Output;
    fn subscribe<S>(&mut self, Box<S>) where S : Subscriber<Input=Self::Output>;

    fn next(&mut self) -> bool {
        panic!("Unimplemented fn, presumably run() or next() is being attempted on a processor, not a publisher");
    }

    fn run(&mut self) {
        loop {
            if ! self.next() {
                break
            }
        }
    }
}

pub trait Processor<'a> : Subscriber + Publisher<'a> { }

impl<'a, P> Processor<'a> for P
where P : Subscriber + Publisher<'a> { }
<|endoftext|>