<commit_before>//
// Author: Patrick Walton
//

use std::fs::File;
use std::io::{self, Read, Write, Result};

/// Reads until the buffer is filled or the reader signals EOF
pub fn read_to_buf(mut buf: &mut [u8], rd: &mut Read) -> io::Result<()> {
    let mut total = 0;
    while total < buf.len() {
        let count = try!(rd.read(&mut buf[total..]));
        if count == 0 {
            // Buffer not yet filled, but EOF reached
            return Err(io::Error::new(io::ErrorKind::Other, "eof reached prematurely"))
        }
        total += count;
    }

    Ok(())
}

//
// A tiny custom serialization infrastructure, used for savestates.
//
// TODO: Use the standard library's ToBytes and add a FromBytes -- or don't; this is such a small
// amount of code it barely seems worth it.
//

// TODO: use `serde` (if it's ready) or `rustc-serialize` and `bincode`

pub trait Save {
    fn save(&mut self, fd: &mut File);
    fn load(&mut self, fd: &mut File);
}

impl Save for u8 {
    fn save(&mut self, fd: &mut File) {
        fd.write_all(&[*self]).unwrap();
    }
    fn load(&mut self, fd: &mut File) {
        let mut buf = [ 0 ];
        read_to_buf(&mut buf, fd).unwrap();
        *self = buf[0];
    }
}

impl Save for u16 {
    fn save(&mut self, fd: &mut File) {
        fd.write(&[*self as u8, (*self >> 8) as u8]).unwrap();
    }
    fn load(&mut self, fd: &mut File) {
        let mut buf = [ 0, 0 ];
        read_to_buf(&mut buf, fd).unwrap();
        *self = (buf[0] as u16) | ((buf[1] as u16) << 8);
    }
}

impl Save for u64 {
    fn save(&mut self, fd: &mut File) {
        let mut buf = [0; 8];
        for i in 0..8 {
            buf[i] = ((*self) >> (i * 8)) as u8;
        }
        fd.write_all(&buf).unwrap();
    }
    fn load(&mut self, fd: &mut File) {
        let mut buf = [0; 8];
        read_to_buf(&mut buf, fd).unwrap();
        *self = 0;
        for i in 0..8 {
            *self = *self | (buf[i] as u64) << (i * 8);
        }
    }
}

impl<'a> Save for &'a mut [u8] {
    fn save(&mut self, fd: &mut File) {
        fd.write(*self).unwrap();
    }
    fn load(&mut self, fd: &mut File) {
        read_to_buf(self, fd).unwrap();
    }
}

impl Save for bool {
    fn save(&mut self, fd: &mut File) {
        fd.write(&[ if *self { 0 } else { 1 } ]).unwrap();
    }
    fn load(&mut self, fd: &mut File) {
        let mut val: [u8; 1] = [ 0 ];
        read_to_buf(&mut val, fd).unwrap();
        *self = val[0] != 0
    }
}

// A convenience macro to save and load entire structs.
macro_rules! save_struct(
    ($name:ident { $($field:ident),* }) => (
        impl Save for $name {
            fn save(&mut self, fd: &mut File) {
                $(self.$field.save(fd);)*
            }
            fn load(&mut self, fd: &mut File) {
                $(self.$field.load(fd);)*
            }
        }
    )
);

macro_rules! save_enum(
    ($name:ident { $val_0:ident, $val_1:ident }) => (
        impl Save for $name {
            fn save(&mut self, fd: &mut File) {
                let mut val: u8 = match *self { $name::$val_0 => 0, $name::$val_1 => 1 };
                val.save(fd)
            }
            fn load(&mut self, fd: &mut File) {
                let mut val: u8 = 0;
                val.load(fd);
                *self = if val == 0 { $name::$val_0 } else { $name::$val_1 };
            }
        }
    )
);

//
// Random number generation
//

// TODO use the `rand` crate

#[derive(Copy, Clone)]
pub struct Xorshift {
    pub x: u32,
    pub y: u32,
    pub z: u32,
    pub w: u32,
}

impl Xorshift {
    pub fn new() -> Xorshift {
        Xorshift { x: 123456789, y: 362436069, z: 521288629, w: 88675123 }
    }

    pub fn next(&mut self) -> u32 {
        let t = self.x ^ (self.x << 11);
        self.x = self.y; self.y = self.z; self.z = self.w;
        self.w = self.w ^ (self.w >> 19) ^ (t ^ (t >> 8));
        self.w
    }
}
<commit_msg>Update comment for Xorshift utility<commit_after>//
// Author: Patrick Walton
//

use std::fs::File;
use std::io::{self, Read, Write, Result};

/// Reads until the buffer is filled or the reader signals EOF
pub fn read_to_buf(mut buf: &mut [u8], rd: &mut Read) -> io::Result<()> {
    let mut total = 0;
    while total < buf.len() {
        let count = try!(rd.read(&mut buf[total..]));
        if count == 0 {
            // Buffer not yet filled, but EOF reached
            return Err(io::Error::new(io::ErrorKind::Other, "eof reached prematurely"))
        }
        total += count;
    }

    Ok(())
}

//
// A tiny custom serialization infrastructure, used for savestates.
//
// TODO: Use the standard library's ToBytes and add a FromBytes -- or don't; this is such a small
// amount of code it barely seems worth it.
//

// TODO: use `serde` (if it's ready) or `rustc-serialize` and `bincode`

pub trait Save {
    fn save(&mut self, fd: &mut File);
    fn load(&mut self, fd: &mut File);
}

impl Save for u8 {
    fn save(&mut self, fd: &mut File) {
        fd.write_all(&[*self]).unwrap();
    }
    fn load(&mut self, fd: &mut File) {
        let mut buf = [ 0 ];
        read_to_buf(&mut buf, fd).unwrap();
        *self = buf[0];
    }
}

impl Save for u16 {
    fn save(&mut self, fd: &mut File) {
        fd.write(&[*self as u8, (*self >> 8) as u8]).unwrap();
    }
    fn load(&mut self, fd: &mut File) {
        let mut buf = [ 0, 0 ];
        read_to_buf(&mut buf, fd).unwrap();
        *self = (buf[0] as u16) | ((buf[1] as u16) << 8);
    }
}

impl Save for u64 {
    fn save(&mut self, fd: &mut File) {
        let mut buf = [0; 8];
        for i in 0..8 {
            buf[i] = ((*self) >> (i * 8)) as u8;
        }
        fd.write_all(&buf).unwrap();
    }
    fn load(&mut self, fd: &mut File) {
        let mut buf = [0; 8];
        read_to_buf(&mut buf, fd).unwrap();
        *self = 0;
        for i in 0..8 {
            *self = *self | (buf[i] as u64) << (i * 8);
        }
    }
}

impl<'a> Save for &'a mut [u8] {
    fn save(&mut self, fd: &mut File) {
        fd.write(*self).unwrap();
    }
    fn load(&mut self, fd: &mut File) {
        read_to_buf(self, fd).unwrap();
    }
}

impl Save for bool {
    fn save(&mut self, fd: &mut File) {
        fd.write(&[ if *self { 0 } else { 1 } ]).unwrap();
    }
    fn load(&mut self, fd: &mut File) {
        let mut val: [u8; 1] = [ 0 ];
        read_to_buf(&mut val, fd).unwrap();
        *self = val[0] != 0
    }
}

// A convenience macro to save and load entire structs.
macro_rules! save_struct(
    ($name:ident { $($field:ident),* }) => (
        impl Save for $name {
            fn save(&mut self, fd: &mut File) {
                $(self.$field.save(fd);)*
            }
            fn load(&mut self, fd: &mut File) {
                $(self.$field.load(fd);)*
            }
        }
    )
);

macro_rules! save_enum(
    ($name:ident { $val_0:ident, $val_1:ident }) => (
        impl Save for $name {
            fn save(&mut self, fd: &mut File) {
                let mut val: u8 = match *self { $name::$val_0 => 0, $name::$val_1 => 1 };
                val.save(fd)
            }
            fn load(&mut self, fd: &mut File) {
                let mut val: u8 = 0;
                val.load(fd);
                *self = if val == 0 { $name::$val_0 } else { $name::$val_1 };
            }
        }
    )
);

//
// Random number generation
//

// TODO remove this and emulate the APU's noise generator properly

#[derive(Copy, Clone)]
pub struct Xorshift {
    pub x: u32,
    pub y: u32,
    pub z: u32,
    pub w: u32,
}

impl Xorshift {
    pub fn new() -> Xorshift {
        Xorshift { x: 123456789, y: 362436069, z: 521288629, w: 88675123 }
    }

    pub fn next(&mut self) -> u32 {
        let t = self.x ^ (self.x << 11);
        self.x = self.y; self.y = self.z; self.z = self.w;
        self.w = self.w ^ (self.w >> 19) ^ (t ^ (t >> 8));
        self.w
    }
}
<|endoftext|>


<commit_before>//! Vectors on a plane.
use std::ops::{Add, Sub, Mul, Div, Neg};
use std::cmp::PartialEq;
use std::str::FromStr;
use std::fmt;
use std::num;

/// 2D vector in cartesian coordinates
#[derive(Debug, Clone, Copy)]
pub struct Vec2 {
    /// component of vector
    pub x: f64,
    /// component of vector
    pub y: f64,
}

impl Vec2 {
    /// Constructs a new `Vec2`.
    pub fn new<I: Into<f64>>(x: I, y: I) -> Vec2 {
        Vec2 {
            x: x.into(),
            y: y.into(),
        }
    }
    /// Constructs a new `Vec2` from polar coordinates $(r, \theta)$.
    pub fn from_polar<I: Into<f64>>(r: I, theta: I) -> Vec2 {
        let (r, theta) = (r.into(), theta.into());
        Vec2::new(r * f64::cos(theta), r * f64::sin(theta))
    }
    /// Create a zero `Vec2`
    pub fn zero() -> Vec2 {
        Vec2::new(0.0, 0.0)
    }
    /// Scalar product
    pub fn dot(self, rhs: Vec2) -> f64 {
        self.x * rhs.x + self.y * rhs.y
    }
    /// Orthogonal vector
    pub fn cross(self) -> Vec2 {
        Vec2::new(self.y, -self.x)
    }
    /// Area of parallelogramm
    pub fn area(self, rhs: Vec2) -> f64 {
        self.dot(rhs.cross())
    }
    /// Vector length
    pub fn len(self) -> f64 {
        self.dot(self).sqrt()
    }
    /// Unary vector, co-directed with given
    pub fn ort(self) -> Vec2 {
        self / self.len()
    }
    /// Squares of the vector coordinates
    pub fn sqr(self) -> Vec2 {
        self * self
    }
    /// Square root of vector coordinates
    pub fn sqrt(self) -> Vec2 {
        Vec2::new(self.x.sqrt(), self.y.sqrt())
    }
    /// Constructs dual basis for given.
    ///
    /// Dual basis $(\vec{b}_1, \vec{b}_2)$ for basis $(\vec{a}_1, \vec{a}_2)$ satisfies relation
    /// $$\vec{a}_i \cdot \vec{b}_j = \delta_{ij}$$
    ///
    /// # Example
    /// ```
    /// use linal::Vec2;
    ///
    /// let a1 = Vec2::new(2, 0);
    /// let a2 = Vec2::new(3, 4);
    ///
    /// let (b1, b2) = Vec2::dual_basis((a1, a2));
    /// assert_eq!(b1, Vec2::new(0.5, -0.375));
    /// assert_eq!(b2, Vec2::new(0.0, 0.25));
    /// ```
    pub fn dual_basis(basis: (Vec2, Vec2)) -> (Vec2, Vec2) {
        let (a, b) = basis;
        let area = a.area(b);
        (b.cross() / area, -a.cross() / area)
    }
}

impl Add for Vec2 {
    type Output = Self;

    fn add(self, _rhs: Self) -> Self {
        Vec2::new(self.x + _rhs.x, self.y + _rhs.y)
    }
}

impl Sub for Vec2 {
    type Output = Self;

    fn sub(self, _rhs: Self) -> Self {
        Vec2::new(self.x - _rhs.x, self.y - _rhs.y)
    }
}

impl Mul for Vec2 {
    type Output = Self;

    fn mul(self, _rhs: Vec2) -> Vec2 {
        Vec2::new(self.x * _rhs.x, self.y * _rhs.y)
    }
}

impl<I: Into<f64>> Mul<I> for Vec2 {
    type Output = Self;

    fn mul(self, _rhs: I) -> Vec2 {
        let _rhs = _rhs.into();
        Vec2::new(self.x * _rhs, self.y * _rhs)
    }
}

impl<I: Into<f64>> Div<I> for Vec2 {
    type Output = Self;

    fn div(self, _rhs: I) -> Vec2 {
        let _rhs = _rhs.into();
        if _rhs == 0.0 {
            panic!("Can't divide by zero!");
        }
        Vec2::new(self.x / _rhs, self.y / _rhs)
    }
}

impl Neg for Vec2 {
    type Output = Self;

    fn neg(self) -> Self {
        Self::new(-self.x, -self.y)
    }
}

impl PartialEq for Vec2 {
    fn eq(&self, other: &Self) -> bool {
        self.x == other.x && self.y == other.y
    }
}

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

impl FromStr for Vec2 {
    type Err = num::ParseFloatError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let words: Vec<&str> = s.split_whitespace().collect();
        let x: f64 = try!(words[0].parse());
        let y: f64 = try!(words[1].parse());
        Ok(Self::new(x, y))
    }
}

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

    #[test]
    fn vec2_mul() {
        let a = Vec2::new(1, 2);
        let b = Vec2::new(3, 6);
        let r = a * 3;
        assert_eq!(r, b);
    }

    #[test]
    #[should_panic]
    fn vec2_div() {
        let a = Vec2::new(1, 2);
        let _ = a / 0.0;
    }

    #[test]
    fn vec2_from_polar() {
        let a = Vec2::new(3, 4);
        let b = Vec2::from_polar(5.0, f64::atan2(4.0, 3.0));
        assert!((a - b).len() < 1e-10);
    }

    #[test]
    fn vec2_add() {
        let a = Vec2::new(1, 2);
        let b = Vec2::new(-3, 6);
        let c = Vec2::new(-2, 8);
        assert_eq!(a + b, c);
    }

    #[test]
    fn vec2_sub() {
        let a = Vec2::new(1, 2);
        let b = Vec2::new(-3, 6);
        let c = Vec2::new(4, -4);
        assert_eq!(a - b, c);
    }

    #[test]
    fn vec2_dot() {
        let a = Vec2::new(1, 2);
        let b = Vec2::new(-3, 6);
        let c = 9.0;
        assert_eq!(a.dot(b), c);
        assert_eq!(b.dot(a), c);
    }

    #[test]
    fn vec2_area() {
        let a = Vec2::new(1, 2);
        let b = Vec2::new(-3, 6);
        let c = 12.0;
        assert_eq!(a.area(b), c);
        assert_eq!(b.area(a), -c);
    }

    #[test]
    fn vec2_cross_z() {
        let a = Vec2::new(1, 2);
        let b = 2.0;
        let c = Vec2::new(4, -2);
        assert_eq!(a.cross() * b, c);
    }

    #[test]
    fn vec2_neg() {
        let a = Vec2::new(1, 2);
        let b = Vec2::new(-1, -2);
        assert_eq!(-a, b);
    }

    #[test]
    fn vec2_parse() {
        let a: Vec2 = "1 2".parse().unwrap();
        assert_eq!(a, Vec2::new(1, 2));
    }
}
<commit_msg>[add] more examples for vec2<commit_after>//! Vectors on a plane.
use std::ops::{Add, Sub, Mul, Div, Neg};
use std::cmp::PartialEq;
use std::str::FromStr;
use std::fmt;
use std::num;

/// 2D vector in cartesian coordinates
#[derive(Debug, Clone, Copy)]
pub struct Vec2 {
    /// component of vector
    pub x: f64,
    /// component of vector
    pub y: f64,
}

impl Vec2 {
    /// Constructs a new `Vec2`.
    ///
    /// # Example
    /// ```
    /// use linal::Vec2;
    ///
    /// // create `Vec2` with int
    /// let a = Vec2::new(10, 20);
    /// // create `Vec2` with float
    /// let b = Vec2::new(3.5, 2.5);
    /// // Supported types implemented for trait Into (with convertion to f64)
    /// ```
    pub fn new<I: Into<f64>>(x: I, y: I) -> Vec2 {
        Vec2 {
            x: x.into(),
            y: y.into(),
        }
    }
    /// Constructs a new `Vec2` from polar coordinates $(r, \theta)$.
    ///
    /// # Example
    /// ```
    /// use std::f64::consts::PI;
    /// use linal::Vec2;
    ///
    /// // calculation error
    /// let eps = 1E-15;
    /// // Create `Vec2` use polar coordinates
    /// let v = Vec2::from_polar(2.0, PI / 2.0);
    /// assert!(v.x < eps && v.y - 2.0 < eps);
    /// ```
    pub fn from_polar<I: Into<f64>>(r: I, theta: I) -> Vec2 {
        let (r, theta) = (r.into(), theta.into());
        Vec2::new(r * f64::cos(theta), r * f64::sin(theta))
    }
    /// Create a zero `Vec2`
    ///
    /// # Example
    /// ```
    /// use linal::Vec2;
    ///
    /// // create zero `Vec2`
    /// let zero = Vec2::zero();
    /// assert_eq!(zero, Vec2::new(0, 0));
    /// ```
    pub fn zero() -> Vec2 {
        Vec2::new(0.0, 0.0)
    }
    /// Scalar product
    ///
    /// # Example
    /// ```
    /// use linal::Vec2;
    ///
    /// let a = Vec2::new(1, 2);
    /// let b = Vec2::new(3, 4);
    /// // The scalar production of `a` by `b`
    /// let r = a.dot(b);
    /// assert_eq!(r, 11.0);
    /// ```
    pub fn dot(self, rhs: Vec2) -> f64 {
        self.x * rhs.x + self.y * rhs.y
    }
    /// Orthogonal vector
    ///
    /// # Example
    /// ```
    /// use linal::Vec2;
    ///
    /// let a = Vec2::new(2, 2);
    /// let b = Vec2::new(2, -2);
    /// // create orthogonal vector
    /// //             y ^
    /// //               |
    /// //               |
    /// //             2 - ...... /a
    /// //               |     //  :
    /// //             1 -   //    :
    /// //    -2   -1    | //      :
    /// //  -- | -- | -- 0 -- | -- | ---->
    /// //     :      // |    1    2     x
    /// //     :    //   - -1
    /// //     :  //     |
    /// //     b/ ...... - -2
    /// let c = a.cross();
    /// assert_eq!(b, c);
    /// ```
    pub fn cross(self) -> Vec2 {
        Vec2::new(self.y, -self.x)
    }
    /// Area of parallelogramm
    ///
    /// # Example
    /// ```
    /// use linal::Vec2;
    ///
    /// let a = Vec2::new(2, 0);
    /// let b = Vec2::new(0, 2);
    /// // Calculate the area of the parallelogram formed by the vectors
    /// // y ^
    /// //   |
    /// //   |
    /// // 2 b .........
    /// //   |         :
    /// // 1 -         :
    /// //   |         :
    /// //   0 -- | -- a ---->
    /// //        1    2     x
    /// let area = a.area(b);
    /// assert_eq!(area, 4.0);
    /// ```
    pub fn area(self, rhs: Vec2) -> f64 {
        self.dot(rhs.cross())
    }
    /// Vector length
    ///
    /// # Example
    /// ```
    /// use linal::Vec2;
    ///
    /// let vec = Vec2::new(2, 0);
    /// // Calculate vector length
    /// let len1 = vec.len();
    /// let len2 = (-vec.cross()).len();
    /// assert!(len1 == len2 && len1 == 2.0);
    /// ```
    pub fn len(self) -> f64 {
        self.dot(self).sqrt()
    }
    /// Unary vector, co-directed with given
    ///
    /// # Example
    /// ```
    /// use linal::Vec2;
    ///
    /// let a = Vec2::new(2, 0);
    /// // Calculate unary vector from `a`
    /// let b = a.ort();
    /// assert_eq!(b, Vec2::new(1, 0));
    /// ```
    pub fn ort(self) -> Vec2 {
        self / self.len()
    }
    /// Squares of the vector coordinates
    ///
    /// # Example
    /// ```
    /// use linal::Vec2;
    ///
    /// let a = Vec2::new(2, 3);
    /// let b = Vec2::new(4, 9);
    /// // Calculate squre of `a`
    /// let c = a.sqr();
    /// assert_eq!(b, c);
    /// ```
    pub fn sqr(self) -> Vec2 {
        self * self
    }
    /// Square root of vector coordinates
    ///
    /// # Example
    /// ```
    /// use linal::Vec2;
    ///
    /// let a = Vec2::new(2, 3);
    /// let b = Vec2::new(4, 9);
    /// // Calculate squre root of `b`
    /// let c = b.sqrt();
    /// assert_eq!(a, c);
    /// ```
    pub fn sqrt(self) -> Vec2 {
        Vec2::new(self.x.sqrt(), self.y.sqrt())
    }
    /// Constructs dual basis for given.
    ///
    /// Dual basis $(\vec{b}_1, \vec{b}_2)$ for basis $(\vec{a}_1, \vec{a}_2)$ satisfies relation
    /// $$\vec{a}_i \cdot \vec{b}_j = \delta_{ij}$$
    ///
    /// # Example
    /// ```
    /// use linal::Vec2;
    ///
    /// let a1 = Vec2::new(2, 0);
    /// let a2 = Vec2::new(3, 4);
    ///
    /// let (b1, b2) = Vec2::dual_basis((a1, a2));
    /// assert_eq!(b1, Vec2::new(0.5, -0.375));
    /// assert_eq!(b2, Vec2::new(0.0, 0.25));
    /// ```
    pub fn dual_basis(basis: (Vec2, Vec2)) -> (Vec2, Vec2) {
        let (a, b) = basis;
        let area = a.area(b);
        (b.cross() / area, -a.cross() / area)
    }
}

impl Add for Vec2 {
    type Output = Self;

    fn add(self, _rhs: Self) -> Self {
        Vec2::new(self.x + _rhs.x, self.y + _rhs.y)
    }
}

impl Sub for Vec2 {
    type Output = Self;

    fn sub(self, _rhs: Self) -> Self {
        Vec2::new(self.x - _rhs.x, self.y - _rhs.y)
    }
}

impl Mul for Vec2 {
    type Output = Self;

    fn mul(self, _rhs: Vec2) -> Vec2 {
        Vec2::new(self.x * _rhs.x, self.y * _rhs.y)
    }
}

impl<I: Into<f64>> Mul<I> for Vec2 {
    type Output = Self;

    fn mul(self, _rhs: I) -> Vec2 {
        let _rhs = _rhs.into();
        Vec2::new(self.x * _rhs, self.y * _rhs)
    }
}

impl<I: Into<f64>> Div<I> for Vec2 {
    type Output = Self;

    fn div(self, _rhs: I) -> Vec2 {
        let _rhs = _rhs.into();
        if _rhs == 0.0 {
            panic!("Can't divide by zero!");
        }
        Vec2::new(self.x / _rhs, self.y / _rhs)
    }
}

impl Neg for Vec2 {
    type Output = Self;

    fn neg(self) -> Self {
        Self::new(-self.x, -self.y)
    }
}

impl PartialEq for Vec2 {
    fn eq(&self, other: &Self) -> bool {
        self.x == other.x && self.y == other.y
    }
}

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

impl FromStr for Vec2 {
    type Err = num::ParseFloatError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let words: Vec<&str> = s.split_whitespace().collect();
        let x: f64 = try!(words[0].parse());
        let y: f64 = try!(words[1].parse());
        Ok(Self::new(x, y))
    }
}

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

    #[test]
    fn vec2_mul() {
        let a = Vec2::new(1, 2);
        let b = Vec2::new(3, 6);
        let r = a * 3;
        assert_eq!(r, b);
    }

    #[test]
    #[should_panic]
    fn vec2_div() {
        let a = Vec2::new(1, 2);
        let _ = a / 0.0;
    }

    #[test]
    fn vec2_from_polar() {
        let a = Vec2::new(3, 4);
        let b = Vec2::from_polar(5.0, f64::atan2(4.0, 3.0));
        assert!((a - b).len() < 1e-10);
    }

    #[test]
    fn vec2_add() {
        let a = Vec2::new(1, 2);
        let b = Vec2::new(-3, 6);
        let c = Vec2::new(-2, 8);
        assert_eq!(a + b, c);
    }

    #[test]
    fn vec2_sub() {
        let a = Vec2::new(1, 2);
        let b = Vec2::new(-3, 6);
        let c = Vec2::new(4, -4);
        assert_eq!(a - b, c);
    }

    #[test]
    fn vec2_dot() {
        let a = Vec2::new(1, 2);
        let b = Vec2::new(-3, 6);
        let c = 9.0;
        assert_eq!(a.dot(b), c);
        assert_eq!(b.dot(a), c);
    }

    #[test]
    fn vec2_area() {
        let a = Vec2::new(1, 2);
        let b = Vec2::new(-3, 6);
        let c = 12.0;
        assert_eq!(a.area(b), c);
        assert_eq!(b.area(a), -c);
    }

    #[test]
    fn vec2_cross_z() {
        let a = Vec2::new(1, 2);
        let b = 2.0;
        let c = Vec2::new(4, -2);
        assert_eq!(a.cross() * b, c);
    }

    #[test]
    fn vec2_neg() {
        let a = Vec2::new(1, 2);
        let b = Vec2::new(-1, -2);
        assert_eq!(-a, b);
    }

    #[test]
    fn vec2_parse() {
        let a: Vec2 = "1 2".parse().unwrap();
        assert_eq!(a, Vec2::new(1, 2));
    }
}
<|endoftext|>


<commit_before>use master_smasher::drawable::{Asset, Drawable};
use master_smasher::shape::{Circle, Intersect};
use super::world_assets::WorldAssets;
use super::collidable::Collidable;
use super::level_data::{PlanetData, PlanetKind};

use glm::{self, GenNum};
use glm::ext::normalize_to;
use num_traits::Zero;

use std::cmp;
use std::time::Duration;

struct Ring {
    radius: f64,
    strength: f64,
    asset: Asset,
    moving: Asset,
}

impl Ring {
    pub fn new(radius: f64, strength: f64, asset: Asset) -> Self {
        Ring {
            radius: radius,
            strength: strength,
            asset: asset.clone(),
            moving: asset,
        }
    }

    pub fn animate(&mut self, delta: Duration) {
        let moving_radius = self.moving.dims().x as f64 / 2.;
        let pull = glm::length(self.pull_vector(glm::dvec2(moving_radius, 0.), 0.));
        let zoom = 1. / 2_f64.powf(pull / 500.);
        self.moving.zoom(glm::DVec2::from_s(zoom));
    }

    pub fn drawables(&self) -> Vec<Drawable> {
        vec![Drawable::Asset(self.asset), Drawable::Asset(self.moving)]
    }

    pub fn pull_vector(&self, dist: glm::DVec2, radius: f64) -> glm::DVec2 {
        let len = glm::length(dist);
        if len > (self.radius + radius) {
            glm::DVec2::zero()
        } else {
            let force = self.strength / (len.powf(0.8));
            normalize_to(dist, force)
        }
    }
}

pub struct Planet {
    body: Circle,
    asset: Asset,
    ring: Option<Ring>,
}

impl Planet {
    pub fn new(data: &PlanetData, textures: &WorldAssets) -> Self {
        let (asset, ring) = Self::load_assets(data, textures);
        let dims = asset.dims();
        let radius = cmp::min(dims.x, dims.y) as f64 / 2.;
        let center = glm::dvec2(data.x as f64, data.y as f64);
        let body = Circle {
            center: center,
            radius: radius,
        };

        Planet {
            body: body,
            asset: asset,
            ring: ring,
        }
    }

    pub fn animate(&mut self, delta: Duration) {
        if let Some(ref mut r) = self.ring {
            if r.moving.dims().x / 2 < self.body.radius as u32 {
                r.moving = r.asset.clone();
            }
            r.animate(delta)
        }
    }

    pub fn pull_vector(&self, point: glm::DVec2, radius: f64) -> glm::DVec2 {
        self.ring.as_ref().map_or(glm::DVec2::zero(),
                                  |r| r.pull_vector(self.body.center - point, radius))
    }

    pub fn drawables(&self) -> Vec<Drawable> {
        let mut drawables = self.ring.as_ref().map_or(vec![], |r| r.drawables());
        drawables.push(Drawable::Asset(self.asset));
        drawables
    }

    fn load_assets(data: &PlanetData, textures: &WorldAssets) -> (Asset, Option<Ring>) {
        let center = glm::ivec2(data.x, data.y);
        let (planet, ring) = match data.kind {
            PlanetKind::RED { ring, strength } => {
                (textures.red_planet, Some((textures.red_ring, ring, strength)))
            }
            PlanetKind::BLUE { ring, strength } => {
                (textures.blue_planet, Some((textures.blue_ring, ring, strength)))
            }
            PlanetKind::WHITE { ring, strength } => {
                (textures.white_planet, Some((textures.white_ring, ring, strength)))
            }
            PlanetKind::DEAD => (textures.dead_planet, None),
        };

        let planet = Asset::from_texture(&planet, center);
        let ring = ring.map(|(t, r, s)| {
            let dims = glm::UVec2::from_s((r * 2.) as u32);
            let asset = Asset::centered_on(t.id, center, dims);
            Ring::new(r, s, asset)
        });

        (planet, ring)
    }
}

impl<I: Intersect<Circle>> Collidable<Circle, I> for Planet {
    fn collides(&self, shape: &I) -> bool {
        shape.intersects(&self.body)
    }
}
<commit_msg>keep track of zoom instead of separate asset in planet radius<commit_after>use master_smasher::drawable::{Asset, Drawable};
use master_smasher::shape::{Circle, Intersect};
use super::world_assets::WorldAssets;
use super::collidable::Collidable;
use super::level_data::{PlanetData, PlanetKind};

use glm::{self, GenNum};
use glm::ext::normalize_to;
use num_traits::Zero;

use std::cmp;
use std::time::Duration;

struct Ring {
    radius: f64,
    strength: f64,
    asset: Asset,
    zoom: f64,
}

impl Ring {
    pub fn new(radius: f64, strength: f64, asset: Asset) -> Self {
        Ring {
            radius: radius,
            strength: strength,
            asset: asset.clone(),
            zoom: 1.,
        }
    }

    pub fn animate(&mut self, delta: Duration) {
        let moving_radius = self.asset.dims().x as f64 * self.zoom / 2.;
        let pull = glm::length(self.pull_vector(glm::dvec2(moving_radius, 0.), 0.));
        let zoom = 1. / 2_f64.powf(pull / 500.);
        self.zoom *= zoom;
    }

    pub fn drawables(&self) -> Vec<Drawable> {
        let mut moving = self.asset.clone();
        moving.zoom(glm::DVec2::from_s(self.zoom));
        vec![Drawable::Asset(self.asset), Drawable::Asset(moving)]
    }

    pub fn pull_vector(&self, dist: glm::DVec2, radius: f64) -> glm::DVec2 {
        let len = glm::length(dist);
        if len > (self.radius + radius) {
            glm::DVec2::zero()
        } else {
            let force = self.strength / (len.powf(0.8));
            normalize_to(dist, force)
        }
    }
}

pub struct Planet {
    body: Circle,
    asset: Asset,
    ring: Option<Ring>,
}

impl Planet {
    pub fn new(data: &PlanetData, textures: &WorldAssets) -> Self {
        let (asset, ring) = Self::load_assets(data, textures);
        let dims = asset.dims();
        let radius = cmp::min(dims.x, dims.y) as f64 / 2.;
        let center = glm::dvec2(data.x as f64, data.y as f64);
        let body = Circle {
            center: center,
            radius: radius,
        };

        Planet {
            body: body,
            asset: asset,
            ring: ring,
        }
    }

    pub fn animate(&mut self, delta: Duration) {
        if let Some(ref mut r) = self.ring {
            if r.asset.dims().x as f64 * r.zoom / 2. < self.body.radius {
                r.zoom = 1.;
            }
            r.animate(delta)
        }
    }

    pub fn pull_vector(&self, point: glm::DVec2, radius: f64) -> glm::DVec2 {
        self.ring.as_ref().map_or(glm::DVec2::zero(),
                                  |r| r.pull_vector(self.body.center - point, radius))
    }

    pub fn drawables(&self) -> Vec<Drawable> {
        let mut drawables = self.ring.as_ref().map_or(vec![], |r| r.drawables());
        drawables.push(Drawable::Asset(self.asset));
        drawables
    }

    fn load_assets(data: &PlanetData, textures: &WorldAssets) -> (Asset, Option<Ring>) {
        let center = glm::ivec2(data.x, data.y);
        let (planet, ring) = match data.kind {
            PlanetKind::RED { ring, strength } => {
                (textures.red_planet, Some((textures.red_ring, ring, strength)))
            }
            PlanetKind::BLUE { ring, strength } => {
                (textures.blue_planet, Some((textures.blue_ring, ring, strength)))
            }
            PlanetKind::WHITE { ring, strength } => {
                (textures.white_planet, Some((textures.white_ring, ring, strength)))
            }
            PlanetKind::DEAD => (textures.dead_planet, None),
        };

        let planet = Asset::from_texture(&planet, center);
        let ring = ring.map(|(t, r, s)| {
            let dims = glm::UVec2::from_s((r * 2.) as u32);
            let asset = Asset::centered_on(t.id, center, dims);
            Ring::new(r, s, asset)
        });

        (planet, ring)
    }
}

impl<I: Intersect<Circle>> Collidable<Circle, I> for Planet {
    fn collides(&self, shape: &I) -> bool {
        shape.intersects(&self.body)
    }
}
<|endoftext|>


<commit_before>//! Reject certain requests as instance load reaches capacity.
//!
//! The primary goal of this middleware is to avoid starving the download endpoint of resources.
//! When bots send many parallel requests that run slow database queries, download requests may
//! block and eventually timeout waiting for a database connection.
//!
//! Bots must continue to respect our crawler policy, but until we can manually block bad clients
//! we should avoid dropping download requests even if that means rejecting some legitimate
//! requests to other endpoints.

use std::env;
use std::sync::atomic::{AtomicUsize, Ordering};

use super::prelude::*;
use conduit::{RequestExt, StatusCode};

#[derive(Default)]
pub(super) struct BalanceCapacity {
    handler: Option<Box<dyn Handler>>,
    in_flight_total: AtomicUsize,
    db_capacity: usize,
    in_flight_non_dl_requests: AtomicUsize,
    report_only: bool,
    log_total_at_count: usize,
    log_at_percentage: usize,
    throttle_at_percentage: usize,
    dl_only_at_percentage: usize,
}

impl BalanceCapacity {
    pub fn new(db_capacity: usize) -> Self {
        Self {
            handler: None,
            in_flight_total: AtomicUsize::new(0),
            db_capacity,
            in_flight_non_dl_requests: AtomicUsize::new(0),

            report_only: env::var("WEB_CAPACITY_REPORT_ONLY").ok().is_some(),
            log_total_at_count: read_env_percentage("WEB_CAPACITY_LOG_TOTAL_AT_COUNT", 50),
            // The following are a percentage of `db_capacity`
            log_at_percentage: read_env_percentage("WEB_CAPACITY_LOG_PCT", 50),
            throttle_at_percentage: read_env_percentage("WEB_CAPACITY_THROTTLE_PCT", 70),
            dl_only_at_percentage: read_env_percentage("WEB_CAPACITY_DL_ONLY_PCT", 80),
        }
    }

    /// Handle a request normally
    fn handle(&self, request: &mut dyn RequestExt) -> AfterResult {
        self.handler.as_ref().unwrap().call(request)
    }

    /// Handle a request when load exceeds a threshold
    ///
    /// In report-only mode, log metadata is added but the request is still served. Otherwise,
    /// the request is rejected with a service unavailable response.
    fn handle_high_load(&self, request: &mut dyn RequestExt, note: &str) -> AfterResult {
        if self.report_only {
            // In report-only mode we serve all requests but add log metadata
            super::log_request::add_custom_metadata(request, "would_reject", note);
            self.handle(request)
        } else {
            // Reject the request
            super::log_request::add_custom_metadata(request, "cause", note);
            let body = "Service temporarily unavailable";
            Response::builder()
                .status(StatusCode::SERVICE_UNAVAILABLE)
                .header(header::CONTENT_LENGTH, body.len())
                .body(Body::from_static(body.as_bytes()))
                .map_err(box_error)
        }
    }
}

impl AroundMiddleware for BalanceCapacity {
    fn with_handler(&mut self, handler: Box<dyn Handler>) {
        self.handler = Some(handler);
    }
}

impl Handler for BalanceCapacity {
    fn call(&self, request: &mut dyn RequestExt) -> AfterResult {
        let (_drop_on_exit1, in_flight_total) = RequestCounter::add_one(&self.in_flight_total);
        if in_flight_total >= self.log_total_at_count {
            super::log_request::add_custom_metadata(request, "in_flight_total", in_flight_total);
        }

        // Download requests are always accepted and do not affect the request count
        if request.path().starts_with("/api/v1/crates/") && request.path().ends_with("/download") {
            return self.handle(request);
        }

        // The _drop_on_exit ensures the counter is decremented for all exit paths (including panics)
        let (_drop_on_exit2, count) = RequestCounter::add_one(&self.in_flight_non_dl_requests);
        let load = 100 * count / self.db_capacity;

        // Begin logging request count so early stages of load increase can be located
        if load >= self.log_at_percentage {
            super::log_request::add_custom_metadata(request, "in_flight_non_dl_requests", count);
        }

        // Reject read-only requests as load nears capacity. Bots are likely to send only safe
        // requests and this helps prioritize requests that users may be reluctant to retry.
        if load >= self.throttle_at_percentage && request.method().is_safe() {
            return self.handle_high_load(request, "over capacity (throttle)");
        }

        // As load reaches capacity, all non-download requests are rejected
        if load >= self.dl_only_at_percentage {
            return self.handle_high_load(request, "over capacity (download only)");
        }

        self.handle(request)
    }
}

fn read_env_percentage(name: &str, default: usize) -> usize {
    if let Ok(value) = env::var(name) {
        value.parse().unwrap_or(default)
    } else {
        default
    }
}

/// A struct that stores a reference to an atomic counter so it can be decremented when dropped
struct RequestCounter<'a> {
    counter: &'a AtomicUsize,
}

impl<'a> RequestCounter<'a> {
    fn add_one(counter: &'a AtomicUsize) -> (Self, usize) {
        let previous = counter.fetch_add(1, Ordering::SeqCst);
        (Self { counter }, previous + 1)
    }
}

impl<'a> Drop for RequestCounter<'a> {
    fn drop(&mut self) {
        self.counter.fetch_sub(1, Ordering::SeqCst);
    }
}
<commit_msg>Update comments in BalanceCapacity middleware<commit_after>//! Reject certain requests as instance load reaches capacity.
//!
//! The primary goal of this middleware is to avoid starving the download endpoint of resources.
//! When bots send many parallel requests that run slow database queries, download requests may
//! block and eventually timeout waiting for a database connection.
//!
//! Bots must continue to respect our crawler policy, but until we can manually block bad clients
//! we should avoid dropping download requests even if that means rejecting some legitimate
//! requests to other endpoints.

use std::env;
use std::sync::atomic::{AtomicUsize, Ordering};

use super::prelude::*;
use conduit::{RequestExt, StatusCode};

#[derive(Default)]
pub(super) struct BalanceCapacity {
    handler: Option<Box<dyn Handler>>,
    in_flight_total: AtomicUsize,
    db_capacity: usize,
    in_flight_non_dl_requests: AtomicUsize,
    report_only: bool,
    log_total_at_count: usize,
    log_at_percentage: usize,
    throttle_at_percentage: usize,
    dl_only_at_percentage: usize,
}

impl BalanceCapacity {
    pub fn new(db_capacity: usize) -> Self {
        Self {
            handler: None,
            in_flight_total: AtomicUsize::new(0),
            db_capacity,
            in_flight_non_dl_requests: AtomicUsize::new(0),

            report_only: env::var("WEB_CAPACITY_REPORT_ONLY").ok().is_some(),
            log_total_at_count: read_env_percentage("WEB_CAPACITY_LOG_TOTAL_AT_COUNT", 50),
            // The following are a percentage of `db_capacity`
            log_at_percentage: read_env_percentage("WEB_CAPACITY_LOG_PCT", 50),
            throttle_at_percentage: read_env_percentage("WEB_CAPACITY_THROTTLE_PCT", 70),
            dl_only_at_percentage: read_env_percentage("WEB_CAPACITY_DL_ONLY_PCT", 80),
        }
    }

    /// Handle a request normally
    fn handle(&self, request: &mut dyn RequestExt) -> AfterResult {
        self.handler.as_ref().unwrap().call(request)
    }

    /// Handle a request when load exceeds a threshold
    ///
    /// In report-only mode, log metadata is added but the request is still served. Otherwise,
    /// the request is rejected with a service unavailable response.
    fn handle_high_load(&self, request: &mut dyn RequestExt, note: &str) -> AfterResult {
        if self.report_only {
            // In report-only mode we serve all requests but add log metadata
            super::log_request::add_custom_metadata(request, "would_reject", note);
            self.handle(request)
        } else {
            // Reject the request
            super::log_request::add_custom_metadata(request, "cause", note);
            let body = "Service temporarily unavailable";
            Response::builder()
                .status(StatusCode::SERVICE_UNAVAILABLE)
                .header(header::CONTENT_LENGTH, body.len())
                .body(Body::from_static(body.as_bytes()))
                .map_err(box_error)
        }
    }
}

impl AroundMiddleware for BalanceCapacity {
    fn with_handler(&mut self, handler: Box<dyn Handler>) {
        self.handler = Some(handler);
    }
}

impl Handler for BalanceCapacity {
    fn call(&self, request: &mut dyn RequestExt) -> AfterResult {
        // The _drop_on_exit ensures the counter is decremented for all exit paths (including panics)
        let (_drop_on_exit1, in_flight_total) = RequestCounter::add_one(&self.in_flight_total);

        // Begin logging total request count so early stages of load increase can be located
        if in_flight_total >= self.log_total_at_count {
            super::log_request::add_custom_metadata(request, "in_flight_total", in_flight_total);
        }

        // Download requests are always accepted and do not affect the capacity tracking
        if request.path().starts_with("/api/v1/crates/") && request.path().ends_with("/download") {
            return self.handle(request);
        }

        // The _drop_on_exit ensures the counter is decremented for all exit paths (including panics)
        let (_drop_on_exit2, count) = RequestCounter::add_one(&self.in_flight_non_dl_requests);
        let load = 100 * count / self.db_capacity;

        // Begin logging non-download request count so early stages of non-download load increase can be located
        if load >= self.log_at_percentage {
            super::log_request::add_custom_metadata(request, "in_flight_non_dl_requests", count);
        }

        // Reject read-only requests as load nears capacity. Bots are likely to send only safe
        // requests and this helps prioritize requests that users may be reluctant to retry.
        if load >= self.throttle_at_percentage && request.method().is_safe() {
            return self.handle_high_load(request, "over capacity (throttle)");
        }

        // As load reaches capacity, all non-download requests are rejected
        if load >= self.dl_only_at_percentage {
            return self.handle_high_load(request, "over capacity (download only)");
        }

        self.handle(request)
    }
}

fn read_env_percentage(name: &str, default: usize) -> usize {
    if let Ok(value) = env::var(name) {
        value.parse().unwrap_or(default)
    } else {
        default
    }
}

/// A struct that stores a reference to an atomic counter so it can be decremented when dropped
struct RequestCounter<'a> {
    counter: &'a AtomicUsize,
}

impl<'a> RequestCounter<'a> {
    fn add_one(counter: &'a AtomicUsize) -> (Self, usize) {
        let previous = counter.fetch_add(1, Ordering::SeqCst);
        (Self { counter }, previous + 1)
    }
}

impl<'a> Drop for RequestCounter<'a> {
    fn drop(&mut self) {
        self.counter.fetch_sub(1, Ordering::SeqCst);
    }
}
<|endoftext|>


<commit_before>use crate::{error::{Error,
                    Result},
            package::PackageIdent};
use serde::Serialize;
use std::{self,
          collections::BTreeMap,
          env,
          fmt,
          fs::File,
          io::Read,
          iter::IntoIterator,
          path::{Path,
                 PathBuf},
          str::FromStr,
          string::ToString,
          vec::IntoIter};

#[cfg(not(windows))]
const ENV_PATH_SEPARATOR: char = ':';

#[cfg(windows)]
const ENV_PATH_SEPARATOR: char = ';';

pub fn parse_key_value(s: &str) -> Result<BTreeMap<String, String>> {
    Ok(s.lines()
        .map(|l| l.splitn(2, '=').collect::<Vec<_>>())
        .map(|kv| (kv[0].to_string(), kv[1].to_string()))
        .collect())
}

#[derive(Clone, Debug, Serialize)]
pub struct Bind {
    pub service: String,
    pub exports: Vec<String>,
}

impl FromStr for Bind {
    type Err = Error;

    fn from_str(line: &str) -> Result<Self> {
        let mut parts = line.split('=');
        let service = match parts.next() {
            None => return Err(Error::MetaFileBadBind),
            Some(service) => service.to_string(),
        };
        let exports = match parts.next() {
            None => return Err(Error::MetaFileBadBind),
            Some(exports) => exports.split_whitespace().map(str::to_string).collect(),
        };
        Ok(Bind { service, exports })
    }
}

impl fmt::Display for Bind {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let formatted_exports = self.exports.join(" ");
        write!(f, "[{}]={}", self.service, formatted_exports)
    }
}

#[derive(Debug, PartialEq)]
pub struct EnvVar {
    pub key:       String,
    pub value:     String,
    pub separator: Option<char>,
}

#[derive(Debug)]
pub struct PkgEnv {
    inner: Vec<EnvVar>,
}

impl PkgEnv {
    pub fn new(values: BTreeMap<String, String>, separators: &BTreeMap<String, String>) -> Self {
        Self { inner: values.into_iter()
                            .map(|(key, value)| {
                                if let Some(sep) = separators.get(&key) {
                                    EnvVar { key,
                                             value,
                                             separator: sep.to_owned().pop() }
                                } else {
                                    EnvVar { key,
                                             value,
                                             separator: None }
                                }
                            })
                            .collect(), }
    }

    pub fn from_paths(paths: &[PathBuf]) -> Self {
        let p = env::join_paths(paths).expect("Failed to build path string");
        Self { inner: vec![EnvVar { key:       "PATH".to_string(),
                                    value:     p.into_string()
                                                .expect("Failed to convert path to utf8 string"),
                                    separator: Some(ENV_PATH_SEPARATOR), }], }
    }

    pub fn is_empty(&self) -> bool { self.inner.is_empty() }
}

impl IntoIterator for PkgEnv {
    type IntoIter = IntoIter<EnvVar>;
    type Item = EnvVar;

    fn into_iter(self) -> Self::IntoIter { self.inner.into_iter() }
}

#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
pub enum MetaFile {
    Binds,
    BindsOptional,
    BuildDeps,
    BuildTDeps,
    CFlags,
    Config,
    Deps,
    Environment,
    EnvironmentSep,
    Exports,
    Exposes,
    Ident,
    LdFlags,
    LdRunPath,
    Manifest,
    Path,
    RuntimeEnvironment,
    RuntimeEnvironmentPaths,
    RuntimePath,
    ShutdownSignal,
    ShutdownTimeout,
    SvcGroup,
    SvcUser,
    Target,
    TDeps,
    PackageType,
}

impl fmt::Display for MetaFile {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let id = match *self {
            MetaFile::Binds => "BINDS",
            MetaFile::BindsOptional => "BINDS_OPTIONAL",
            MetaFile::BuildDeps => "BUILD_DEPS",
            MetaFile::BuildTDeps => "BUILD_TDEPS",
            MetaFile::CFlags => "CFLAGS",
            MetaFile::Config => "default.toml",
            MetaFile::Deps => "DEPS",
            MetaFile::Environment => "ENVIRONMENT",
            MetaFile::EnvironmentSep => "ENVIRONMENT_SEP",
            MetaFile::Exports => "EXPORTS",
            MetaFile::Exposes => "EXPOSES",
            MetaFile::Ident => "IDENT",
            MetaFile::LdFlags => "LDFLAGS",
            MetaFile::LdRunPath => "LD_RUN_PATH",
            MetaFile::Manifest => "MANIFEST",
            MetaFile::Path => "PATH",
            MetaFile::RuntimeEnvironment => "RUNTIME_ENVIRONMENT",
            MetaFile::RuntimeEnvironmentPaths => "RUNTIME_ENVIRONMENT_PATHS",
            MetaFile::RuntimePath => "RUNTIME_PATH",
            MetaFile::ShutdownSignal => "SHUTDOWN_SIGNAL",
            MetaFile::ShutdownTimeout => "SHUTDOWN_TIMEOUT",
            MetaFile::SvcGroup => "SVC_GROUP",
            MetaFile::SvcUser => "SVC_USER",
            MetaFile::Target => "TARGET",
            MetaFile::TDeps => "TDEPS",
            MetaFile::PackageType => "PACKAGE_TYPE",
        };
        write!(f, "{}", id)
    }
}

/// Read a metadata file from within a package directory if it exists
///
/// Returns the contents of the file
pub fn read_metafile<P: AsRef<Path>>(installed_path: P, file: MetaFile) -> Result<String> {
    match existing_metafile(installed_path, file) {
        Some(filepath) => {
            match File::open(&filepath) {
                Ok(mut f) => {
                    let mut data = String::new();
                    if f.read_to_string(&mut data).is_err() {
                        return Err(Error::MetaFileMalformed(file));
                    }
                    Ok(data.trim().to_string())
                }
                Err(e) => Err(Error::MetaFileIO(e)),
            }
        }
        None => Err(Error::MetaFileNotFound(file)),
    }
}

/// Returns the path to a specified MetaFile in an installed path if it exists.
///
/// Useful for fallback logic for dealing with older Habitat packages.
fn existing_metafile<P: AsRef<Path>>(installed_path: P, file: MetaFile) -> Option<PathBuf> {
    let filepath = installed_path.as_ref().join(file.to_string());
    match std::fs::metadata(&filepath) {
        Ok(_) => Some(filepath),
        Err(_) => None,
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PackageType {
    Standard,
    Native,
}

impl fmt::Display for PackageType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let id = match *self {
            PackageType::Standard => "standard",
            PackageType::Native => "native",
        };
        write!(f, "{}", id)
    }
}

impl FromStr for PackageType {
    type Err = Error;

    fn from_str(value: &str) -> Result<Self> {
        match value {
            "standard" => Ok(PackageType::Standard),
            "native" => Ok(PackageType::Native),
            _ => Err(Error::InvalidPackageType(value.to_string())),
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::io::Write;
    use tempfile::Builder;

    static ENVIRONMENT: &str = r#"PATH=/hab/pkgs/python/setuptools/35.0.1/20170424072606/bin
PYTHONPATH=/hab/pkgs/python/setuptools/35.0.1/20170424072606/lib/python3.6/site-packages
"#;
    static ENVIRONMENT_SEP: &str = r#"PATH=:
PYTHONPATH=:
"#;
    static EXPORTS: &str = r#"status-port=status.port
port=front-end.port
"#;
    static PATH: &str = "/hab/pkgs/python/setuptools/35.0.1/20170424072606/bin";

    /// Write the given contents into the specified metadata file for
    /// the package.
    fn write_metafile(install_dir: &Path, metafile: MetaFile, content: &str) {
        let path = install_dir.join(metafile.to_string());
        let mut f = File::create(path).expect("Could not create metafile");
        f.write_all(content.as_bytes())
         .expect("Could not write metafile contents");
    }

    #[test]
    #[should_panic]
    fn malformed_file() { parse_key_value("PATH").unwrap(); }

    #[test]
    fn can_parse_environment_file() {
        let mut m: BTreeMap<String, String> = BTreeMap::new();
        m.insert("PATH".to_string(),
                 "/hab/pkgs/python/setuptools/35.0.1/20170424072606/bin".to_string());
        m.insert(
            "PYTHONPATH".to_string(),
            "/hab/pkgs/python/setuptools/35.0.1/20170424072606/lib/python3.6/site-packages"
                .to_string(),
        );

        assert_eq!(parse_key_value(ENVIRONMENT).unwrap(), m);
    }

    #[test]
    fn can_parse_environment_sep_file() {
        let mut m: BTreeMap<String, String> = BTreeMap::new();
        m.insert("PATH".to_string(), ":".to_string());
        m.insert("PYTHONPATH".to_string(), ":".to_string());

        assert_eq!(parse_key_value(ENVIRONMENT_SEP).unwrap(), m);
    }

    #[test]
    fn can_parse_exports_file() {
        let mut m: BTreeMap<String, String> = BTreeMap::new();
        m.insert("status-port".to_string(), "status.port".to_string());
        m.insert("port".to_string(), "front-end.port".to_string());

        assert_eq!(parse_key_value(EXPORTS).unwrap(), m);
    }

    #[test]
    fn build_pkg_env() {
        let mut result =
            PkgEnv::new(parse_key_value(ENVIRONMENT).unwrap(),
                        &parse_key_value(ENVIRONMENT_SEP).unwrap()).into_iter()
                                                                   .collect::<Vec<_>>();
        // Sort the result by key, so we have a guarantee of order
        result.sort_by_key(|v| v.key.to_owned());

        let expected =
            vec![EnvVar { key:       "PATH".to_string(),
                          value:
                              "/hab/pkgs/python/setuptools/35.0.1/20170424072606/bin".to_string(),
                          separator: Some(':'), },
                 EnvVar { key:       "PYTHONPATH".to_string(),
                          value:     "/hab/pkgs/python/setuptools/35.0.1/20170424072606/lib/\
                                      python3.6/site-packages"
                                                              .to_string(),
                          separator: Some(':'), },];

        assert_eq!(result, expected);
    }

    #[test]
    fn build_pkg_env_is_empty() {
        let result = PkgEnv::new(BTreeMap::new(), &BTreeMap::new());
        assert!(result.is_empty());
    }

    #[test]
    fn build_pkg_env_from_path() {
        let result = PkgEnv::from_paths(&[PathBuf::from(PATH)]).into_iter()
                                                               .collect::<Vec<_>>();

        let expected = vec![EnvVar { key:       "PATH".to_string(),
                                     value:     "/hab/pkgs/python/setuptools/35.0.1/\
                                                 20170424072606/bin"
                                                                    .to_string(),
                                     separator: Some(ENV_PATH_SEPARATOR), }];

        assert_eq!(result, expected);
    }

    #[test]
    fn can_read_metafile() {
        let pkg_root = Builder::new().prefix("pkg-root").tempdir().unwrap();
        let install_dir = pkg_root.path();

        let expected = "core/foo=db:core/database";
        write_metafile(install_dir, MetaFile::Binds, expected);

        let bind_map = read_metafile(install_dir, MetaFile::Binds).unwrap();

        assert_eq!(expected, bind_map);
    }

    #[test]
    fn reading_a_non_existing_metafile_is_an_error() {
        let pkg_root = Builder::new().prefix("pkg-root").tempdir().unwrap();
        let install_dir = pkg_root.path();
        let bind_map = read_metafile(install_dir, MetaFile::Binds);

        assert!(bind_map.is_err());
    }
}
<commit_msg>adds missing derives for PackageType for builder<commit_after>use crate::error::{Error,
                   Result};
use serde::{Deserialize,
            Serialize};
use std::{self,
          collections::BTreeMap,
          env,
          fmt,
          fs::File,
          io::Read,
          iter::IntoIterator,
          path::{Path,
                 PathBuf},
          str::FromStr,
          string::ToString,
          vec::IntoIter};

#[cfg(not(windows))]
const ENV_PATH_SEPARATOR: char = ':';

#[cfg(windows)]
const ENV_PATH_SEPARATOR: char = ';';

pub fn parse_key_value(s: &str) -> Result<BTreeMap<String, String>> {
    Ok(s.lines()
        .map(|l| l.splitn(2, '=').collect::<Vec<_>>())
        .map(|kv| (kv[0].to_string(), kv[1].to_string()))
        .collect())
}

#[derive(Clone, Debug, Serialize)]
pub struct Bind {
    pub service: String,
    pub exports: Vec<String>,
}

impl FromStr for Bind {
    type Err = Error;

    fn from_str(line: &str) -> Result<Self> {
        let mut parts = line.split('=');
        let service = match parts.next() {
            None => return Err(Error::MetaFileBadBind),
            Some(service) => service.to_string(),
        };
        let exports = match parts.next() {
            None => return Err(Error::MetaFileBadBind),
            Some(exports) => exports.split_whitespace().map(str::to_string).collect(),
        };
        Ok(Bind { service, exports })
    }
}

impl fmt::Display for Bind {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let formatted_exports = self.exports.join(" ");
        write!(f, "[{}]={}", self.service, formatted_exports)
    }
}

#[derive(Debug, PartialEq)]
pub struct EnvVar {
    pub key:       String,
    pub value:     String,
    pub separator: Option<char>,
}

#[derive(Debug)]
pub struct PkgEnv {
    inner: Vec<EnvVar>,
}

impl PkgEnv {
    pub fn new(values: BTreeMap<String, String>, separators: &BTreeMap<String, String>) -> Self {
        Self { inner: values.into_iter()
                            .map(|(key, value)| {
                                if let Some(sep) = separators.get(&key) {
                                    EnvVar { key,
                                             value,
                                             separator: sep.to_owned().pop() }
                                } else {
                                    EnvVar { key,
                                             value,
                                             separator: None }
                                }
                            })
                            .collect(), }
    }

    pub fn from_paths(paths: &[PathBuf]) -> Self {
        let p = env::join_paths(paths).expect("Failed to build path string");
        Self { inner: vec![EnvVar { key:       "PATH".to_string(),
                                    value:     p.into_string()
                                                .expect("Failed to convert path to utf8 string"),
                                    separator: Some(ENV_PATH_SEPARATOR), }], }
    }

    pub fn is_empty(&self) -> bool { self.inner.is_empty() }
}

impl IntoIterator for PkgEnv {
    type IntoIter = IntoIter<EnvVar>;
    type Item = EnvVar;

    fn into_iter(self) -> Self::IntoIter { self.inner.into_iter() }
}

#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
pub enum MetaFile {
    Binds,
    BindsOptional,
    BuildDeps,
    BuildTDeps,
    CFlags,
    Config,
    Deps,
    Environment,
    EnvironmentSep,
    Exports,
    Exposes,
    Ident,
    LdFlags,
    LdRunPath,
    Manifest,
    Path,
    RuntimeEnvironment,
    RuntimeEnvironmentPaths,
    RuntimePath,
    ShutdownSignal,
    ShutdownTimeout,
    SvcGroup,
    SvcUser,
    Target,
    TDeps,
    PackageType,
}

impl fmt::Display for MetaFile {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let id = match *self {
            MetaFile::Binds => "BINDS",
            MetaFile::BindsOptional => "BINDS_OPTIONAL",
            MetaFile::BuildDeps => "BUILD_DEPS",
            MetaFile::BuildTDeps => "BUILD_TDEPS",
            MetaFile::CFlags => "CFLAGS",
            MetaFile::Config => "default.toml",
            MetaFile::Deps => "DEPS",
            MetaFile::Environment => "ENVIRONMENT",
            MetaFile::EnvironmentSep => "ENVIRONMENT_SEP",
            MetaFile::Exports => "EXPORTS",
            MetaFile::Exposes => "EXPOSES",
            MetaFile::Ident => "IDENT",
            MetaFile::LdFlags => "LDFLAGS",
            MetaFile::LdRunPath => "LD_RUN_PATH",
            MetaFile::Manifest => "MANIFEST",
            MetaFile::Path => "PATH",
            MetaFile::RuntimeEnvironment => "RUNTIME_ENVIRONMENT",
            MetaFile::RuntimeEnvironmentPaths => "RUNTIME_ENVIRONMENT_PATHS",
            MetaFile::RuntimePath => "RUNTIME_PATH",
            MetaFile::ShutdownSignal => "SHUTDOWN_SIGNAL",
            MetaFile::ShutdownTimeout => "SHUTDOWN_TIMEOUT",
            MetaFile::SvcGroup => "SVC_GROUP",
            MetaFile::SvcUser => "SVC_USER",
            MetaFile::Target => "TARGET",
            MetaFile::TDeps => "TDEPS",
            MetaFile::PackageType => "PACKAGE_TYPE",
        };
        write!(f, "{}", id)
    }
}

/// Read a metadata file from within a package directory if it exists
///
/// Returns the contents of the file
pub fn read_metafile<P: AsRef<Path>>(installed_path: P, file: MetaFile) -> Result<String> {
    match existing_metafile(installed_path, file) {
        Some(filepath) => {
            match File::open(&filepath) {
                Ok(mut f) => {
                    let mut data = String::new();
                    if f.read_to_string(&mut data).is_err() {
                        return Err(Error::MetaFileMalformed(file));
                    }
                    Ok(data.trim().to_string())
                }
                Err(e) => Err(Error::MetaFileIO(e)),
            }
        }
        None => Err(Error::MetaFileNotFound(file)),
    }
}

/// Returns the path to a specified MetaFile in an installed path if it exists.
///
/// Useful for fallback logic for dealing with older Habitat packages.
fn existing_metafile<P: AsRef<Path>>(installed_path: P, file: MetaFile) -> Option<PathBuf> {
    let filepath = installed_path.as_ref().join(file.to_string());
    match std::fs::metadata(&filepath) {
        Ok(_) => Some(filepath),
        Err(_) => None,
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash)]
pub enum PackageType {
    Standard,
    Native,
}

impl fmt::Display for PackageType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let id = match *self {
            PackageType::Standard => "standard",
            PackageType::Native => "native",
        };
        write!(f, "{}", id)
    }
}

impl FromStr for PackageType {
    type Err = Error;

    fn from_str(value: &str) -> Result<Self> {
        match value {
            "standard" => Ok(PackageType::Standard),
            "native" => Ok(PackageType::Native),
            _ => Err(Error::InvalidPackageType(value.to_string())),
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::io::Write;
    use tempfile::Builder;

    static ENVIRONMENT: &str = r#"PATH=/hab/pkgs/python/setuptools/35.0.1/20170424072606/bin
PYTHONPATH=/hab/pkgs/python/setuptools/35.0.1/20170424072606/lib/python3.6/site-packages
"#;
    static ENVIRONMENT_SEP: &str = r#"PATH=:
PYTHONPATH=:
"#;
    static EXPORTS: &str = r#"status-port=status.port
port=front-end.port
"#;
    static PATH: &str = "/hab/pkgs/python/setuptools/35.0.1/20170424072606/bin";

    /// Write the given contents into the specified metadata file for
    /// the package.
    fn write_metafile(install_dir: &Path, metafile: MetaFile, content: &str) {
        let path = install_dir.join(metafile.to_string());
        let mut f = File::create(path).expect("Could not create metafile");
        f.write_all(content.as_bytes())
         .expect("Could not write metafile contents");
    }

    #[test]
    #[should_panic]
    fn malformed_file() { parse_key_value("PATH").unwrap(); }

    #[test]
    fn can_parse_environment_file() {
        let mut m: BTreeMap<String, String> = BTreeMap::new();
        m.insert("PATH".to_string(),
                 "/hab/pkgs/python/setuptools/35.0.1/20170424072606/bin".to_string());
        m.insert(
            "PYTHONPATH".to_string(),
            "/hab/pkgs/python/setuptools/35.0.1/20170424072606/lib/python3.6/site-packages"
                .to_string(),
        );

        assert_eq!(parse_key_value(ENVIRONMENT).unwrap(), m);
    }

    #[test]
    fn can_parse_environment_sep_file() {
        let mut m: BTreeMap<String, String> = BTreeMap::new();
        m.insert("PATH".to_string(), ":".to_string());
        m.insert("PYTHONPATH".to_string(), ":".to_string());

        assert_eq!(parse_key_value(ENVIRONMENT_SEP).unwrap(), m);
    }

    #[test]
    fn can_parse_exports_file() {
        let mut m: BTreeMap<String, String> = BTreeMap::new();
        m.insert("status-port".to_string(), "status.port".to_string());
        m.insert("port".to_string(), "front-end.port".to_string());

        assert_eq!(parse_key_value(EXPORTS).unwrap(), m);
    }

    #[test]
    fn build_pkg_env() {
        let mut result =
            PkgEnv::new(parse_key_value(ENVIRONMENT).unwrap(),
                        &parse_key_value(ENVIRONMENT_SEP).unwrap()).into_iter()
                                                                   .collect::<Vec<_>>();
        // Sort the result by key, so we have a guarantee of order
        result.sort_by_key(|v| v.key.to_owned());

        let expected =
            vec![EnvVar { key:       "PATH".to_string(),
                          value:
                              "/hab/pkgs/python/setuptools/35.0.1/20170424072606/bin".to_string(),
                          separator: Some(':'), },
                 EnvVar { key:       "PYTHONPATH".to_string(),
                          value:     "/hab/pkgs/python/setuptools/35.0.1/20170424072606/lib/\
                                      python3.6/site-packages"
                                                              .to_string(),
                          separator: Some(':'), },];

        assert_eq!(result, expected);
    }

    #[test]
    fn build_pkg_env_is_empty() {
        let result = PkgEnv::new(BTreeMap::new(), &BTreeMap::new());
        assert!(result.is_empty());
    }

    #[test]
    fn build_pkg_env_from_path() {
        let result = PkgEnv::from_paths(&[PathBuf::from(PATH)]).into_iter()
                                                               .collect::<Vec<_>>();

        let expected = vec![EnvVar { key:       "PATH".to_string(),
                                     value:     "/hab/pkgs/python/setuptools/35.0.1/\
                                                 20170424072606/bin"
                                                                    .to_string(),
                                     separator: Some(ENV_PATH_SEPARATOR), }];

        assert_eq!(result, expected);
    }

    #[test]
    fn can_read_metafile() {
        let pkg_root = Builder::new().prefix("pkg-root").tempdir().unwrap();
        let install_dir = pkg_root.path();

        let expected = "core/foo=db:core/database";
        write_metafile(install_dir, MetaFile::Binds, expected);

        let bind_map = read_metafile(install_dir, MetaFile::Binds).unwrap();

        assert_eq!(expected, bind_map);
    }

    #[test]
    fn reading_a_non_existing_metafile_is_an_error() {
        let pkg_root = Builder::new().prefix("pkg-root").tempdir().unwrap();
        let install_dir = pkg_root.path();
        let bind_map = read_metafile(install_dir, MetaFile::Binds);

        assert!(bind_map.is_err());
    }
}
<|endoftext|>


<commit_before>// http://stackoverflow.com/questions/25877285/how-to-disable-unused-code-warnings-in-rust
// https://users.rust-lang.org/t/turning-off-compiler-warning-messages/4975/2
#![allow(non_snake_case)]

use postgres::{Connection, TlsMode};

use std::env;

use actix_web::{HttpRequest, HttpResponse};
use futures::future::{result, FutureResult};

#[derive(Serialize, Deserialize)]
struct UserInformation {
    userId: i32,
    name: String,
    surname: String,
    magicUrl: String,
    notifications: Vec<Notification>,
}

#[derive(Serialize, Deserialize)]
struct Notification {
    context: String,
    status: bool,
}

fn connection() -> Connection {
    let s = "postgres://".to_owned()
        + &env::var("PGUSER").unwrap()
        + "@localhost/"
        + &env::var("PGDATABASE").unwrap();
    println!("s: {}", s);

    Connection::connect(
        "postgres://".to_owned()
            + &env::var("PGUSER").unwrap()
            + "@localhost/"
            + &env::var("PGDATABASE").unwrap(),
        TlsMode::None,
    )
    .unwrap()
}

pub fn user_information(req: &HttpRequest) -> FutureResult<HttpResponse, actix_web::error::Error> {
    let conn = connection();
    let user_id = 1;
    let rows = &conn.query(
    "SELECT \"userId\", name, surname, \"magicUrl\" FROM user_information where \"userId\" = $1",
                           &[&user_id])
                    .unwrap();
    let row = rows.into_iter().next().unwrap();

    let mut notifications = Vec::new();
    for row in &conn.query(
        "select context, status from user_information as u join notifications as n on n.\"userId\" \
         = u.\"userId\" and u.\"userId\" = $1",
                           &[&user_id])
                    .unwrap() {
        let notification = Notification {
            context: row.get(0),
            status: row.get(1),
        };
        notifications.push(notification);
    }

    let s = UserInformation {
        userId: row.get(0),
        name: row.get(1),
        surname: row.get(2),
        magicUrl: row.get(3),
        notifications: notifications,
    };
    result(Ok(HttpResponse::Ok().json(s)))
}
/*
#[derive(Serialize, Deserialize)]
struct DataSet {
    id: i32,
    name: String,
}

#[get("/dataSets")]
fn data_sets() -> CORS<JSON<Vec<DataSet>>> {
    let conn = connection();
    let mut data_sets = Vec::new();

    for row in &conn.query("SELECT id, name FROM data_sets", &[]).unwrap() {
        let data_set = DataSet {
            id: row.get(0),
            name: row.get(1),
        };
        // note: move occurs because `data_set` has type `DataSet`,
        // which does not implement the `Copy` trait
        println!("Found DataSet {}", &data_set.name);
        data_sets.push(data_set);
    }
    CORS::any(JSON(data_sets))
}

#[derive(Serialize, Deserialize)]
struct DataSetWithComments {
    id: i32,
    name: String,
    comments: Vec<Comment>,
}

#[derive(Serialize, Deserialize)]
struct Comment {
    id: i32,
    content: String,
    userName: String,
    userPhotoUrl: String,
    date: String,
}

#[get("/dataSets/<url>")]
fn data_set(url: &str) -> CORS<JSON<DataSetWithComments>> {
    let conn = connection();
    let url2 = "dataSets/".to_owned() + url;
    let rows = &conn
        .query("SELECT id, name FROM data_sets where url = $1", &[&url2])
        .unwrap();
    let row = rows.into_iter().next().unwrap();
    let data_set_id: i32 = row.get(0);

    let mut comments = Vec::new();
    for row in &conn
        .query(
            "select c.id, content, \"userName\", \"userPhotoUrl\", date from comments as c \
             join data_sets as d on c.data_set_id = d.id and d.id = $1",
            &[&data_set_id],
        )
        .unwrap()
    {
        let comment = Comment {
            id: row.get(0),
            content: row.get(1),
            userName: row.get(2),
            userPhotoUrl: row.get(3),
            date: row.get(4),
        };
        comments.push(comment);
    }

    CORS::any(JSON(DataSetWithComments {
        id: row.get(0),
        name: row.get(1),
        comments: comments,
    }))
}

#[derive(Serialize, Deserialize)]
struct DataSetShort {
    id: i32,
    name: String,
    description: String,
    owner: String,
    releaseDate: String,
    rating: f32,
    favourite: bool,
    url: String,
}

#[get("/dataSetsCategories/<url>")]
fn data_set_category(url: &str) -> CORS<JSON<DataSetShort>> {
    let conn = connection();
    let url2 = "dataSetsCategories/".to_owned() + url;
    let rows = &conn
        .query(
            "select id from categories where \"contentUrl\" = $1",
            &[&url2],
        )
        .unwrap();
    let row = rows.into_iter().next().unwrap();
    let category_id: i32 = row.get(0);

    let dataSetShortRows = &conn.query("select d.id, name, SUBSTRING(description,0,100) as description, owner, \"releaseDate\", \
        rating, favourite, url from data_sets d join data_sets_in_categories di on d.id = di.data_sets_id \
        and di.categories_id = $1",
                    &[&category_id])
             .unwrap();
    let dataSetShortRow = dataSetShortRows.into_iter().next().unwrap();

    CORS::any(JSON(DataSetShort {
        id: dataSetShortRow.get(0),
        name: dataSetShortRow.get(1),
        description: dataSetShortRow.get(2),
        owner: dataSetShortRow.get(3),
        releaseDate: dataSetShortRow.get(4),
        rating: dataSetShortRow.get(5),
        favourite: dataSetShortRow.get(6),
        url: dataSetShortRow.get(7),
    }))
}

#[derive(Serialize, Deserialize)]
struct Category {
    id: i32,
    title: String,
    route: String,
    count: i32,
    contentUrl: String,
    subcategories: Vec<Subcategory>,
}

#[derive(Serialize, Deserialize)]
struct Subcategory {
    id: i32,
    title: String,
    route: String,
    count: i32,
    contentUrl: String,
}

#[get("/dataSetsCategories")]
fn data_sets_categories() -> CORS<JSON<Vec<Category>>> {
    let conn = connection();
    let mut categories = Vec::new();
    for row in &conn
        .query(
            "SELECT id, title, route, count, \"contentUrl\" FROM categories \
             where type = 'dataSet' and \"parentId\" is null",
            &[],
        )
        .unwrap()
    {
        let row_id: i32 = row.get(0);

        let mut subcategories = Vec::new();
        for subcategoryRow in &conn
            .query(
                "SELECT id, title, route, count, \"contentUrl\" FROM categories \
                 where type = 'dataSet' and \"parentId\" = $1",
                &[&row_id],
            )
            .unwrap()
        {
            let subcategory = Subcategory {
                id: subcategoryRow.get(0),
                title: subcategoryRow.get(1),
                route: subcategoryRow.get(2),
                count: subcategoryRow.get(3),
                contentUrl: subcategoryRow.get(4),
            };

            subcategories.push(subcategory);
        }

        let category = Category {
            id: row.get(0),
            title: row.get(1),
            route: row.get(2),
            count: row.get(3),
            contentUrl: row.get(4),
            subcategories: subcategories,
        };
        println!("Found Category {}", &category.title);
        categories.push(category);
    }
    CORS::any(JSON(categories))
}

use std::fs::File;
use std::io::{BufWriter, Write};

#[post("/dataSets/new", data = "<upload>")]
fn data_sets_new(upload: DataSetMultipart) -> CORS<String> {
    let f = File::create("plik").expect("Unable to create file");
    let mut f = BufWriter::new(f);
    f.write_all(&*upload.metadata)
        .expect("Unable to write data");
    CORS::any(format!("I read this: {:?}", upload))
}

#[derive(Debug)]
struct DataSetMultipart {
    name: String,
    description: String,
    categoryId: i32,
    metadata: Vec<u8>,
}

use std::io::{Cursor, Read};

impl FromData for DataSetMultipart {
    type Error = ();

    fn from_data(request: &Request, data: Data) -> data::Outcome<Self, Self::Error> {
        // All of these errors should be reported
        let ct = request
            .headers()
            .get_one("Content-Type")
            .expect("no content-type");
        let idx = ct.find("boundary=").expect("no boundary");
        let boundary = &ct[(idx + "boundary=".len())..];

        let mut d = Vec::new();
        data.stream_to(&mut d).expect("Unable to read");

        let mut mp = Multipart::with_body(Cursor::new(d), boundary);

        // Custom implementation parts

        let mut name = None;
        let mut description = None;
        let mut categoryId = None;
        let mut metadata = None;

        mp.foreach_entry(|mut entry| match entry.name.as_str() {
            "name" => {
                let t = entry.data.as_text().expect("not text");
                name = Some(t.into());
            }
            "description" => {
                let t = entry.data.as_text().expect("not text");
                description = Some(t.into());
            }
            "categoryId" => {
                let t = entry.data.as_text().expect("not text");
                let n = t.parse().expect("not number");
                categoryId = Some(n);
            }
            "metadata" => {
                let mut d = Vec::new();
                let f = entry.data.as_file().expect("not file");
                f.read_to_end(&mut d).expect("can't read");
                metadata = Some(d);
            }
            other => panic!("No known key {}", other),
        })
        .expect("Unable to iterate");

        let v = DataSetMultipart {
            name: name.expect("name not set"),
            description: description.expect("description not set"),
            categoryId: categoryId.expect("categoryId not set"),
            metadata: metadata.expect("file not set"),
        };

        // End custom

        Outcome::Success(v)
    }
}
*/
<commit_msg>Remove redundant code<commit_after>// http://stackoverflow.com/questions/25877285/how-to-disable-unused-code-warnings-in-rust
// https://users.rust-lang.org/t/turning-off-compiler-warning-messages/4975/2
#![allow(non_snake_case)]

use postgres::{Connection, TlsMode};

use std::env;

use actix_web::{HttpRequest, HttpResponse};
use futures::future::{result, FutureResult};

#[derive(Serialize, Deserialize)]
struct UserInformation {
    userId: i32,
    name: String,
    surname: String,
    magicUrl: String,
    notifications: Vec<Notification>,
}

#[derive(Serialize, Deserialize)]
struct Notification {
    context: String,
    status: bool,
}

fn connection() -> Connection {
    Connection::connect(
        "postgres://".to_owned()
            + &env::var("PGUSER").unwrap()
            + "@localhost/"
            + &env::var("PGDATABASE").unwrap(),
        TlsMode::None,
    )
    .unwrap()
}

pub fn user_information(req: &HttpRequest) -> FutureResult<HttpResponse, actix_web::error::Error> {
    let conn = connection();
    let user_id = 1;
    let rows = &conn.query(
    "SELECT \"userId\", name, surname, \"magicUrl\" FROM user_information where \"userId\" = $1",
                           &[&user_id])
                    .unwrap();
    let row = rows.into_iter().next().unwrap();

    let mut notifications = Vec::new();
    for row in &conn.query(
        "select context, status from user_information as u join notifications as n on n.\"userId\" \
         = u.\"userId\" and u.\"userId\" = $1",
                           &[&user_id])
                    .unwrap() {
        let notification = Notification {
            context: row.get(0),
            status: row.get(1),
        };
        notifications.push(notification);
    }

    let s = UserInformation {
        userId: row.get(0),
        name: row.get(1),
        surname: row.get(2),
        magicUrl: row.get(3),
        notifications: notifications,
    };
    result(Ok(HttpResponse::Ok().json(s)))
}
/*
#[derive(Serialize, Deserialize)]
struct DataSet {
    id: i32,
    name: String,
}

#[get("/dataSets")]
fn data_sets() -> CORS<JSON<Vec<DataSet>>> {
    let conn = connection();
    let mut data_sets = Vec::new();

    for row in &conn.query("SELECT id, name FROM data_sets", &[]).unwrap() {
        let data_set = DataSet {
            id: row.get(0),
            name: row.get(1),
        };
        // note: move occurs because `data_set` has type `DataSet`,
        // which does not implement the `Copy` trait
        println!("Found DataSet {}", &data_set.name);
        data_sets.push(data_set);
    }
    CORS::any(JSON(data_sets))
}

#[derive(Serialize, Deserialize)]
struct DataSetWithComments {
    id: i32,
    name: String,
    comments: Vec<Comment>,
}

#[derive(Serialize, Deserialize)]
struct Comment {
    id: i32,
    content: String,
    userName: String,
    userPhotoUrl: String,
    date: String,
}

#[get("/dataSets/<url>")]
fn data_set(url: &str) -> CORS<JSON<DataSetWithComments>> {
    let conn = connection();
    let url2 = "dataSets/".to_owned() + url;
    let rows = &conn
        .query("SELECT id, name FROM data_sets where url = $1", &[&url2])
        .unwrap();
    let row = rows.into_iter().next().unwrap();
    let data_set_id: i32 = row.get(0);

    let mut comments = Vec::new();
    for row in &conn
        .query(
            "select c.id, content, \"userName\", \"userPhotoUrl\", date from comments as c \
             join data_sets as d on c.data_set_id = d.id and d.id = $1",
            &[&data_set_id],
        )
        .unwrap()
    {
        let comment = Comment {
            id: row.get(0),
            content: row.get(1),
            userName: row.get(2),
            userPhotoUrl: row.get(3),
            date: row.get(4),
        };
        comments.push(comment);
    }

    CORS::any(JSON(DataSetWithComments {
        id: row.get(0),
        name: row.get(1),
        comments: comments,
    }))
}

#[derive(Serialize, Deserialize)]
struct DataSetShort {
    id: i32,
    name: String,
    description: String,
    owner: String,
    releaseDate: String,
    rating: f32,
    favourite: bool,
    url: String,
}

#[get("/dataSetsCategories/<url>")]
fn data_set_category(url: &str) -> CORS<JSON<DataSetShort>> {
    let conn = connection();
    let url2 = "dataSetsCategories/".to_owned() + url;
    let rows = &conn
        .query(
            "select id from categories where \"contentUrl\" = $1",
            &[&url2],
        )
        .unwrap();
    let row = rows.into_iter().next().unwrap();
    let category_id: i32 = row.get(0);

    let dataSetShortRows = &conn.query("select d.id, name, SUBSTRING(description,0,100) as description, owner, \"releaseDate\", \
        rating, favourite, url from data_sets d join data_sets_in_categories di on d.id = di.data_sets_id \
        and di.categories_id = $1",
                    &[&category_id])
             .unwrap();
    let dataSetShortRow = dataSetShortRows.into_iter().next().unwrap();

    CORS::any(JSON(DataSetShort {
        id: dataSetShortRow.get(0),
        name: dataSetShortRow.get(1),
        description: dataSetShortRow.get(2),
        owner: dataSetShortRow.get(3),
        releaseDate: dataSetShortRow.get(4),
        rating: dataSetShortRow.get(5),
        favourite: dataSetShortRow.get(6),
        url: dataSetShortRow.get(7),
    }))
}

#[derive(Serialize, Deserialize)]
struct Category {
    id: i32,
    title: String,
    route: String,
    count: i32,
    contentUrl: String,
    subcategories: Vec<Subcategory>,
}

#[derive(Serialize, Deserialize)]
struct Subcategory {
    id: i32,
    title: String,
    route: String,
    count: i32,
    contentUrl: String,
}

#[get("/dataSetsCategories")]
fn data_sets_categories() -> CORS<JSON<Vec<Category>>> {
    let conn = connection();
    let mut categories = Vec::new();
    for row in &conn
        .query(
            "SELECT id, title, route, count, \"contentUrl\" FROM categories \
             where type = 'dataSet' and \"parentId\" is null",
            &[],
        )
        .unwrap()
    {
        let row_id: i32 = row.get(0);

        let mut subcategories = Vec::new();
        for subcategoryRow in &conn
            .query(
                "SELECT id, title, route, count, \"contentUrl\" FROM categories \
                 where type = 'dataSet' and \"parentId\" = $1",
                &[&row_id],
            )
            .unwrap()
        {
            let subcategory = Subcategory {
                id: subcategoryRow.get(0),
                title: subcategoryRow.get(1),
                route: subcategoryRow.get(2),
                count: subcategoryRow.get(3),
                contentUrl: subcategoryRow.get(4),
            };

            subcategories.push(subcategory);
        }

        let category = Category {
            id: row.get(0),
            title: row.get(1),
            route: row.get(2),
            count: row.get(3),
            contentUrl: row.get(4),
            subcategories: subcategories,
        };
        println!("Found Category {}", &category.title);
        categories.push(category);
    }
    CORS::any(JSON(categories))
}

use std::fs::File;
use std::io::{BufWriter, Write};

#[post("/dataSets/new", data = "<upload>")]
fn data_sets_new(upload: DataSetMultipart) -> CORS<String> {
    let f = File::create("plik").expect("Unable to create file");
    let mut f = BufWriter::new(f);
    f.write_all(&*upload.metadata)
        .expect("Unable to write data");
    CORS::any(format!("I read this: {:?}", upload))
}

#[derive(Debug)]
struct DataSetMultipart {
    name: String,
    description: String,
    categoryId: i32,
    metadata: Vec<u8>,
}

use std::io::{Cursor, Read};

impl FromData for DataSetMultipart {
    type Error = ();

    fn from_data(request: &Request, data: Data) -> data::Outcome<Self, Self::Error> {
        // All of these errors should be reported
        let ct = request
            .headers()
            .get_one("Content-Type")
            .expect("no content-type");
        let idx = ct.find("boundary=").expect("no boundary");
        let boundary = &ct[(idx + "boundary=".len())..];

        let mut d = Vec::new();
        data.stream_to(&mut d).expect("Unable to read");

        let mut mp = Multipart::with_body(Cursor::new(d), boundary);

        // Custom implementation parts

        let mut name = None;
        let mut description = None;
        let mut categoryId = None;
        let mut metadata = None;

        mp.foreach_entry(|mut entry| match entry.name.as_str() {
            "name" => {
                let t = entry.data.as_text().expect("not text");
                name = Some(t.into());
            }
            "description" => {
                let t = entry.data.as_text().expect("not text");
                description = Some(t.into());
            }
            "categoryId" => {
                let t = entry.data.as_text().expect("not text");
                let n = t.parse().expect("not number");
                categoryId = Some(n);
            }
            "metadata" => {
                let mut d = Vec::new();
                let f = entry.data.as_file().expect("not file");
                f.read_to_end(&mut d).expect("can't read");
                metadata = Some(d);
            }
            other => panic!("No known key {}", other),
        })
        .expect("Unable to iterate");

        let v = DataSetMultipart {
            name: name.expect("name not set"),
            description: description.expect("description not set"),
            categoryId: categoryId.expect("categoryId not set"),
            metadata: metadata.expect("file not set"),
        };

        // End custom

        Outcome::Success(v)
    }
}
*/
<|endoftext|>


<commit_before>#![feature(test)]
// PLAYGROUND FOR PERFORMANCE TESTS
//
extern crate libc;
extern crate test;
use test::Bencher;

use libc::c_char;
use std::ffi::{CStr,CString};
use std::str;

#[bench]
fn rust_to_ruby_c_char_convenient(b: &mut Bencher){
  let s: String = "hello".to_string();

  // (185ns)
  b.iter(|| {
    let s = s.clone(); //To imitate .into()
    let s_slice: &str = &s[..];
    CString::new(s_slice).unwrap().into_raw()
  })
}

// SANCTIONED USAGE
#[bench]
fn rust_to_ruby_c_char(b: &mut Bencher){
  let s: String = "hello".to_string();
  let s = s.as_str();

  // USE THIS METHOD!!! (153ns)
  b.iter(|| {
    CString::new(s).unwrap().into_raw()
  })
}

#[bench]
fn ruby_to_rust_string_convenient(b: &mut Bencher){
  let s: *const c_char = CString::new("hello").unwrap().into_raw();

  // (46ns)
  b.iter(|| {
    let c_str = unsafe {
      assert!(!s.is_null());
      CStr::from_ptr(s)
    };
    (*str::from_utf8(c_str.to_bytes()).unwrap_or("")).to_string()
  })
}

// SANCTIONED USAGE
#[bench]
fn ruby_to_rust_from_c_char(b: &mut Bencher){
  let s: *const c_char = CString::new("hello").unwrap().into_raw();

  // USE THIS METHOD!!! (19ns)
  b.iter(|| {
    let c_str = unsafe {
      assert!(!s.is_null());
      CStr::from_ptr(s)
    };
    str::from_utf8(c_str.to_bytes()).unwrap_or("")
  })
}
<commit_msg>Updated sanctioned usage<commit_after>#![feature(test)]
// PLAYGROUND FOR PERFORMANCE TESTS
//
extern crate libc;
extern crate test;
use test::Bencher;

use libc::c_char;
use std::ffi::{CStr,CString};
use std::str;

#[bench]
fn rust_to_ruby_c_char_convenient(b: &mut Bencher){
  let s: String = "hello".to_string();

  // (185ns)
  b.iter(|| {
    let s = s.clone(); //To imitate .into()
    let s_slice: &str = &s[..];
    CString::new(s_slice).unwrap().into_raw()
  })
}

// SANCTIONED USAGE
#[bench]
fn rust_to_ruby_c_char(b: &mut Bencher){
  let s: String = "hello".to_string();
  let s = s.as_str();

  // USE THIS METHOD!!! (153ns)
  b.iter(|| {
    CString::new(s).unwrap().into_raw()
  })
}

#[bench]
fn ruby_to_rust_string_convenient(b: &mut Bencher){
  let s: *const c_char = CString::new("hello").unwrap().into_raw();

  // (46ns)
  b.iter(|| {
    let c_str = unsafe {
      assert!(!s.is_null());
      CStr::from_ptr(s)
    };
    (*str::from_utf8(c_str.to_bytes()).unwrap_or("")).to_string()
  })
}

// SANCTIONED USAGE
#[bench]
fn ruby_to_rust_from_c_char(b: &mut Bencher){
  let s: *const c_char = CString::new("hello").unwrap().into_raw();

  // USE THIS METHOD!!! (19ns)
  b.iter(|| {
    let c_str = unsafe {
      if s.is_null() {
        return "";
      }
      CStr::from_ptr(s)
    };
    str::from_utf8(c_str.to_bytes()).unwrap_or("")
  })
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate rand;
extern crate splittable_random as splittable;
extern crate test;

const RAND_BENCH_N: u64 = 1000;

use std::mem::size_of;
use test::{black_box, Bencher};
use rand::{Rng, OsRng};
use splittable::siprng::SipRng;

#[bench]
fn rand_siprng(b: &mut Bencher) {
    let mut rng: SipRng = OsRng::new().unwrap().gen();
    b.iter(|| {
        for _ in 0..RAND_BENCH_N {
            black_box(rng.gen::<usize>());
        }
    });
    b.bytes = size_of::<usize>() as u64 * RAND_BENCH_N;
}
<commit_msg>Crate has been renamed.<commit_after>#![feature(test)]

extern crate rand;
extern crate split_rand;
extern crate test;

const RAND_BENCH_N: u64 = 1000;

use std::mem::size_of;
use test::{black_box, Bencher};
use rand::{Rng, OsRng};
use split_rand::siprng::SipRng;

#[bench]
fn rand_siprng(b: &mut Bencher) {
    let mut rng: SipRng = OsRng::new().unwrap().gen();
    b.iter(|| {
        for _ in 0..RAND_BENCH_N {
            black_box(rng.gen::<usize>());
        }
    });
    b.bytes = size_of::<usize>() as u64 * RAND_BENCH_N;
}
<|endoftext|>


<commit_before><commit_msg>Cleanup RIAPI parsing and add tests<commit_after><|endoftext|>


<commit_before><commit_msg>server: add more ir4_local tests on windows to exercise different path styles<commit_after><|endoftext|>