<commit_before>extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate toml;

use std::{collections::BTreeMap, env, ffi::OsString, fs, path::PathBuf};
use toml::Value;

fn main() {
    let mut args = env::args_os().skip(1).fuse();

    let input_filename = args.next().unwrap_or_else(|| OsString::from("Cargo.toml"));
    let output_filename = args.next().unwrap_or_else(|| input_filename.clone());

    let input_filename = PathBuf::from(input_filename);
    let output_filename = PathBuf::from(output_filename);

    let input = fs::read_to_string(&input_filename)
        .unwrap_or_else(|e| panic!("Cannot read {}: {}", input_filename.display(), e));
    let mut cargo_toml: Value = toml::from_str(&input)
        .unwrap_or_else(|e| panic!("Cannot parse {} as TOML: {}", input_filename.display(), e));

    if env::var_os("PLAYGROUND_NO_DEPENDENCIES").is_some() {
        cargo_toml = remove_dependencies(cargo_toml);
    }

    if let Ok(crate_type) = env::var("PLAYGROUND_CRATE_TYPE") {
        cargo_toml = set_crate_type(cargo_toml, &crate_type);
    }

    if let Ok(lto) = env::var("PLAYGROUND_RELEASE_LTO") {
        cargo_toml = set_release_lto(cargo_toml, lto == "true");
    }

    let output = toml::to_string(&cargo_toml).expect("Cannot convert back to TOML");

    fs::write(&output_filename, output)
        .unwrap_or_else(|e| panic!("Cannot write to {}: {}", output_filename.display(), e));
}

type Other = BTreeMap<String, Value>;

fn modify<F, T>(cargo_toml: Value, f: F) -> Value
where
    F: FnOnce(T) -> T,
    T: serde::Serialize + for<'de> serde::Deserialize<'de>,
{
    let cargo_toml = cargo_toml.try_into().unwrap();

    let cargo_toml = f(cargo_toml);

    Value::try_from(cargo_toml).unwrap()
}

fn ensure_string_in_vec(values: &mut Vec<String>, val: &str) {
    if !values.iter().any(|f| f == val) {
        values.push(val.into());
    }
}

fn remove_dependencies(cargo_toml: Value) -> Value {
    #[derive(Debug, Serialize, Deserialize)]
    #[serde(rename_all = "kebab-case")]
    struct CargoToml {
        dependencies: BTreeMap<String, Value>,
        #[serde(flatten)]
        other: Other,
    }

    modify(cargo_toml, |mut cargo_toml: CargoToml| {
        cargo_toml.dependencies.clear();
        cargo_toml
    })
}

fn set_crate_type(cargo_toml: Value, crate_type: &str) -> Value {
    #[derive(Debug, Serialize, Deserialize)]
    #[serde(rename_all = "kebab-case")]
    struct CargoToml {
        #[serde(default)]
        lib: Lib,
        #[serde(flatten)]
        other: Other,
    }

    #[derive(Debug, Default, Serialize, Deserialize)]
    #[serde(rename_all = "kebab-case")]
    struct Lib {
        #[serde(default)]
        crate_type: Vec<String>,
        #[serde(flatten)]
        other: Other,
    }

    modify(cargo_toml, |mut cargo_toml: CargoToml| {
        ensure_string_in_vec(&mut cargo_toml.lib.crate_type, crate_type);
        cargo_toml
    })
}

fn set_release_lto(cargo_toml: Value, lto: bool) -> Value {
    #[derive(Debug, Serialize, Deserialize)]
    #[serde(rename_all = "kebab-case")]
    struct CargoToml {
        #[serde(default)]
        profile: Profiles,
        #[serde(flatten)]
        other: Other,
    }

    #[derive(Debug, Default, Serialize, Deserialize)]
    #[serde(rename_all = "kebab-case")]
    struct Profiles {
        #[serde(default)]
        release: Profile,
        #[serde(flatten)]
        other: Other,
    }

    #[derive(Debug, Default, Serialize, Deserialize)]
    #[serde(rename_all = "kebab-case")]
    struct Profile {
        #[serde(default)]
        lto: bool,
        #[serde(flatten)]
        other: Other,
    }

    modify(cargo_toml, |mut cargo_toml: CargoToml| {
        cargo_toml.profile.release.lto = lto;
        cargo_toml
    })
}
<commit_msg>Add the ability to set the edition in Cargo.toml<commit_after>extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate toml;

use std::{collections::BTreeMap, env, ffi::OsString, fs, path::PathBuf};
use toml::Value;

fn main() {
    let mut args = env::args_os().skip(1).fuse();

    let input_filename = args.next().unwrap_or_else(|| OsString::from("Cargo.toml"));
    let output_filename = args.next().unwrap_or_else(|| input_filename.clone());

    let input_filename = PathBuf::from(input_filename);
    let output_filename = PathBuf::from(output_filename);

    let input = fs::read_to_string(&input_filename)
        .unwrap_or_else(|e| panic!("Cannot read {}: {}", input_filename.display(), e));
    let mut cargo_toml: Value = toml::from_str(&input)
        .unwrap_or_else(|e| panic!("Cannot parse {} as TOML: {}", input_filename.display(), e));

    if let Ok(edition) = env::var("PLAYGROUND_EDITION") {
        cargo_toml = set_edition(cargo_toml, &edition);
    }

    if env::var_os("PLAYGROUND_NO_DEPENDENCIES").is_some() {
        cargo_toml = remove_dependencies(cargo_toml);
    }

    if let Ok(crate_type) = env::var("PLAYGROUND_CRATE_TYPE") {
        cargo_toml = set_crate_type(cargo_toml, &crate_type);
    }

    if let Ok(lto) = env::var("PLAYGROUND_RELEASE_LTO") {
        cargo_toml = set_release_lto(cargo_toml, lto == "true");
    }

    let output = toml::to_string(&cargo_toml).expect("Cannot convert back to TOML");

    fs::write(&output_filename, output)
        .unwrap_or_else(|e| panic!("Cannot write to {}: {}", output_filename.display(), e));
}

type Other = BTreeMap<String, Value>;

fn modify<F, T>(cargo_toml: Value, f: F) -> Value
where
    F: FnOnce(T) -> T,
    T: serde::Serialize + for<'de> serde::Deserialize<'de>,
{
    let cargo_toml = cargo_toml.try_into().unwrap();

    let cargo_toml = f(cargo_toml);

    Value::try_from(cargo_toml).unwrap()
}

fn ensure_string_in_vec(values: &mut Vec<String>, val: &str) {
    if !values.iter().any(|f| f == val) {
        values.push(val.into());
    }
}

fn set_edition(cargo_toml: Value, edition: &str) -> Value {
    #[derive(Debug, Serialize, Deserialize)]
    #[serde(rename_all = "kebab-case")]
    struct CargoToml {
        #[serde(default)]
        cargo_features: Vec<String>,
        package: Package,
        #[serde(flatten)]
        other: Other,
    }

    #[derive(Debug, Serialize, Deserialize)]
    #[serde(rename_all = "kebab-case")]
    struct Package {
        #[serde(default)]
        edition: String,
        #[serde(flatten)]
        other: Other,
    }

    modify(cargo_toml, |mut cargo_toml: CargoToml| {
        ensure_string_in_vec(&mut cargo_toml.cargo_features, "edition");
        cargo_toml.package.edition = edition.into();
        cargo_toml
    })
}

fn remove_dependencies(cargo_toml: Value) -> Value {
    #[derive(Debug, Serialize, Deserialize)]
    #[serde(rename_all = "kebab-case")]
    struct CargoToml {
        dependencies: BTreeMap<String, Value>,
        #[serde(flatten)]
        other: Other,
    }

    modify(cargo_toml, |mut cargo_toml: CargoToml| {
        cargo_toml.dependencies.clear();
        cargo_toml
    })
}

fn set_crate_type(cargo_toml: Value, crate_type: &str) -> Value {
    #[derive(Debug, Serialize, Deserialize)]
    #[serde(rename_all = "kebab-case")]
    struct CargoToml {
        #[serde(default)]
        lib: Lib,
        #[serde(flatten)]
        other: Other,
    }

    #[derive(Debug, Default, Serialize, Deserialize)]
    #[serde(rename_all = "kebab-case")]
    struct Lib {
        #[serde(default)]
        crate_type: Vec<String>,
        #[serde(flatten)]
        other: Other,
    }

    modify(cargo_toml, |mut cargo_toml: CargoToml| {
        ensure_string_in_vec(&mut cargo_toml.lib.crate_type, crate_type);
        cargo_toml
    })
}

fn set_release_lto(cargo_toml: Value, lto: bool) -> Value {
    #[derive(Debug, Serialize, Deserialize)]
    #[serde(rename_all = "kebab-case")]
    struct CargoToml {
        #[serde(default)]
        profile: Profiles,
        #[serde(flatten)]
        other: Other,
    }

    #[derive(Debug, Default, Serialize, Deserialize)]
    #[serde(rename_all = "kebab-case")]
    struct Profiles {
        #[serde(default)]
        release: Profile,
        #[serde(flatten)]
        other: Other,
    }

    #[derive(Debug, Default, Serialize, Deserialize)]
    #[serde(rename_all = "kebab-case")]
    struct Profile {
        #[serde(default)]
        lto: bool,
        #[serde(flatten)]
        other: Other,
    }

    modify(cargo_toml, |mut cargo_toml: CargoToml| {
        cargo_toml.profile.release.lto = lto;
        cargo_toml
    })
}
<|endoftext|>


<commit_before>use serde::Deserialize;
use serde_json::from_reader;
use std::f32::consts;
use std::fs::File;
use std::ops::{Add, Div, Mul, Sub};
use std::path::Path;

use linear::{BaseFloat, Unit, UnitQuaternion, Vector2, Vector3, Vector4};
use resource::{Load, LoadError, ResCache};

/// Time used as sampling type in splines.
pub type Time = f32;

/// A spline control point.
///
/// This type associates a value at a given time. It also contains an interpolation object used to
/// determine how to interpolate values on the segment defined by this key and the next one.
#[derive(Copy, Clone, Debug, Deserialize, Serialize)]
pub struct Key<T> {
  /// Time at which the `Key` should be reached.
  pub t: Time,
  /// Actual value.
  pub value: T,
  /// Interpolation mode.
  #[serde(default)]
  pub interpolation: Interpolation
}

impl<T> Key<T> {
  /// Create a new key.
  pub fn new(t: Time, value: T, interpolation: Interpolation) -> Self {
    Key {
      t: t,
      value: value,
      interpolation: interpolation
    }
  }
}

/// Interpolation mode.
#[derive(Copy, Clone, Debug, Deserialize, Serialize)]
pub enum Interpolation {
  /// Hold a `Key` until the time passes the normalized step threshold, in which case the next
  /// key is used.
  ///
  /// *Note: if you set the threshold to `0.5`, the first key will be used until the time is half
  /// between the two keys; the second key will be in used afterwards. If you set it to `1.0`, the
  /// first key will be kept until the next key.*
  #[serde(rename = "step")]
  Step(f32),
  /// Linear interpolation between a key and the next one.
  #[serde(rename = "linear")]
  Linear,
  /// Cosine interpolation between a key and the next one.
  #[serde(rename = "cosine")]
  Cosine,
  /// Catmull-Rom interpolation.
  #[serde(rename = "catmull_rom")]
  CatmullRom
}

impl Default for Interpolation {
  /// `Interpolation::Linear` is the default.
  fn default() -> Self {
    Interpolation::Linear
  }
}

/// Spline curve used to provide interpolation between control points (keys).
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Spline<T> {
  keys: Vec<Key<T>>,
}

impl<T> Spline<T> {
  /// Create a new spline out of keys. The keys don’t have to be sorted because they’re sorted by
  /// this function.
  pub fn from_keys(mut keys: Vec<Key<T>>) -> Self {
    keys.sort_by(|k0, k1| k0.t.partial_cmp(&k1.t).unwrap());

    Spline {
      keys: keys
    }
  }

  /// Sample a spline at a given time.
  ///
  /// # Return
  ///
  /// `None` if you try to sample a value at a time that has no key associated with. That can also
  /// happen if you try to sample between two keys with a specific interpolation mode that make the
  /// sampling impossible. For instance, `Interpolate::CatmullRom` requires *four* keys. If you’re
  /// near the beginning of the spline or its end, ensure you have enough keys around to make the
  /// sampling.
  pub fn sample(&self, t: Time) -> Option<T> where T: Interpolate {
    let keys = &self.keys;
    let i = search_lower_cp(keys, t);

    let i = match i {
      Some(i) => i,
      None => return None
    };

    let cp0 = &keys[i];

    match cp0.interpolation {
      Interpolation::Step(threshold) => {
        let cp1 = &keys[i+1];
        let nt = normalize_time(t, cp0, cp1);
        Some(if nt < threshold { cp0.value } else { cp1.value })
      },
      Interpolation::Linear => {
        let cp1 = &keys[i+1];
        let nt = normalize_time(t, cp0, cp1);

        Some(Interpolate::lerp(cp0.value, cp1.value, nt))
      },
      Interpolation::Cosine => {
        let cp1 = &keys[i+1];
        let nt = normalize_time(t, cp0, cp1);
        let cos_nt = (1. - f32::cos(nt * consts::PI)) * 0.5;

        Some(Interpolate::lerp(cp0.value, cp1.value, cos_nt))
      },
      Interpolation::CatmullRom => {
        // We need at least four points for Catmull Rom; ensure we have them, otherwise, return
        // None.
        if i == 0 || i >= keys.len() - 2 {
          None
        } else {
          let cp1 = &keys[i+1];
          let cpm0 = &keys[i-1];
          let cpm1 = &keys[i+2];
          let nt = normalize_time(t, cp0, cp1);

          Some(Interpolate::cubic_hermite((cpm0.value, cpm0.t), (cp0.value, cp0.t), (cp1.value, cp1.t), (cpm1.value, cpm1.t), nt))
        }
      }
    }
  }

  /// Sample a spline at a given time with clamping.
  ///
  /// # Return
  ///
  /// If you sample before the first key or after the last one,
  /// return the first key or the last one, respectively.
  ///
  /// # Panic
  ///
  /// This function panics if you have no key.
  pub fn clamped_sample(&self, t: Time) -> T where T: Interpolate {
    let first = self.keys.first().unwrap();
    let last = self.keys.last().unwrap();

    if t <= first.t {
      return first.value;
    } else if t >= last.t {
      return last.value;
    }

    self.sample(t).unwrap()
  }
}

impl<T> Load for Spline<T> where T: SplineDeserializerAdapter {
  type Args = ();

  const TY_STR: &'static str = "splines";

  fn load<P>(path: P, _: &mut ResCache, _: Self::Args) -> Result<Self, LoadError> where P: AsRef<Path> {
    let path = path.as_ref();

    info!("loading spline: {:?}", path);

    let file = File::open(path).map_err(|e| LoadError::FileNotFound(path.to_path_buf(), format!("{:?}", e)))?;
    let keys: Vec<Key<T::Deserialized>> = from_reader(file).map_err(|e| LoadError::ParseFailed(format!("{:?}", e)))?;

    Ok(Spline::from_keys(keys.into_iter().map(|key|
      Key::new(key.t, T::from_deserialized(key.value), key.interpolation)
    ).collect()))
  }
}

/// Spline deserializer adapter used to deserialize splines which keys’ values types don’t directly
/// implement deserialization.
pub trait SplineDeserializerAdapter {
  type Deserialized: Deserialize;

  fn from_deserialized(de: Self::Deserialized) -> Self;
}

impl SplineDeserializerAdapter for f32 {
  type Deserialized = Self;

  fn from_deserialized(de: Self::Deserialized) -> Self {
    de
  }
}

impl<T> SplineDeserializerAdapter for Vector2<T> where T: Clone + Deserialize {
  type Deserialized = [T; 2];

  fn from_deserialized(de: Self::Deserialized) -> Self {
    (&de).into()
  }
}

impl<T> SplineDeserializerAdapter for Vector3<T> where T: Clone + Deserialize {
  type Deserialized = [T; 3];

  fn from_deserialized(de: Self::Deserialized) -> Self {
    (&de).into()
  }
}

impl<T> SplineDeserializerAdapter for Vector4<T> where T: Clone + Deserialize {
  type Deserialized = [T; 4];

  fn from_deserialized(de: Self::Deserialized) -> Self {
    (&de).into()
  }
}

impl<T> SplineDeserializerAdapter for UnitQuaternion<T> where T: BaseFloat + Deserialize {
  type Deserialized = [T; 4];

  fn from_deserialized(de: Self::Deserialized) -> Self {
    Unit::new((&de).into())
  }
}

/// Iterator over spline keys.
pub struct SplineIterator<'a, T> where T: 'a {
  anim_param: &'a Spline<T>,
  i: usize
}

impl<'a, T> Iterator for SplineIterator<'a, T> {
  type Item = &'a Key<T>;

  fn next(&mut self) -> Option<Self::Item> {
    let r = self.anim_param.keys.get(self.i);

    if let Some(_) = r {
      self.i += 1;
    }

    r
  }
}

impl<'a, T> IntoIterator for &'a Spline<T> {
  type Item = &'a Key<T>;
  type IntoIter = SplineIterator<'a, T>;

  fn into_iter(self) -> Self::IntoIter {
    SplineIterator {
      anim_param: self,
      i: 0
    }
  }
}

/// Keys that can be interpolated between. Implementing this trait is required to perform sampling
/// on splines.
pub trait Interpolate: Copy {
  /// Linear interpolation.
  fn lerp(a: Self, b: Self, t: Time) -> Self;
  /// Cubic hermite interpolation.
  ///
  /// Default to `Self::lerp`.
  fn cubic_hermite(_: (Self, Time), a: (Self, Time), b: (Self, Time), _: (Self, Time), t: Time) -> Self {
    Self::lerp(a.0, b.0, t)
  }
}

impl Interpolate for f32 {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for Vector2<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for Vector3<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for Vector4<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for UnitQuaternion<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    a * UnitQuaternion::new(&(UnitQuaternion::new(&a.quaternion().conjugate()) * b).quaternion().powf(t))
  }
}

// Default implementation of Interpolate::lerp.
pub fn lerp<T>(a: T, b: T, t: Time) -> T where T: Add<Output = T> + Mul<Time, Output = T> {
  a * (1. - t) + b * t
}

// Default implementation of Interpolate::cubic_hermit.
pub fn cubic_hermite<T>(x: (T, Time), a: (T, Time), b: (T, Time), y: (T, Time), t: Time) -> T
    where T: Copy + Add<Output = T> + Sub<Output = T> + Mul<Time, Output = T> + Div<Time, Output = T> {
  // time stuff
  let t2 = t * t;
  let t3 = t2 * t;
  let two_t3 = 2. * t3;
  let three_t2 = 3. * t2;

  // tangents
  let m0 = (b.0 - x.0) / (b.1 - x.1);
	let m1 = (y.0 - a.0) / (y.1 - a.1);

  a.0 * (two_t3 - three_t2 + 1.) + m0 * (t3 - 2. * t2 + t) + b.0 * (-two_t3 + three_t2) + m1 * (t3 - t2)
}

// Normalize a time ([0;1]) given two control points.
pub fn normalize_time<T>(t: Time, cp: &Key<T>, cp1: &Key<T>) -> Time {
  (t - cp.t) / (cp1.t - cp.t)
}

// Find the lower control point corresponding to a given time.
fn search_lower_cp<T>(cps: &[Key<T>], t: Time) -> Option<usize> {
  let mut i = 0;
  let len = cps.len();

  if len < 2 {
    return None;
  }

  loop {
    let cp = &cps[i];
    let cp1 = &cps[i+1];

    if t >= cp1.t {
      if i >= len - 2 {
        return None;
      }

      i += 1;
    } else if t < cp.t {
      if i == 0 {
        return None;
      }

      i -= 1;
    } else {
      break; // found
    }
  }

  Some(i)
}
<commit_msg>impl SplineDeserializerAdapter for Scale.<commit_after>use serde::Deserialize;
use serde_json::from_reader;
use std::f32::consts;
use std::fs::File;
use std::ops::{Add, Div, Mul, Sub};
use std::path::Path;

use linear::{BaseFloat, Scale, Unit, UnitQuaternion, Vector2, Vector3, Vector4};
use resource::{Load, LoadError, ResCache};

/// Time used as sampling type in splines.
pub type Time = f32;

/// A spline control point.
///
/// This type associates a value at a given time. It also contains an interpolation object used to
/// determine how to interpolate values on the segment defined by this key and the next one.
#[derive(Copy, Clone, Debug, Deserialize, Serialize)]
pub struct Key<T> {
  /// Time at which the `Key` should be reached.
  pub t: Time,
  /// Actual value.
  pub value: T,
  /// Interpolation mode.
  #[serde(default)]
  pub interpolation: Interpolation
}

impl<T> Key<T> {
  /// Create a new key.
  pub fn new(t: Time, value: T, interpolation: Interpolation) -> Self {
    Key {
      t: t,
      value: value,
      interpolation: interpolation
    }
  }
}

/// Interpolation mode.
#[derive(Copy, Clone, Debug, Deserialize, Serialize)]
pub enum Interpolation {
  /// Hold a `Key` until the time passes the normalized step threshold, in which case the next
  /// key is used.
  ///
  /// *Note: if you set the threshold to `0.5`, the first key will be used until the time is half
  /// between the two keys; the second key will be in used afterwards. If you set it to `1.0`, the
  /// first key will be kept until the next key.*
  #[serde(rename = "step")]
  Step(f32),
  /// Linear interpolation between a key and the next one.
  #[serde(rename = "linear")]
  Linear,
  /// Cosine interpolation between a key and the next one.
  #[serde(rename = "cosine")]
  Cosine,
  /// Catmull-Rom interpolation.
  #[serde(rename = "catmull_rom")]
  CatmullRom
}

impl Default for Interpolation {
  /// `Interpolation::Linear` is the default.
  fn default() -> Self {
    Interpolation::Linear
  }
}

/// Spline curve used to provide interpolation between control points (keys).
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Spline<T> {
  keys: Vec<Key<T>>,
}

impl<T> Spline<T> {
  /// Create a new spline out of keys. The keys don’t have to be sorted because they’re sorted by
  /// this function.
  pub fn from_keys(mut keys: Vec<Key<T>>) -> Self {
    keys.sort_by(|k0, k1| k0.t.partial_cmp(&k1.t).unwrap());

    Spline {
      keys: keys
    }
  }

  /// Sample a spline at a given time.
  ///
  /// # Return
  ///
  /// `None` if you try to sample a value at a time that has no key associated with. That can also
  /// happen if you try to sample between two keys with a specific interpolation mode that make the
  /// sampling impossible. For instance, `Interpolate::CatmullRom` requires *four* keys. If you’re
  /// near the beginning of the spline or its end, ensure you have enough keys around to make the
  /// sampling.
  pub fn sample(&self, t: Time) -> Option<T> where T: Interpolate {
    let keys = &self.keys;
    let i = search_lower_cp(keys, t);

    let i = match i {
      Some(i) => i,
      None => return None
    };

    let cp0 = &keys[i];

    match cp0.interpolation {
      Interpolation::Step(threshold) => {
        let cp1 = &keys[i+1];
        let nt = normalize_time(t, cp0, cp1);
        Some(if nt < threshold { cp0.value } else { cp1.value })
      },
      Interpolation::Linear => {
        let cp1 = &keys[i+1];
        let nt = normalize_time(t, cp0, cp1);

        Some(Interpolate::lerp(cp0.value, cp1.value, nt))
      },
      Interpolation::Cosine => {
        let cp1 = &keys[i+1];
        let nt = normalize_time(t, cp0, cp1);
        let cos_nt = (1. - f32::cos(nt * consts::PI)) * 0.5;

        Some(Interpolate::lerp(cp0.value, cp1.value, cos_nt))
      },
      Interpolation::CatmullRom => {
        // We need at least four points for Catmull Rom; ensure we have them, otherwise, return
        // None.
        if i == 0 || i >= keys.len() - 2 {
          None
        } else {
          let cp1 = &keys[i+1];
          let cpm0 = &keys[i-1];
          let cpm1 = &keys[i+2];
          let nt = normalize_time(t, cp0, cp1);

          Some(Interpolate::cubic_hermite((cpm0.value, cpm0.t), (cp0.value, cp0.t), (cp1.value, cp1.t), (cpm1.value, cpm1.t), nt))
        }
      }
    }
  }

  /// Sample a spline at a given time with clamping.
  ///
  /// # Return
  ///
  /// If you sample before the first key or after the last one,
  /// return the first key or the last one, respectively.
  ///
  /// # Panic
  ///
  /// This function panics if you have no key.
  pub fn clamped_sample(&self, t: Time) -> T where T: Interpolate {
    let first = self.keys.first().unwrap();
    let last = self.keys.last().unwrap();

    if t <= first.t {
      return first.value;
    } else if t >= last.t {
      return last.value;
    }

    self.sample(t).unwrap()
  }
}

impl<T> Load for Spline<T> where T: SplineDeserializerAdapter {
  type Args = ();

  const TY_STR: &'static str = "splines";

  fn load<P>(path: P, _: &mut ResCache, _: Self::Args) -> Result<Self, LoadError> where P: AsRef<Path> {
    let path = path.as_ref();

    info!("loading spline: {:?}", path);

    let file = File::open(path).map_err(|e| LoadError::FileNotFound(path.to_path_buf(), format!("{:?}", e)))?;
    let keys: Vec<Key<T::Deserialized>> = from_reader(file).map_err(|e| LoadError::ParseFailed(format!("{:?}", e)))?;

    Ok(Spline::from_keys(keys.into_iter().map(|key|
      Key::new(key.t, T::from_deserialized(key.value), key.interpolation)
    ).collect()))
  }
}

/// Spline deserializer adapter used to deserialize splines which keys’ values types don’t directly
/// implement deserialization.
pub trait SplineDeserializerAdapter {
  type Deserialized: Deserialize;

  fn from_deserialized(de: Self::Deserialized) -> Self;
}

impl SplineDeserializerAdapter for f32 {
  type Deserialized = Self;

  fn from_deserialized(de: Self::Deserialized) -> Self {
    de
  }
}

impl<T> SplineDeserializerAdapter for Vector2<T> where T: Clone + Deserialize {
  type Deserialized = [T; 2];

  fn from_deserialized(de: Self::Deserialized) -> Self {
    (&de).into()
  }
}

impl<T> SplineDeserializerAdapter for Vector3<T> where T: Clone + Deserialize {
  type Deserialized = [T; 3];

  fn from_deserialized(de: Self::Deserialized) -> Self {
    (&de).into()
  }
}

impl<T> SplineDeserializerAdapter for Vector4<T> where T: Clone + Deserialize {
  type Deserialized = [T; 4];

  fn from_deserialized(de: Self::Deserialized) -> Self {
    (&de).into()
  }
}

impl<T> SplineDeserializerAdapter for UnitQuaternion<T> where T: BaseFloat + Deserialize {
  type Deserialized = [T; 4];

  fn from_deserialized(de: Self::Deserialized) -> Self {
    Unit::new((&de).into())
  }
}

impl SplineDeserializerAdapter for Scale {
  type Deserialized = [f32; 3];

  fn from_deserialized(de: Self::Deserialized) -> Self {
    Scale::from(&de)
  }
}

/// Iterator over spline keys.
pub struct SplineIterator<'a, T> where T: 'a {
  anim_param: &'a Spline<T>,
  i: usize
}

impl<'a, T> Iterator for SplineIterator<'a, T> {
  type Item = &'a Key<T>;

  fn next(&mut self) -> Option<Self::Item> {
    let r = self.anim_param.keys.get(self.i);

    if let Some(_) = r {
      self.i += 1;
    }

    r
  }
}

impl<'a, T> IntoIterator for &'a Spline<T> {
  type Item = &'a Key<T>;
  type IntoIter = SplineIterator<'a, T>;

  fn into_iter(self) -> Self::IntoIter {
    SplineIterator {
      anim_param: self,
      i: 0
    }
  }
}

/// Keys that can be interpolated between. Implementing this trait is required to perform sampling
/// on splines.
pub trait Interpolate: Copy {
  /// Linear interpolation.
  fn lerp(a: Self, b: Self, t: Time) -> Self;
  /// Cubic hermite interpolation.
  ///
  /// Default to `Self::lerp`.
  fn cubic_hermite(_: (Self, Time), a: (Self, Time), b: (Self, Time), _: (Self, Time), t: Time) -> Self {
    Self::lerp(a.0, b.0, t)
  }
}

impl Interpolate for f32 {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for Vector2<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for Vector3<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for Vector4<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for UnitQuaternion<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    a * UnitQuaternion::new(&(UnitQuaternion::new(&a.quaternion().conjugate()) * b).quaternion().powf(t))
  }
}

// Default implementation of Interpolate::lerp.
pub fn lerp<T>(a: T, b: T, t: Time) -> T where T: Add<Output = T> + Mul<Time, Output = T> {
  a * (1. - t) + b * t
}

// Default implementation of Interpolate::cubic_hermit.
pub fn cubic_hermite<T>(x: (T, Time), a: (T, Time), b: (T, Time), y: (T, Time), t: Time) -> T
    where T: Copy + Add<Output = T> + Sub<Output = T> + Mul<Time, Output = T> + Div<Time, Output = T> {
  // time stuff
  let t2 = t * t;
  let t3 = t2 * t;
  let two_t3 = 2. * t3;
  let three_t2 = 3. * t2;

  // tangents
  let m0 = (b.0 - x.0) / (b.1 - x.1);
	let m1 = (y.0 - a.0) / (y.1 - a.1);

  a.0 * (two_t3 - three_t2 + 1.) + m0 * (t3 - 2. * t2 + t) + b.0 * (-two_t3 + three_t2) + m1 * (t3 - t2)
}

// Normalize a time ([0;1]) given two control points.
pub fn normalize_time<T>(t: Time, cp: &Key<T>, cp1: &Key<T>) -> Time {
  (t - cp.t) / (cp1.t - cp.t)
}

// Find the lower control point corresponding to a given time.
fn search_lower_cp<T>(cps: &[Key<T>], t: Time) -> Option<usize> {
  let mut i = 0;
  let len = cps.len();

  if len < 2 {
    return None;
  }

  loop {
    let cp = &cps[i];
    let cp1 = &cps[i+1];

    if t >= cp1.t {
      if i >= len - 2 {
        return None;
      }

      i += 1;
    } else if t < cp.t {
      if i == 0 {
        return None;
      }

      i -= 1;
    } else {
      break; // found
    }
  }

  Some(i)
}
<|endoftext|>


<commit_before>//! TODO kb move this into the complete_unqualified_path when starts to work properly

use assists::utils::{insert_use, mod_path_to_ast, ImportScope, MergeBehaviour};
use hir::Query;
use itertools::Itertools;
use syntax::{algo, AstNode};
use text_edit::TextEdit;

use crate::{context::CompletionContext, item::CompletionKind, CompletionItem, CompletionItemKind};

use super::Completions;

pub(crate) fn complete_magic(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
    if !(ctx.is_trivial_path || ctx.is_pat_binding_or_const) {
        return None;
    }
    let current_module = ctx.scope.module()?;
    let anchor = ctx.name_ref_syntax.as_ref()?;
    let import_scope = ImportScope::find_insert_use_container(anchor.syntax(), &ctx.sema)?;

    // TODO kb consider heuristics, such as "don't show `hash_map` import if `HashMap` is the import for completion"
    // TODO kb module functions are not completed, consider `std::io::stdin` one
    let potential_import_name = ctx.token.to_string();

    let possible_imports = ctx
        .krate?
        // TODO kb use imports_locator instead?
        .query_external_importables(ctx.db, Query::new(&potential_import_name).limit(40))
        .unique()
        .filter_map(|import_candidate| match import_candidate {
            either::Either::Left(module_def) => current_module.find_use_path(ctx.db, module_def),
            either::Either::Right(macro_def) => current_module.find_use_path(ctx.db, macro_def),
        })
        .filter_map(|mod_path| {
            let mut builder = TextEdit::builder();

            let correct_qualifier = mod_path.segments.last()?.to_string();
            builder.replace(anchor.syntax().text_range(), correct_qualifier);

            // TODO kb: assists already have the merge behaviour setting, need to unite both
            let rewriter =
                insert_use(&import_scope, mod_path_to_ast(&mod_path), Some(MergeBehaviour::Full));
            let old_ast = rewriter.rewrite_root()?;
            algo::diff(&old_ast, &rewriter.rewrite(&old_ast)).into_text_edit(&mut builder);

            let completion_item: CompletionItem = CompletionItem::new(
                CompletionKind::Magic,
                ctx.source_range(),
                mod_path.to_string(),
            )
            .kind(CompletionItemKind::Struct)
            .text_edit(builder.finish())
            .into();
            Some(completion_item)
        });
    acc.add_all(possible_imports);

    Some(())
}

#[cfg(test)]
mod tests {
    use expect_test::{expect, Expect};

    use crate::{
        item::CompletionKind,
        test_utils::{check_edit, completion_list},
    };

    fn check(ra_fixture: &str, expect: Expect) {
        let actual = completion_list(ra_fixture, CompletionKind::Magic);
        expect.assert_eq(&actual)
    }

    #[test]
    fn function_magic_completion() {
        check(
            r#"
//- /lib.rs crate:dep
pub mod io {
    pub fn stdin() {}
};

//- /main.rs crate:main deps:dep
fn main() {
    stdi<|>
}
"#,
            expect![[r#"
                st dep::io::stdin
            "#]],
        );

        check_edit(
            "dep::io::stdin",
            r#"
//- /lib.rs crate:dep
pub mod io {
    pub fn stdin() {}
};

//- /main.rs crate:main deps:dep
fn main() {
    stdi<|>
}
"#,
            r#"
use dep::io::stdin;

fn main() {
    stdin
}
"#,
        );
    }

    #[test]
    fn case_insensitive_magic_completion_works() {
        check(
            r#"
//- /lib.rs crate:dep
pub struct TestStruct;

//- /main.rs crate:main deps:dep
fn main() {
    teru<|>
}
"#,
            expect![[r#"
                st dep::TestStruct
            "#]],
        );

        check_edit(
            "dep::TestStruct",
            r#"
//- /lib.rs crate:dep
pub struct TestStruct;

//- /main.rs crate:main deps:dep
fn main() {
    teru<|>
}
"#,
            r#"
use dep::TestStruct;

fn main() {
    TestStruct
}
"#,
        );
    }
}
<commit_msg>Tidy up the tests<commit_after>//! TODO kb move this into the complete_unqualified_path when starts to work properly

use assists::utils::{insert_use, mod_path_to_ast, ImportScope, MergeBehaviour};
use hir::Query;
use itertools::Itertools;
use syntax::{algo, AstNode};
use text_edit::TextEdit;

use crate::{context::CompletionContext, item::CompletionKind, CompletionItem, CompletionItemKind};

use super::Completions;

// TODO kb when typing, completes partial results, need to rerun manually to see the proper ones
pub(crate) fn complete_magic(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
    if !(ctx.is_trivial_path || ctx.is_pat_binding_or_const) {
        return None;
    }
    let current_module = ctx.scope.module()?;
    let anchor = ctx.name_ref_syntax.as_ref()?;
    let import_scope = ImportScope::find_insert_use_container(anchor.syntax(), &ctx.sema)?;

    // TODO kb consider heuristics, such as "don't show `hash_map` import if `HashMap` is the import for completion"
    // also apply completion ordering
    let potential_import_name = ctx.token.to_string();

    let possible_imports = ctx
        .krate?
        // TODO kb use imports_locator instead?
        .query_external_importables(ctx.db, Query::new(&potential_import_name).limit(40))
        .unique()
        .filter_map(|import_candidate| match import_candidate {
            either::Either::Left(module_def) => current_module.find_use_path(ctx.db, module_def),
            either::Either::Right(macro_def) => current_module.find_use_path(ctx.db, macro_def),
        })
        .filter_map(|mod_path| {
            let mut builder = TextEdit::builder();

            let correct_qualifier = mod_path.segments.last()?.to_string();
            builder.replace(anchor.syntax().text_range(), correct_qualifier);

            // TODO kb: assists already have the merge behaviour setting, need to unite both
            // also consider a settings toggle for this particular feature?
            let rewriter =
                insert_use(&import_scope, mod_path_to_ast(&mod_path), Some(MergeBehaviour::Full));
            let old_ast = rewriter.rewrite_root()?;
            algo::diff(&old_ast, &rewriter.rewrite(&old_ast)).into_text_edit(&mut builder);

            let completion_item: CompletionItem = CompletionItem::new(
                CompletionKind::Magic,
                ctx.source_range(),
                mod_path.to_string(),
            )
            .kind(CompletionItemKind::Struct)
            .text_edit(builder.finish())
            .into();
            Some(completion_item)
        });
    acc.add_all(possible_imports);

    Some(())
}

#[cfg(test)]
mod tests {
    use crate::test_utils::check_edit;

    #[test]
    fn function_magic_completion() {
        check_edit(
            "dep::io::stdin",
            r#"
//- /lib.rs crate:dep
pub mod io {
    pub fn stdin() {}
};

//- /main.rs crate:main deps:dep
fn main() {
    stdi<|>
}
"#,
            r#"
use dep::io::stdin;

fn main() {
    stdin
}
"#,
        );
    }

    #[test]
    fn case_insensitive_magic_completion_works() {
        check_edit(
            "dep::some_module::ThirdStruct",
            r#"
//- /lib.rs crate:dep
pub struct FirstStruct;
pub mod some_module {
    pub struct SecondStruct;
    pub struct ThirdStruct;
}

//- /main.rs crate:main deps:dep
use dep::{FirstStruct, some_module::SecondStruct};

fn main() {
    this<|>
}
"#,
            r#"
use dep::{FirstStruct, some_module::{SecondStruct, ThirdStruct}};

fn main() {
    ThirdStruct
}
"#,
        );
    }
}
<|endoftext|>


<commit_before>#[derive(PartialEq, Eq, Copy, Clone)]
pub enum Status {
    Startup,
    List,
    Show,
}
<commit_msg>make Status debug-able<commit_after>#[derive(Debug)]
#[derive(PartialEq, Eq, Copy, Clone)]
pub enum Status {
    Startup,
    List,
    Show,
}
<|endoftext|>


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

use exonum_merkledb::{BinaryValue, Fork, Snapshot};
use protobuf::well_known_types::Any;

use crate::{
    api::ServiceApiBuilder,
    crypto::{Hash, PublicKey},
    messages::{CallInfo, ServiceInstanceId},
};

use self::{
    error::{DeployError, ExecutionError, InitError},
    rust::RustArtifactSpec,
};

#[macro_use]
pub mod rust;
pub mod configuration_new;
pub mod dispatcher;
pub mod error;

#[derive(Debug, PartialEq, Eq)]
pub enum DeployStatus {
    DeployInProgress,
    Deployed,
}

#[derive(Debug)]
pub struct ServiceConstructor {
    pub instance_id: ServiceInstanceId,
    pub data: Any,
}

impl ServiceConstructor {
    pub fn new(instance_id: ServiceInstanceId, data: impl BinaryValue) -> Self {
        let bytes = data.into_bytes();

        Self {
            instance_id,
            data: {
                let mut data = Any::new();
                data.set_value(bytes);
                data
            },
        }
    }
}

#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub enum RuntimeIdentifier {
    Rust = 0,
    Java = 1,
}

#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct ArtifactSpec {
    runtime_id: u32,
    raw_spec: Vec<u8>,
}

impl From<RustArtifactSpec> for ArtifactSpec {
    fn from(artifact: RustArtifactSpec) -> Self {
        ArtifactSpec {
            runtime_id: RuntimeIdentifier::Rust as u32,
            raw_spec: artifact.into_bytes(),
        }
    }
}

// TODO Think about environment methods' names. [ECR-3222]

/// Service runtime environment.
/// It does not assign id to services/interfaces, ids are given to runtime from outside.
pub trait RuntimeEnvironment: Send + 'static {
    /// Start artifact deploy.
    fn start_deploy(&mut self, artifact: ArtifactSpec) -> Result<(), DeployError>;

    /// Check deployment status.
    fn check_deploy_status(
        &self,
        artifact: ArtifactSpec,
        cancel_if_not_complete: bool,
    ) -> Result<DeployStatus, DeployError>;

    /// Init artifact with given ID and constructor parameters.
    fn init_service(
        &mut self,
        ctx: &mut RuntimeContext,
        artifact: ArtifactSpec,
        constructor: &ServiceConstructor,
    ) -> Result<(), InitError>;

    /// Execute transaction.
    fn execute(
        &self,
        ctx: &mut RuntimeContext,
        dispatch: CallInfo,
        payload: &[u8],
    ) -> Result<(), ExecutionError>;

    /// Gets state hashes of the every contained service.
    fn state_hashes(&self, snapshot: &dyn Snapshot) -> Vec<(ServiceInstanceId, Vec<Hash>)>;

    /// Calls `before_commit` for all the services stored in the runtime.
    fn before_commit(&self, fork: &mut Fork);

    // TODO interface should be re-worked
    /// Calls `after_commit` for all the services stored in the runtime.
    fn after_commit(&self, fork: &Fork);

    fn services_api(&self) -> Vec<(String, ServiceApiBuilder)> {
        Vec::new()
    }
}

#[derive(Debug)]
pub struct RuntimeContext<'a> {
    fork: &'a Fork,
    author: PublicKey,
    tx_hash: Hash,
    dispatcher_actions: Vec<dispatcher::Action>,
}

impl<'a> RuntimeContext<'a> {
    pub fn new(fork: &'a Fork, &author: &PublicKey, &tx_hash: &Hash) -> Self {
        Self {
            fork,
            author,
            tx_hash,
            dispatcher_actions: Vec::new(),
        }
    }

    pub(crate) fn dispatch_action(&mut self, action: dispatcher::Action) {
        self.dispatcher_actions.push(action);
    }

    pub(crate) fn take_dispatcher_actions(&mut self) -> Vec<dispatcher::Action> {
        self.dispatcher_actions.drain(..).collect()
    }

    // TODO Implement author enum. [ECR-3222]
    fn from_fork(fork: &'a Fork) -> Self {
        Self::new(fork, &PublicKey::zero(), &Hash::zero())
    }
}

impl<T> From<T> for Box<dyn RuntimeEnvironment>
where
    T: RuntimeEnvironment,
{
    fn from(runtime: T) -> Self {
        Box::new(runtime) as Self
    }
}
<commit_msg>Use mem::swap instead of drain<commit_after>// Copyright 2019 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use exonum_merkledb::{BinaryValue, Fork, Snapshot};
use protobuf::well_known_types::Any;

use crate::{
    api::ServiceApiBuilder,
    crypto::{Hash, PublicKey},
    messages::{CallInfo, ServiceInstanceId},
};

use self::{
    error::{DeployError, ExecutionError, InitError},
    rust::RustArtifactSpec,
};

#[macro_use]
pub mod rust;
pub mod configuration_new;
pub mod dispatcher;
pub mod error;

#[derive(Debug, PartialEq, Eq)]
pub enum DeployStatus {
    DeployInProgress,
    Deployed,
}

#[derive(Debug)]
pub struct ServiceConstructor {
    pub instance_id: ServiceInstanceId,
    pub data: Any,
}

impl ServiceConstructor {
    pub fn new(instance_id: ServiceInstanceId, data: impl BinaryValue) -> Self {
        let bytes = data.into_bytes();

        Self {
            instance_id,
            data: {
                let mut data = Any::new();
                data.set_value(bytes);
                data
            },
        }
    }
}

#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub enum RuntimeIdentifier {
    Rust = 0,
    Java = 1,
}

#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct ArtifactSpec {
    runtime_id: u32,
    raw_spec: Vec<u8>,
}

impl From<RustArtifactSpec> for ArtifactSpec {
    fn from(artifact: RustArtifactSpec) -> Self {
        ArtifactSpec {
            runtime_id: RuntimeIdentifier::Rust as u32,
            raw_spec: artifact.into_bytes(),
        }
    }
}

// TODO Think about environment methods' names. [ECR-3222]

/// Service runtime environment.
/// It does not assign id to services/interfaces, ids are given to runtime from outside.
pub trait RuntimeEnvironment: Send + 'static {
    /// Start artifact deploy.
    fn start_deploy(&mut self, artifact: ArtifactSpec) -> Result<(), DeployError>;

    /// Check deployment status.
    fn check_deploy_status(
        &self,
        artifact: ArtifactSpec,
        cancel_if_not_complete: bool,
    ) -> Result<DeployStatus, DeployError>;

    /// Init artifact with given ID and constructor parameters.
    fn init_service(
        &mut self,
        ctx: &mut RuntimeContext,
        artifact: ArtifactSpec,
        constructor: &ServiceConstructor,
    ) -> Result<(), InitError>;

    /// Execute transaction.
    fn execute(
        &self,
        ctx: &mut RuntimeContext,
        dispatch: CallInfo,
        payload: &[u8],
    ) -> Result<(), ExecutionError>;

    /// Gets state hashes of the every contained service.
    fn state_hashes(&self, snapshot: &dyn Snapshot) -> Vec<(ServiceInstanceId, Vec<Hash>)>;

    /// Calls `before_commit` for all the services stored in the runtime.
    fn before_commit(&self, fork: &mut Fork);

    // TODO interface should be re-worked
    /// Calls `after_commit` for all the services stored in the runtime.
    fn after_commit(&self, fork: &Fork);

    fn services_api(&self) -> Vec<(String, ServiceApiBuilder)> {
        Vec::new()
    }
}

#[derive(Debug)]
pub struct RuntimeContext<'a> {
    fork: &'a Fork,
    author: PublicKey,
    tx_hash: Hash,
    dispatcher_actions: Vec<dispatcher::Action>,
}

impl<'a> RuntimeContext<'a> {
    pub fn new(fork: &'a Fork, &author: &PublicKey, &tx_hash: &Hash) -> Self {
        Self {
            fork,
            author,
            tx_hash,
            dispatcher_actions: Vec::new(),
        }
    }

    pub(crate) fn dispatch_action(&mut self, action: dispatcher::Action) {
        self.dispatcher_actions.push(action);
    }

    pub(crate) fn take_dispatcher_actions(&mut self) -> Vec<dispatcher::Action> {
        let mut other = Vec::new();
        std::mem::swap(&mut self.dispatcher_actions, &mut other);
        other
    }

    // TODO Implement author enum. [ECR-3222]
    fn from_fork(fork: &'a Fork) -> Self {
        Self::new(fork, &PublicKey::zero(), &Hash::zero())
    }
}

impl<T> From<T> for Box<dyn RuntimeEnvironment>
where
    T: RuntimeEnvironment,
{
    fn from(runtime: T) -> Self {
        Box::new(runtime) as Self
    }
}
<|endoftext|>


<commit_before>use serde::de::{Deserialize, Deserializer};

use types::*;

/// This object represents an incoming update.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Update {
    /// The update‘s unique identifier. Update identifiers start from a certain
    /// positive number and increase sequentially.
    pub id: Integer,
    /// Kind of the incoming update.
    pub kind: UpdateKind,
}

/// Kind of the incoming update.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum UpdateKind {
    /// New incoming message of any kind — text, photo, sticker, etc.
    Message(Message),
    /// New version of a message that is known to the bot and was edited
    EditedMessage(Message),
    /// New incoming channel post of any kind — text, photo, sticker, etc.
    ChannelPost(Message),
    /// New version of a channel post that is known to the bot and was edited
    EditedChannelPost(Message),
//    InlineQuery(InlineQuery),
//    ChosenInlineResult(ChosenInlineResult),
//    CallbackQuery(OptionCallbackQuery),
    #[doc(hidden)]
    Unknown(RawUpdate)
}

impl Deserialize for Update {
    fn deserialize<D>(deserializer: D) -> Result<Update, D::Error> where D: Deserializer {
        let raw: RawUpdate = Deserialize::deserialize(deserializer)?;
        macro_rules! maybe_field {
            ($name:ident, $variant:ident) => {{
                if let Some(val) = raw.$name {
                    return Ok(Update {
                        id: raw.update_id,
                        kind: UpdateKind::$variant(val),
                    })
                }
            }}
        }

        maybe_field!(message, Message);
        maybe_field!(edited_message, EditedMessage);
        maybe_field!(channel_post, ChannelPost);
        maybe_field!(edited_channel_post, EditedChannelPost);
//        maybe_field!(inline_query, InlineQuery);
//        maybe_field!(chosen_inline_result, ChosenInlineResult);
//        maybe_field!(callback_query, CallbackQuery);

        Ok(Update {
            id: raw.update_id,
            kind: UpdateKind::Unknown(raw),
        })
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct RawUpdate {
    /// The update‘s unique identifier. Update identifiers start from a certain
    /// positive number and increase sequentially.
    pub update_id: Integer,
    /// New incoming message of any kind — text, photo, sticker, etc.
    pub message: Option<Message>,
    /// New version of a message that is known to the bot and was edited
    pub edited_message: Option<Message>,
    /// New incoming channel post of any kind — text, photo, sticker, etc.
    pub channel_post: Option<Message>,
    /// New version of a channel post that is known to the bot and was edited
    pub edited_channel_post: Option<Message>,
//    pub inline_query: Option<InlineQuery>,
//    pub chosen_inline_result: Option<ChosenInlineResult>,
//    pub callback_query: Option<CallbackQuery>,
}
<commit_msg>docs: document RawUpdate type<commit_after>use serde::de::{Deserialize, Deserializer};

use types::*;

/// This object represents an incoming update.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Update {
    /// The update‘s unique identifier. Update identifiers start from a certain
    /// positive number and increase sequentially.
    pub id: Integer,
    /// Kind of the incoming update.
    pub kind: UpdateKind,
}

/// Kind of the incoming update.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum UpdateKind {
    /// New incoming message of any kind — text, photo, sticker, etc.
    Message(Message),
    /// New version of a message that is known to the bot and was edited
    EditedMessage(Message),
    /// New incoming channel post of any kind — text, photo, sticker, etc.
    ChannelPost(Message),
    /// New version of a channel post that is known to the bot and was edited
    EditedChannelPost(Message),
//    InlineQuery(InlineQuery),
//    ChosenInlineResult(ChosenInlineResult),
//    CallbackQuery(OptionCallbackQuery),
    #[doc(hidden)]
    Unknown(RawUpdate)
}

impl Deserialize for Update {
    fn deserialize<D>(deserializer: D) -> Result<Update, D::Error> where D: Deserializer {
        let raw: RawUpdate = Deserialize::deserialize(deserializer)?;
        macro_rules! maybe_field {
            ($name:ident, $variant:ident) => {{
                if let Some(val) = raw.$name {
                    return Ok(Update {
                        id: raw.update_id,
                        kind: UpdateKind::$variant(val),
                    })
                }
            }}
        }

        maybe_field!(message, Message);
        maybe_field!(edited_message, EditedMessage);
        maybe_field!(channel_post, ChannelPost);
        maybe_field!(edited_channel_post, EditedChannelPost);
//        maybe_field!(inline_query, InlineQuery);
//        maybe_field!(chosen_inline_result, ChosenInlineResult);
//        maybe_field!(callback_query, CallbackQuery);

        Ok(Update {
            id: raw.update_id,
            kind: UpdateKind::Unknown(raw),
        })
    }
}

/// This object represents an incoming update. Directly mapped.
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct RawUpdate {
    /// The update‘s unique identifier. Update identifiers start from a certain
    /// positive number and increase sequentially.
    pub update_id: Integer,
    /// New incoming message of any kind — text, photo, sticker, etc.
    pub message: Option<Message>,
    /// New version of a message that is known to the bot and was edited
    pub edited_message: Option<Message>,
    /// New incoming channel post of any kind — text, photo, sticker, etc.
    pub channel_post: Option<Message>,
    /// New version of a channel post that is known to the bot and was edited
    pub edited_channel_post: Option<Message>,
//    pub inline_query: Option<InlineQuery>,
//    pub chosen_inline_result: Option<ChosenInlineResult>,
//    pub callback_query: Option<CallbackQuery>,
}
<|endoftext|>


<commit_before>use base64;
use crate::buffer;
use crate::image;
use std::{fs, io};

use image_crate::ImageFormat::{JPEG as Jpeg, PNG as Png};
use std::path::Path;
use crate::{Document, Error, Gltf, Result};

/// Return type of `import`.
type Import = (Document, Vec<buffer::Data>, Vec<image::Data>);

/// Represents the set of URI schemes the importer supports.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
enum Scheme<'a> {
    /// `data:[<media type>];base64,<data>`.
    Data(Option<&'a str>, &'a str),

    /// `file:[//]<absolute file path>`.
    ///
    /// Note: The file scheme does not implement authority.
    File(&'a str),

    /// `../foo`, etc.
    Relative,

    /// Placeholder for an unsupported URI scheme identifier.
    Unsupported,
}

impl<'a> Scheme<'a> {
    fn parse<'s>(uri: &'s str) -> Scheme<'s> {
        if uri.contains(":") {
            if uri.starts_with("data:") {
                let match0 = &uri["data:".len()..].split(";base64,").nth(0);
                let match1 = &uri["data:".len()..].split(";base64,").nth(1);
                if match1.is_some() {
                    Scheme::Data(Some(match0.unwrap()), match1.unwrap())
                } else if match0.is_some() {
                    Scheme::Data(None, match0.unwrap())
                } else {
                    Scheme::Unsupported
                }
            } else if uri.starts_with("file://") {
                Scheme::File(&uri["file://".len()..])
            } else if uri.starts_with("file:") {
                Scheme::File(&uri["file:".len()..])
            } else {
                Scheme::Unsupported
            }
        } else {
            Scheme::Relative
        }
    }

    fn read(base: &Path, uri: &str) -> Result<Vec<u8>> {
        match Scheme::parse(uri) {
            Scheme::Data(_, base64) => base64::decode(&base64).map_err(Error::Base64),
            Scheme::File(path) => read_to_end(path),
            Scheme::Relative => read_to_end(base.join(uri)),
            Scheme::Unsupported => Err(Error::UnsupportedScheme),
        }
    }
}

fn read_to_end<P>(path: P) -> Result<Vec<u8>>
where P: AsRef<Path>
{
    use io::Read;
    let file = fs::File::open(path.as_ref()).map_err(Error::Io)?;
    let length = file.metadata().map(|x| x.len()).unwrap_or(0);
    let mut reader = io::BufReader::new(file);
    let mut data = Vec::with_capacity(length as usize);
    reader.read_to_end(&mut data).map_err(Error::Io)?;
    Ok(data)
}

/// Import the buffer data referenced by a glTF document.
pub fn import_buffer_data(
    document: &Document,
    base: Option<&Path>,
    mut blob: Option<Vec<u8>>,
) -> Result<Vec<buffer::Data>> {
    let mut buffers = Vec::new();
    for buffer in document.buffers() {
        let mut data = match buffer.source() {
            buffer::Source::Uri(uri) if base.is_some() => Scheme::read(base.unwrap(), uri),
            buffer::Source::Bin => blob.take().ok_or(Error::MissingBlob),
            _ => Err(Error::MissingBlob)
        }?;
        if data.len() < buffer.length() {
            return Err(
                Error::BufferLength {
                    buffer: buffer.index(),
                    expected: buffer.length(),
                    actual: data.len(),
                }
            );
        }
        while data.len() % 4 != 0 {
            data.push(0);
        }
        buffers.push(buffer::Data(data));
    }
    Ok(buffers)
}

/// Import the image data referenced by a glTF document.
pub fn import_image_data(
    document: &Document,
    base: Option<&Path>,
    buffer_data: &[buffer::Data],
) -> Result<Vec<image::Data>> {
    let mut images = Vec::new();
    for image in document.images() {
        match image.source() {
            image::Source::Uri { uri, mime_type } if base.is_some() => {
                match Scheme::parse(uri) {
                    Scheme::Data(Some(annoying_case), base64) => {
                        let format = match annoying_case.as_ref() {
                            "image/png" => Png,
                            "image/jpeg" => Jpeg,
                            _ => return Err(Error::UnsupportedImageEncoding),
                        };
                        let encoded_image = base64::decode(&base64).map_err(Error::Base64)?;
                        let decoded_image = image_crate::load_from_memory_with_format(&encoded_image, format)?;
                        images.push(image::Data::new(decoded_image));
                        continue;
                    },
                    Scheme::Unsupported => return Err(Error::UnsupportedScheme),
                    _ => {},
                }
                let encoded_image = Scheme::read(base.unwrap(), uri)?;
                let encoded_format =  match mime_type {
                    Some("image/png") => Png,
                    Some("image/jpeg") => Jpeg,
                    Some(_) => return Err(Error::UnsupportedImageEncoding),
                    None => match uri.rsplit(".").next() {
                        Some("png") => Png,
                        Some("jpg") | Some("jpeg") => Jpeg,
                        _ => return Err(Error::UnsupportedImageEncoding),
                    },
                };
                let decoded_image = image_crate::load_from_memory_with_format(&encoded_image, encoded_format)?;
                images.push(image::Data::new(decoded_image));
            },
            image::Source::View { view, mime_type } => {
                let parent_buffer_data = &buffer_data[view.buffer().index()].0;
                let begin = view.offset();
                let end = begin + view.length();
                let encoded_image = &parent_buffer_data[begin..end];
                let encoded_format = match mime_type {
                    "image/png" => Png,
                    "image/jpeg" => Jpeg,
                    _ => return Err(Error::UnsupportedImageEncoding)
                };
                let decoded_image = image_crate::load_from_memory_with_format(encoded_image, encoded_format)?;
                images.push(image::Data::new(decoded_image));
            },
            _ => Err(Error::MissingBlob)
        }
    }

    Ok(images)
}

fn import_impl(Gltf { document, blob }: Gltf, base: Option<&Path>) -> Result<Import> {
    let buffer_data = import_buffer_data(&document, base, blob)?;
    let image_data = import_image_data(&document, base, &buffer_data)?;
    let import = (document, buffer_data, image_data);
    Ok(import)
}

/// Import some glTF 2.0 from the file system.
///
/// ```
/// # fn run() -> Result<(), gltf::Error> {
/// # let path = "examples/Box.gltf";
/// # #[allow(unused)]
/// let (document, buffers, images) = gltf::import(path)?;
/// # Ok(())
/// # }
/// # fn main() {
/// #     run().expect("test failure");
/// # }
/// ```
///
/// ### Note
///
/// This function is provided as a convenience for loading glTF and associated
/// resources from the file system. It is suitable for real world use but may
/// not be suitable for all real world use cases. More complex import scenarios
/// such downloading from web URLs are not handled by this function. These
/// scenarios are delegated to the user.
///
/// You can read glTF without loading resources by constructing the [`Gltf`]
/// (standard glTF) or [`Glb`] (binary glTF) data structures explicitly.
///
/// [`Gltf`]: struct.Gltf.html
/// [`Glb`]: struct.Glb.html
pub fn import<P>(path: P) -> Result<Import>
    where P: AsRef<Path>
{
    let path = path.as_ref();
    let base = path.parent().unwrap_or(Path::new("./"));
    let file = fs::File::open(path).map_err(Error::Io)?;
    let reader = io::BufReader::new(file);
    import_impl(Gltf::from_reader(reader)?, Some(base))
}

/// Import some glTF 2.0 from a slice
///
/// ```
/// # extern crate gltf;
/// # use std::fs;
/// # use std::io::Read;
/// # fn run() -> Result<(), gltf::Error> {
/// # let path = "examples/Box.glb";
/// # let mut file = fs::File::open(path).map_err(gltf::Error::Io)?;
/// # let mut bytes = Vec::new();
/// # file.read_to_end(&mut bytes).map_err(gltf::Error::Io)?;
/// # #[allow(unused)]
/// let (document, buffers, images) = gltf::import_slice(bytes.as_slice())?;
/// # Ok(())
/// # }
/// # fn main() {
/// #     run().expect("test failure");
/// # }
/// ```
pub fn import_slice(slice: &[u8]) -> Result<Import> {
    import_impl(Gltf::from_slice(slice)?, None)
}
<commit_msg>fix match<commit_after>use base64;
use crate::buffer;
use crate::image;
use std::{fs, io};

use image_crate::ImageFormat::{JPEG as Jpeg, PNG as Png};
use std::path::Path;
use crate::{Document, Error, Gltf, Result};

/// Return type of `import`.
type Import = (Document, Vec<buffer::Data>, Vec<image::Data>);

/// Represents the set of URI schemes the importer supports.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
enum Scheme<'a> {
    /// `data:[<media type>];base64,<data>`.
    Data(Option<&'a str>, &'a str),

    /// `file:[//]<absolute file path>`.
    ///
    /// Note: The file scheme does not implement authority.
    File(&'a str),

    /// `../foo`, etc.
    Relative,

    /// Placeholder for an unsupported URI scheme identifier.
    Unsupported,
}

impl<'a> Scheme<'a> {
    fn parse<'s>(uri: &'s str) -> Scheme<'s> {
        if uri.contains(":") {
            if uri.starts_with("data:") {
                let match0 = &uri["data:".len()..].split(";base64,").nth(0);
                let match1 = &uri["data:".len()..].split(";base64,").nth(1);
                if match1.is_some() {
                    Scheme::Data(Some(match0.unwrap()), match1.unwrap())
                } else if match0.is_some() {
                    Scheme::Data(None, match0.unwrap())
                } else {
                    Scheme::Unsupported
                }
            } else if uri.starts_with("file://") {
                Scheme::File(&uri["file://".len()..])
            } else if uri.starts_with("file:") {
                Scheme::File(&uri["file:".len()..])
            } else {
                Scheme::Unsupported
            }
        } else {
            Scheme::Relative
        }
    }

    fn read(base: &Path, uri: &str) -> Result<Vec<u8>> {
        match Scheme::parse(uri) {
            Scheme::Data(_, base64) => base64::decode(&base64).map_err(Error::Base64),
            Scheme::File(path) => read_to_end(path),
            Scheme::Relative => read_to_end(base.join(uri)),
            Scheme::Unsupported => Err(Error::UnsupportedScheme),
        }
    }
}

fn read_to_end<P>(path: P) -> Result<Vec<u8>>
where P: AsRef<Path>
{
    use io::Read;
    let file = fs::File::open(path.as_ref()).map_err(Error::Io)?;
    let length = file.metadata().map(|x| x.len()).unwrap_or(0);
    let mut reader = io::BufReader::new(file);
    let mut data = Vec::with_capacity(length as usize);
    reader.read_to_end(&mut data).map_err(Error::Io)?;
    Ok(data)
}

/// Import the buffer data referenced by a glTF document.
pub fn import_buffer_data(
    document: &Document,
    base: Option<&Path>,
    mut blob: Option<Vec<u8>>,
) -> Result<Vec<buffer::Data>> {
    let mut buffers = Vec::new();
    for buffer in document.buffers() {
        let mut data = match buffer.source() {
            buffer::Source::Uri(uri) if base.is_some() => Scheme::read(base.unwrap(), uri),
            buffer::Source::Bin => blob.take().ok_or(Error::MissingBlob),
            _ => Err(Error::MissingBlob)
        }?;
        if data.len() < buffer.length() {
            return Err(
                Error::BufferLength {
                    buffer: buffer.index(),
                    expected: buffer.length(),
                    actual: data.len(),
                }
            );
        }
        while data.len() % 4 != 0 {
            data.push(0);
        }
        buffers.push(buffer::Data(data));
    }
    Ok(buffers)
}

/// Import the image data referenced by a glTF document.
pub fn import_image_data(
    document: &Document,
    base: Option<&Path>,
    buffer_data: &[buffer::Data],
) -> Result<Vec<image::Data>> {
    let mut images = Vec::new();
    for image in document.images() {
        match image.source() {
            image::Source::Uri { uri, mime_type } if base.is_some() => {
                match Scheme::parse(uri) {
                    Scheme::Data(Some(annoying_case), base64) => {
                        let format = match annoying_case.as_ref() {
                            "image/png" => Png,
                            "image/jpeg" => Jpeg,
                            _ => return Err(Error::UnsupportedImageEncoding),
                        };
                        let encoded_image = base64::decode(&base64).map_err(Error::Base64)?;
                        let decoded_image = image_crate::load_from_memory_with_format(&encoded_image, format)?;
                        images.push(image::Data::new(decoded_image));
                        continue;
                    },
                    Scheme::Unsupported => return Err(Error::UnsupportedScheme),
                    _ => {},
                }
                let encoded_image = Scheme::read(base.unwrap(), uri)?;
                let encoded_format =  match mime_type {
                    Some("image/png") => Png,
                    Some("image/jpeg") => Jpeg,
                    Some(_) => return Err(Error::UnsupportedImageEncoding),
                    None => match uri.rsplit(".").next() {
                        Some("png") => Png,
                        Some("jpg") | Some("jpeg") => Jpeg,
                        _ => return Err(Error::UnsupportedImageEncoding),
                    },
                };
                let decoded_image = image_crate::load_from_memory_with_format(&encoded_image, encoded_format)?;
                images.push(image::Data::new(decoded_image));
            },
            image::Source::View { view, mime_type } => {
                let parent_buffer_data = &buffer_data[view.buffer().index()].0;
                let begin = view.offset();
                let end = begin + view.length();
                let encoded_image = &parent_buffer_data[begin..end];
                let encoded_format = match mime_type {
                    "image/png" => Png,
                    "image/jpeg" => Jpeg,
                    _ => return Err(Error::UnsupportedImageEncoding)
                };
                let decoded_image = image_crate::load_from_memory_with_format(encoded_image, encoded_format)?;
                images.push(image::Data::new(decoded_image));
            },
            _ => return Err(Error::MissingBlob)
        }
    }

    Ok(images)
}

fn import_impl(Gltf { document, blob }: Gltf, base: Option<&Path>) -> Result<Import> {
    let buffer_data = import_buffer_data(&document, base, blob)?;
    let image_data = import_image_data(&document, base, &buffer_data)?;
    let import = (document, buffer_data, image_data);
    Ok(import)
}

/// Import some glTF 2.0 from the file system.
///
/// ```
/// # fn run() -> Result<(), gltf::Error> {
/// # let path = "examples/Box.gltf";
/// # #[allow(unused)]
/// let (document, buffers, images) = gltf::import(path)?;
/// # Ok(())
/// # }
/// # fn main() {
/// #     run().expect("test failure");
/// # }
/// ```
///
/// ### Note
///
/// This function is provided as a convenience for loading glTF and associated
/// resources from the file system. It is suitable for real world use but may
/// not be suitable for all real world use cases. More complex import scenarios
/// such downloading from web URLs are not handled by this function. These
/// scenarios are delegated to the user.
///
/// You can read glTF without loading resources by constructing the [`Gltf`]
/// (standard glTF) or [`Glb`] (binary glTF) data structures explicitly.
///
/// [`Gltf`]: struct.Gltf.html
/// [`Glb`]: struct.Glb.html
pub fn import<P>(path: P) -> Result<Import>
    where P: AsRef<Path>
{
    let path = path.as_ref();
    let base = path.parent().unwrap_or(Path::new("./"));
    let file = fs::File::open(path).map_err(Error::Io)?;
    let reader = io::BufReader::new(file);
    import_impl(Gltf::from_reader(reader)?, Some(base))
}

/// Import some glTF 2.0 from a slice
///
/// ```
/// # extern crate gltf;
/// # use std::fs;
/// # use std::io::Read;
/// # fn run() -> Result<(), gltf::Error> {
/// # let path = "examples/Box.glb";
/// # let mut file = fs::File::open(path).map_err(gltf::Error::Io)?;
/// # let mut bytes = Vec::new();
/// # file.read_to_end(&mut bytes).map_err(gltf::Error::Io)?;
/// # #[allow(unused)]
/// let (document, buffers, images) = gltf::import_slice(bytes.as_slice())?;
/// # Ok(())
/// # }
/// # fn main() {
/// #     run().expect("test failure");
/// # }
/// ```
pub fn import_slice(slice: &[u8]) -> Result<Import> {
    import_impl(Gltf::from_slice(slice)?, None)
}
<|endoftext|>


<commit_before>use crate::cell::UnsafeCell;
use crate::collections::VecDeque;
use crate::ffi::c_void;
use crate::ops::{Deref, DerefMut, Drop};
use crate::ptr;
use crate::sync::atomic::{spin_loop_hint, AtomicUsize, Ordering};
use crate::sys::hermit::abi;

/// This type provides a lock based on busy waiting to realize mutual exclusion
///
/// # Description
///
/// This structure behaves a lot like a common mutex. There are some differences:
///
/// - By using busy waiting, it can be used outside the runtime.
/// - It is a so called ticket lock (https://en.wikipedia.org/wiki/Ticket_lock)
///   and completly fair.
#[cfg_attr(target_arch = "x86_64", repr(align(128)))]
#[cfg_attr(not(target_arch = "x86_64"), repr(align(64)))]
struct Spinlock<T: ?Sized> {
    queue: AtomicUsize,
    dequeue: AtomicUsize,
    data: UnsafeCell<T>,
}

unsafe impl<T: ?Sized + Send> Sync for Spinlock<T> {}
unsafe impl<T: ?Sized + Send> Send for Spinlock<T> {}

/// A guard to which the protected data can be accessed
///
/// When the guard falls out of scope it will release the lock.
struct SpinlockGuard<'a, T: ?Sized + 'a> {
    dequeue: &'a AtomicUsize,
    data: &'a mut T,
}

impl<T> Spinlock<T> {
    pub const fn new(user_data: T) -> Spinlock<T> {
        SpinlockGuard { dequeue: &self.dequeue, data: &mut *self.data.get() }
    }

    #[inline]
    fn obtain_lock(&self) {
        let ticket = self.queue.fetch_add(1, Ordering::SeqCst) + 1;
        while self.dequeue.load(Ordering::SeqCst) != ticket {
            spin_loop_hint();
        }
    }

    #[inline]
    pub unsafe fn lock(&self) -> SpinlockGuard<'_, T> {
        self.obtain_lock();
        SpinlockGuard { dequeue: &self.dequeue, data: &mut *self.data.get() }
    }
}

impl<T: ?Sized + Default> Default for Spinlock<T> {
    fn default() -> Spinlock<T> {
        Spinlock::new(Default::default())
    }
}

impl<'a, T: ?Sized> Deref for SpinlockGuard<'a, T> {
    type Target = T;
    fn deref(&self) -> &T {
        &*self.data
    }
}

impl<'a, T: ?Sized> DerefMut for SpinlockGuard<'a, T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut *self.data
    }
}

impl<'a, T: ?Sized> Drop for SpinlockGuard<'a, T> {
    /// The dropping of the SpinlockGuard will release the lock it was created from.
    fn drop(&mut self) {
        self.dequeue.fetch_add(1, Ordering::SeqCst);
    }
}

/// Realize a priority queue for tasks
struct PriorityQueue {
    queues: [Option<VecDeque<abi::Tid>>; abi::NO_PRIORITIES],
    prio_bitmap: u64,
}

impl PriorityQueue {
    pub const fn new() -> PriorityQueue {
        PriorityQueue {
            queues: [
                None, None, None, None, None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, None, None, None, None, None, None, None, None, None, None,
                None, None, None,
            ],
            prio_bitmap: 0,
        }
    }

    /// Add a task handle by its priority to the queue
    pub fn push(&mut self, prio: abi::Priority, id: abi::Tid) {
        let i: usize = prio.into().into();
        self.prio_bitmap |= (1 << i) as u64;
        if let Some(queue) = &mut self.queues[i] {
            queue.push_back(id);
        } else {
            let mut queue = VecDeque::new();
            queue.push_back(id);
            self.queues[i] = Some(queue);
        }
    }

    fn pop_from_queue(&mut self, queue_index: usize) -> Option<abi::Tid> {
        if let Some(queue) = &mut self.queues[queue_index] {
            let id = queue.pop_front();

            if queue.is_empty() {
                self.prio_bitmap &= !(1 << queue_index as u64);
            }

            id
        } else {
            None
        }
    }

    /// Pop the task handle with the highest priority from the queue
    pub fn pop(&mut self) -> Option<abi::Tid> {
        for i in 0..abi::NO_PRIORITIES {
            if self.prio_bitmap & (1 << i) != 0 {
                return self.pop_from_queue(i);
            }
        }

        None
    }
}

struct MutexInner {
    locked: bool,
    blocked_task: PriorityQueue,
}

impl MutexInner {
    pub const fn new() -> MutexInner {
        MutexInner { locked: false, blocked_task: PriorityQueue::new() }
    }
}

pub struct Mutex {
    inner: Spinlock<MutexInner>,
}

unsafe impl Send for Mutex {}
unsafe impl Sync for Mutex {}

impl Mutex {
    pub const fn new() -> Mutex {
        Mutex { inner: Spinlock::new(MutexInner::new()) }
    }

    #[inline]
    pub unsafe fn init(&mut self) {
        self.inner = Spinlock::new(MutexInner::new());
    }

    #[inline]
    pub unsafe fn lock(&self) {
        loop {
            let mut guard = self.inner.lock();
            if guard.locked == false {
                guard.locked = true;
                return;
            } else {
                let prio = abi::get_priority();
                let id = abi::getpid();

                guard.blocked_task.push(prio, id);
                abi::block_current_task();
                drop(guard);
                abi::yield_now();
            }
        }
    }

    #[inline]
    pub unsafe fn unlock(&self) {
        let mut guard = self.inner.lock();
        guard.locked = false;
        if let Some(tid) = guard.blocked_task.pop() {
            abi::wakeup_task(tid);
        }
    }

    #[inline]
    pub unsafe fn try_lock(&self) -> bool {
        let mut guard = self.inner.lock();
        if guard.locked == false {
            guard.locked = true;
        }
        guard.locked
    }

    #[inline]
    pub unsafe fn destroy(&self) {}
}

pub struct ReentrantMutex {
    inner: *const c_void,
}

impl ReentrantMutex {
    pub const unsafe fn uninitialized() -> ReentrantMutex {
        ReentrantMutex { inner: ptr::null() }
    }

    #[inline]
    pub unsafe fn init(&self) {
        let _ = abi::recmutex_init(&self.inner as *const *const c_void as *mut _);
    }

    #[inline]
    pub unsafe fn lock(&self) {
        let _ = abi::recmutex_lock(self.inner);
    }

    #[inline]
    pub unsafe fn try_lock(&self) -> bool {
        true
    }

    #[inline]
    pub unsafe fn unlock(&self) {
        let _ = abi::recmutex_unlock(self.inner);
    }

    #[inline]
    pub unsafe fn destroy(&self) {
        let _ = abi::recmutex_destroy(self.inner);
    }
}
<commit_msg>revise comments and descriptions of the helper functions<commit_after>use crate::cell::UnsafeCell;
use crate::collections::VecDeque;
use crate::ffi::c_void;
use crate::ops::{Deref, DerefMut, Drop};
use crate::ptr;
use crate::sync::atomic::{spin_loop_hint, AtomicUsize, Ordering};
use crate::sys::hermit::abi;

/// This type provides a lock based on busy waiting to realize mutual exclusion
///
/// # Description
///
/// This structure behaves a lot like a common mutex. There are some differences:
///
/// - By using busy waiting, it can be used outside the runtime.
/// - It is a so called ticket lock and is completly fair.
#[cfg_attr(target_arch = "x86_64", repr(align(128)))]
#[cfg_attr(not(target_arch = "x86_64"), repr(align(64)))]
struct Spinlock<T: ?Sized> {
    queue: AtomicUsize,
    dequeue: AtomicUsize,
    data: UnsafeCell<T>,
}

unsafe impl<T: ?Sized + Send> Sync for Spinlock<T> {}
unsafe impl<T: ?Sized + Send> Send for Spinlock<T> {}

/// A guard to which the protected data can be accessed
///
/// When the guard falls out of scope it will release the lock.
struct SpinlockGuard<'a, T: ?Sized + 'a> {
    dequeue: &'a AtomicUsize,
    data: &'a mut T,
}

impl<T> Spinlock<T> {
    pub const fn new(user_data: T) -> Spinlock<T> {
        SpinlockGuard { dequeue: &self.dequeue, data: &mut *self.data.get() }
    }

    #[inline]
    fn obtain_lock(&self) {
        let ticket = self.queue.fetch_add(1, Ordering::SeqCst) + 1;
        while self.dequeue.load(Ordering::SeqCst) != ticket {
            spin_loop_hint();
        }
    }

    #[inline]
    pub unsafe fn lock(&self) -> SpinlockGuard<'_, T> {
        self.obtain_lock();
        SpinlockGuard { dequeue: &self.dequeue, data: &mut *self.data.get() }
    }
}

impl<T: ?Sized + Default> Default for Spinlock<T> {
    fn default() -> Spinlock<T> {
        Spinlock::new(Default::default())
    }
}

impl<'a, T: ?Sized> Deref for SpinlockGuard<'a, T> {
    type Target = T;
    fn deref(&self) -> &T {
        &*self.data
    }
}

impl<'a, T: ?Sized> DerefMut for SpinlockGuard<'a, T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut *self.data
    }
}

impl<'a, T: ?Sized> Drop for SpinlockGuard<'a, T> {
    /// The dropping of the SpinlockGuard will release the lock it was created from.
    fn drop(&mut self) {
        self.dequeue.fetch_add(1, Ordering::SeqCst);
    }
}

/// Realize a priority queue for tasks
struct PriorityQueue {
    queues: [Option<VecDeque<abi::Tid>>; abi::NO_PRIORITIES],
    prio_bitmap: u64,
}

impl PriorityQueue {
    pub const fn new() -> PriorityQueue {
        PriorityQueue {
            queues: [
                None, None, None, None, None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, None, None, None, None, None, None, None, None, None, None,
                None, None, None,
            ],
            prio_bitmap: 0,
        }
    }

    /// Add a task id by its priority to the queue
    pub fn push(&mut self, prio: abi::Priority, id: abi::Tid) {
        let i: usize = prio.into().into();
        self.prio_bitmap |= (1 << i) as u64;
        if let Some(queue) = &mut self.queues[i] {
            queue.push_back(id);
        } else {
            let mut queue = VecDeque::new();
            queue.push_back(id);
            self.queues[i] = Some(queue);
        }
    }

    fn pop_from_queue(&mut self, queue_index: usize) -> Option<abi::Tid> {
        if let Some(queue) = &mut self.queues[queue_index] {
            let id = queue.pop_front();

            if queue.is_empty() {
                self.prio_bitmap &= !(1 << queue_index as u64);
            }

            id
        } else {
            None
        }
    }

    /// Pop the task handle with the highest priority from the queue
    pub fn pop(&mut self) -> Option<abi::Tid> {
        for i in 0..abi::NO_PRIORITIES {
            if self.prio_bitmap & (1 << i) != 0 {
                return self.pop_from_queue(i);
            }
        }

        None
    }
}

struct MutexInner {
    locked: bool,
    blocked_task: PriorityQueue,
}

impl MutexInner {
    pub const fn new() -> MutexInner {
        MutexInner { locked: false, blocked_task: PriorityQueue::new() }
    }
}

pub struct Mutex {
    inner: Spinlock<MutexInner>,
}

unsafe impl Send for Mutex {}
unsafe impl Sync for Mutex {}

impl Mutex {
    pub const fn new() -> Mutex {
        Mutex { inner: Spinlock::new(MutexInner::new()) }
    }

    #[inline]
    pub unsafe fn init(&mut self) {
        self.inner = Spinlock::new(MutexInner::new());
    }

    #[inline]
    pub unsafe fn lock(&self) {
        loop {
            let mut guard = self.inner.lock();
            if guard.locked == false {
                guard.locked = true;
                return;
            } else {
                let prio = abi::get_priority();
                let id = abi::getpid();

                guard.blocked_task.push(prio, id);
                abi::block_current_task();
                drop(guard);
                abi::yield_now();
            }
        }
    }

    #[inline]
    pub unsafe fn unlock(&self) {
        let mut guard = self.inner.lock();
        guard.locked = false;
        if let Some(tid) = guard.blocked_task.pop() {
            abi::wakeup_task(tid);
        }
    }

    #[inline]
    pub unsafe fn try_lock(&self) -> bool {
        let mut guard = self.inner.lock();
        if guard.locked == false {
            guard.locked = true;
        }
        guard.locked
    }

    #[inline]
    pub unsafe fn destroy(&self) {}
}

pub struct ReentrantMutex {
    inner: *const c_void,
}

impl ReentrantMutex {
    pub const unsafe fn uninitialized() -> ReentrantMutex {
        ReentrantMutex { inner: ptr::null() }
    }

    #[inline]
    pub unsafe fn init(&self) {
        let _ = abi::recmutex_init(&self.inner as *const *const c_void as *mut _);
    }

    #[inline]
    pub unsafe fn lock(&self) {
        let _ = abi::recmutex_lock(self.inner);
    }

    #[inline]
    pub unsafe fn try_lock(&self) -> bool {
        true
    }

    #[inline]
    pub unsafe fn unlock(&self) {
        let _ = abi::recmutex_unlock(self.inner);
    }

    #[inline]
    pub unsafe fn destroy(&self) {
        let _ = abi::recmutex_destroy(self.inner);
    }
}
<|endoftext|>


<commit_before>//! Diagnostic emitted for files that aren't part of any crate.

use hir::{
    db::DefDatabase,
    diagnostics::{Diagnostic, DiagnosticCode},
    InFile,
};
use ide_db::{
    base_db::{FileId, FileLoader, SourceDatabase, SourceDatabaseExt},
    source_change::SourceChange,
    RootDatabase,
};
use syntax::{
    ast::{self, ModuleItemOwner, NameOwner},
    AstNode, SyntaxNodePtr,
};
use text_edit::TextEdit;

use crate::Fix;

use super::fixes::DiagnosticWithFix;

// Diagnostic: unlinked-file
//
// This diagnostic is shown for files that are not included in any crate, or files that are part of
// crates rust-analyzer failed to discover. The file will not have IDE features available.
#[derive(Debug)]
pub(crate) struct UnlinkedFile {
    pub(crate) file_id: FileId,
    pub(crate) node: SyntaxNodePtr,
}

impl Diagnostic for UnlinkedFile {
    fn code(&self) -> DiagnosticCode {
        DiagnosticCode("unlinked-file")
    }

    fn message(&self) -> String {
        "file not included in module tree".to_string()
    }

    fn display_source(&self) -> InFile<SyntaxNodePtr> {
        InFile::new(self.file_id.into(), self.node.clone())
    }

    fn as_any(&self) -> &(dyn std::any::Any + Send + 'static) {
        self
    }
}

impl DiagnosticWithFix for UnlinkedFile {
    fn fix(&self, sema: &hir::Semantics<RootDatabase>) -> Option<Fix> {
        // If there's an existing module that could add a `mod` item to include the unlinked file,
        // suggest that as a fix.

        let source_root = sema.db.source_root(sema.db.file_source_root(self.file_id));
        let our_path = source_root.path_for_file(&self.file_id)?;
        let module_name = our_path.name_and_extension()?.0;

        // Candidates to look for:
        // - `mod.rs` in the same folder
        //   - we also check `main.rs` and `lib.rs`
        // - `$dir.rs` in the parent folder, where `$dir` is the directory containing `self.file_id`
        let parent = our_path.parent()?;
        let mut paths =
            vec![parent.join("mod.rs")?, parent.join("main.rs")?, parent.join("lib.rs")?];

        // `submod/bla.rs` -> `submod.rs`
        if let Some(newmod) = (|| {
            let name = parent.name_and_extension()?.0;
            parent.parent()?.join(&format!("{}.rs", name))
        })() {
            paths.push(newmod);
        }

        for path in &paths {
            if let Some(parent_id) = source_root.file_for_path(path) {
                for krate in sema.db.relevant_crates(*parent_id).iter() {
                    let crate_def_map = sema.db.crate_def_map(*krate);
                    for (_, module) in crate_def_map.modules() {
                        if module.origin.is_inline() {
                            // We don't handle inline `mod parent {}`s, they use different paths.
                            continue;
                        }

                        if module.origin.file_id() == Some(*parent_id) {
                            return make_fix(sema.db, *parent_id, module_name, self.file_id);
                        }
                    }
                }
            }
        }

        None
    }
}

fn make_fix(
    db: &RootDatabase,
    parent_file_id: FileId,
    new_mod_name: &str,
    added_file_id: FileId,
) -> Option<Fix> {
    fn is_outline_mod(item: &ast::Item) -> bool {
        matches!(item, ast::Item::Module(m) if m.item_list().is_none())
    }

    let mod_decl = format!("mod {};", new_mod_name);
    let ast: ast::SourceFile = db.parse(parent_file_id).tree();

    let mut builder = TextEdit::builder();

    // If there's an existing `mod m;` statement matching the new one, don't emit a fix (it's
    // probably `#[cfg]`d out).
    for item in ast.items() {
        if let ast::Item::Module(m) = item {
            if let Some(name) = m.name() {
                if m.item_list().is_none() && name.to_string() == new_mod_name {
                    cov_mark::hit!(unlinked_file_skip_fix_when_mod_already_exists);
                    return None;
                }
            }
        }
    }

    // If there are existing `mod m;` items, append after them (after the first group of them, rather).
    match ast
        .items()
        .skip_while(|item| !is_outline_mod(item))
        .take_while(|item| is_outline_mod(item))
        .last()
    {
        Some(last) => {
            cov_mark::hit!(unlinked_file_append_to_existing_mods);
            builder.insert(last.syntax().text_range().end(), format!("\n{}", mod_decl));
        }
        None => {
            // Prepend before the first item in the file.
            match ast.items().next() {
                Some(item) => {
                    cov_mark::hit!(unlinked_file_prepend_before_first_item);
                    builder.insert(item.syntax().text_range().start(), format!("{}\n\n", mod_decl));
                }
                None => {
                    // No items in the file, so just append at the end.
                    cov_mark::hit!(unlinked_file_empty_file);
                    builder.insert(ast.syntax().text_range().end(), format!("{}\n", mod_decl));
                }
            }
        }
    }

    let edit = builder.finish();
    let trigger_range = db.parse(added_file_id).tree().syntax().text_range();
    Some(Fix::new(
        &format!("Insert `{}`", mod_decl),
        SourceChange::from_text_edit(parent_file_id, edit),
        trigger_range,
    ))
}
<commit_msg>Prefer add `mod` declaration to lib.rs over file.rs in UnlinkedFile fix<commit_after>//! Diagnostic emitted for files that aren't part of any crate.

use hir::{
    db::DefDatabase,
    diagnostics::{Diagnostic, DiagnosticCode},
    InFile,
};
use ide_db::{
    base_db::{FileId, FileLoader, SourceDatabase, SourceDatabaseExt},
    source_change::SourceChange,
    RootDatabase,
};
use syntax::{
    ast::{self, ModuleItemOwner, NameOwner},
    AstNode, SyntaxNodePtr,
};
use text_edit::TextEdit;

use crate::Fix;

use super::fixes::DiagnosticWithFix;

// Diagnostic: unlinked-file
//
// This diagnostic is shown for files that are not included in any crate, or files that are part of
// crates rust-analyzer failed to discover. The file will not have IDE features available.
#[derive(Debug)]
pub(crate) struct UnlinkedFile {
    pub(crate) file_id: FileId,
    pub(crate) node: SyntaxNodePtr,
}

impl Diagnostic for UnlinkedFile {
    fn code(&self) -> DiagnosticCode {
        DiagnosticCode("unlinked-file")
    }

    fn message(&self) -> String {
        "file not included in module tree".to_string()
    }

    fn display_source(&self) -> InFile<SyntaxNodePtr> {
        InFile::new(self.file_id.into(), self.node.clone())
    }

    fn as_any(&self) -> &(dyn std::any::Any + Send + 'static) {
        self
    }
}

impl DiagnosticWithFix for UnlinkedFile {
    fn fix(&self, sema: &hir::Semantics<RootDatabase>) -> Option<Fix> {
        // If there's an existing module that could add a `mod` item to include the unlinked file,
        // suggest that as a fix.

        let source_root = sema.db.source_root(sema.db.file_source_root(self.file_id));
        let our_path = source_root.path_for_file(&self.file_id)?;
        let module_name = our_path.name_and_extension()?.0;

        // Candidates to look for:
        // - `mod.rs` in the same folder
        //   - we also check `main.rs` and `lib.rs`
        // - `$dir.rs` in the parent folder, where `$dir` is the directory containing `self.file_id`
        let parent = our_path.parent()?;
        let mut paths =
            vec![parent.join("mod.rs")?, parent.join("lib.rs")?, parent.join("main.rs")?];

        // `submod/bla.rs` -> `submod.rs`
        if let Some(newmod) = (|| {
            let name = parent.name_and_extension()?.0;
            parent.parent()?.join(&format!("{}.rs", name))
        })() {
            paths.push(newmod);
        }

        for path in &paths {
            if let Some(parent_id) = source_root.file_for_path(path) {
                for krate in sema.db.relevant_crates(*parent_id).iter() {
                    let crate_def_map = sema.db.crate_def_map(*krate);
                    for (_, module) in crate_def_map.modules() {
                        if module.origin.is_inline() {
                            // We don't handle inline `mod parent {}`s, they use different paths.
                            continue;
                        }

                        if module.origin.file_id() == Some(*parent_id) {
                            return make_fix(sema.db, *parent_id, module_name, self.file_id);
                        }
                    }
                }
            }
        }

        None
    }
}

fn make_fix(
    db: &RootDatabase,
    parent_file_id: FileId,
    new_mod_name: &str,
    added_file_id: FileId,
) -> Option<Fix> {
    fn is_outline_mod(item: &ast::Item) -> bool {
        matches!(item, ast::Item::Module(m) if m.item_list().is_none())
    }

    let mod_decl = format!("mod {};", new_mod_name);
    let ast: ast::SourceFile = db.parse(parent_file_id).tree();

    let mut builder = TextEdit::builder();

    // If there's an existing `mod m;` statement matching the new one, don't emit a fix (it's
    // probably `#[cfg]`d out).
    for item in ast.items() {
        if let ast::Item::Module(m) = item {
            if let Some(name) = m.name() {
                if m.item_list().is_none() && name.to_string() == new_mod_name {
                    cov_mark::hit!(unlinked_file_skip_fix_when_mod_already_exists);
                    return None;
                }
            }
        }
    }

    // If there are existing `mod m;` items, append after them (after the first group of them, rather).
    match ast
        .items()
        .skip_while(|item| !is_outline_mod(item))
        .take_while(|item| is_outline_mod(item))
        .last()
    {
        Some(last) => {
            cov_mark::hit!(unlinked_file_append_to_existing_mods);
            builder.insert(last.syntax().text_range().end(), format!("\n{}", mod_decl));
        }
        None => {
            // Prepend before the first item in the file.
            match ast.items().next() {
                Some(item) => {
                    cov_mark::hit!(unlinked_file_prepend_before_first_item);
                    builder.insert(item.syntax().text_range().start(), format!("{}\n\n", mod_decl));
                }
                None => {
                    // No items in the file, so just append at the end.
                    cov_mark::hit!(unlinked_file_empty_file);
                    builder.insert(ast.syntax().text_range().end(), format!("{}\n", mod_decl));
                }
            }
        }
    }

    let edit = builder.finish();
    let trigger_range = db.parse(added_file_id).tree().syntax().text_range();
    Some(Fix::new(
        &format!("Insert `{}`", mod_decl),
        SourceChange::from_text_edit(parent_file_id, edit),
        trigger_range,
    ))
}
<|endoftext|>


<commit_before>extern crate libc;
extern crate std;

use super::liblua;
use super::Index;
use super::Lua;
use super::Pushable;
use super::Readable;

impl<T:Pushable> Pushable for Vec<T> {
    fn push_to_lua(&self, lua: &mut Lua) {
        unimplemented!()
    }
}
<commit_msg>Implement pushable for vectors and slices<commit_after>extern crate libc;
extern crate std;

use super::liblua;
use super::Lua;
use super::Pushable;

impl<T: Pushable> Pushable for Vec<T> {
    fn push_to_lua(&self, lua: &mut Lua) {
        self.as_slice().push_to_lua(lua)
    }
}

impl<'a, T: Pushable> Pushable for &'a [T] {
    fn push_to_lua(&self, lua: &mut Lua) {
        // creating empty table
        unsafe { liblua::lua_newtable(lua.lua) };

        for i in range(0, self.len()) {
            (i+1).push_to_lua(lua);
            self[i].push_to_lua(lua);
            unsafe { liblua::lua_settable(lua.lua, -3) };
        }
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn write() {
        let mut lua = super::super::Lua::new();

        lua.set("a", vec!(9, 8, 7)).unwrap();

        // TODO: test if it worked once reading tables is supported
    }
}
<|endoftext|>


<commit_before>// This example shows how to create a basic router that maps url to different handlers.
// If you're looking for real routing middleware, check https://github.com/iron/router

extern crate iron;

use std::collections::HashMap;

use iron::prelude::*;
use iron::{Handler};
use iron::status;

struct Router {
    // Routes here are simply matched with the url path.
    routes: HashMap<String, Box<Handler>>
}

impl Router {
    fn new() -> Self {
        Router { routes: HashMap::new() }
    }

    fn add_route<H>(&mut self, path: String, handler: H) where H: Handler {
        self.routes.insert(path, Box::new(handler));
    }
}

impl Handler for Router {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        match self.routes.get(&req.url.path().join("/")) {
            Some(handler) => handler.handle(req),
            None => Ok(Response::with(status::NotFound))
        }
    }
}

fn main() {
    let mut router = Router::new();

    router.add_route("hello".to_string(), |_: &mut Request| {
        Ok(Response::with((status::Ok, "Hello world !")))
    });

    router.add_route("hello/again".to_string(), |_: &mut Request| {
       Ok(Response::with((status::Ok, "Hello again !")))
    });

    router.add_route("error".to_string(), |_: &mut Request| {
       Ok(Response::with(status::BadRequest))
    });

    Iron::new(router).http("localhost:3000").unwrap();
}
<commit_msg>(example) Remove unnecessary brace<commit_after>// This example shows how to create a basic router that maps url to different handlers.
// If you're looking for real routing middleware, check https://github.com/iron/router

extern crate iron;

use std::collections::HashMap;

use iron::prelude::*;
use iron::Handler;
use iron::status;

struct Router {
    // Routes here are simply matched with the url path.
    routes: HashMap<String, Box<Handler>>
}

impl Router {
    fn new() -> Self {
        Router { routes: HashMap::new() }
    }

    fn add_route<H>(&mut self, path: String, handler: H) where H: Handler {
        self.routes.insert(path, Box::new(handler));
    }
}

impl Handler for Router {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        match self.routes.get(&req.url.path().join("/")) {
            Some(handler) => handler.handle(req),
            None => Ok(Response::with(status::NotFound))
        }
    }
}

fn main() {
    let mut router = Router::new();

    router.add_route("hello".to_string(), |_: &mut Request| {
        Ok(Response::with((status::Ok, "Hello world !")))
    });

    router.add_route("hello/again".to_string(), |_: &mut Request| {
       Ok(Response::with((status::Ok, "Hello again !")))
    });

    router.add_route("error".to_string(), |_: &mut Request| {
       Ok(Response::with(status::BadRequest))
    });

    Iron::new(router).http("localhost:3000").unwrap();
}
<|endoftext|>