<commit_before>use std::ops::{
  Add, AddAssign,
  Sub, SubAssign,
  Mul, MulAssign,
  Div, DivAssign,
  Index, IndexMut,
};

#[derive(Debug, Copy, Clone)]
pub struct Vec3 {
  pub i : f64,
  pub j : f64,
  pub k : f64,
}

impl Vec3 {
  pub fn length(&self) -> f64 {
    (self.i * self.i + self.j * self.j + self.k * self.k).sqrt()
  }
}

impl Add for Vec3 {
  type Output = Vec3;
  fn add(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i + other.i, j: self.j + other.j, k: self.k + other.k}
  }
}

impl AddAssign for Vec3 {
  fn add_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i + other.i,
      j: self.j + other.j,
      k: self.k + other.k,
    };
  }
}

impl Sub for Vec3 {
  type Output = Vec3;
  fn sub(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i - other.i, j: self.j - other.j, k: self.k - other.k}
  }
}

impl SubAssign for Vec3 {
  fn sub_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i - other.i,
      j: self.j - other.j,
      k: self.k - other.k,
    }
  }
}

impl Mul for Vec3 {
  type Output = Vec3;
  fn mul(self, rhs: Vec3) -> Vec3 {
    Vec3 {i: self.i * rhs.i, j: self.j * rhs.j, k: self.k * rhs.k}
  }
}

impl MulAssign for Vec3 {
  fn mul_assign(&mut self, rhs: Vec3) {
    *self = Vec3 {
      i: self.i * rhs.i,
      j: self.j * rhs.j,
      k: self.k * rhs.k,
    }
  }
}

impl Div<Vec3> for Vec3 {
  type Output = Vec3;
  fn div(self, rhs: Vec3) -> Vec3 {
    Vec3 {i: self.i / rhs.i, j: self.j / rhs.j, k: self.k / rhs.k}
  }
}

impl Div<f64> for Vec3 {
  type Output = Vec3;
  fn div(self, scalar: f64) -> Vec3 {
    Vec3 {i: self.i / scalar, j: self.j / scalar, k: self.k / scalar}
  }
}

impl DivAssign<Vec3> for Vec3 {
  fn div_assign(&mut self, rhs: Vec3) {
    *self = Vec3 {
      i: self.i / rhs.i,
      j: self.j / rhs.j,
      k: self.k / rhs.k,
    }
  }
}

impl DivAssign<f64> for Vec3 {
  fn div_assign(&mut self, scalar: f64) {
    *self = Vec3 {
      i: self.i / scalar,
      j: self.j / scalar,
      k: self.k / scalar,
    }
  }
}

impl Index<i32> for Vec3 {
  type Output = f64;
  fn index(&self, idx: i32) -> &f64 {
    match idx {
      0 => &self.i,
      1 => &self.j,
      2 => &self.k,
      _ => panic!("index out of range: {}", idx),
    }
  }
}

impl IndexMut<i32> for Vec3 {
  fn index_mut<'a>(&'a mut self, idx: i32) -> &'a mut f64 {
    match idx {
      0 => &mut self.i,
      1 => &mut self.j,
      2 => &mut self.k,
      _ => panic!("index out of range: {}", idx),
    }
  }
}

#[cfg(test)]
mod should {
  use super::Vec3;
  #[test]
  fn add() {
    let v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let sum = v1 + v2;
    assert_eq!(sum.i, 3.0);
    assert_eq!(sum.j, 3.0);
    assert_eq!(sum.k, 3.0);
  }
  #[test]
  fn add_assign() {
    let mut v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1 += v2;
    assert_eq!(v1.i, 3.0);
    assert_eq!(v1.j, 3.0);
    assert_eq!(v1.k, 3.0);
  }
  #[test]
  fn subtract() {
    let v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let diff = v1 - v2;
    assert_eq!(diff.i, -1.0);
    assert_eq!(diff.j, -1.0);
    assert_eq!(diff.k, -1.0);
  }
  #[test]
  fn subtract_assign() {
    let mut v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1 -= v2;
    assert_eq!(v1.i, -1.0);
    assert_eq!(v1.j, -1.0);
    assert_eq!(v1.k, -1.0);
  }
  #[test]
  fn multiply_elementwise() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    let product = v1 * v2;
    assert_eq!(product.i, 6.0);
    assert_eq!(product.j, 6.0);
    assert_eq!(product.k, 6.0);
  }
  #[test]
  fn multiply_assign_elementwise() {
    let mut v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    v1 *= v2;
    assert_eq!(v1.i, 6.0);
    assert_eq!(v1.j, 6.0);
    assert_eq!(v1.k, 6.0);
  }
  #[test]
  fn divide_by_vec3_elementwise() {
    let v1 = Vec3 { i: 6.0, j: 6.0, k: 6.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    let quotient = v1 / v2;
    assert_eq!(quotient.i, 2.0);
    assert_eq!(quotient.j, 2.0);
    assert_eq!(quotient.k, 2.0);
  }
  #[test]
  fn divide_by_vec3_assign_elementwise() {
    let mut v1 = Vec3 { i: 6.0, j: 6.0, k: 6.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    v1 /= v2;
    assert_eq!(v1.i, 2.0);
    assert_eq!(v1.j, 2.0);
    assert_eq!(v1.k, 2.0);
  }
  #[test]
  fn divide_by_f64() {
    let v1 = Vec3 { i: 6.0, j: 6.0, k: 6.0};
    let quotient = v1 / 3.0;

    assert_eq!(quotient.i, 2.0);
    assert_eq!(quotient.j, 2.0);
    assert_eq!(quotient.k, 2.0);
  }
  #[test]
  fn divide_by_f64_assign() {
    let mut v1 = Vec3 { i: 6.0, j: 6.0, k: 6.0};
    v1 /= 3.0;

    assert_eq!(v1.i, 2.0);
    assert_eq!(v1.j, 2.0);
    assert_eq!(v1.k, 2.0);
  }
  #[test]
  fn allow_index_access() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};

    assert_eq!(v1[0], 2.0);
    assert_eq!(v1[1], 2.0);
    assert_eq!(v1[2], 2.0);
  }
  #[test]
  #[should_panic(expected = "index out of range: 9")]
  fn panic_on_bad_index() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};

    assert_eq!(v1[9], 2.0);
  }
  #[test]
  fn allow_index_mut_access() {
    let mut v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1[0] = 9.0;

    assert_eq!(v1[0], 9.0);
    assert_eq!(v1[1], 2.0);
    assert_eq!(v1[2], 2.0);
  }
}<commit_msg>Add multiply by f64 and test<commit_after>use std::ops::{
  Add, AddAssign,
  Sub, SubAssign,
  Mul, MulAssign,
  Div, DivAssign,
  Index, IndexMut,
};

#[derive(Debug, Copy, Clone)]
pub struct Vec3 {
  pub i : f64,
  pub j : f64,
  pub k : f64,
}

impl Vec3 {
  pub fn length(&self) -> f64 {
    (self.i * self.i + self.j * self.j + self.k * self.k).sqrt()
  }
}

impl Add for Vec3 {
  type Output = Vec3;
  fn add(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i + other.i, j: self.j + other.j, k: self.k + other.k}
  }
}

impl AddAssign for Vec3 {
  fn add_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i + other.i,
      j: self.j + other.j,
      k: self.k + other.k,
    };
  }
}

impl Sub for Vec3 {
  type Output = Vec3;
  fn sub(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i - other.i, j: self.j - other.j, k: self.k - other.k}
  }
}

impl SubAssign for Vec3 {
  fn sub_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i - other.i,
      j: self.j - other.j,
      k: self.k - other.k,
    }
  }
}

impl Mul<Vec3> for Vec3 {
  type Output = Vec3;
  fn mul(self, rhs: Vec3) -> Vec3 {
    Vec3 {i: self.i * rhs.i, j: self.j * rhs.j, k: self.k * rhs.k}
  }
}

impl Mul<f64> for Vec3 {
  type Output = Vec3;
  fn mul(self, scalar: f64) -> Vec3 {
    Vec3 {i: self.i * scalar, j: self.j * scalar, k: self.k * scalar}
  }
}

impl MulAssign<Vec3> for Vec3 {
  fn mul_assign(&mut self, rhs: Vec3) {
    *self = Vec3 {
      i: self.i * rhs.i,
      j: self.j * rhs.j,
      k: self.k * rhs.k,
    }
  }
}

impl MulAssign<f64> for Vec3 {
  fn mul_assign(&mut self, scalar: f64) {
    *self = Vec3 {
      i: self.i * scalar,
      j: self.j * scalar,
      k: self.k * scalar,
    }
  }
}

impl Div<Vec3> for Vec3 {
  type Output = Vec3;
  fn div(self, rhs: Vec3) -> Vec3 {
    Vec3 {i: self.i / rhs.i, j: self.j / rhs.j, k: self.k / rhs.k}
  }
}

impl Div<f64> for Vec3 {
  type Output = Vec3;
  fn div(self, scalar: f64) -> Vec3 {
    Vec3 {i: self.i / scalar, j: self.j / scalar, k: self.k / scalar}
  }
}

impl DivAssign<Vec3> for Vec3 {
  fn div_assign(&mut self, rhs: Vec3) {
    *self = Vec3 {
      i: self.i / rhs.i,
      j: self.j / rhs.j,
      k: self.k / rhs.k,
    }
  }
}

impl DivAssign<f64> for Vec3 {
  fn div_assign(&mut self, scalar: f64) {
    *self = Vec3 {
      i: self.i / scalar,
      j: self.j / scalar,
      k: self.k / scalar,
    }
  }
}

impl Index<i32> for Vec3 {
  type Output = f64;
  fn index(&self, idx: i32) -> &f64 {
    match idx {
      0 => &self.i,
      1 => &self.j,
      2 => &self.k,
      _ => panic!("index out of range: {}", idx),
    }
  }
}

impl IndexMut<i32> for Vec3 {
  fn index_mut<'a>(&'a mut self, idx: i32) -> &'a mut f64 {
    match idx {
      0 => &mut self.i,
      1 => &mut self.j,
      2 => &mut self.k,
      _ => panic!("index out of range: {}", idx),
    }
  }
}

#[cfg(test)]
mod should {
  use super::Vec3;
  #[test]
  fn add() {
    let v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let sum = v1 + v2;
    assert_eq!(sum.i, 3.0);
    assert_eq!(sum.j, 3.0);
    assert_eq!(sum.k, 3.0);
  }
  #[test]
  fn add_assign() {
    let mut v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1 += v2;
    assert_eq!(v1.i, 3.0);
    assert_eq!(v1.j, 3.0);
    assert_eq!(v1.k, 3.0);
  }
  #[test]
  fn subtract() {
    let v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let diff = v1 - v2;
    assert_eq!(diff.i, -1.0);
    assert_eq!(diff.j, -1.0);
    assert_eq!(diff.k, -1.0);
  }
  #[test]
  fn subtract_assign() {
    let mut v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1 -= v2;
    assert_eq!(v1.i, -1.0);
    assert_eq!(v1.j, -1.0);
    assert_eq!(v1.k, -1.0);
  }
  #[test]
  fn multiply_by_vec3_elementwise() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    let product = v1 * v2;
    assert_eq!(product.i, 6.0);
    assert_eq!(product.j, 6.0);
    assert_eq!(product.k, 6.0);
  }
  #[test]
  fn multiply_by_vec3_assign_elementwise() {
    let mut v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    v1 *= v2;
    assert_eq!(v1.i, 6.0);
    assert_eq!(v1.j, 6.0);
    assert_eq!(v1.k, 6.0);
  }
  #[test]
  fn multiply_by_f64() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let product = v1 * 3.0;

    assert_eq!(product.i, 6.0);
    assert_eq!(product.j, 6.0);
    assert_eq!(product.k, 6.0);
  }
  #[test]
  fn multiply_by_f64_assign() {
    let mut v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1 *= 3.0;

    assert_eq!(v1.i, 6.0);
    assert_eq!(v1.j, 6.0);
    assert_eq!(v1.k, 6.0);
  }
  #[test]
  fn divide_by_vec3_elementwise() {
    let v1 = Vec3 { i: 6.0, j: 6.0, k: 6.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    let quotient = v1 / v2;
    assert_eq!(quotient.i, 2.0);
    assert_eq!(quotient.j, 2.0);
    assert_eq!(quotient.k, 2.0);
  }
  #[test]
  fn divide_by_vec3_assign_elementwise() {
    let mut v1 = Vec3 { i: 6.0, j: 6.0, k: 6.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    v1 /= v2;
    assert_eq!(v1.i, 2.0);
    assert_eq!(v1.j, 2.0);
    assert_eq!(v1.k, 2.0);
  }
  #[test]
  fn divide_by_f64() {
    let v1 = Vec3 { i: 6.0, j: 6.0, k: 6.0};
    let quotient = v1 / 3.0;

    assert_eq!(quotient.i, 2.0);
    assert_eq!(quotient.j, 2.0);
    assert_eq!(quotient.k, 2.0);
  }
  #[test]
  fn divide_by_f64_assign() {
    let mut v1 = Vec3 { i: 6.0, j: 6.0, k: 6.0};
    v1 /= 3.0;

    assert_eq!(v1.i, 2.0);
    assert_eq!(v1.j, 2.0);
    assert_eq!(v1.k, 2.0);
  }
  #[test]
  fn allow_index_access() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};

    assert_eq!(v1[0], 2.0);
    assert_eq!(v1[1], 2.0);
    assert_eq!(v1[2], 2.0);
  }
  #[test]
  #[should_panic(expected = "index out of range: 9")]
  fn panic_on_bad_index() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};

    assert_eq!(v1[9], 2.0);
  }
  #[test]
  fn allow_index_mut_access() {
    let mut v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1[0] = 9.0;

    assert_eq!(v1[0], 9.0);
    assert_eq!(v1[1], 2.0);
    assert_eq!(v1[2], 2.0);
  }
}<|endoftext|>


<commit_before>//! Types for computing game time from wall time.
use float_duration::FloatDuration;
use framerate::FrameCount;

/// Compute elapsed game time for a frame.
pub trait TimeProgression {
    fn compute_game_time(&mut self, wall_time: &FloatDuration) -> FloatDuration;
}

#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct VariableStep {}
#[derive(Debug)]
pub struct FixedStep<'a, C: 'a + FrameCount + ?Sized> {
    counter: &'a mut C,
}

impl VariableStep {
    pub fn new() -> VariableStep {
        VariableStep {}
    }
}
impl<'a, C> FixedStep<'a, C>
    where C: 'a + FrameCount + ?Sized
{
    pub fn new(counter: &'a mut C) -> FixedStep<'a, C> {
        FixedStep { counter: counter }
    }
}

impl TimeProgression for VariableStep {
    fn compute_game_time(&mut self, wall_time: &FloatDuration) -> FloatDuration {
        *wall_time
    }
}
impl<'a, C> TimeProgression for FixedStep<'a, C>
    where C: 'a + FrameCount + ?Sized
{
    fn compute_game_time(&mut self, _: &FloatDuration) -> FloatDuration {
        self.counter.target_time_per_frame()
    }
}
<commit_msg>Added `ConstantStep` progression.<commit_after>//! Types for computing game time from wall time.
use float_duration::FloatDuration;
use framerate::FrameCount;

/// Compute elapsed game time for a frame.
pub trait TimeProgression {
    /// Compute the game time.
    fn compute_game_time(&mut self, wall_time: &FloatDuration) -> FloatDuration;
}

#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct VariableStep {}
#[derive(Debug)]
pub struct FixedStep<'a, C: 'a + FrameCount + ?Sized> {
    counter: &'a mut C,
}
#[derive(Debug, Clone, Copy, Default, PartialEq)]
pub struct ConstantStep {
    step: FloatDuration,
}

impl VariableStep {
    pub fn new() -> VariableStep {
        VariableStep {}
    }
}
impl<'a, C> FixedStep<'a, C>
    where C: 'a + FrameCount + ?Sized
{
    pub fn new(counter: &'a mut C) -> FixedStep<'a, C> {
        FixedStep { counter: counter }
    }
}
impl ConstantStep {
    pub fn new(step: FloatDuration) -> ConstantStep {
        ConstantStep { step }
    }
}

impl TimeProgression for VariableStep {
    fn compute_game_time(&mut self, wall_time: &FloatDuration) -> FloatDuration {
        *wall_time
    }
}
impl<'a, C> TimeProgression for FixedStep<'a, C>
    where C: 'a + FrameCount + ?Sized
{
    fn compute_game_time(&mut self, _: &FloatDuration) -> FloatDuration {
        self.counter.target_time_per_frame()
    }
}
impl TimeProgression for ConstantStep {
    fn compute_game_time(&mut self, _: &FloatDuration) -> FloatDuration {
        self.step.clone()
    }
}
<|endoftext|>


<commit_before>//! `ToSql` and `FromSql` implementation for JSON `Value`.
extern crate serde_json;

use libc::c_int;
use self::serde_json::Value;

use {Error, Result};
use types::{FromSql, ToSql};

use ffi;
use ffi::sqlite3_stmt;
use ffi::sqlite3_column_type;

/// Serialize JSON `Value` to text.
impl ToSql for Value {
    unsafe fn bind_parameter(&self, stmt: *mut sqlite3_stmt, col: c_int) -> c_int {
        let s = serde_json::to_string(self).unwrap();
        s.bind_parameter(stmt, col)
    }
}

/// Deserialize text/blob to JSON `Value`.
impl FromSql for Value {
    unsafe fn column_result(stmt: *mut sqlite3_stmt, col: c_int) -> Result<Value> {
        match sqlite3_column_type(stmt, col) {
            ffi::SQLITE_TEXT => {
                let s = try!(String::column_result(stmt, col));
                match serde_json::from_str(&s) {
                    Ok(v) => Ok(v),
                    Err(err) => Err(Error::FromSqlConversionFailure(Box::new(err))),
                }
            }
            ffi::SQLITE_BLOB => {
                let blob: Vec<u8> = try!(FromSql::column_result(stmt, col));
                match serde_json::from_slice(&blob[..]) {
                    Ok(v) => Ok(v),
                    Err(err) => Err(Error::FromSqlConversionFailure(Box::new(err))),
                }
            }
            _ => Err(Error::InvalidColumnType),
        }
    }

    unsafe fn column_has_valid_sqlite_type(_: *mut sqlite3_stmt, _: c_int) -> bool {
        true // to avoid double check
    }
}

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

    fn checked_memory_handle() -> Connection {
        let db = Connection::open_in_memory().unwrap();
        db.execute_batch("CREATE TABLE foo (t TEXT, b BLOB)").unwrap();
        db
    }

    #[test]
    fn test_json_value() {
        let db = checked_memory_handle();

        let json = "{\"foo\": 13, \"bar\": \"baz\"}";
        let data: serde_json::Value = serde_json::from_str(json).unwrap();
        db.execute("INSERT INTO foo (t, b) VALUES (?, ?)",
                   &[&data, &json.as_bytes()])
          .unwrap();

        let t: serde_json::Value = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!(data, t);
        let b: serde_json::Value = db.query_row("SELECT b FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!(data, b);
    }
}
<commit_msg>Remove unnecessary column_has_valid_sqlite_type impl<commit_after>//! `ToSql` and `FromSql` implementation for JSON `Value`.
extern crate serde_json;

use libc::c_int;
use self::serde_json::Value;

use {Error, Result};
use types::{FromSql, ToSql};

use ffi;
use ffi::sqlite3_stmt;
use ffi::sqlite3_column_type;

/// Serialize JSON `Value` to text.
impl ToSql for Value {
    unsafe fn bind_parameter(&self, stmt: *mut sqlite3_stmt, col: c_int) -> c_int {
        let s = serde_json::to_string(self).unwrap();
        s.bind_parameter(stmt, col)
    }
}

/// Deserialize text/blob to JSON `Value`.
impl FromSql for Value {
    unsafe fn column_result(stmt: *mut sqlite3_stmt, col: c_int) -> Result<Value> {
        match sqlite3_column_type(stmt, col) {
            ffi::SQLITE_TEXT => {
                let s = try!(String::column_result(stmt, col));
                match serde_json::from_str(&s) {
                    Ok(v) => Ok(v),
                    Err(err) => Err(Error::FromSqlConversionFailure(Box::new(err))),
                }
            }
            ffi::SQLITE_BLOB => {
                let blob: Vec<u8> = try!(FromSql::column_result(stmt, col));
                match serde_json::from_slice(&blob[..]) {
                    Ok(v) => Ok(v),
                    Err(err) => Err(Error::FromSqlConversionFailure(Box::new(err))),
                }
            }
            _ => Err(Error::InvalidColumnType),
        }
    }
}

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

    fn checked_memory_handle() -> Connection {
        let db = Connection::open_in_memory().unwrap();
        db.execute_batch("CREATE TABLE foo (t TEXT, b BLOB)").unwrap();
        db
    }

    #[test]
    fn test_json_value() {
        let db = checked_memory_handle();

        let json = "{\"foo\": 13, \"bar\": \"baz\"}";
        let data: serde_json::Value = serde_json::from_str(json).unwrap();
        db.execute("INSERT INTO foo (t, b) VALUES (?, ?)",
                   &[&data, &json.as_bytes()])
          .unwrap();

        let t: serde_json::Value = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!(data, t);
        let b: serde_json::Value = db.query_row("SELECT b FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!(data, b);
    }
}
<|endoftext|>


<commit_before>extern crate triangle;

use triangle::*;

#[test]
fn positive_length_sides_are_ok() {
    let sides = [2, 2, 2];
    let triangle = Triangle::build(sides);
    assert!(triangle.is_ok());
}

#[test]
#[ignore]
fn zero_length_sides_are_illegal() {
    let sides = [0, 0, 0];
    let triangle = Triangle::build(sides);
    assert!(triangle.is_err());
}

#[test]
#[ignore]
fn equilateral_triangles_have_equal_sides() {
    let sides = [2, 2, 2];
    let triangle = Triangle::build(sides).unwrap();
    assert!(triangle.is_equilateral());
    assert!(!triangle.is_scalene());
}

#[test]
#[ignore]
fn larger_equilateral_triangles_have_equal_sides() {
    let sides = [10, 10, 10];
    let triangle = Triangle::build(sides).unwrap();
    assert!(triangle.is_equilateral());
    assert!(!triangle.is_scalene());
}

#[test]
#[ignore]
fn isocseles_triangles_have_two_equal_sides_one() {
    let sides = [3, 4, 4];
    let triangle = Triangle::build(sides).unwrap();
    assert!(!triangle.is_equilateral());
    assert!(triangle.is_isosceles());
    assert!(!triangle.is_scalene());
}

#[test]
#[ignore]
fn isocseles_triangles_have_two_equal_sides_two() {
    let sides = [4, 4, 3];
    let triangle = Triangle::build(sides).unwrap();
    assert!(!triangle.is_equilateral());
    assert!(triangle.is_isosceles());
    assert!(!triangle.is_scalene());
}

#[test]
#[ignore]
fn isocseles_triangles_have_two_equal_sides_three() {
    let sides = [4, 3, 4];
    let triangle = Triangle::build(sides).unwrap();
    assert!(!triangle.is_equilateral());
    assert!(triangle.is_isosceles());
    assert!(!triangle.is_scalene());
}

#[test]
#[ignore]
fn isocseles_triangles_have_two_equal_sides_four() {
    let sides = [4, 7, 4];
    let triangle = Triangle::build(sides).unwrap();
    assert!(!triangle.is_equilateral());
    assert!(triangle.is_isosceles());
    assert!(!triangle.is_scalene());
}

#[test]
#[ignore]
fn scalene_triangle_has_no_equal_sides_one() {
    let sides = [3, 4, 5];
    let triangle = Triangle::build(sides).unwrap();
    assert!(!triangle.is_equilateral());
    assert!(!triangle.is_isosceles());
    assert!(triangle.is_scalene());
}

#[test]
#[ignore]
fn scalene_triangle_has_no_equal_sides_two() {
    let sides = [5, 4, 6];
    let triangle = Triangle::build(sides).unwrap();
    assert!(!triangle.is_equilateral());
    assert!(!triangle.is_isosceles());
    assert!(triangle.is_scalene());
}

#[test]
#[ignore]
fn scalene_triangle_has_no_equal_sides_three() {
    let sides = [10, 11, 12];
    let triangle = Triangle::build(sides).unwrap();
    assert!(!triangle.is_equilateral());
    assert!(!triangle.is_isosceles());
    assert!(triangle.is_scalene());
}

#[test]
#[ignore]
fn scalene_triangle_has_no_equal_sides_four() {
    let sides = [5, 4, 2];
    let triangle = Triangle::build(sides).unwrap();
    assert!(!triangle.is_equilateral());
    assert!(!triangle.is_isosceles());
    assert!(triangle.is_scalene());
}

#[test]
#[ignore]
fn sum_of_two_sides_must_equal_or_exceed_the_remaining_side_one() {
    let sides = [7, 3, 2];
    let triangle = Triangle::build(sides);
    assert!(triangle.is_err());
}

#[test]
#[ignore]
fn sum_of_two_sides_must_equal_or_exceed_the_remaining_side_two() {
    let sides = [1, 1, 3];
    let triangle = Triangle::build(sides);
    assert!(triangle.is_err());
}

// Optional Tests
//
// Support Triangles with non-integer sides.
//
// You'll probably want to use the Num crate
//
// https://crates.io/crates/num
//

// #[test]
// fn scalene_triangle_with_floating_point_sides() {
//     let sides = [0.4, 0.6, 0.3];
//     let triangle = Triangle::build(sides).unwrap();
//     assert!(!triangle.is_equilateral());
//     assert!(!triangle.is_isosceles());
//     assert!(triangle.is_scalene());
// }
//
// #[test]
// fn equilateral_triangles_with_floating_point_sides() {
//     let sides = [0.2, 0.2, 0.2];
//     let triangle = Triangle::build(sides).unwrap();
//     assert!(triangle.is_equilateral());
//     assert!(!triangle.is_scalene());
// }
//
// #[test]
// fn isocseles_triangle_with_floating_point_sides() {
//     let sides = [0.3, 0.4, 0.4];
//     let triangle = Triangle::build(sides).unwrap();
//     assert!(!triangle.is_equilateral());
//     assert!(triangle.is_isosceles());
//     assert!(!triangle.is_scalene());
// }
<commit_msg>triangle: Fix spelling of "isosceles" in tests (#273)<commit_after>extern crate triangle;

use triangle::*;

#[test]
fn positive_length_sides_are_ok() {
    let sides = [2, 2, 2];
    let triangle = Triangle::build(sides);
    assert!(triangle.is_ok());
}

#[test]
#[ignore]
fn zero_length_sides_are_illegal() {
    let sides = [0, 0, 0];
    let triangle = Triangle::build(sides);
    assert!(triangle.is_err());
}

#[test]
#[ignore]
fn equilateral_triangles_have_equal_sides() {
    let sides = [2, 2, 2];
    let triangle = Triangle::build(sides).unwrap();
    assert!(triangle.is_equilateral());
    assert!(!triangle.is_scalene());
}

#[test]
#[ignore]
fn larger_equilateral_triangles_have_equal_sides() {
    let sides = [10, 10, 10];
    let triangle = Triangle::build(sides).unwrap();
    assert!(triangle.is_equilateral());
    assert!(!triangle.is_scalene());
}

#[test]
#[ignore]
fn isosceles_triangles_have_two_equal_sides_one() {
    let sides = [3, 4, 4];
    let triangle = Triangle::build(sides).unwrap();
    assert!(!triangle.is_equilateral());
    assert!(triangle.is_isosceles());
    assert!(!triangle.is_scalene());
}

#[test]
#[ignore]
fn isosceles_triangles_have_two_equal_sides_two() {
    let sides = [4, 4, 3];
    let triangle = Triangle::build(sides).unwrap();
    assert!(!triangle.is_equilateral());
    assert!(triangle.is_isosceles());
    assert!(!triangle.is_scalene());
}

#[test]
#[ignore]
fn isosceles_triangles_have_two_equal_sides_three() {
    let sides = [4, 3, 4];
    let triangle = Triangle::build(sides).unwrap();
    assert!(!triangle.is_equilateral());
    assert!(triangle.is_isosceles());
    assert!(!triangle.is_scalene());
}

#[test]
#[ignore]
fn isosceles_triangles_have_two_equal_sides_four() {
    let sides = [4, 7, 4];
    let triangle = Triangle::build(sides).unwrap();
    assert!(!triangle.is_equilateral());
    assert!(triangle.is_isosceles());
    assert!(!triangle.is_scalene());
}

#[test]
#[ignore]
fn scalene_triangle_has_no_equal_sides_one() {
    let sides = [3, 4, 5];
    let triangle = Triangle::build(sides).unwrap();
    assert!(!triangle.is_equilateral());
    assert!(!triangle.is_isosceles());
    assert!(triangle.is_scalene());
}

#[test]
#[ignore]
fn scalene_triangle_has_no_equal_sides_two() {
    let sides = [5, 4, 6];
    let triangle = Triangle::build(sides).unwrap();
    assert!(!triangle.is_equilateral());
    assert!(!triangle.is_isosceles());
    assert!(triangle.is_scalene());
}

#[test]
#[ignore]
fn scalene_triangle_has_no_equal_sides_three() {
    let sides = [10, 11, 12];
    let triangle = Triangle::build(sides).unwrap();
    assert!(!triangle.is_equilateral());
    assert!(!triangle.is_isosceles());
    assert!(triangle.is_scalene());
}

#[test]
#[ignore]
fn scalene_triangle_has_no_equal_sides_four() {
    let sides = [5, 4, 2];
    let triangle = Triangle::build(sides).unwrap();
    assert!(!triangle.is_equilateral());
    assert!(!triangle.is_isosceles());
    assert!(triangle.is_scalene());
}

#[test]
#[ignore]
fn sum_of_two_sides_must_equal_or_exceed_the_remaining_side_one() {
    let sides = [7, 3, 2];
    let triangle = Triangle::build(sides);
    assert!(triangle.is_err());
}

#[test]
#[ignore]
fn sum_of_two_sides_must_equal_or_exceed_the_remaining_side_two() {
    let sides = [1, 1, 3];
    let triangle = Triangle::build(sides);
    assert!(triangle.is_err());
}

// Optional Tests
//
// Support Triangles with non-integer sides.
//
// You'll probably want to use the Num crate
//
// https://crates.io/crates/num
//

// #[test]
// fn scalene_triangle_with_floating_point_sides() {
//     let sides = [0.4, 0.6, 0.3];
//     let triangle = Triangle::build(sides).unwrap();
//     assert!(!triangle.is_equilateral());
//     assert!(!triangle.is_isosceles());
//     assert!(triangle.is_scalene());
// }
//
// #[test]
// fn equilateral_triangles_with_floating_point_sides() {
//     let sides = [0.2, 0.2, 0.2];
//     let triangle = Triangle::build(sides).unwrap();
//     assert!(triangle.is_equilateral());
//     assert!(!triangle.is_scalene());
// }
//
// #[test]
// fn isosceles_triangle_with_floating_point_sides() {
//     let sides = [0.3, 0.4, 0.4];
//     let triangle = Triangle::build(sides).unwrap();
//     assert!(!triangle.is_equilateral());
//     assert!(triangle.is_isosceles());
//     assert!(!triangle.is_scalene());
// }
<|endoftext|>


<commit_before>//! Seat global utilities
//!
//! This module provides you with utilities for handling the seat globals
//! and the associated input wayland objects.
//!
//! ## How to use it
//!
//! ### Initialization
//!
//! ```
//! # extern crate wayland_server;
//! # #[macro_use] extern crate smithay;
//!
//! use smithay::wayland::seat::Seat;
//!
//! # fn main(){
//! # let (_display, mut event_loop) = wayland_server::create_display();
//! // insert the seat:
//! let (seat_state_token, seat_global) = Seat::new(
//!     &mut event_loop,
//!     "seat-0".into(), // the name of the seat, will be advertize to clients
//!     None /* insert a logger here*/
//! );
//! # }
//! ```
//!
//! ### Run usage
//!
//! Once the seat is initialized, you can add capabilities to it.
//!
//! Currently, only pointer and keyboard capabilities are supported by
//! smithay.
//!
//! You can add these capabilities via methods of the `Seat` struct that was
//! inserted in the event loop, that you can retreive via its token:
//!
//! ```
//! # extern crate wayland_server;
//! # #[macro_use] extern crate smithay;
//! #
//! # use smithay::wayland::seat::Seat;
//! #
//! # fn main(){
//! # let (_display, mut event_loop) = wayland_server::create_display();
//! # let (seat_state_token, seat_global) = Seat::new(
//! #     &mut event_loop,
//! #     "seat-0".into(), // the name of the seat, will be advertize to clients
//! #     None /* insert a logger here*/
//! # );
//! let pointer_handle = event_loop.state().get_mut(&seat_state_token).add_pointer();
//! # }
//! ```
//!
//! These handles can be cloned and sent accross thread, so you can keep one around
//! in your event-handling code to forward inputs to your clients.

mod keyboard;
mod pointer;

pub use self::keyboard::{Error as KeyboardError, KeyboardHandle, ModifiersState};
pub use self::pointer::PointerHandle;
use wayland_server::{Client, EventLoopHandle, Global, Liveness, Resource, StateToken};
use wayland_server::protocol::{wl_keyboard, wl_pointer, wl_seat};

/// Internal data of a seat global
///
/// This struct gives you access to the control of the
/// capabilities of the associated seat.
///
/// It is directly inserted in the event loop by its `new` method.
///
/// See module-level documentation for details of use.
pub struct Seat {
    log: ::slog::Logger,
    name: String,
    pointer: Option<PointerHandle>,
    keyboard: Option<KeyboardHandle>,
    known_seats: Vec<wl_seat::WlSeat>,
}

impl Seat {
    /// Create a new seat global
    ///
    /// A new seat global is created with given name and inserted
    /// into this event loop.
    ///
    /// You are provided with the state token to retrieve it (allowing
    /// you to add or remove capabilities from it), and the global handle,
    /// in case you want to remove it.
    pub fn new<L>(
        evlh: &mut EventLoopHandle, name: String, logger: L
    ) -> (StateToken<Seat>, Global<wl_seat::WlSeat, StateToken<Seat>>)
    where
        L: Into<Option<::slog::Logger>>,
    {
        let log = ::slog_or_stdlog(logger);
        let seat = Seat {
            log: log.new(o!("smithay_module" => "seat_handler", "seat_name" => name.clone())),
            name: name,
            pointer: None,
            keyboard: None,
            known_seats: Vec::new(),
        };
        let token = evlh.state().insert(seat);
        // TODO: support version 5 (axis)
        let global = evlh.register_global(4, seat_global_bind, token.clone());
        (token, global)
    }

    /// Adds the pointer capability to this seat
    ///
    /// You are provided a `PointerHandle`, which allows you to send input events
    /// to this keyboard. This handle can be cloned and sent accross threads.
    ///
    /// Calling this method on a seat that already has a pointer capability
    /// will overwrite it, and will be seen by the clients as if the
    /// mouse was unplugged and a new one was plugged.
    pub fn add_pointer(&mut self) -> PointerHandle {
        let pointer = self::pointer::create_pointer_handler();
        if self.pointer.is_some() {
            // there is already a pointer, remove it and notify the clients
            // of the change
            self.pointer = None;
            let caps = self.compute_caps();
            for seat in &self.known_seats {
                seat.capabilities(caps);
            }
        }
        self.pointer = Some(pointer.clone());
        let caps = self.compute_caps();
        for seat in &self.known_seats {
            seat.capabilities(caps);
        }
        pointer
    }

    /// Remove the pointer capability from this seat
    ///
    /// Clients will be appropriately notified.
    pub fn remove_pointer(&mut self) {
        if self.pointer.is_some() {
            self.pointer = None;
            let caps = self.compute_caps();
            for seat in &self.known_seats {
                seat.capabilities(caps);
            }
        }
    }

    /// Adds the keyboard capability to this seat
    ///
    /// You are provided a `KbdHandle`, which allows you to send input events
    /// to this keyboard. This handle can be cloned and sent accross threads.
    ///
    /// You also provide a Model/Layout/Variant/Options specification of the
    /// keymap to be used for this keyboard, as well as any repeat-info that
    /// will be forwarded to the clients.
    ///
    /// Calling this method on a seat that already has a keyboard capability
    /// will overwrite it, and will be seen by the clients as if the
    /// keyboard was unplugged and a new one was plugged.
    pub fn add_keyboard(
        &mut self, model: &str, layout: &str, variant: &str, options: Option<String>, repeat_delay: i32,
        repeat_rate: i32,
    ) -> Result<KeyboardHandle, KeyboardError> {
        let keyboard = self::keyboard::create_keyboard_handler(
            "evdev", // we need this one
            model,
            layout,
            variant,
            options,
            repeat_delay,
            repeat_rate,
            &self.log,
        )?;
        if self.keyboard.is_some() {
            // there is already a keyboard, remove it and notify the clients
            // of the change
            self.keyboard = None;
            let caps = self.compute_caps();
            for seat in &self.known_seats {
                seat.capabilities(caps);
            }
        }
        self.keyboard = Some(keyboard.clone());
        let caps = self.compute_caps();
        for seat in &self.known_seats {
            seat.capabilities(caps);
        }
        Ok(keyboard)
    }

    /// Remove the keyboard capability from this seat
    ///
    /// Clients will be appropriately notified.
    pub fn remove_keyboard(&mut self) {
        if self.keyboard.is_some() {
            self.keyboard = None;
            let caps = self.compute_caps();
            for seat in &self.known_seats {
                seat.capabilities(caps);
            }
        }
    }

    /// Cleanup internal states from old resources
    ///
    /// Deletes all remnnant of ressources from clients that
    /// are now disconnected.
    ///
    /// It can be wise to run this from time to time.
    pub fn cleanup(&mut self) {
        if let Some(ref pointer) = self.pointer {
            pointer.cleanup_old_pointers();
        }
        if let Some(ref kbd) = self.keyboard {
            kbd.cleanup_old_kbds();
        }
        self.known_seats.retain(|s| s.status() == Liveness::Alive);
    }

    fn compute_caps(&self) -> wl_seat::Capability {
        let mut caps = wl_seat::Capability::empty();
        if self.pointer.is_some() {
            caps |= wl_seat::Capability::Pointer;
        }
        if self.keyboard.is_some() {
            caps |= wl_seat::Capability::Keyboard;
        }
        caps
    }
}

fn seat_global_bind(
    evlh: &mut EventLoopHandle, token: &mut StateToken<Seat>, _: &Client, seat: wl_seat::WlSeat
) {
    evlh.register(&seat, seat_implementation(), token.clone(), None);
    let seat_mgr = evlh.state().get_mut(token);
    if seat.version() >= 2 {
        seat.name(seat_mgr.name.clone());
    }
    seat.capabilities(seat_mgr.compute_caps());
    seat_mgr.known_seats.push(seat);
}

fn seat_implementation() -> wl_seat::Implementation<StateToken<Seat>> {
    wl_seat::Implementation {
        get_pointer: |evlh, token, _, _, pointer| {
            evlh.register(&pointer, pointer_implementation(), (), None);
            if let Some(ref ptr_handle) = evlh.state().get(token).pointer {
                ptr_handle.new_pointer(pointer);
            } else {
                // we should send a protocol error... but the protocol does not allow
                // us, so this pointer will just remain inactive ¯\_(ツ)_/¯
            }
        },
        get_keyboard: |evlh, token, _, _, keyboard| {
            evlh.register(&keyboard, keyboard_implementation(), (), None);
            if let Some(ref kbd_handle) = evlh.state().get(token).keyboard {
                kbd_handle.new_kbd(keyboard);
            } else {
                // same, should error but cant
            }
        },
        get_touch: |_evlh, _token, _, _, _touch| {
            // TODO
        },
        release: |_, _, _, _| {},
    }
}

fn pointer_implementation() -> wl_pointer::Implementation<()> {
    wl_pointer::Implementation {
        set_cursor: |_, _, _, _, _, _, _, _| {},
        release: |_, _, _, _| {},
    }
}

fn keyboard_implementation() -> wl_keyboard::Implementation<()> {
    wl_keyboard::Implementation {
        release: |_, _, _, _| {},
    }
}
<commit_msg>wayland: introduce Seat::owns<commit_after>//! Seat global utilities
//!
//! This module provides you with utilities for handling the seat globals
//! and the associated input wayland objects.
//!
//! ## How to use it
//!
//! ### Initialization
//!
//! ```
//! # extern crate wayland_server;
//! # #[macro_use] extern crate smithay;
//!
//! use smithay::wayland::seat::Seat;
//!
//! # fn main(){
//! # let (_display, mut event_loop) = wayland_server::create_display();
//! // insert the seat:
//! let (seat_state_token, seat_global) = Seat::new(
//!     &mut event_loop,
//!     "seat-0".into(), // the name of the seat, will be advertize to clients
//!     None /* insert a logger here*/
//! );
//! # }
//! ```
//!
//! ### Run usage
//!
//! Once the seat is initialized, you can add capabilities to it.
//!
//! Currently, only pointer and keyboard capabilities are supported by
//! smithay.
//!
//! You can add these capabilities via methods of the `Seat` struct that was
//! inserted in the event loop, that you can retreive via its token:
//!
//! ```
//! # extern crate wayland_server;
//! # #[macro_use] extern crate smithay;
//! #
//! # use smithay::wayland::seat::Seat;
//! #
//! # fn main(){
//! # let (_display, mut event_loop) = wayland_server::create_display();
//! # let (seat_state_token, seat_global) = Seat::new(
//! #     &mut event_loop,
//! #     "seat-0".into(), // the name of the seat, will be advertize to clients
//! #     None /* insert a logger here*/
//! # );
//! let pointer_handle = event_loop.state().get_mut(&seat_state_token).add_pointer();
//! # }
//! ```
//!
//! These handles can be cloned and sent accross thread, so you can keep one around
//! in your event-handling code to forward inputs to your clients.

mod keyboard;
mod pointer;

pub use self::keyboard::{Error as KeyboardError, KeyboardHandle, ModifiersState};
pub use self::pointer::PointerHandle;
use wayland_server::{Client, EventLoopHandle, Global, Liveness, Resource, StateToken};
use wayland_server::protocol::{wl_keyboard, wl_pointer, wl_seat};

/// Internal data of a seat global
///
/// This struct gives you access to the control of the
/// capabilities of the associated seat.
///
/// It is directly inserted in the event loop by its `new` method.
///
/// See module-level documentation for details of use.
pub struct Seat {
    log: ::slog::Logger,
    name: String,
    pointer: Option<PointerHandle>,
    keyboard: Option<KeyboardHandle>,
    known_seats: Vec<wl_seat::WlSeat>,
}

impl Seat {
    /// Create a new seat global
    ///
    /// A new seat global is created with given name and inserted
    /// into this event loop.
    ///
    /// You are provided with the state token to retrieve it (allowing
    /// you to add or remove capabilities from it), and the global handle,
    /// in case you want to remove it.
    pub fn new<L>(
        evlh: &mut EventLoopHandle, name: String, logger: L
    ) -> (StateToken<Seat>, Global<wl_seat::WlSeat, StateToken<Seat>>)
    where
        L: Into<Option<::slog::Logger>>,
    {
        let log = ::slog_or_stdlog(logger);
        let seat = Seat {
            log: log.new(o!("smithay_module" => "seat_handler", "seat_name" => name.clone())),
            name: name,
            pointer: None,
            keyboard: None,
            known_seats: Vec::new(),
        };
        let token = evlh.state().insert(seat);
        // TODO: support version 5 (axis)
        let global = evlh.register_global(4, seat_global_bind, token.clone());
        (token, global)
    }

    /// Adds the pointer capability to this seat
    ///
    /// You are provided a `PointerHandle`, which allows you to send input events
    /// to this keyboard. This handle can be cloned and sent accross threads.
    ///
    /// Calling this method on a seat that already has a pointer capability
    /// will overwrite it, and will be seen by the clients as if the
    /// mouse was unplugged and a new one was plugged.
    pub fn add_pointer(&mut self) -> PointerHandle {
        let pointer = self::pointer::create_pointer_handler();
        if self.pointer.is_some() {
            // there is already a pointer, remove it and notify the clients
            // of the change
            self.pointer = None;
            let caps = self.compute_caps();
            for seat in &self.known_seats {
                seat.capabilities(caps);
            }
        }
        self.pointer = Some(pointer.clone());
        let caps = self.compute_caps();
        for seat in &self.known_seats {
            seat.capabilities(caps);
        }
        pointer
    }

    /// Remove the pointer capability from this seat
    ///
    /// Clients will be appropriately notified.
    pub fn remove_pointer(&mut self) {
        if self.pointer.is_some() {
            self.pointer = None;
            let caps = self.compute_caps();
            for seat in &self.known_seats {
                seat.capabilities(caps);
            }
        }
    }

    /// Adds the keyboard capability to this seat
    ///
    /// You are provided a `KbdHandle`, which allows you to send input events
    /// to this keyboard. This handle can be cloned and sent accross threads.
    ///
    /// You also provide a Model/Layout/Variant/Options specification of the
    /// keymap to be used for this keyboard, as well as any repeat-info that
    /// will be forwarded to the clients.
    ///
    /// Calling this method on a seat that already has a keyboard capability
    /// will overwrite it, and will be seen by the clients as if the
    /// keyboard was unplugged and a new one was plugged.
    pub fn add_keyboard(
        &mut self, model: &str, layout: &str, variant: &str, options: Option<String>, repeat_delay: i32,
        repeat_rate: i32,
    ) -> Result<KeyboardHandle, KeyboardError> {
        let keyboard = self::keyboard::create_keyboard_handler(
            "evdev", // we need this one
            model,
            layout,
            variant,
            options,
            repeat_delay,
            repeat_rate,
            &self.log,
        )?;
        if self.keyboard.is_some() {
            // there is already a keyboard, remove it and notify the clients
            // of the change
            self.keyboard = None;
            let caps = self.compute_caps();
            for seat in &self.known_seats {
                seat.capabilities(caps);
            }
        }
        self.keyboard = Some(keyboard.clone());
        let caps = self.compute_caps();
        for seat in &self.known_seats {
            seat.capabilities(caps);
        }
        Ok(keyboard)
    }

    /// Remove the keyboard capability from this seat
    ///
    /// Clients will be appropriately notified.
    pub fn remove_keyboard(&mut self) {
        if self.keyboard.is_some() {
            self.keyboard = None;
            let caps = self.compute_caps();
            for seat in &self.known_seats {
                seat.capabilities(caps);
            }
        }
    }

    /// Checks wether a given `WlSeat` is associated with this `Seat`
    pub fn owns(&self, seat: &wl_seat::WlSeat) -> bool {
        self.known_seats.iter().any(|s| s.equals(seat))
    }

    /// Cleanup internal states from old resources
    ///
    /// Deletes all remnnant of ressources from clients that
    /// are now disconnected.
    ///
    /// It can be wise to run this from time to time.
    pub fn cleanup(&mut self) {
        if let Some(ref pointer) = self.pointer {
            pointer.cleanup_old_pointers();
        }
        if let Some(ref kbd) = self.keyboard {
            kbd.cleanup_old_kbds();
        }
        self.known_seats.retain(|s| s.status() == Liveness::Alive);
    }

    fn compute_caps(&self) -> wl_seat::Capability {
        let mut caps = wl_seat::Capability::empty();
        if self.pointer.is_some() {
            caps |= wl_seat::Capability::Pointer;
        }
        if self.keyboard.is_some() {
            caps |= wl_seat::Capability::Keyboard;
        }
        caps
    }
}

fn seat_global_bind(
    evlh: &mut EventLoopHandle, token: &mut StateToken<Seat>, _: &Client, seat: wl_seat::WlSeat
) {
    evlh.register(&seat, seat_implementation(), token.clone(), None);
    let seat_mgr = evlh.state().get_mut(token);
    if seat.version() >= 2 {
        seat.name(seat_mgr.name.clone());
    }
    seat.capabilities(seat_mgr.compute_caps());
    seat_mgr.known_seats.push(seat);
}

fn seat_implementation() -> wl_seat::Implementation<StateToken<Seat>> {
    wl_seat::Implementation {
        get_pointer: |evlh, token, _, _, pointer| {
            evlh.register(&pointer, pointer_implementation(), (), None);
            if let Some(ref ptr_handle) = evlh.state().get(token).pointer {
                ptr_handle.new_pointer(pointer);
            } else {
                // we should send a protocol error... but the protocol does not allow
                // us, so this pointer will just remain inactive ¯\_(ツ)_/¯
            }
        },
        get_keyboard: |evlh, token, _, _, keyboard| {
            evlh.register(&keyboard, keyboard_implementation(), (), None);
            if let Some(ref kbd_handle) = evlh.state().get(token).keyboard {
                kbd_handle.new_kbd(keyboard);
            } else {
                // same, should error but cant
            }
        },
        get_touch: |_evlh, _token, _, _, _touch| {
            // TODO
        },
        release: |_, _, _, _| {},
    }
}

fn pointer_implementation() -> wl_pointer::Implementation<()> {
    wl_pointer::Implementation {
        set_cursor: |_, _, _, _, _, _, _, _| {},
        release: |_, _, _, _| {},
    }
}

fn keyboard_implementation() -> wl_keyboard::Implementation<()> {
    wl_keyboard::Implementation {
        release: |_, _, _, _| {},
    }
}
<|endoftext|>


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

use glib::translate::*;
use glib::types;
use ffi;

use adjustment::Adjustment;
use object::{Object, Downcast, Upcast};
use super::widget::Widget;

use SelectionMode;

///////////////////////////////////////////////////////////////////////////////

/// A container that allows reflowing its children.
pub type FlowBox = Object<ffi::GtkFlowBox>;

unsafe impl Upcast<Widget> for FlowBox { }
unsafe impl Upcast<super::container::Container> for FlowBox { }
unsafe impl Upcast<super::orientable::Orientable> for FlowBox { }
unsafe impl Upcast<::builder::Buildable> for FlowBox { }

impl FlowBox {
    pub fn new() -> FlowBox {
        unsafe { Widget::from_glib_none(ffi::gtk_revealer_new()).downcast_unchecked() }
    }

    pub fn set_homogeneous(&self, homogeneous: bool) {
        unsafe { ffi::gtk_flow_box_set_homogeneous(self.to_glib_none().0, homogeneous.to_glib()); }
    }

    pub fn is_homogeneous(&self) -> bool {
        unsafe { from_glib(ffi::gtk_flow_box_get_homogeneous(self.to_glib_none().0)) }
    }

    pub fn get_row_spacing(&self) -> u32 {
        unsafe { ffi::gtk_flow_box_get_row_spacing(self.to_glib_none().0) }
    }

    pub fn set_row_spacing(&self, spacing: u32) {
        unsafe { ffi::gtk_flow_box_set_row_spacing(self.to_glib_none().0, spacing) }
    }

    pub fn set_colum_spacing(&self, spacing: u32) {
        unsafe { ffi::gtk_flow_box_set_column_spacing(self.to_glib_none().0, spacing) }
    }

    pub fn get_column_spacing(&self) -> u32 {
        unsafe { ffi::gtk_flow_box_get_column_spacing(self.to_glib_none().0) }
    }

    pub fn set_min_children_per_line(&self, n_children: u32) {
        unsafe { ffi::gtk_flow_box_set_min_children_per_line(self.to_glib_none().0, n_children) }
    }

    pub fn get_min_children_per_line(&self) -> u32 {
        unsafe { ffi::gtk_flow_box_get_min_children_per_line(self.to_glib_none().0) }
    }

    pub fn set_max_children_per_line(&self, n_children: u32) {
        unsafe { ffi::gtk_flow_box_set_max_children_per_line(self.to_glib_none().0, n_children) }
    }

    pub fn get_max_children_per_line(&self) -> u32 {
        unsafe { ffi::gtk_flow_box_get_max_children_per_line(self.to_glib_none().0) }
    }

    pub fn set_activate_on_single_click(&self, single: bool) {
        unsafe {
            ffi::gtk_flow_box_set_activate_on_single_click(self.to_glib_none().0,
                                                           single.to_glib())
        }
    }

    pub fn is_activate_on_single_click(&self) -> bool {
        unsafe { from_glib(ffi::gtk_flow_box_get_activate_on_single_click(self.to_glib_none().0)) }
    }

    pub fn insert<T: Upcast<Widget>>(&self, widget: &T, position: i32) {
        unsafe {
            ffi::gtk_flow_box_insert(self.to_glib_none().0,
                                     widget.upcast().to_glib_none().0,
                                     position)
        }
    }

    pub fn get_child_at_index(&self, idx: i32) -> Option<FlowBoxChild> {
        unsafe {
            from_glib_none(ffi::gtk_flow_box_get_child_at_index(self.to_glib_none().0, idx))
        }
    }

    pub fn select_child(&self, child: &FlowBoxChild) {
        unsafe { ffi::gtk_flow_box_select_child(self.to_glib_none().0, child.to_glib_none().0) }
    }

    pub fn unselect_child(&self, child: &FlowBoxChild) {
        unsafe { ffi::gtk_flow_box_unselect_child(self.to_glib_none().0, child.to_glib_none().0) }
    }

    pub fn select_all(&self) {
        unsafe { ffi::gtk_flow_box_select_all(self.to_glib_none().0) }
    }

    pub fn unselect_all(&self) {
        unsafe { ffi::gtk_flow_box_unselect_all(self.to_glib_none().0) }
    }

    pub fn set_selection_mode(&self, mode: SelectionMode) {
        unsafe { ffi::gtk_flow_box_set_selection_mode(self.to_glib_none().0, mode) }
    }

    pub fn get_selection_mode(&self) -> SelectionMode {
        unsafe {
            ffi::gtk_flow_box_get_selection_mode(self.to_glib_none().0)
        }
    }

    pub fn set_hadjustment(&self, adjustment: &Adjustment) {
        unsafe {
            ffi::gtk_flow_box_set_hadjustment(self.to_glib_none().0, adjustment.to_glib_none().0)
        }
    }

    pub fn set_vadjustment(&self, adjustment: &Adjustment) {
        unsafe {
            ffi::gtk_flow_box_set_vadjustment(self.to_glib_none().0, adjustment.to_glib_none().0)
        }
    }
}

impl types::StaticType for FlowBox {
    #[inline]
    fn static_type() -> types::Type {
        unsafe { from_glib(ffi::gtk_flow_box_get_type()) }
    }
}

///////////////////////////////////////////////////////////////////////////////

pub type FlowBoxChild = Object<ffi::GtkFlowBoxChild>;

unsafe impl Upcast<Widget> for FlowBoxChild { }
unsafe impl Upcast<super::container::Container> for FlowBoxChild { }
unsafe impl Upcast<super::bin::Bin> for FlowBoxChild { }
unsafe impl Upcast<::builder::Buildable> for FlowBoxChild { }

impl FlowBoxChild {
    pub fn new() -> FlowBoxChild {
        unsafe { Widget::from_glib_none(ffi::gtk_flow_box_child_new()).downcast_unchecked() }
    }

    pub fn get_index(&self) -> i32 {
        unsafe { ffi::gtk_flow_box_child_get_index(self.to_glib_none().0) }
    }

    pub fn is_selected(&self) -> bool {
        unsafe { from_glib(ffi::gtk_flow_box_child_is_selected(self.to_glib_none().0)) }
    }

    pub fn changed(&self) {
        unsafe { ffi::gtk_flow_box_child_changed(self.to_glib_none().0) }
    }
}

impl types::StaticType for FlowBoxChild {
    #[inline]
    fn static_type() -> types::Type {
        unsafe { from_glib(ffi::gtk_flow_box_child_get_type()) }
    }
}
<commit_msg>Fix construction of FlowBox<commit_after>// Copyright 2013-2015, The Rust-GNOME Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use glib::translate::*;
use glib::types;
use ffi;

use adjustment::Adjustment;
use object::{Object, Downcast, Upcast};
use super::widget::Widget;

use SelectionMode;

///////////////////////////////////////////////////////////////////////////////

/// A container that allows reflowing its children.
pub type FlowBox = Object<ffi::GtkFlowBox>;

unsafe impl Upcast<Widget> for FlowBox { }
unsafe impl Upcast<super::container::Container> for FlowBox { }
unsafe impl Upcast<super::orientable::Orientable> for FlowBox { }
unsafe impl Upcast<::builder::Buildable> for FlowBox { }

impl FlowBox {
    pub fn new() -> FlowBox {
        unsafe { Widget::from_glib_none(ffi::gtk_flow_box_new()).downcast_unchecked() }
    }

    pub fn set_homogeneous(&self, homogeneous: bool) {
        unsafe { ffi::gtk_flow_box_set_homogeneous(self.to_glib_none().0, homogeneous.to_glib()); }
    }

    pub fn is_homogeneous(&self) -> bool {
        unsafe { from_glib(ffi::gtk_flow_box_get_homogeneous(self.to_glib_none().0)) }
    }

    pub fn get_row_spacing(&self) -> u32 {
        unsafe { ffi::gtk_flow_box_get_row_spacing(self.to_glib_none().0) }
    }

    pub fn set_row_spacing(&self, spacing: u32) {
        unsafe { ffi::gtk_flow_box_set_row_spacing(self.to_glib_none().0, spacing) }
    }

    pub fn set_colum_spacing(&self, spacing: u32) {
        unsafe { ffi::gtk_flow_box_set_column_spacing(self.to_glib_none().0, spacing) }
    }

    pub fn get_column_spacing(&self) -> u32 {
        unsafe { ffi::gtk_flow_box_get_column_spacing(self.to_glib_none().0) }
    }

    pub fn set_min_children_per_line(&self, n_children: u32) {
        unsafe { ffi::gtk_flow_box_set_min_children_per_line(self.to_glib_none().0, n_children) }
    }

    pub fn get_min_children_per_line(&self) -> u32 {
        unsafe { ffi::gtk_flow_box_get_min_children_per_line(self.to_glib_none().0) }
    }

    pub fn set_max_children_per_line(&self, n_children: u32) {
        unsafe { ffi::gtk_flow_box_set_max_children_per_line(self.to_glib_none().0, n_children) }
    }

    pub fn get_max_children_per_line(&self) -> u32 {
        unsafe { ffi::gtk_flow_box_get_max_children_per_line(self.to_glib_none().0) }
    }

    pub fn set_activate_on_single_click(&self, single: bool) {
        unsafe {
            ffi::gtk_flow_box_set_activate_on_single_click(self.to_glib_none().0,
                                                           single.to_glib())
        }
    }

    pub fn is_activate_on_single_click(&self) -> bool {
        unsafe { from_glib(ffi::gtk_flow_box_get_activate_on_single_click(self.to_glib_none().0)) }
    }

    pub fn insert<T: Upcast<Widget>>(&self, widget: &T, position: i32) {
        unsafe {
            ffi::gtk_flow_box_insert(self.to_glib_none().0,
                                     widget.upcast().to_glib_none().0,
                                     position)
        }
    }

    pub fn get_child_at_index(&self, idx: i32) -> Option<FlowBoxChild> {
        unsafe {
            from_glib_none(ffi::gtk_flow_box_get_child_at_index(self.to_glib_none().0, idx))
        }
    }

    pub fn select_child(&self, child: &FlowBoxChild) {
        unsafe { ffi::gtk_flow_box_select_child(self.to_glib_none().0, child.to_glib_none().0) }
    }

    pub fn unselect_child(&self, child: &FlowBoxChild) {
        unsafe { ffi::gtk_flow_box_unselect_child(self.to_glib_none().0, child.to_glib_none().0) }
    }

    pub fn select_all(&self) {
        unsafe { ffi::gtk_flow_box_select_all(self.to_glib_none().0) }
    }

    pub fn unselect_all(&self) {
        unsafe { ffi::gtk_flow_box_unselect_all(self.to_glib_none().0) }
    }

    pub fn set_selection_mode(&self, mode: SelectionMode) {
        unsafe { ffi::gtk_flow_box_set_selection_mode(self.to_glib_none().0, mode) }
    }

    pub fn get_selection_mode(&self) -> SelectionMode {
        unsafe {
            ffi::gtk_flow_box_get_selection_mode(self.to_glib_none().0)
        }
    }

    pub fn set_hadjustment(&self, adjustment: &Adjustment) {
        unsafe {
            ffi::gtk_flow_box_set_hadjustment(self.to_glib_none().0, adjustment.to_glib_none().0)
        }
    }

    pub fn set_vadjustment(&self, adjustment: &Adjustment) {
        unsafe {
            ffi::gtk_flow_box_set_vadjustment(self.to_glib_none().0, adjustment.to_glib_none().0)
        }
    }
}

impl types::StaticType for FlowBox {
    #[inline]
    fn static_type() -> types::Type {
        unsafe { from_glib(ffi::gtk_flow_box_get_type()) }
    }
}

///////////////////////////////////////////////////////////////////////////////

pub type FlowBoxChild = Object<ffi::GtkFlowBoxChild>;

unsafe impl Upcast<Widget> for FlowBoxChild { }
unsafe impl Upcast<super::container::Container> for FlowBoxChild { }
unsafe impl Upcast<super::bin::Bin> for FlowBoxChild { }
unsafe impl Upcast<::builder::Buildable> for FlowBoxChild { }

impl FlowBoxChild {
    pub fn new() -> FlowBoxChild {
        unsafe { Widget::from_glib_none(ffi::gtk_flow_box_child_new()).downcast_unchecked() }
    }

    pub fn get_index(&self) -> i32 {
        unsafe { ffi::gtk_flow_box_child_get_index(self.to_glib_none().0) }
    }

    pub fn is_selected(&self) -> bool {
        unsafe { from_glib(ffi::gtk_flow_box_child_is_selected(self.to_glib_none().0)) }
    }

    pub fn changed(&self) {
        unsafe { ffi::gtk_flow_box_child_changed(self.to_glib_none().0) }
    }
}

impl types::StaticType for FlowBoxChild {
    #[inline]
    fn static_type() -> types::Type {
        unsafe { from_glib(ffi::gtk_flow_box_child_get_type()) }
    }
}
<|endoftext|>


<commit_before>use std::cmp::min;

use specs::{
    storage::BTreeStorage,
    Builder,
    Component,
    Entities,
    Entity,
    EntityBuilder,
    LazyUpdate,
    Read,
    World,
    WorldExt,
};
use specs_derive::*;

use super::{
    AnimationState,
    Body,
    DaggersInventory,
    Draw,
    Facing,
    Health,
    Intent,
    MustLive,
    Palette,
    Position,
    State,
    Velocity,
    WalkingState,
    Weapon,
};
use crate::animation::Frame;
use crate::components::RenderOrder;
use crate::piv::Colour;

/// Non consuming (but mutating) builder for Entities
/// This provides a more game oriented interface for building entities
/// e.g
///   - build a combatant as a black knight
///   - armed with a sword of sharpness
///   - controlled by the AI
///
/// Since this is a non-consuming builder it can be used multiple times to
/// spawn many types of the same entity
#[derive(Clone, Debug, Default)]
pub struct CharacterTemplate {
    resource: String,
    position: Position,
    state: State,
    palette: Palette,
    draw: Draw,
}

impl CharacterTemplate {
    pub fn build_entity<'a>(&mut self, world: &'a mut World) -> EntityBuilder<'a> {
        world
            .create_entity()
            .with(MustLive {})
            .with(self.position.clone())
            .with(Intent {
                ..Default::default()
            })
            .with(WalkingState {
                ..Default::default()
            })
            .with(Velocity {
                ..Default::default()
            })
            .with(AnimationState {
                ..Default::default()
            })
            .with(RenderOrder {
                ..Default::default()
            })
            .with(self.draw.clone())
            .with(self.palette.clone())
            .with(self.state.clone())
            .with(Health {
                ..Default::default()
            })
            .with(Body {
                ..Default::default()
            })
            .with(Weapon {
                ..Default::default()
            })
            .with(DaggersInventory {
                ..Default::default()
            })
    }

    pub fn build_from_template<'a>(&self, builder: impl Builder) -> impl Builder {
        builder
            .with(MustLive {})
            .with(self.position.clone())
            .with(Intent {
                ..Default::default()
            })
            .with(WalkingState {
                ..Default::default()
            })
            .with(Velocity {
                ..Default::default()
            })
            .with(AnimationState {
                ..Default::default()
            })
            .with(RenderOrder {
                ..Default::default()
            })
            .with(self.draw.clone())
            .with(self.palette.clone())
            .with(self.state.clone())
            .with(Health {
                ..Default::default()
            })
            .with(Body {
                ..Default::default()
            })
            .with(Weapon {
                ..Default::default()
            })
            .with(DaggersInventory {
                ..Default::default()
            })
    }

    pub fn position<'a>(&'a mut self, x: i32, y: i32) -> &'a mut Self {
        self.position.x = x;
        self.position.y = y;
        self
    }

    pub fn draw<'a>(
        &'a mut self,
        frame: &Frame,
        animation: &str,
        direction: Facing,
    ) -> &'a mut Self {
        self.draw = Draw {
            frame: frame.clone(),
            animation: animation.to_string(),
            resource_name: self.resource.clone(),
            direction: direction,
        };
        self
    }

    pub fn state<'a>(&'a mut self, direction: Facing) -> &'a mut Self {
        self.state.direction = direction;
        self
    }

    pub fn palette<'a>(&'a mut self, name: &str, colours: &[Colour]) -> &'a mut Self {
        self.palette.name = name.to_string();
        self.palette.palette.splice(.., colours.to_vec());
        self
    }
}

#[derive(Copy, Clone, Debug)]
pub struct SpawnPoint {
    x: i32,
    y: i32,
    direction: Facing,
}

#[derive(Clone, Debug, Component)]
#[storage(BTreeStorage)]
pub struct SpawnPool {
    pub character: CharacterTemplate,
    pub remaining: usize,
    pub max_active: usize,
    pub active: Vec<Entity>,
    pub spawn_points: Vec<SpawnPoint>,
}

impl Default for SpawnPool {
    fn default() -> Self {
        SpawnPool {
            character: CharacterTemplate {
                resource: "knight".to_string(),
                ..Default::default()
            },
            remaining: 1,
            max_active: 1,
            active: Vec::new(),
            spawn_points: Vec::new(),
        }
    }
}

impl SpawnPool {
    pub fn new(resource: &str) -> Self {
        SpawnPool {
            character: CharacterTemplate {
                resource: resource.to_string(),
                ..Default::default()
            },
            ..Default::default()
        }
    }

    pub fn spawn<'a>(&mut self, world: &'a mut World) -> Option<EntityBuilder<'a>> {
        if self.remaining > 0 {
            self.remaining -= 1;
            Some(self.character.build_entity(world))
        } else {
            None
        }
    }

    pub fn spawn_lazy<'a>(&mut self, lazy: &Read<'a, LazyUpdate>, entities: &Entities<'a>) {
        let spaces = min(self.max_active - self.active.len(), self.remaining);
        for _ in 0..spaces {
            let builder = self
                .character
                .build_from_template(lazy.create_entity(&entities));
            builder.build();
        }
    }
}
<commit_msg>restore UnitType when creating entities.<commit_after>use std::cmp::min;

use specs::{
    storage::BTreeStorage,
    Builder,
    Component,
    Entities,
    Entity,
    EntityBuilder,
    LazyUpdate,
    Read,
    World,
    WorldExt,
};
use specs_derive::*;

use super::{
    AnimationState,
    Body,
    DaggersInventory,
    Draw,
    Facing,
    Health,
    Intent,
    MustLive,
    Palette,
    Position,
    State,
    UnitType,
    Velocity,
    WalkingState,
    Weapon,
};
use crate::animation::Frame;
use crate::components::RenderOrder;
use crate::piv::Colour;

/// Non consuming (but mutating) builder for Entities
/// This provides a more game oriented interface for building entities
/// e.g
///   - build a combatant as a black knight
///   - armed with a sword of sharpness
///   - controlled by the AI
///
/// Since this is a non-consuming builder it can be used multiple times to
/// spawn many types of the same entity
#[derive(Clone, Debug, Default)]
pub struct CharacterTemplate {
    resource: String,
    position: Position,
    state: State,
    palette: Palette,
    draw: Draw,
}

impl CharacterTemplate {
    pub fn build_entity<'a>(&mut self, world: &'a mut World) -> EntityBuilder<'a> {
        world
            .create_entity()
            .with(UnitType {
                name: self.resource.clone(),
            })
            .with(MustLive {})
            .with(self.position.clone())
            .with(Intent {
                ..Default::default()
            })
            .with(WalkingState {
                ..Default::default()
            })
            .with(Velocity {
                ..Default::default()
            })
            .with(AnimationState {
                ..Default::default()
            })
            .with(RenderOrder {
                ..Default::default()
            })
            .with(self.draw.clone())
            .with(self.palette.clone())
            .with(self.state.clone())
            .with(Health {
                ..Default::default()
            })
            .with(Body {
                ..Default::default()
            })
            .with(Weapon {
                ..Default::default()
            })
            .with(DaggersInventory {
                ..Default::default()
            })
    }

    pub fn build_from_template<'a>(&self, builder: impl Builder) -> impl Builder {
        builder
            .with(MustLive {})
            .with(self.position.clone())
            .with(Intent {
                ..Default::default()
            })
            .with(WalkingState {
                ..Default::default()
            })
            .with(Velocity {
                ..Default::default()
            })
            .with(AnimationState {
                ..Default::default()
            })
            .with(RenderOrder {
                ..Default::default()
            })
            .with(self.draw.clone())
            .with(self.palette.clone())
            .with(self.state.clone())
            .with(Health {
                ..Default::default()
            })
            .with(Body {
                ..Default::default()
            })
            .with(Weapon {
                ..Default::default()
            })
            .with(DaggersInventory {
                ..Default::default()
            })
    }

    pub fn position<'a>(&'a mut self, x: i32, y: i32) -> &'a mut Self {
        self.position.x = x;
        self.position.y = y;
        self
    }

    pub fn draw<'a>(
        &'a mut self,
        frame: &Frame,
        animation: &str,
        direction: Facing,
    ) -> &'a mut Self {
        self.draw = Draw {
            frame: frame.clone(),
            animation: animation.to_string(),
            resource_name: self.resource.clone(),
            direction: direction,
        };
        self
    }

    pub fn state<'a>(&'a mut self, direction: Facing) -> &'a mut Self {
        self.state.direction = direction;
        self
    }

    pub fn palette<'a>(&'a mut self, name: &str, colours: &[Colour]) -> &'a mut Self {
        self.palette.name = name.to_string();
        self.palette.palette.splice(.., colours.to_vec());
        self
    }
}

#[derive(Copy, Clone, Debug)]
pub struct SpawnPoint {
    x: i32,
    y: i32,
    direction: Facing,
}

#[derive(Clone, Debug, Component)]
#[storage(BTreeStorage)]
pub struct SpawnPool {
    pub character: CharacterTemplate,
    pub remaining: usize,
    pub max_active: usize,
    pub active: Vec<Entity>,
    pub spawn_points: Vec<SpawnPoint>,
}

impl Default for SpawnPool {
    fn default() -> Self {
        SpawnPool {
            character: CharacterTemplate {
                resource: "knight".to_string(),
                ..Default::default()
            },
            remaining: 1,
            max_active: 1,
            active: Vec::new(),
            spawn_points: Vec::new(),
        }
    }
}

impl SpawnPool {
    pub fn new(resource: &str) -> Self {
        SpawnPool {
            character: CharacterTemplate {
                resource: resource.to_string(),
                ..Default::default()
            },
            ..Default::default()
        }
    }

    pub fn spawn<'a>(&mut self, world: &'a mut World) -> Option<EntityBuilder<'a>> {
        if self.remaining > 0 {
            self.remaining -= 1;
            Some(self.character.build_entity(world))
        } else {
            None
        }
    }

    pub fn spawn_lazy<'a>(&mut self, lazy: &Read<'a, LazyUpdate>, entities: &Entities<'a>) {
        let spaces = min(self.max_active - self.active.len(), self.remaining);
        for _ in 0..spaces {
            let builder = self
                .character
                .build_from_template(lazy.create_entity(&entities));
            builder.build();
        }
    }
}
<|endoftext|>


<commit_before>use super::{heap::ObjectPointer, use_provider::UseProvider, value::Value, Vm};
use crate::{builtin_functions::BuiltinFunction, compiler::lir::Instruction, input::Input};
use itertools::Itertools;
use log;

macro_rules! destructure {
    ($args:expr, $enum:pat, $body:block) => {{
        if let $enum = &$args[..] {
            $body
        } else {
            Err(format!("a builtin function received invalid arguments"))
        }
    }};
}

impl Vm {
    pub(super) fn run_builtin_function<U: UseProvider>(
        &mut self,
        use_provider: &U,
        builtin_function: &BuiltinFunction,
        args: &[ObjectPointer],
    ) {
        log::trace!("run_builtin_function: builtin{builtin_function:?}");

        let args = args.iter().map(|it| self.heap.export(*it)).collect_vec();

        let return_value_or_panic_message = match &builtin_function {
            BuiltinFunction::Add => self.add(args),
            BuiltinFunction::Equals => self.equals(args),
            BuiltinFunction::GetArgumentCount => self.get_argument_count(args),
            BuiltinFunction::IfElse => match self.if_else(use_provider, args) {
                // If successful, IfElse doesn't return a value, but diverges
                // the control flow.
                Ok(()) => return,
                Err(message) => Err(message),
            },
            BuiltinFunction::Panic => self.panic_builtin(args).map(|_| panic!()),
            BuiltinFunction::Print => self.print(args),
            BuiltinFunction::StructGet => self.struct_get(args),
            BuiltinFunction::StructGetKeys => self.struct_get_keys(args),
            BuiltinFunction::StructHasKey => self.struct_has_key(args),
            BuiltinFunction::TypeOf => self.type_of(args),
            BuiltinFunction::UseAsset => self.use_asset(use_provider, args),
            BuiltinFunction::UseLocalModule => {
                // If successful, UseLocalModule doesn't return a value, but
                // diverges the control flow.
                match self.use_local_module(use_provider, args) {
                    Ok(()) => return,
                    Err(message) => Err(message),
                }
            }
        };
        let return_value = match return_value_or_panic_message {
            Ok(value) => value,
            Err(panic_message) => self.panic(panic_message),
        };

        let return_object = self.heap.import(return_value);
        self.data_stack.push(return_object);
    }

    fn add(&mut self, args: Vec<Value>) -> Result<Value, String> {
        destructure!(args, [Value::Int(a), Value::Int(b)], { Ok((a + b).into()) })
    }

    fn equals(&mut self, args: Vec<Value>) -> Result<Value, String> {
        destructure!(args, [a, b], { Ok((a == b).into()) })
    }

    fn get_argument_count(&mut self, args: Vec<Value>) -> Result<Value, String> {
        destructure!(args, [Value::Closure { num_args, .. }], {
            Ok((*num_args as u64).into())
        })
    }

    fn if_else<U: UseProvider>(
        &mut self,
        use_provider: &U,
        args: Vec<Value>,
    ) -> Result<(), String> {
        destructure!(
            args,
            [
                Value::Symbol(condition),
                Value::Closure {
                    captured: then_captured,
                    num_args: then_num_args,
                    body: then_body
                },
                Value::Closure {
                    captured: else_captured,
                    num_args: else_num_args,
                    body: else_body
                }
            ],
            {
                if *then_num_args > 0 {
                    return Err(format!("IfElse expects a closure without arguments as the then, got one with {then_num_args} arguments."));
                }
                if *else_num_args > 0 {
                    return Err(format!("IfElse expects a closure without arguments as the else, got one with {else_num_args} arguments."));
                }
                let condition = match condition.as_str() {
                    "True" => true,
                    "False" => false,
                    _ => {
                        return Err(format!(
                            "IfElse expected True or False as a condition, but got {condition}.",
                        ));
                    }
                };

                let closure_object = self.heap.import(if condition {
                    Value::Closure {
                        captured: then_captured.to_owned(),
                        num_args: *then_num_args,
                        body: then_body.to_owned(),
                    }
                } else {
                    Value::Closure {
                        captured: else_captured.to_owned(),
                        num_args: *else_num_args,
                        body: else_body.to_owned(),
                    }
                });
                log::debug!(
                    "IfElse executing the closure: {:?}",
                    self.heap.export_without_dropping(closure_object)
                );
                self.data_stack.push(closure_object);
                self.run_instruction(use_provider, Instruction::Call { num_args: 0 });
                Ok(())
            }
        )
    }

    fn panic_builtin(&mut self, args: Vec<Value>) -> Result<!, String> {
        destructure!(args, [Value::Text(message)], { Err(message.to_string()) })
    }

    fn print(&mut self, args: Vec<Value>) -> Result<Value, String> {
        destructure!(args, [Value::Text(message)], {
            println!("{message:?}");
            Ok(Value::nothing())
        })
    }

    fn struct_get(&mut self, args: Vec<Value>) -> Result<Value, String> {
        destructure!(args, [Value::Struct(struct_), key], {
            match struct_.get(&key) {
                Some(value) => Ok(value.clone().into()),
                None => Err(format!("Struct does not contain key {key:?}.")),
            }
        })
    }

    fn struct_get_keys(&mut self, args: Vec<Value>) -> Result<Value, String> {
        destructure!(args, [Value::Struct(struct_)], {
            Ok(Value::list(struct_.keys().cloned().collect()))
        })
    }

    fn struct_has_key(&mut self, args: Vec<Value>) -> Result<Value, String> {
        destructure!(args, [Value::Struct(struct_), key], {
            Ok((struct_.contains_key(key)).into())
        })
    }

    fn type_of(&mut self, args: Vec<Value>) -> Result<Value, String> {
        destructure!(args, [value], {
            Ok(Value::Symbol(
                match &value {
                    Value::Int(_) => "Int",
                    Value::Text(_) => "Text",
                    Value::Symbol(_) => "Symbol",
                    Value::Struct(_) => "Struct",
                    Value::Closure { .. } => "Function",
                    Value::Builtin { .. } => "Builtin",
                }
                .to_owned(),
            ))
        })
    }

    fn use_asset<U: UseProvider>(
        &mut self,
        use_provider: &U,
        args: Vec<Value>,
    ) -> Result<Value, String> {
        let (current_path, target) = Self::parse_current_path_and_target(args)?;
        let target = UseAssetTarget::parse(&target)?;
        let input = target.resolve_asset(&current_path)?;
        let content = use_provider.use_asset(input)?;
        Ok(Value::list(
            content
                .iter()
                .map(|byte| Value::Int(*byte as u64))
                .collect_vec(),
        ))
    }

    fn use_local_module<U: UseProvider>(
        &mut self,
        use_provider: &U,
        args: Vec<Value>,
    ) -> Result<(), String> {
        let (current_path, target) = Self::parse_current_path_and_target(args)?;
        let target = UseAssetTarget::parse(&target)?;
        let possible_inputs = target.resolve_local_module(&current_path)?;
        let (input, lir) = 'find_existing_input: {
            for input in possible_inputs {
                if let Some(lir) = use_provider.use_local_module(input.clone()) {
                    break 'find_existing_input (input, lir);
                }
            }
            return Err("couldn't import module".to_string());
        };

        let module_closure = Value::module_closure_of_lir(input.clone(), lir);
        let address = self.heap.import(module_closure);
        self.data_stack.push(address);
        self.run_instruction(use_provider, Instruction::Call { num_args: 0 });
        Ok(())
    }

    fn parse_current_path_and_target(args: Vec<Value>) -> Result<(Vec<String>, String), String> {
        destructure!(
            args,
            [Value::Struct(current_path_struct), Value::Text(target)],
            {
                // `current_path_struct` is set by us and not users, hence we don't have to validate it that strictly.
                let mut current_path = vec![];
                let mut index = 0;
                while let Some(component) = current_path_struct.get(&Value::Int(index)) {
                    current_path.push(component.clone().try_into_text().unwrap());
                    index += 1;
                }
                Ok((current_path, target.to_string()))
            }
        )
    }
}

struct UseAssetTarget {
    parent_navigations: usize,
    path: String,
}
impl UseAssetTarget {
    const PARENT_NAVIGATION_CHAR: char = '.';

    fn parse(mut target: &str) -> Result<Self, String> {
        let parent_navigations = {
            let mut navigations = 0;
            while target.chars().next() == Some(UseAssetTarget::PARENT_NAVIGATION_CHAR) {
                navigations += 1;
                target = &target[UseAssetTarget::PARENT_NAVIGATION_CHAR.len_utf8()..];
            }
            match navigations {
                0 => return Err("the target must start with at least one dot".to_string()),
                i => i - 1, // two dots means one parent navigation
            }
        };
        let path = {
            if !target
                .chars()
                .all(|c| c.is_ascii_alphanumeric() || c == '.')
            {
                return Err("the target name can only contain letters".to_string());
            }
            target.to_string()
        };
        Ok(UseAssetTarget {
            parent_navigations,
            path,
        })
    }

    fn resolve_asset(&self, current_path: &[String]) -> Result<Input, String> {
        let mut path = current_path.to_owned();
        for _ in 0..self.parent_navigations {
            if path.pop() == None {
                return Err("too many parent navigations".to_string());
            }
        }
        if path
            .last()
            .map(|it| it.ends_with(".candy"))
            .unwrap_or(false)
        {
            return Err(
                "importing child files (starting with a single dot) only works from `.candy` files"
                    .to_string(),
            );
        }
        path.push(self.path.to_string());
        Ok(Input::File(path.clone()))
    }

    fn resolve_local_module(&self, current_path: &[String]) -> Result<Vec<Input>, String> {
        if self.path.contains('.') {
            return Err("the target name contains a file ending".to_string());
        }

        let mut path = current_path.to_owned();
        for _ in 0..self.parent_navigations {
            if path.pop() == None {
                return Err("too many parent navigations".to_string());
            }
        }
        let possible_paths = vec![
            path.clone()
                .into_iter()
                .chain([format!("{}.candy", self.path)])
                .collect_vec(),
            path.clone()
                .into_iter()
                .chain([self.path.to_string(), ".candy".to_string()])
                .collect_vec(),
        ];
        Ok(possible_paths
            .into_iter()
            .map(|path| Input::File(path))
            .collect_vec())
    }
}
<commit_msg>Make builtinPrint not actually print, but log::info instead<commit_after>use super::{heap::ObjectPointer, use_provider::UseProvider, value::Value, Vm};
use crate::{builtin_functions::BuiltinFunction, compiler::lir::Instruction, input::Input};
use itertools::Itertools;
use log;

macro_rules! destructure {
    ($args:expr, $enum:pat, $body:block) => {{
        if let $enum = &$args[..] {
            $body
        } else {
            Err(format!("a builtin function received invalid arguments"))
        }
    }};
}

impl Vm {
    pub(super) fn run_builtin_function<U: UseProvider>(
        &mut self,
        use_provider: &U,
        builtin_function: &BuiltinFunction,
        args: &[ObjectPointer],
    ) {
        log::trace!("run_builtin_function: builtin{builtin_function:?}");

        let args = args.iter().map(|it| self.heap.export(*it)).collect_vec();

        let return_value_or_panic_message = match &builtin_function {
            BuiltinFunction::Add => self.add(args),
            BuiltinFunction::Equals => self.equals(args),
            BuiltinFunction::GetArgumentCount => self.get_argument_count(args),
            BuiltinFunction::IfElse => match self.if_else(use_provider, args) {
                // If successful, IfElse doesn't return a value, but diverges
                // the control flow.
                Ok(()) => return,
                Err(message) => Err(message),
            },
            BuiltinFunction::Panic => self.panic_builtin(args).map(|_| panic!()),
            BuiltinFunction::Print => self.print(args),
            BuiltinFunction::StructGet => self.struct_get(args),
            BuiltinFunction::StructGetKeys => self.struct_get_keys(args),
            BuiltinFunction::StructHasKey => self.struct_has_key(args),
            BuiltinFunction::TypeOf => self.type_of(args),
            BuiltinFunction::UseAsset => self.use_asset(use_provider, args),
            BuiltinFunction::UseLocalModule => {
                // If successful, UseLocalModule doesn't return a value, but
                // diverges the control flow.
                match self.use_local_module(use_provider, args) {
                    Ok(()) => return,
                    Err(message) => Err(message),
                }
            }
        };
        let return_value = match return_value_or_panic_message {
            Ok(value) => value,
            Err(panic_message) => self.panic(panic_message),
        };

        let return_object = self.heap.import(return_value);
        self.data_stack.push(return_object);
    }

    fn add(&mut self, args: Vec<Value>) -> Result<Value, String> {
        destructure!(args, [Value::Int(a), Value::Int(b)], { Ok((a + b).into()) })
    }

    fn equals(&mut self, args: Vec<Value>) -> Result<Value, String> {
        destructure!(args, [a, b], { Ok((a == b).into()) })
    }

    fn get_argument_count(&mut self, args: Vec<Value>) -> Result<Value, String> {
        destructure!(args, [Value::Closure { num_args, .. }], {
            Ok((*num_args as u64).into())
        })
    }

    fn if_else<U: UseProvider>(
        &mut self,
        use_provider: &U,
        args: Vec<Value>,
    ) -> Result<(), String> {
        destructure!(
            args,
            [
                Value::Symbol(condition),
                Value::Closure {
                    captured: then_captured,
                    num_args: then_num_args,
                    body: then_body
                },
                Value::Closure {
                    captured: else_captured,
                    num_args: else_num_args,
                    body: else_body
                }
            ],
            {
                if *then_num_args > 0 {
                    return Err(format!("IfElse expects a closure without arguments as the then, got one with {then_num_args} arguments."));
                }
                if *else_num_args > 0 {
                    return Err(format!("IfElse expects a closure without arguments as the else, got one with {else_num_args} arguments."));
                }
                let condition = match condition.as_str() {
                    "True" => true,
                    "False" => false,
                    _ => {
                        return Err(format!(
                            "IfElse expected True or False as a condition, but got {condition}.",
                        ));
                    }
                };

                let closure_object = self.heap.import(if condition {
                    Value::Closure {
                        captured: then_captured.to_owned(),
                        num_args: *then_num_args,
                        body: then_body.to_owned(),
                    }
                } else {
                    Value::Closure {
                        captured: else_captured.to_owned(),
                        num_args: *else_num_args,
                        body: else_body.to_owned(),
                    }
                });
                log::debug!(
                    "IfElse executing the closure: {:?}",
                    self.heap.export_without_dropping(closure_object)
                );
                self.data_stack.push(closure_object);
                self.run_instruction(use_provider, Instruction::Call { num_args: 0 });
                Ok(())
            }
        )
    }

    fn panic_builtin(&mut self, args: Vec<Value>) -> Result<!, String> {
        destructure!(args, [Value::Text(message)], { Err(message.to_string()) })
    }

    fn print(&mut self, args: Vec<Value>) -> Result<Value, String> {
        destructure!(args, [Value::Text(message)], {
            log::info!("{message:?}");
            Ok(Value::nothing())
        })
    }

    fn struct_get(&mut self, args: Vec<Value>) -> Result<Value, String> {
        destructure!(args, [Value::Struct(struct_), key], {
            match struct_.get(&key) {
                Some(value) => Ok(value.clone().into()),
                None => Err(format!("Struct does not contain key {key:?}.")),
            }
        })
    }

    fn struct_get_keys(&mut self, args: Vec<Value>) -> Result<Value, String> {
        destructure!(args, [Value::Struct(struct_)], {
            Ok(Value::list(struct_.keys().cloned().collect()))
        })
    }

    fn struct_has_key(&mut self, args: Vec<Value>) -> Result<Value, String> {
        destructure!(args, [Value::Struct(struct_), key], {
            Ok((struct_.contains_key(key)).into())
        })
    }

    fn type_of(&mut self, args: Vec<Value>) -> Result<Value, String> {
        destructure!(args, [value], {
            Ok(Value::Symbol(
                match &value {
                    Value::Int(_) => "Int",
                    Value::Text(_) => "Text",
                    Value::Symbol(_) => "Symbol",
                    Value::Struct(_) => "Struct",
                    Value::Closure { .. } => "Function",
                    Value::Builtin { .. } => "Builtin",
                }
                .to_owned(),
            ))
        })
    }

    fn use_asset<U: UseProvider>(
        &mut self,
        use_provider: &U,
        args: Vec<Value>,
    ) -> Result<Value, String> {
        let (current_path, target) = Self::parse_current_path_and_target(args)?;
        let target = UseAssetTarget::parse(&target)?;
        let input = target.resolve_asset(&current_path)?;
        let content = use_provider.use_asset(input)?;
        Ok(Value::list(
            content
                .iter()
                .map(|byte| Value::Int(*byte as u64))
                .collect_vec(),
        ))
    }

    fn use_local_module<U: UseProvider>(
        &mut self,
        use_provider: &U,
        args: Vec<Value>,
    ) -> Result<(), String> {
        let (current_path, target) = Self::parse_current_path_and_target(args)?;
        let target = UseAssetTarget::parse(&target)?;
        let possible_inputs = target.resolve_local_module(&current_path)?;
        let (input, lir) = 'find_existing_input: {
            for input in possible_inputs {
                if let Some(lir) = use_provider.use_local_module(input.clone()) {
                    break 'find_existing_input (input, lir);
                }
            }
            return Err("couldn't import module".to_string());
        };

        let module_closure = Value::module_closure_of_lir(input.clone(), lir);
        let address = self.heap.import(module_closure);
        self.data_stack.push(address);
        self.run_instruction(use_provider, Instruction::Call { num_args: 0 });
        Ok(())
    }

    fn parse_current_path_and_target(args: Vec<Value>) -> Result<(Vec<String>, String), String> {
        destructure!(
            args,
            [Value::Struct(current_path_struct), Value::Text(target)],
            {
                // `current_path_struct` is set by us and not users, hence we don't have to validate it that strictly.
                let mut current_path = vec![];
                let mut index = 0;
                while let Some(component) = current_path_struct.get(&Value::Int(index)) {
                    current_path.push(component.clone().try_into_text().unwrap());
                    index += 1;
                }
                Ok((current_path, target.to_string()))
            }
        )
    }
}

struct UseAssetTarget {
    parent_navigations: usize,
    path: String,
}
impl UseAssetTarget {
    const PARENT_NAVIGATION_CHAR: char = '.';

    fn parse(mut target: &str) -> Result<Self, String> {
        let parent_navigations = {
            let mut navigations = 0;
            while target.chars().next() == Some(UseAssetTarget::PARENT_NAVIGATION_CHAR) {
                navigations += 1;
                target = &target[UseAssetTarget::PARENT_NAVIGATION_CHAR.len_utf8()..];
            }
            match navigations {
                0 => return Err("the target must start with at least one dot".to_string()),
                i => i - 1, // two dots means one parent navigation
            }
        };
        let path = {
            if !target
                .chars()
                .all(|c| c.is_ascii_alphanumeric() || c == '.')
            {
                return Err("the target name can only contain letters".to_string());
            }
            target.to_string()
        };
        Ok(UseAssetTarget {
            parent_navigations,
            path,
        })
    }

    fn resolve_asset(&self, current_path: &[String]) -> Result<Input, String> {
        let mut path = current_path.to_owned();
        for _ in 0..self.parent_navigations {
            if path.pop() == None {
                return Err("too many parent navigations".to_string());
            }
        }
        if path
            .last()
            .map(|it| it.ends_with(".candy"))
            .unwrap_or(false)
        {
            return Err(
                "importing child files (starting with a single dot) only works from `.candy` files"
                    .to_string(),
            );
        }
        path.push(self.path.to_string());
        Ok(Input::File(path.clone()))
    }

    fn resolve_local_module(&self, current_path: &[String]) -> Result<Vec<Input>, String> {
        if self.path.contains('.') {
            return Err("the target name contains a file ending".to_string());
        }

        let mut path = current_path.to_owned();
        for _ in 0..self.parent_navigations {
            if path.pop() == None {
                return Err("too many parent navigations".to_string());
            }
        }
        let possible_paths = vec![
            path.clone()
                .into_iter()
                .chain([format!("{}.candy", self.path)])
                .collect_vec(),
            path.clone()
                .into_iter()
                .chain([self.path.to_string(), ".candy".to_string()])
                .collect_vec(),
        ];
        Ok(possible_paths
            .into_iter()
            .map(|path| Input::File(path))
            .collect_vec())
    }
}
<|endoftext|>


<commit_before>use serde::{Deserialize, Serialize};

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

fn main() {
    let rust = serde_json::from_str::<Project>(r#"{"name": "Rust"}"#);
    println!("{:?}", rust);
    let servo = serde_json::from_str::<Project>(r#"{"name": "Servo",}"#);
    println!("{:?}", servo);

    let xz = vec![3, 5, 9];
    println!("Last element of xz: {:?}", xz.last());

    let xz: Vec<i32> = vec![];
    println!("Last element of xz: {:?}", xz.last());
}
<commit_msg>placeholder: more error handling in Rust<commit_after>use serde::{Deserialize, Serialize};

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

fn main() {
    let rust = serde_json::from_str::<Project>(r#"{"name": "Rust"}"#);
    println!("{:?}", rust);
    let servo = serde_json::from_str::<Project>(r#"{"name": "Servo",}"#);
    println!("{:?}", servo);

    let rust_name = match rust {
        Ok(rust) => rust.name,
        _ => unimplemented!(),
    };
    println!("rust project name: {}", rust_name);

    let xz = vec![3, 5, 9];
    println!("Last element of xz: {:?}", xz.last());

    let xz: Vec<i32> = vec![];
    println!("Last element of xz: {:?}", xz.last());
}
<|endoftext|>


<commit_before>use rustc_serialize::json;

use std::error::Error;
use std::ffi::OsStr;
use std::fs;
use std::path::{ Path, PathBuf };

use backend::{ download, verify };
use package;

fn update_list<F>(url: &str, path: &Path, after_download: F) -> Result<bool, String>
    where F: Fn(u64) {
    let mut download_to = PathBuf::new();
        download_to.push(path);
        download_to.push(get_option!(url.split('/').last(), "An error occured while getting package list filename."));

    if download_to.exists() {
        let mut temporary_download_to = PathBuf::new();
            temporary_download_to.push(download_to.as_path());
            temporary_download_to.set_extension(".tmp");
        try!(download::download_file_and(url, temporary_download_to.as_path(), after_download));

        if try!(verify::verify_file_crc32(download_to.as_path())) == try!(verify::verify_file_crc32(temporary_download_to.as_path())) {
            get!(fs::remove_file(temporary_download_to.as_path()), "An error occured while removing unneeded package list.");
            Ok(false)
        } else {
            get!(fs::remove_file(download_to.as_path()), "An error occured while removing unneeded package list.");
            get!(fs::rename(temporary_download_to.as_path(), download_to.as_path()), "An error occured while renaming package list.");
            Ok(true)
        }
    // Indeed, this function is a giant clusterfuck. Apologies for code-gore.
    } else {
        try!(download::download_file_and(url, download_to.as_path(), after_download));
        Ok(true)
    }
}<commit_msg>Documentation for update.rs<commit_after>use rustc_serialize::json;

use std::error::Error;
use std::ffi::OsStr;
use std::fs;
use std::path::{ Path, PathBuf };

use backend::{ download, verify };
use package;

/// Downloads the package list from `url`, and
/// outputs it to `path`. After the download of
/// package list is complete, invokes `after_download`.
fn update_list<F>(url: &str, path: &Path, after_download: F) -> Result<bool, String>
    where F: Fn(u64) {
    let mut download_to = PathBuf::new();
        download_to.push(path);
        download_to.push(get_option!(url.split('/').last(), "An error occured while getting package list filename."));

    if download_to.exists() {
        let mut temporary_download_to = PathBuf::new();
            temporary_download_to.push(download_to.as_path());
            temporary_download_to.set_extension(".tmp");
        try!(download::download_file_and(url, temporary_download_to.as_path(), after_download));

        if try!(verify::verify_file_crc32(download_to.as_path())) == try!(verify::verify_file_crc32(temporary_download_to.as_path())) {
            get!(fs::remove_file(temporary_download_to.as_path()), "An error occured while removing unneeded package list.");
            Ok(false)
        } else {
            get!(fs::remove_file(download_to.as_path()), "An error occured while removing unneeded package list.");
            get!(fs::rename(temporary_download_to.as_path(), download_to.as_path()), "An error occured while renaming package list.");
            Ok(true)
        }
    // Indeed, this function is a giant clusterfuck. Apologies for code-gore.
    } else {
        try!(download::download_file_and(url, download_to.as_path(), after_download));
        Ok(true)
    }
}<|endoftext|>