<commit_before>extern mod png;

use std::num::{sqrt, min, max, cos, sin};

static WIDTH: f64 = 800.;
static HEIGHT: f64 = 800.;

struct Color {
  r: u8,
  g: u8,
  b: u8
}

static Red: Color = Color { r: 255, g: 0, b: 0 };
static Green: Color = Color { r: 0, g: 255, b: 0 };
static Blue: Color = Color { r: 0, g: 0, b: 255 };
static White: Color = Color { r: 255, g: 255, b: 255 };
static Black: Color = Color { r: 0, g: 0, b: 0 };

struct Point {
  x: f64,
  y: f64,
  z: f64
}

struct Spot {
  pos: Point,
  color: Color,
}

struct Scene {
  eye: Point,
  spot: Spot,
  sphere: Sphere
}

fn solve_poly(a: f64, b: f64, c: f64) -> f64 {
  let delta = b.pow(&2.0) - 4. * a * c;

  if delta < 0. {
    return 0.;
  }

  let k1 = (-b - sqrt(delta)) / (2. * a);
  let k2 = (-b + sqrt(delta)) / (2. * a);

  return match (k1, k2) {
    (k1, k2) if k1 < 0. && k2 < 0. => 0.,
    (k1, k2) if k2 <= 0. => k1,
    (k1, k2) if k1 <= 0. => k2,
    _ => min(k1, k2)
  }
}

trait Shape {
  fn hit(&self, eye: &Point, vector: &Point) -> f64;
  fn get_perp(&self, inter: &Point) -> ~Point;
}

struct Sphere {
  pos: Point,
  radius: f64,
  shininess: f64,
  color: Color
}

impl Shape for Sphere {
  fn hit(&self, eye: &Point, vector: &Point) -> f64 {
    let a = vector.x.pow(&2.) + vector.y.pow(&2.) + vector.z.pow(&2.);
    let b = 2. * (eye.x * vector.x + eye.y * vector.y + eye.z * vector.z);
    let c = eye.x.pow(&2.) + eye.y.pow(&2.) + eye.z.pow(&2.) - self.radius.pow(&2.);
    return solve_poly(a, b, c);
  }

  fn get_perp(&self, inter: &Point) -> ~Point {
    ~Point { x: inter.x, y: inter.y, z: inter.z }
  }
}

fn get_closest(obj: &Sphere, eye: &Point, vector: &Point) -> f64 {
  let e = ~Point { x: eye.x - obj.pos.x, y: eye.y - obj.pos.y, z: eye.z - obj.pos.z };
  let v = ~Point { x: vector.x, y: vector.y, z: vector.z };
  return obj.hit(e, v);
}

fn get_light(obj: &Sphere, spot: &Spot, inter: &Point, light: &Point) -> Color {
  let perp = obj.get_perp(inter);
  let norme_l = sqrt(light.x.pow(&2.) + light.y.pow(&2.) + light.z.pow(&2.));
  let norme_n = sqrt(perp.x.pow(&2.) + perp.y.pow(&2.) + perp.z.pow(&2.));
  let cos_a = (light.x * perp.x + light.y * perp.y + light.z * perp.z) / (norme_l * norme_n);

  if cos_a <= 0. {
    return Black;
  }

  Color {
    r: ((obj.color.r as f64) * cos_a * (1. - obj.shininess) + (spot.color.r as f64) * cos_a * obj.shininess) as u8,
    g: ((obj.color.g as f64) * cos_a * (1. - obj.shininess) + (spot.color.g as f64) * cos_a * obj.shininess) as u8,
    b: ((obj.color.b as f64) * cos_a * (1. - obj.shininess) + (spot.color.b as f64) * cos_a * obj.shininess) as u8
  }
}

fn main() {
  let mut pixels = ~[Black, ..((WIDTH * HEIGHT) as uint)];

  let eye = ~Point { x: -300., y: 0., z: 200. };
  let spot = ~Spot {
    pos: Point { x: -300., y: 100., z: 200. },
    color: White
  };
  let sphere = ~Sphere {
    pos: Point { x: 0., y: 0., z: 0. },
    radius: 160.,
    shininess: 0.2,
    color: Red
  };

  for x in range(0., WIDTH) {
    for y in range(0., HEIGHT) {
      let vector = ~Point {
        x: 100.,
        y: WIDTH / 2. - x,
        z: HEIGHT / 2. - y
      };

      let closest = get_closest(sphere, eye, vector);

      // // Shadow
      // let inter = Point {
      //   x: eye.x + closest * vector.x,
      //   y: eye.y + closest * vector.y,
      //   z: eye.z + closest * vector.z
      // };
      // let light = Point {
      //   x: spot.pos.x - inter.x,
      //   y: spot.pos.y - inter.y,
      //   z: spot.pos.z - inter.z
      // };

      let inter = ~Point {
        x: (eye.x - sphere.pos.x) + closest * vector.x,
        y: (eye.y - sphere.pos.y) + closest * vector.y,
        z: (eye.z - sphere.pos.z) + closest * vector.z
      };
      let light = ~Point {
        x: spot.pos.x - inter.x,
        y: spot.pos.y - inter.y,
        z: spot.pos.z - inter.z
      };

      pixels[(y * WIDTH + x) as u32] = get_light(sphere, spot, inter, light);
    }
  }

  let img = png::Image {
    width: WIDTH as u32,
    height: HEIGHT as u32,
    color_type: png::RGB8,
    pixels: pixels.flat_map(|&Color { r, g, b }| { ~[r, g, b] })
  };

  png::store_png(&img, &Path::new("out.png"));
}
<commit_msg>Real ball yo!<commit_after>extern mod png;

use std::num::{sqrt, min, max, cos, sin};

static WIDTH: int = 800;
static HEIGHT: int = 800;

struct Color {
  r: u8,
  g: u8,
  b: u8
}

static Red: Color = Color { r: 255, g: 0, b: 0 };
static Green: Color = Color { r: 0, g: 255, b: 0 };
static Blue: Color = Color { r: 0, g: 0, b: 255 };
static White: Color = Color { r: 255, g: 255, b: 255 };
static Black: Color = Color { r: 0, g: 0, b: 0 };

struct Point {
  x: f64,
  y: f64,
  z: f64
}

struct Spot {
  pos: Point,
  color: Color,
}

struct Scene {
  eye: Point,
  spot: Spot,
  sphere: Sphere
}

fn solve_poly(a: f64, b: f64, c: f64) -> f64 {
  let delta = b.pow(&2.0) - 4. * a * c;

  if delta < 0. {
    return 0.;
  }

  let sign = match c {
    _ if c < 0. => 1.,
    _ => -1.
  };
  let k = (-b + sign * sqrt(delta)) / (2. * a);
  return match k {
    _ if k > 0. => k,
    _ => 0.
  }
}

trait Shape {
  fn hit(&self, eye: &Point, vector: &Point) -> f64;
  fn get_perp(&self, inter: &Point) -> ~Point;
}

struct Sphere {
  pos: Point,
  radius: f64,
  shininess: f64,
  color: Color
}

impl Shape for Sphere {
  fn hit(&self, eye: &Point, vector: &Point) -> f64 {
    let a = vector.x.pow(&2.) + vector.y.pow(&2.) + vector.z.pow(&2.);
    let b = 2. * (eye.x * vector.x + eye.y * vector.y + eye.z * vector.z);
    let c = eye.x.pow(&2.) + eye.y.pow(&2.) + eye.z.pow(&2.) - self.radius.pow(&2.);
    return solve_poly(a, b, c);
  }

  fn get_perp(&self, inter: &Point) -> ~Point {
    ~Point { x: inter.x, y: inter.y, z: inter.z }
  }
}

fn get_closest(obj: &Sphere, eye: &Point, vector: &Point) -> f64 {
  let e = ~Point { x: eye.x - obj.pos.x, y: eye.y - obj.pos.y, z: eye.z - obj.pos.z };
  let v = ~Point { x: vector.x, y: vector.y, z: vector.z };
  return obj.hit(e, v);
}

fn get_light(obj: &Sphere, spot: &Spot, inter: &Point, light: &Point) -> Color {
  let perp = obj.get_perp(inter);
  let norme_l = sqrt(light.x.pow(&2.) + light.y.pow(&2.) + light.z.pow(&2.));
  let norme_n = sqrt(perp.x.pow(&2.) + perp.y.pow(&2.) + perp.z.pow(&2.));
  let cos_a = (light.x * perp.x + light.y * perp.y + light.z * perp.z) / (norme_l * norme_n);

  if cos_a <= 0. {
    return Black;
  }

  Color {
    r: ((obj.color.r as f64) * cos_a * (1. - obj.shininess) + (spot.color.r as f64) * cos_a * obj.shininess) as u8,
    g: ((obj.color.g as f64) * cos_a * (1. - obj.shininess) + (spot.color.g as f64) * cos_a * obj.shininess) as u8,
    b: ((obj.color.b as f64) * cos_a * (1. - obj.shininess) + (spot.color.b as f64) * cos_a * obj.shininess) as u8
  }
}

fn main() {
  let mut pixels = ~[Black, ..((WIDTH * HEIGHT) as uint)];

  let eye = ~Point { x: -300., y: 0., z: 200. };
  let spot = ~Spot {
    pos: Point { x: -300., y: 100., z: 200. },
    color: White
  };
  let sphere = ~Sphere {
    pos: Point { x: 0., y: 0., z: 100. },
    radius: 160.,
    shininess: 0.2,
    color: Red
  };

  for x in range(0, WIDTH) {
    for y in range(0, HEIGHT) {
      let vector = ~Point {
        x: 100.,
        y: (WIDTH / 2 - x) as f64,
        z: (HEIGHT / 2 - y) as f64
      };

      let closest = get_closest(sphere, eye, vector);

      // // Shadow
      // let inter = Point {
      //   x: eye.x + closest * vector.x,
      //   y: eye.y + closest * vector.y,
      //   z: eye.z + closest * vector.z
      // };
      // let light = Point {
      //   x: spot.pos.x - inter.x,
      //   y: spot.pos.y - inter.y,
      //   z: spot.pos.z - inter.z
      // };

      let inter = ~Point {
        x: (eye.x - sphere.pos.x) + closest * vector.x,
        y: (eye.y - sphere.pos.y) + closest * vector.y,
        z: (eye.z - sphere.pos.z) + closest * vector.z
      };
      let light = ~Point {
        x: spot.pos.x - inter.x,
        y: spot.pos.y - inter.y,
        z: spot.pos.z - inter.z
      };

      pixels[y * WIDTH + x] = match closest {
        0. => Black,
        _ => get_light(sphere, spot, inter, light)
      }
    }
  }

  let img = png::Image {
    width: WIDTH as u32,
    height: HEIGHT as u32,
    color_type: png::RGB8,
    pixels: pixels.flat_map(|&Color { r, g, b }| { ~[r, g, b] })
  };

  png::store_png(&img, &Path::new("out.png"));
}
<|endoftext|>


<commit_before>use crate::{Geometry, Wkt, WktFloat};
use serde::de::{Deserializer, Error, Visitor};
use std::{
    default::Default,
    fmt::{self, Debug},
    marker::PhantomData,
    str::FromStr,
};

struct WktVisitor<T> {
    _marker: PhantomData<T>,
}

impl<T> Default for WktVisitor<T> {
    fn default() -> Self {
        WktVisitor {
            _marker: PhantomData::default(),
        }
    }
}

impl<'de, T> Visitor<'de> for WktVisitor<T>
where
    T: FromStr + Default + Debug + WktFloat,
{
    type Value = Wkt<T>;
    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(formatter, "a valid WKT format")
    }
    fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
    where
        E: Error,
    {
        Wkt::from_str(s).map_err(|e| serde::de::Error::custom(e))
    }
}

impl<'de, T> serde::Deserialize<'de> for Wkt<T>
where
    T: FromStr + Default + Debug + WktFloat,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_str(WktVisitor::default())
    }
}

struct GeometryVisitor<T> {
    _marker: PhantomData<T>,
}

impl<T> Default for GeometryVisitor<T> {
    fn default() -> Self {
        GeometryVisitor {
            _marker: PhantomData::default(),
        }
    }
}

impl<'de, T> Visitor<'de> for GeometryVisitor<T>
where
    T: FromStr + Default + WktFloat,
{
    type Value = Geometry<T>;
    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(formatter, "a valid WKT format")
    }
    fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
    where
        E: Error,
    {
        let mut wkt = Wkt::from_str(s).map_err(|e| serde::de::Error::custom(e))?;
        if wkt.items.len() == 1 {
            Ok(wkt.items.remove(0))
        } else {
            Err(serde::de::Error::custom(
                "WKT should have only 1 Geometry item",
            ))
        }
    }
}

impl<'de, T> serde::Deserialize<'de> for Geometry<T>
where
    T: FromStr + Default + WktFloat,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_str(GeometryVisitor::default())
    }
}

/// Deserializes directly from WKT format into a geo_types::Geometry.
/// ```
/// # extern crate wkt;
/// # extern crate geo_types;
/// # extern crate serde_json;
/// use geo_types::Geometry;
///
/// #[derive(serde::Deserialize)]
/// struct MyType {
///     #[serde(deserialize_with = "wkt::deserialize_geometry")]
///     pub geometry: Geometry<f64>,
/// }
///
/// let json = r#"{ "geometry": "POINT (3.14 42)" }"#;
/// let my_type: MyType = serde_json::from_str(json).unwrap();
/// assert!(matches!(my_type.geometry, Geometry::Point(_)));
/// ```
#[cfg(feature = "geo-types")]
pub fn deserialize_geometry<'de, D, T>(deserializer: D) -> Result<geo_types::Geometry<T>, D::Error>
where
    D: Deserializer<'de>,
    T: FromStr + Default + WktFloat,
{
    use serde::Deserialize;
    Geometry::deserialize(deserializer).and_then(|g: Geometry<T>| {
        use std::convert::TryInto;
        g.try_into().map_err(|e| D::Error::custom(e))
    })
}

/// Deserializes directly from WKT format into a `Option<geo_types::Point>`.
///
/// # Examples
///
///
/// ```
/// # extern crate wkt;
/// # extern crate geo_types;
/// # extern crate serde_json;
/// use geo_types::Point;
///
/// #[derive(serde::Deserialize)]
/// struct MyType {
///     #[serde(deserialize_with = "wkt::deserialize_point")]
///     pub geometry: Option<Point<f64>>,
/// }
///
/// let json = r#"{ "geometry": "POINT (3.14 42)" }"#;
/// let my_type: MyType = serde_json::from_str(json).unwrap();
/// assert!(matches!(my_type.geometry, Some(Point(_))));
///
/// let json = r#"{ "geometry": "POINT EMPTY" }"#;
/// let my_type: MyType = serde_json::from_str(json).unwrap();
/// assert!(matches!(my_type.geometry, None));
/// ```
#[cfg(feature = "geo-types")]
pub fn deserialize_point<'de, D, T>(deserializer: D) -> Result<Option<geo_types::Point<T>>, D::Error>
    where
        D: Deserializer<'de>,
        T: FromStr + Default + WktFloat,
{
    use serde::Deserialize;
    Wkt::deserialize(deserializer).and_then(|wkt: Wkt<T>| {
        use std::convert::TryFrom;
        geo_types::Point::try_from(wkt).map(|p| Some(p))
            .or_else(|e| {
            if let crate::conversion::Error::PointConversionError = e {
                // map a WKT: 'POINT EMPTY' to an `Option<geo_types::Point>::None`
                return Ok(None);
            }

            Err(D::Error::custom(e))
        })
    })
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::{
        types::{Coord, Point},
        Geometry,
    };
    use serde::de::{
        value::{Error, StrDeserializer},
        Deserializer, Error as _, IntoDeserializer,
    };

    mod wkt {
        use super::*;

        #[test]
        fn deserialize() {
            let deserializer: StrDeserializer<'_, Error> = "POINT (10 20.1)".into_deserializer();
            let wkt = deserializer
                .deserialize_any(WktVisitor::<f64>::default())
                .unwrap();
            assert!(matches!(
                wkt.items[0],
                Geometry::Point(Point(Some(Coord {
                    x: _, // floating-point types cannot be used in patterns
                    y: _, // floating-point types cannot be used in patterns
                    z: None,
                    m: None,
                })))
            ));
        }

        #[test]
        fn deserialize_error() {
            let deserializer: StrDeserializer<'_, Error> = "POINT (10 20.1A)".into_deserializer();
            let wkt = deserializer.deserialize_any(WktVisitor::<f64>::default());
            assert_eq!(
                wkt.unwrap_err(),
                Error::custom("Expected a number for the Y coordinate")
            );
        }
    }

    mod geometry {
        use super::*;

        #[test]
        fn deserialize() {
            let deserializer: StrDeserializer<'_, Error> = "POINT (42 3.14)".into_deserializer();
            let geometry = deserializer
                .deserialize_any(GeometryVisitor::<f64>::default())
                .unwrap();
            assert!(matches!(
                geometry,
                Geometry::Point(Point(Some(Coord {
                    x: _, // floating-point types cannot be used in patterns
                    y: _, // floating-point types cannot be used in patterns
                    z: None,
                    m: None,
                })))
            ));
        }

        #[test]
        fn deserialize_error() {
            let deserializer: StrDeserializer<'_, Error> = "POINT (42 PI3.14)".into_deserializer();
            let geometry = deserializer.deserialize_any(GeometryVisitor::<f64>::default());
            assert_eq!(
                geometry.unwrap_err(),
                Error::custom("Expected a number for the Y coordinate")
            );
        }
    }
}
<commit_msg>cargo fmt<commit_after>use crate::{Geometry, Wkt, WktFloat};
use serde::de::{Deserializer, Error, Visitor};
use std::{
    default::Default,
    fmt::{self, Debug},
    marker::PhantomData,
    str::FromStr,
};

struct WktVisitor<T> {
    _marker: PhantomData<T>,
}

impl<T> Default for WktVisitor<T> {
    fn default() -> Self {
        WktVisitor {
            _marker: PhantomData::default(),
        }
    }
}

impl<'de, T> Visitor<'de> for WktVisitor<T>
where
    T: FromStr + Default + Debug + WktFloat,
{
    type Value = Wkt<T>;
    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(formatter, "a valid WKT format")
    }
    fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
    where
        E: Error,
    {
        Wkt::from_str(s).map_err(|e| serde::de::Error::custom(e))
    }
}

impl<'de, T> serde::Deserialize<'de> for Wkt<T>
where
    T: FromStr + Default + Debug + WktFloat,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_str(WktVisitor::default())
    }
}

struct GeometryVisitor<T> {
    _marker: PhantomData<T>,
}

impl<T> Default for GeometryVisitor<T> {
    fn default() -> Self {
        GeometryVisitor {
            _marker: PhantomData::default(),
        }
    }
}

impl<'de, T> Visitor<'de> for GeometryVisitor<T>
where
    T: FromStr + Default + WktFloat,
{
    type Value = Geometry<T>;
    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(formatter, "a valid WKT format")
    }
    fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
    where
        E: Error,
    {
        let mut wkt = Wkt::from_str(s).map_err(|e| serde::de::Error::custom(e))?;
        if wkt.items.len() == 1 {
            Ok(wkt.items.remove(0))
        } else {
            Err(serde::de::Error::custom(
                "WKT should have only 1 Geometry item",
            ))
        }
    }
}

impl<'de, T> serde::Deserialize<'de> for Geometry<T>
where
    T: FromStr + Default + WktFloat,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_str(GeometryVisitor::default())
    }
}

/// Deserializes directly from WKT format into a geo_types::Geometry.
/// ```
/// # extern crate wkt;
/// # extern crate geo_types;
/// # extern crate serde_json;
/// use geo_types::Geometry;
///
/// #[derive(serde::Deserialize)]
/// struct MyType {
///     #[serde(deserialize_with = "wkt::deserialize_geometry")]
///     pub geometry: Geometry<f64>,
/// }
///
/// let json = r#"{ "geometry": "POINT (3.14 42)" }"#;
/// let my_type: MyType = serde_json::from_str(json).unwrap();
/// assert!(matches!(my_type.geometry, Geometry::Point(_)));
/// ```
#[cfg(feature = "geo-types")]
pub fn deserialize_geometry<'de, D, T>(deserializer: D) -> Result<geo_types::Geometry<T>, D::Error>
where
    D: Deserializer<'de>,
    T: FromStr + Default + WktFloat,
{
    use serde::Deserialize;
    Geometry::deserialize(deserializer).and_then(|g: Geometry<T>| {
        use std::convert::TryInto;
        g.try_into().map_err(|e| D::Error::custom(e))
    })
}

/// Deserializes directly from WKT format into a `Option<geo_types::Point>`.
///
/// # Examples
///
///
/// ```
/// # extern crate wkt;
/// # extern crate geo_types;
/// # extern crate serde_json;
/// use geo_types::Point;
///
/// #[derive(serde::Deserialize)]
/// struct MyType {
///     #[serde(deserialize_with = "wkt::deserialize_point")]
///     pub geometry: Option<Point<f64>>,
/// }
///
/// let json = r#"{ "geometry": "POINT (3.14 42)" }"#;
/// let my_type: MyType = serde_json::from_str(json).unwrap();
/// assert!(matches!(my_type.geometry, Some(Point(_))));
///
/// let json = r#"{ "geometry": "POINT EMPTY" }"#;
/// let my_type: MyType = serde_json::from_str(json).unwrap();
/// assert!(matches!(my_type.geometry, None));
/// ```
#[cfg(feature = "geo-types")]
pub fn deserialize_point<'de, D, T>(
    deserializer: D,
) -> Result<Option<geo_types::Point<T>>, D::Error>
where
    D: Deserializer<'de>,
    T: FromStr + Default + WktFloat,
{
    use serde::Deserialize;
    Wkt::deserialize(deserializer).and_then(|wkt: Wkt<T>| {
        use std::convert::TryFrom;
        geo_types::Point::try_from(wkt)
            .map(|p| Some(p))
            .or_else(|e| {
                if let crate::conversion::Error::PointConversionError = e {
                    // map a WKT: 'POINT EMPTY' to an `Option<geo_types::Point>::None`
                    return Ok(None);
                }

                Err(D::Error::custom(e))
            })
    })
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::{
        types::{Coord, Point},
        Geometry,
    };
    use serde::de::{
        value::{Error, StrDeserializer},
        Deserializer, Error as _, IntoDeserializer,
    };

    mod wkt {
        use super::*;

        #[test]
        fn deserialize() {
            let deserializer: StrDeserializer<'_, Error> = "POINT (10 20.1)".into_deserializer();
            let wkt = deserializer
                .deserialize_any(WktVisitor::<f64>::default())
                .unwrap();
            assert!(matches!(
                wkt.items[0],
                Geometry::Point(Point(Some(Coord {
                    x: _, // floating-point types cannot be used in patterns
                    y: _, // floating-point types cannot be used in patterns
                    z: None,
                    m: None,
                })))
            ));
        }

        #[test]
        fn deserialize_error() {
            let deserializer: StrDeserializer<'_, Error> = "POINT (10 20.1A)".into_deserializer();
            let wkt = deserializer.deserialize_any(WktVisitor::<f64>::default());
            assert_eq!(
                wkt.unwrap_err(),
                Error::custom("Expected a number for the Y coordinate")
            );
        }
    }

    mod geometry {
        use super::*;

        #[test]
        fn deserialize() {
            let deserializer: StrDeserializer<'_, Error> = "POINT (42 3.14)".into_deserializer();
            let geometry = deserializer
                .deserialize_any(GeometryVisitor::<f64>::default())
                .unwrap();
            assert!(matches!(
                geometry,
                Geometry::Point(Point(Some(Coord {
                    x: _, // floating-point types cannot be used in patterns
                    y: _, // floating-point types cannot be used in patterns
                    z: None,
                    m: None,
                })))
            ));
        }

        #[test]
        fn deserialize_error() {
            let deserializer: StrDeserializer<'_, Error> = "POINT (42 PI3.14)".into_deserializer();
            let geometry = deserializer.deserialize_any(GeometryVisitor::<f64>::default());
            assert_eq!(
                geometry.unwrap_err(),
                Error::custom("Expected a number for the Y coordinate")
            );
        }
    }
}
<|endoftext|>


<commit_before>use utils::*;
use super::{CATCH_STRUCT_PREFIX, CATCH_FN_PREFIX};

use route_decorator::get_fn_decl;

use syntax::codemap::{Span};
use syntax::ast::{MetaItem};
use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::print::pprust::{item_to_string};

#[allow(dead_code)]
const DEBUG: bool = true;

#[derive(Debug)]
struct Params {
    code: KVSpanned<u16>,
}

fn get_error_params(ecx: &mut ExtCtxt, meta_item: &MetaItem) -> Params {
    assert_meta_item_list(ecx, meta_item, "error");

    // Ensure we can unwrap the k = v params.
    let params = meta_item.node.get_list_items().unwrap();

    // Now grab all of the required and optional parameters.
    let req: [&'static str; 1] = ["code"];
    let kv_pairs = get_key_values(ecx, meta_item.span, &req, &[], &*params);

    // Ensure we have a code, just to keep parsing and generating errors.
    let code = kv_pairs.get("code").map_or(dummy_kvspan(404), |c| {
        let numeric_code = match c.node.parse() {
            Ok(n) => n,
            Err(_) => {
                let msg = "Error codes must be integer strings. (e.g. \"404\")";
                ecx.span_err(c.v_span, msg);
                404
            }
        };

        if numeric_code < 100 || numeric_code > 599 {
            ecx.span_err(c.v_span, "Error codes must be >= 100 and <= 599.");
        }

        c.clone().map(|_| { numeric_code })
    });

    Params {
        code: code,
    }
}

pub fn error_decorator(ecx: &mut ExtCtxt, sp: Span, meta_item: &MetaItem,
          annotated: &Annotatable, push: &mut FnMut(Annotatable)) {
    let (item, _fn_decl) = get_fn_decl(ecx, sp, annotated);
    let error_params = get_error_params(ecx, meta_item);
    debug!("Error parameters are: {:?}", error_params);

    let fn_name = item.ident;
    let catch_fn_name = prepend_ident(CATCH_FN_PREFIX, &item.ident);
    let catch_fn_item = quote_item!(ecx,
         fn $catch_fn_name<'rocket>(_req: rocket::Request<'rocket>)
                -> rocket::Response<'rocket> {
             // TODO: Figure out what type signature of catcher should be.
             let result = $fn_name();
             rocket::Response::new(result)
         }
    ).unwrap();

    debug!("{}", item_to_string(&catch_fn_item));
    push(Annotatable::Item(catch_fn_item));

    let struct_name = prepend_ident(CATCH_STRUCT_PREFIX, &item.ident);
    let catch_code = error_params.code.node;
    push(Annotatable::Item(quote_item!(ecx,
        #[allow(non_upper_case_globals)]
        pub static $struct_name: rocket::StaticCatchInfo = rocket::StaticCatchInfo {
            code: $catch_code,
            handler: $catch_fn_name
        };
    ).unwrap()));
}

<commit_msg>Stricter error code checking.<commit_after>use utils::*;
use super::{CATCH_STRUCT_PREFIX, CATCH_FN_PREFIX};

use route_decorator::get_fn_decl;

use syntax::codemap::{Span};
use syntax::ast::{MetaItem};
use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::print::pprust::{item_to_string};

#[allow(dead_code)]
const DEBUG: bool = true;

#[derive(Debug)]
struct Params {
    code: KVSpanned<u16>,
}

fn get_error_params(ecx: &mut ExtCtxt, meta_item: &MetaItem) -> Params {
    assert_meta_item_list(ecx, meta_item, "error");

    // Ensure we can unwrap the k = v params.
    let params = meta_item.node.get_list_items().unwrap();

    // Now grab all of the required and optional parameters.
    let req: [&'static str; 1] = ["code"];
    let kv_pairs = get_key_values(ecx, meta_item.span, &req, &[], &*params);

    // Ensure we have a code, just to keep parsing and generating errors.
    let code = kv_pairs.get("code").map_or(dummy_kvspan(404), |c| {
        let numeric_code = match c.node.parse() {
            Ok(n) => n,
            Err(_) => {
                let msg = "Error codes must be integer strings. (e.g. \"404\")";
                ecx.span_err(c.v_span, msg);
                404
            }
        };

        if numeric_code < 400 || numeric_code > 599 {
            ecx.span_err(c.v_span, "Error codes must be >= 400 and <= 599.");
        }

        c.clone().map(|_| { numeric_code })
    });

    Params {
        code: code,
    }
}

pub fn error_decorator(ecx: &mut ExtCtxt, sp: Span, meta_item: &MetaItem,
          annotated: &Annotatable, push: &mut FnMut(Annotatable)) {
    let (item, _fn_decl) = get_fn_decl(ecx, sp, annotated);
    let error_params = get_error_params(ecx, meta_item);
    debug!("Error parameters are: {:?}", error_params);

    let fn_name = item.ident;
    let catch_fn_name = prepend_ident(CATCH_FN_PREFIX, &item.ident);
    let catch_fn_item = quote_item!(ecx,
         fn $catch_fn_name<'rocket>(_req: rocket::Request<'rocket>)
                -> rocket::Response<'rocket> {
             // TODO: Figure out what type signature of catcher should be.
             let result = $fn_name();
             rocket::Response::new(result)
         }
    ).unwrap();

    debug!("{}", item_to_string(&catch_fn_item));
    push(Annotatable::Item(catch_fn_item));

    let struct_name = prepend_ident(CATCH_STRUCT_PREFIX, &item.ident);
    let catch_code = error_params.code.node;
    push(Annotatable::Item(quote_item!(ecx,
        #[allow(non_upper_case_globals)]
        pub static $struct_name: rocket::StaticCatchInfo = rocket::StaticCatchInfo {
            code: $catch_code,
            handler: $catch_fn_name
        };
    ).unwrap()));
}

<|endoftext|>


<commit_before>use quote;
use syn;

use migrations::migration_directory_from_given_path;
use migrations_internals::{migration_paths_in_directory, version_from_path};
use std::error::Error;
use std::path::Path;

use util::{get_option, get_options_from_input};

pub fn derive_embed_migrations(input: &syn::DeriveInput) -> quote::Tokens {
    fn bug() -> ! {
        panic!(
            "This is a bug. Please open a Github issue \
             with your invocation of `embed_migrations!"
        );
    }

    let options = get_options_from_input("embed_migrations_options", &input.attrs, bug);
    let migrations_path_opt = options
        .as_ref()
        .map(|o| get_option(o, "migrations_path", bug));
    let migrations_expr = migration_directory_from_given_path(migrations_path_opt)
        .and_then(|path| migration_literals_from_path(&path));
    let migrations_expr = match migrations_expr {
        Ok(v) => v,
        Err(e) => panic!("Error reading migrations: {}", e),
    };

    // These are split into multiple `quote!` calls to avoid recursion limit
    let embedded_migration_def = quote!(
        struct EmbeddedMigration {
            version: &'static str,
            up_sql: &'static str,
        }

        impl Migration for EmbeddedMigration {
            fn version(&self) -> &str {
                self.version
            }

            fn run(&self, conn: &SimpleConnection) -> Result<(), RunMigrationsError> {
                conn.batch_execute(self.up_sql).map_err(Into::into)
            }

            fn revert(&self, _conn: &SimpleConnection) -> Result<(), RunMigrationsError> {
                unreachable!()
            }
        }
    );

    let run_fns = quote!(
        pub fn run<C: MigrationConnection>(conn: &C) -> Result<(), RunMigrationsError> {
            run_with_output(conn, &mut io::sink())
        }

        pub fn run_with_output<C: MigrationConnection>(conn: &C, out: &mut io::Write)
            -> Result<(), RunMigrationsError>
        {
            run_migrations(conn, ALL_MIGRATIONS.iter().map(|v| *v), out)
        }
    );

    quote! {
        extern crate diesel;
        extern crate diesel_migrations;

        use self::diesel_migrations::*;
        use self::diesel::connection::SimpleConnection;
        use std::io;

        const ALL_MIGRATIONS: &[&Migration] = &[#(#migrations_expr),*];

        #embedded_migration_def

        #run_fns
    }
}

fn migration_literals_from_path(path: &Path) -> Result<Vec<quote::Tokens>, Box<Error>> {
    try!(migration_paths_in_directory(path))
        .into_iter()
        .map(|e| migration_literal_from_path(&e.path()))
        .collect()
}

fn migration_literal_from_path(path: &Path) -> Result<quote::Tokens, Box<Error>> {
    let version = try!(version_from_path(path));
    let sql_file = path.join("up.sql");
    let sql_file_path = sql_file.to_str();

    Ok(quote!(&EmbeddedMigration {
        version: #version,
        up_sql: include_str!(#sql_file_path),
    }))
}
<commit_msg>Sort database migrations before embedding<commit_after>use quote;
use syn;

use migrations::migration_directory_from_given_path;
use migrations_internals::{migration_paths_in_directory, version_from_path};
use std::error::Error;
use std::path::Path;

use util::{get_option, get_options_from_input};

pub fn derive_embed_migrations(input: &syn::DeriveInput) -> quote::Tokens {
    fn bug() -> ! {
        panic!(
            "This is a bug. Please open a Github issue \
             with your invocation of `embed_migrations!"
        );
    }

    let options = get_options_from_input("embed_migrations_options", &input.attrs, bug);
    let migrations_path_opt = options
        .as_ref()
        .map(|o| get_option(o, "migrations_path", bug));
    let migrations_expr = migration_directory_from_given_path(migrations_path_opt)
        .and_then(|path| migration_literals_from_path(&path));
    let migrations_expr = match migrations_expr {
        Ok(v) => v,
        Err(e) => panic!("Error reading migrations: {}", e),
    };

    // These are split into multiple `quote!` calls to avoid recursion limit
    let embedded_migration_def = quote!(
        struct EmbeddedMigration {
            version: &'static str,
            up_sql: &'static str,
        }

        impl Migration for EmbeddedMigration {
            fn version(&self) -> &str {
                self.version
            }

            fn run(&self, conn: &SimpleConnection) -> Result<(), RunMigrationsError> {
                conn.batch_execute(self.up_sql).map_err(Into::into)
            }

            fn revert(&self, _conn: &SimpleConnection) -> Result<(), RunMigrationsError> {
                unreachable!()
            }
        }
    );

    let run_fns = quote!(
        pub fn run<C: MigrationConnection>(conn: &C) -> Result<(), RunMigrationsError> {
            run_with_output(conn, &mut io::sink())
        }

        pub fn run_with_output<C: MigrationConnection>(conn: &C, out: &mut io::Write)
            -> Result<(), RunMigrationsError>
        {
            run_migrations(conn, ALL_MIGRATIONS.iter().map(|v| *v), out)
        }
    );

    quote! {
        extern crate diesel;
        extern crate diesel_migrations;

        use self::diesel_migrations::*;
        use self::diesel::connection::SimpleConnection;
        use std::io;

        const ALL_MIGRATIONS: &[&Migration] = &[#(#migrations_expr),*];

        #embedded_migration_def

        #run_fns
    }
}

fn migration_literals_from_path(path: &Path) -> Result<Vec<quote::Tokens>, Box<Error>> {
    let mut migrations = migration_paths_in_directory(path)?;

    migrations.sort_by_key(|a| a.path());

    migrations
        .into_iter()
        .map(|e| migration_literal_from_path(&e.path()))
        .collect()
}

fn migration_literal_from_path(path: &Path) -> Result<quote::Tokens, Box<Error>> {
    let version = try!(version_from_path(path));
    let sql_file = path.join("up.sql");
    let sql_file_path = sql_file.to_str();

    Ok(quote!(&EmbeddedMigration {
        version: #version,
        up_sql: include_str!(#sql_file_path),
    }))
}
<|endoftext|>


<commit_before>#[macro_use]
#[cfg(test)]
extern crate lazy_static;
#[cfg(test)]
extern crate itertools;
extern crate r68k_common;
#[cfg(test)]
extern crate r68k_tools;

pub mod cpu;
pub mod ram;
pub mod interrupts;
pub mod musashi;

#[cfg(test)]
mod tests {
    use cpu::TestCore;
    use r68k_tools::memory::MemoryVec;
    use r68k_tools::PC;
    use r68k_tools::disassembler::disassemble;
    use r68k_tools::Exception;
    use cpu::ops::handlers::InstructionSetGenerator;
    use cpu::ops::handlers::OpcodeHandler;
    use r68k_tools::disassembler::Disassembler;

    #[test]
    // #[ignore]
    fn roundtrips() {
        let mut over = 0;
        let mut under = 0;
        let gen = InstructionSetGenerator::<TestCore>::new();
        let optable: Vec<&str> = gen.generate_with("???", |ref op| op.name);
        let d = Disassembler::new();
        for opcode in 0x0000..0xffff {
            let op = optable[opcode];
            let mut pc = PC(0);
            let extension_word_mask = 0b1111_1000_1111_1111;
            // bits 8-10 should always be zero in the ea extension word
            // as we don't know which word will be seen as the ea extension word
            // (as opposed to immediate operand values) just make sure these aren't set.
            let dasm_mem = &mut MemoryVec::new16(pc, vec![opcode as u16, 0x001f, 0x00a4, 0x1234 & extension_word_mask, 0x5678 & extension_word_mask]);
            // println!("PREDASM {:04x}", opcode);
            match d.disassemble(pc, dasm_mem) {
                Err(Exception::IllegalInstruction(_opcode, _)) => if op != "???" && op != "unimplemented_1111" && op != "unimplemented_1010" && op != "illegal" {
                    under += 1;
                    println!("{:04x}: {} disasm under", opcode, op);
                }
                , //println!("{:04x}:\t\tover", opcode),
                Ok((new_pc, dis_inst)) => if op == "???" || op == "unimplemented_1111" || op == "unimplemented_1010" || op == "illegal" {
                    over += 1;
                    println!("{:04x}: {} disasm over, {}", opcode, op, dis_inst);
                },
            }
        };
        println!("{}  opcodes over, {} under", over, under);
    }
}
<commit_msg>Verify disasm mnemonic is correct<commit_after>#[macro_use]
#[cfg(test)]
extern crate lazy_static;
#[cfg(test)]
extern crate itertools;
extern crate r68k_common;
#[cfg(test)]
extern crate r68k_tools;

pub mod cpu;
pub mod ram;
pub mod interrupts;
pub mod musashi;

#[cfg(test)]
mod tests {
    use cpu::TestCore;
    use r68k_tools::memory::MemoryVec;
    use r68k_tools::PC;
    use r68k_tools::disassembler::disassemble;
    use r68k_tools::Exception;
    use cpu::ops::handlers::InstructionSetGenerator;
    use cpu::ops::handlers::OpcodeHandler;
    use r68k_tools::disassembler::Disassembler;

    #[test]
    // #[ignore]
    fn roundtrips() {
        let mut over = 0;
        let mut under = 0;
        let mut wrong = 0;
        let gen = InstructionSetGenerator::<TestCore>::new();
        let optable: Vec<&str> = gen.generate_with("???", |ref op| op.name);
        let d = Disassembler::new();
        for opcode in 0x0000..0xffff {
            let op = optable[opcode];
            let parts:Vec<&str> = op.split('_').collect();
            let mnemonic = parts[0];
            let mut pc = PC(0);
            let extension_word_mask = 0b1111_1000_1111_1111;
            // bits 8-10 should always be zero in the ea extension word
            // as we don't know which word will be seen as the ea extension word
            // (as opposed to immediate operand values) just make sure these aren't set.
            let dasm_mem = &mut MemoryVec::new16(pc, vec![opcode as u16, 0x001f, 0x00a4, 0x1234 & extension_word_mask, 0x5678 & extension_word_mask]);
            // println!("PREDASM {:04x}", opcode);
            match d.disassemble(pc, dasm_mem) {
                Err(Exception::IllegalInstruction(_opcode, _)) => if op != "???" && op != "unimplemented_1111" && op != "unimplemented_1010" && op != "illegal" {
                    under += 1;
                    println!("{:04x}: {} disasm under", opcode, op);
                }
                , //println!("{:04x}:\t\tover", opcode),
                Ok((new_pc, dis_inst)) => if op == "???" || op == "unimplemented_1111" || op == "unimplemented_1010" || op == "illegal" {
                    over += 1;
                    println!("{:04x}: {} disasm over, {}", opcode, op, dis_inst);
                } else if dis_inst.mnemonic.to_lowercase() != mnemonic && mnemonic != "real" { // ILLEGAL == real_illegal
                    wrong += 1;
                    println!("{:04x}: {} disasm different {}", opcode, op, dis_inst);
                },
            }
        };
        println!("{}  opcodes over, {} under, {} wrong", over, under, wrong);
    }
}
<|endoftext|>


<commit_before>#[macro_use] extern crate iron;
#[macro_use] extern crate log;
extern crate env_logger;
extern crate hyper;
extern crate router;
extern crate rust_playpen;
extern crate rustc_serialize;
extern crate staticfile;
extern crate unicase;

use rust_playpen::*;

use iron::prelude::*;
use iron::status;
use iron::headers;
use iron::middleware::AfterMiddleware;
use iron::modifiers::Header;
use iron::method::Method;
use hyper::header;
use staticfile::Static;
use router::Router;
use unicase::UniCase;
use rustc_serialize::json;

use std::fmt;
use std::path::Path;
use std::io::Read;
use std::process::Command;

#[derive(Clone, Debug)]
struct XXssProtection(bool);

impl header::Header for XXssProtection {
    fn header_name() -> &'static str {
        "X-XSS-Protection"
    }

    fn parse_header(raw: &[Vec<u8>]) -> hyper::Result<Self> {
        if raw.len() == 1 {
            let line = &raw[0];
            if line.len() == 1 {
                let byte = line[0];
                match byte {
                    b'1' => return Ok(XXssProtection(true)),
                    b'0' => return Ok(XXssProtection(false)),
                    _ => ()
                }
            }
        }
        Err(hyper::Error::Header)
    }
}

impl header::HeaderFormat for XXssProtection {
    fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.0 {
            f.write_str("1")
        } else {
            f.write_str("0")
        }
    }
}

fn index(_: &mut Request) -> IronResult<Response> {
    Ok(Response::with((Path::new("static/web.html"),
                       Header(XXssProtection(false)))))
}

/// The JSON-encoded request sent to `evaluate.json`.
#[derive(RustcDecodable)]
struct EvaluateReq {
    color: Option<bool>,
    test: Option<bool>,
    version: Option<String>,
    optimize: Option<String>,
    separate_output: Option<bool>,
    code: String,
}

fn evaluate(req: &mut Request) -> IronResult<Response> {
    let mut body = String::new();
    itry!(req.body.read_to_string(&mut body));

    let data: EvaluateReq = itry!(json::decode(&body));
    let color = data.color.unwrap_or(false);
    let test = data.test.unwrap_or(false);
    let version = itry!(data.version.map(|v| v.parse()).unwrap_or(Ok(ReleaseChannel::Stable)));
    let opt = itry!(data.optimize.map(|opt| opt.parse()).unwrap_or(Ok(OptLevel::O2)));
    let separate_output = data.separate_output.unwrap_or(false);

    let mut args = vec![String::from("-C"), format!("opt-level={}", opt.as_u8())];
    if opt == OptLevel::O0 {
        args.push(String::from("-g"));
    }
    if color {
        args.push(String::from("--color=always"));
    }
    if test {
        args.push(String::from("--test"));
    }

    let (_status, output) = itry!(rust_playpen::exec(version,
                                                     "/usr/local/bin/evaluate.sh",
                                                     args,
                                                     data.code));

    let mut obj = json::Object::new();
    if separate_output {
        // {"rustc": "...", "program": "..."}
        let mut split = output.splitn(2, |b| *b == b'\xff');
        let rustc = String::from_utf8(split.next().unwrap().into()).unwrap();

        obj.insert(String::from("rustc"), json::Json::String(rustc));

        if let Some(program) = split.next() {
            // Compilation succeeded
            let output = String::from_utf8_lossy(program).into_owned();
            obj.insert(String::from("program"), json::Json::String(output));
        }
    } else {
        // {"result": "...""}
        let result = output.splitn(2, |b| *b == b'\xff')
                           .map(|sub| String::from_utf8_lossy(sub).into_owned())
                           .collect::<String>();

        obj.insert(String::from("result"), json::Json::String(result));
    }

    Ok(Response::with((status::Ok, format!("{}", json::Json::Object(obj)))))
}

#[derive(RustcDecodable)]
struct CompileReq {
    syntax: Option<String>,
    color: Option<bool>,
    version: Option<String>,
    optimize: Option<String>,
    emit: Option<String>,
    code: String,
}

fn compile(req: &mut Request) -> IronResult<Response> {
    let mut body = String::new();
    itry!(req.body.read_to_string(&mut body));

    let data: CompileReq = itry!(json::decode(&body));
    let syntax = data.syntax.map(|s| s.parse().unwrap()).unwrap_or(AsmFlavor::Att);
    let color = data.color.unwrap_or(false);
    let version = itry!(data.version.map(|v| v.parse()).unwrap_or(Ok(ReleaseChannel::Stable)));
    let opt = itry!(data.optimize.map(|opt| opt.parse()).unwrap_or(Ok(OptLevel::O2)));
    let emit = itry!(data.emit.map(|emit| emit.parse()).unwrap_or(Ok(CompileOutput::Asm)));

    let mut args = vec![
        String::from("-C"),
        format!("opt-level={}", opt.as_u8()),
        String::from("-C"),
        format!("llvm-args=-x86-asm-syntax={}", syntax.as_str()),
    ];
    for opt in emit.as_opts() {
        args.push(String::from(*opt));
    }
    if opt == OptLevel::O0 {
        args.push(String::from("-g"));
    }
    if color {
        args.push(String::from("--color=always"));
    }

    let (_status, output) = itry!(
        rust_playpen::exec(version, "/usr/local/bin/compile.sh", args, data.code));
    let mut split = output.splitn(2, |b| *b == b'\xff');
    let rustc = String::from_utf8(split.next().unwrap().into()).unwrap();

    let mut obj = json::Object::new();
    match split.next() {
        Some(program_out) => {
            // Compilation succeeded
            let output = highlight(emit,
                                   &String::from_utf8_lossy(program_out).into_owned());
            obj.insert(String::from("result"), json::Json::String(output));
        }
        None => {
            obj.insert(String::from("error"), json::Json::String(rustc));
        }
    }

    Ok(Response::with((status::Ok, format!("{}", json::Json::Object(obj)))))
}

#[derive(RustcDecodable)]
struct FormatReq {
    version: Option<String>,
    code: String,
}

fn format(req: &mut Request) -> IronResult<Response> {
    let mut body = String::new();
    req.body.read_to_string(&mut body).unwrap();

    let data: FormatReq = itry!(json::decode(&body));
    let version = itry!(data.version.map(|v| v.parse()).unwrap_or(Ok(ReleaseChannel::Stable)));

    let (status, output) = itry!(
        rust_playpen::exec(version, "rustfmt", Vec::new(), data.code));
    let output = String::from_utf8(output).unwrap();
    let mut response_obj = json::Object::new();
    if status.success() {
        response_obj.insert(String::from("result"), json::Json::String(output));
    } else {
        response_obj.insert(String::from("error"), json::Json::String(output));
    }

    Ok(Response::with((status::Ok, format!("{}", json::Json::Object(response_obj)))))
}

// This is neat!
struct EnablePostCors;
impl AfterMiddleware for EnablePostCors {
    fn after(&self, _: &mut Request, res: Response) -> IronResult<Response> {
        Ok(res.set(Header(headers::AccessControlAllowOrigin::Any))
              .set(Header(headers::AccessControlAllowMethods(
                  vec![Method::Post,
                       Method::Options])))
              .set(Header(headers::AccessControlAllowHeaders(
                  vec![UniCase(String::from("Origin")),
                       UniCase(String::from("Accept")),
                       UniCase(String::from("Content-Type"))]))))
    }
}

fn main() {
    env_logger::init().unwrap();

    // Make sure pygmentize is installed before starting the server
    Command::new("pygmentize").spawn().unwrap().kill().unwrap();

    let mut router = Router::new();
    router.get("/", index);
    router.get("/:path", Static::new("static"));
    router.post("/evaluate.json", evaluate);
    router.post("/compile.json", compile);
    router.post("/format.json", format);

    // Use our router as the middleware, and pass the generated response through `EnablePostCors`
    let mut chain = Chain::new(router);
    chain.link_after(EnablePostCors);

    let addr = ("127.0.0.1", 8080);
    println!("listening on {:?}", addr);
    Iron::new(chain).http(addr).unwrap();
}
<commit_msg>Read address to listen on from command line<commit_after>#[macro_use] extern crate iron;
#[macro_use] extern crate log;
extern crate env_logger;
extern crate hyper;
extern crate router;
extern crate rust_playpen;
extern crate rustc_serialize;
extern crate staticfile;
extern crate unicase;

use rust_playpen::*;

use iron::prelude::*;
use iron::status;
use iron::headers;
use iron::middleware::AfterMiddleware;
use iron::modifiers::Header;
use iron::method::Method;
use hyper::header;
use staticfile::Static;
use router::Router;
use unicase::UniCase;
use rustc_serialize::json;

use std::env;
use std::fmt;
use std::io::Read;
use std::path::Path;
use std::process::Command;

#[derive(Clone, Debug)]
struct XXssProtection(bool);

impl header::Header for XXssProtection {
    fn header_name() -> &'static str {
        "X-XSS-Protection"
    }

    fn parse_header(raw: &[Vec<u8>]) -> hyper::Result<Self> {
        if raw.len() == 1 {
            let line = &raw[0];
            if line.len() == 1 {
                let byte = line[0];
                match byte {
                    b'1' => return Ok(XXssProtection(true)),
                    b'0' => return Ok(XXssProtection(false)),
                    _ => ()
                }
            }
        }
        Err(hyper::Error::Header)
    }
}

impl header::HeaderFormat for XXssProtection {
    fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.0 {
            f.write_str("1")
        } else {
            f.write_str("0")
        }
    }
}

fn index(_: &mut Request) -> IronResult<Response> {
    Ok(Response::with((Path::new("static/web.html"),
                       Header(XXssProtection(false)))))
}

/// The JSON-encoded request sent to `evaluate.json`.
#[derive(RustcDecodable)]
struct EvaluateReq {
    color: Option<bool>,
    test: Option<bool>,
    version: Option<String>,
    optimize: Option<String>,
    separate_output: Option<bool>,
    code: String,
}

fn evaluate(req: &mut Request) -> IronResult<Response> {
    let mut body = String::new();
    itry!(req.body.read_to_string(&mut body));

    let data: EvaluateReq = itry!(json::decode(&body));
    let color = data.color.unwrap_or(false);
    let test = data.test.unwrap_or(false);
    let version = itry!(data.version.map(|v| v.parse()).unwrap_or(Ok(ReleaseChannel::Stable)));
    let opt = itry!(data.optimize.map(|opt| opt.parse()).unwrap_or(Ok(OptLevel::O2)));
    let separate_output = data.separate_output.unwrap_or(false);

    let mut args = vec![String::from("-C"), format!("opt-level={}", opt.as_u8())];
    if opt == OptLevel::O0 {
        args.push(String::from("-g"));
    }
    if color {
        args.push(String::from("--color=always"));
    }
    if test {
        args.push(String::from("--test"));
    }

    let (_status, output) = itry!(rust_playpen::exec(version,
                                                     "/usr/local/bin/evaluate.sh",
                                                     args,
                                                     data.code));

    let mut obj = json::Object::new();
    if separate_output {
        // {"rustc": "...", "program": "..."}
        let mut split = output.splitn(2, |b| *b == b'\xff');
        let rustc = String::from_utf8(split.next().unwrap().into()).unwrap();

        obj.insert(String::from("rustc"), json::Json::String(rustc));

        if let Some(program) = split.next() {
            // Compilation succeeded
            let output = String::from_utf8_lossy(program).into_owned();
            obj.insert(String::from("program"), json::Json::String(output));
        }
    } else {
        // {"result": "...""}
        let result = output.splitn(2, |b| *b == b'\xff')
                           .map(|sub| String::from_utf8_lossy(sub).into_owned())
                           .collect::<String>();

        obj.insert(String::from("result"), json::Json::String(result));
    }

    Ok(Response::with((status::Ok, format!("{}", json::Json::Object(obj)))))
}

#[derive(RustcDecodable)]
struct CompileReq {
    syntax: Option<String>,
    color: Option<bool>,
    version: Option<String>,
    optimize: Option<String>,
    emit: Option<String>,
    code: String,
}

fn compile(req: &mut Request) -> IronResult<Response> {
    let mut body = String::new();
    itry!(req.body.read_to_string(&mut body));

    let data: CompileReq = itry!(json::decode(&body));
    let syntax = data.syntax.map(|s| s.parse().unwrap()).unwrap_or(AsmFlavor::Att);
    let color = data.color.unwrap_or(false);
    let version = itry!(data.version.map(|v| v.parse()).unwrap_or(Ok(ReleaseChannel::Stable)));
    let opt = itry!(data.optimize.map(|opt| opt.parse()).unwrap_or(Ok(OptLevel::O2)));
    let emit = itry!(data.emit.map(|emit| emit.parse()).unwrap_or(Ok(CompileOutput::Asm)));

    let mut args = vec![
        String::from("-C"),
        format!("opt-level={}", opt.as_u8()),
        String::from("-C"),
        format!("llvm-args=-x86-asm-syntax={}", syntax.as_str()),
    ];
    for opt in emit.as_opts() {
        args.push(String::from(*opt));
    }
    if opt == OptLevel::O0 {
        args.push(String::from("-g"));
    }
    if color {
        args.push(String::from("--color=always"));
    }

    let (_status, output) = itry!(
        rust_playpen::exec(version, "/usr/local/bin/compile.sh", args, data.code));
    let mut split = output.splitn(2, |b| *b == b'\xff');
    let rustc = String::from_utf8(split.next().unwrap().into()).unwrap();

    let mut obj = json::Object::new();
    match split.next() {
        Some(program_out) => {
            // Compilation succeeded
            let output = highlight(emit,
                                   &String::from_utf8_lossy(program_out).into_owned());
            obj.insert(String::from("result"), json::Json::String(output));
        }
        None => {
            obj.insert(String::from("error"), json::Json::String(rustc));
        }
    }

    Ok(Response::with((status::Ok, format!("{}", json::Json::Object(obj)))))
}

#[derive(RustcDecodable)]
struct FormatReq {
    version: Option<String>,
    code: String,
}

fn format(req: &mut Request) -> IronResult<Response> {
    let mut body = String::new();
    req.body.read_to_string(&mut body).unwrap();

    let data: FormatReq = itry!(json::decode(&body));
    let version = itry!(data.version.map(|v| v.parse()).unwrap_or(Ok(ReleaseChannel::Stable)));

    let (status, output) = itry!(
        rust_playpen::exec(version, "rustfmt", Vec::new(), data.code));
    let output = String::from_utf8(output).unwrap();
    let mut response_obj = json::Object::new();
    if status.success() {
        response_obj.insert(String::from("result"), json::Json::String(output));
    } else {
        response_obj.insert(String::from("error"), json::Json::String(output));
    }

    Ok(Response::with((status::Ok, format!("{}", json::Json::Object(response_obj)))))
}

// This is neat!
struct EnablePostCors;
impl AfterMiddleware for EnablePostCors {
    fn after(&self, _: &mut Request, res: Response) -> IronResult<Response> {
        Ok(res.set(Header(headers::AccessControlAllowOrigin::Any))
              .set(Header(headers::AccessControlAllowMethods(
                  vec![Method::Post,
                       Method::Options])))
              .set(Header(headers::AccessControlAllowHeaders(
                  vec![UniCase(String::from("Origin")),
                       UniCase(String::from("Accept")),
                       UniCase(String::from("Content-Type"))]))))
    }
}

fn main() {
    env_logger::init().unwrap();

    // Make sure pygmentize is installed before starting the server
    Command::new("pygmentize").spawn().unwrap().kill().unwrap();

    let mut router = Router::new();
    router.get("/", index);
    router.get("/:path", Static::new("static"));
    router.post("/evaluate.json", evaluate);
    router.post("/compile.json", compile);
    router.post("/format.json", format);

    // Use our router as the middleware, and pass the generated response through `EnablePostCors`
    let mut chain = Chain::new(router);
    chain.link_after(EnablePostCors);

    let addr = env::args().skip(1).next().unwrap_or("127.0.0.1".to_string());
    let addr = (&addr[..], 8080);
    println!("listening on {:?}", addr);
    Iron::new(chain).http(addr).unwrap();
}
<|endoftext|>


<commit_before>//! Extensions to the parsing API with niche applicability.

use super::*;

/// Extensions to the `ParseStream` API to support speculative parsing.
pub trait Speculative {
    /// Advance this parse stream to the position of a forked parse stream.
    ///
    /// This is the opposite operation to [`ParseStream::fork`].
    /// You can fork a parse stream, perform some speculative parsing, then join
    /// the original stream to the fork to "commit" the parsing from the fork to
    /// the main stream.
    ///
    /// If you can avoid doing this, you should, as it limits the ability to
    /// generate useful errors. That said, it is often the only way to parse
    /// syntax of the form `A* B*` for arbitrary syntax `A` and `B`. The problem
    /// is that when the fork fails to parse an `A`, it's impossible to tell
    /// whether that was because of a syntax error and the user meant to provide
    /// an `A`, or that the `A`s are finished and its time to start parsing `B`s.
    /// Use with care.
    ///
    /// Also note that if `A` is a subset of `B`, `A* B*` can be parsed by parsing
    /// `B*` and removing the leading members of `A` from the repetition, bypassing
    /// the need to involve the downsides associated with speculative parsing.
    ///
    /// [`ParseStream::fork`]: ../struct.ParseBuffer.html#method.fork
    ///
    /// # Example
    ///
    /// There has been chatter about the possibility of making the colons in the
    /// turbofish syntax like `path::to::<T>` no longer required by accepting
    /// `path::to<T>` in expression position. Specifically, according to [RFC#2544],
    /// [`PathSegment`] parsing should always try to consume a following `<` token
    /// as the start of generic arguments, and reset to the `<` if that fails
    /// (e.g. the token is acting as a less-than operator).
    ///
    /// This is the exact kind of parsing behavior which requires the "fork, try,
    /// commit" behavior that [`ParseStream::fork`] discourages. With `advance_to`,
    /// we can avoid having to parse the speculatively parsed content a second time.
    ///
    /// This change in behavior can be implemented in syn by replacing just the
    /// `Parse` implementation for `PathSegment`:
    ///
    /// ```edition2018
    /// # use syn::ext::IdentExt;
    /// use syn::parse::discouraged::Speculative;
    /// # use syn::parse::{Parse, ParseStream};
    /// # use syn::{Ident, PathArguments, Result, Token};
    ///
    /// pub struct PathSegment {
    ///     pub ident: Ident,
    ///     pub arguments: PathArguments,
    /// }
    ///
    /// # impl<T> From<T> for PathSegment
    /// # where
    /// #     T: Into<Ident>,
    /// # {
    /// #     fn from(ident: T) -> Self {
    /// #         PathSegment {
    /// #             ident: ident.into(),
    /// #             arguments: PathArguments::None,
    /// #         }
    /// #     }
    /// # }
    ///
    ///
    /// impl Parse for PathSegment {
    ///     fn parse(input: ParseStream) -> Result<Self> {
    ///         if input.peek(Token![super])
    ///             || input.peek(Token![self])
    ///             || input.peek(Token![Self])
    ///             || input.peek(Token![crate])
    ///             || input.peek(Token![extern])
    ///         {
    ///             let ident = input.call(Ident::parse_any)?;
    ///             return Ok(PathSegment::from(ident));
    ///         }
    ///
    ///         let ident = input.parse()?;
    ///         if input.peek(Token![::]) && input.peek3(Token![<]) {
    ///             return Ok(PathSegment {
    ///                 ident: ident,
    ///                 arguments: PathArguments::AngleBracketed(input.parse()?),
    ///             });
    ///         }
    ///         if input.peek(Token![<]) && !input.peek(Token![<=]) {
    ///             let fork = input.fork();
    ///             if let Ok(arguments) = fork.parse() {
    ///                 input.advance_to(&fork);
    ///                 return Ok(PathSegment {
    ///                     ident: ident,
    ///                     arguments: PathArguments::AngleBracketed(arguments),
    ///                 });
    ///             }
    ///         }
    ///         Ok(PathSegment::from(ident))
    ///     }
    /// }
    ///
    /// # syn::parse_str::<PathSegment>("a<b,c>").unwrap();
    /// ```
    ///
    /// # Drawbacks
    ///
    /// The main drawback of this style of speculative parsing is in error
    /// presentation. Even if the lookahead is the "correct" parse, the error
    /// that is shown is that of the "fallback" parse. To use the same example
    /// as the turbofish above, take the following unfinished "turbofish":
    ///
    /// ```text
    /// let _ = f<&'a fn(), for<'a> serde::>();
    /// ```
    ///
    /// If this is parsed as generic arguments, we can provide the error message
    ///
    /// ```text
    /// error: expected identifier
    ///  --> src.rs:L:C
    ///   |
    /// L | let _ = f<&'a fn(), for<'a> serde::>();
    ///   |                                    ^
    /// ```
    ///
    /// but if parsed using the above speculative parsing, it falls back to
    /// assuming that the `<` is a less-than when it fails to parse the
    /// generic arguments, and tries to interpret the `&'a` as the start of a
    /// labelled loop, resulting in the much less helpful error
    ///
    /// ```text
    /// error: expected `:`
    ///  --> src.rs:L:C
    ///   |
    /// L | let _ = f<&'a fn(), for<'a> serde::>();
    ///   |               ^^
    /// ```
    ///
    /// This can be mitigated with various heuristics (two examples: show both
    /// forks' parse errors, or show the one that consumed more tokens), but
    /// when you can control the grammar, sticking to something that can be
    /// parsed LL(3) and without the LL(*) speculative parsing this makes
    /// possible, displaying reasonable errors becomes much more simple.
    ///
    /// [RFC#2544]: https://github.com/rust-lang/rfcs/pull/2544
    /// [`PathSegment`]: ../../struct.PathSegment.html
    ///
    /// # Performance
    ///
    /// This method performs a cheap fixed amount of work that does not depend
    /// on how far apart the two streams are positioned.
    ///
    /// # Panics
    ///
    /// The forked stream that this joins with must be derived by forking this parse stream.
    fn advance_to(&self, fork: &Self);
}

impl<'a> Speculative for ParseBuffer<'a> {
    fn advance_to(&self, fork: &Self) {
        if !private::same_scope(self.cursor(), fork.cursor()) {
            panic!("Fork was not derived from the advancing parse stream");
        }

        // See comment on `cell` in the struct definition.
        self.cell
            .set(unsafe { mem::transmute::<Cursor, Cursor<'static>>(fork.cursor()) })
    }
}
<commit_msg>Adjust wording of advance_to panic documentation<commit_after>//! Extensions to the parsing API with niche applicability.

use super::*;

/// Extensions to the `ParseStream` API to support speculative parsing.
pub trait Speculative {
    /// Advance this parse stream to the position of a forked parse stream.
    ///
    /// This is the opposite operation to [`ParseStream::fork`].
    /// You can fork a parse stream, perform some speculative parsing, then join
    /// the original stream to the fork to "commit" the parsing from the fork to
    /// the main stream.
    ///
    /// If you can avoid doing this, you should, as it limits the ability to
    /// generate useful errors. That said, it is often the only way to parse
    /// syntax of the form `A* B*` for arbitrary syntax `A` and `B`. The problem
    /// is that when the fork fails to parse an `A`, it's impossible to tell
    /// whether that was because of a syntax error and the user meant to provide
    /// an `A`, or that the `A`s are finished and its time to start parsing `B`s.
    /// Use with care.
    ///
    /// Also note that if `A` is a subset of `B`, `A* B*` can be parsed by parsing
    /// `B*` and removing the leading members of `A` from the repetition, bypassing
    /// the need to involve the downsides associated with speculative parsing.
    ///
    /// [`ParseStream::fork`]: ../struct.ParseBuffer.html#method.fork
    ///
    /// # Example
    ///
    /// There has been chatter about the possibility of making the colons in the
    /// turbofish syntax like `path::to::<T>` no longer required by accepting
    /// `path::to<T>` in expression position. Specifically, according to [RFC#2544],
    /// [`PathSegment`] parsing should always try to consume a following `<` token
    /// as the start of generic arguments, and reset to the `<` if that fails
    /// (e.g. the token is acting as a less-than operator).
    ///
    /// This is the exact kind of parsing behavior which requires the "fork, try,
    /// commit" behavior that [`ParseStream::fork`] discourages. With `advance_to`,
    /// we can avoid having to parse the speculatively parsed content a second time.
    ///
    /// This change in behavior can be implemented in syn by replacing just the
    /// `Parse` implementation for `PathSegment`:
    ///
    /// ```edition2018
    /// # use syn::ext::IdentExt;
    /// use syn::parse::discouraged::Speculative;
    /// # use syn::parse::{Parse, ParseStream};
    /// # use syn::{Ident, PathArguments, Result, Token};
    ///
    /// pub struct PathSegment {
    ///     pub ident: Ident,
    ///     pub arguments: PathArguments,
    /// }
    ///
    /// # impl<T> From<T> for PathSegment
    /// # where
    /// #     T: Into<Ident>,
    /// # {
    /// #     fn from(ident: T) -> Self {
    /// #         PathSegment {
    /// #             ident: ident.into(),
    /// #             arguments: PathArguments::None,
    /// #         }
    /// #     }
    /// # }
    ///
    ///
    /// impl Parse for PathSegment {
    ///     fn parse(input: ParseStream) -> Result<Self> {
    ///         if input.peek(Token![super])
    ///             || input.peek(Token![self])
    ///             || input.peek(Token![Self])
    ///             || input.peek(Token![crate])
    ///             || input.peek(Token![extern])
    ///         {
    ///             let ident = input.call(Ident::parse_any)?;
    ///             return Ok(PathSegment::from(ident));
    ///         }
    ///
    ///         let ident = input.parse()?;
    ///         if input.peek(Token![::]) && input.peek3(Token![<]) {
    ///             return Ok(PathSegment {
    ///                 ident: ident,
    ///                 arguments: PathArguments::AngleBracketed(input.parse()?),
    ///             });
    ///         }
    ///         if input.peek(Token![<]) && !input.peek(Token![<=]) {
    ///             let fork = input.fork();
    ///             if let Ok(arguments) = fork.parse() {
    ///                 input.advance_to(&fork);
    ///                 return Ok(PathSegment {
    ///                     ident: ident,
    ///                     arguments: PathArguments::AngleBracketed(arguments),
    ///                 });
    ///             }
    ///         }
    ///         Ok(PathSegment::from(ident))
    ///     }
    /// }
    ///
    /// # syn::parse_str::<PathSegment>("a<b,c>").unwrap();
    /// ```
    ///
    /// # Drawbacks
    ///
    /// The main drawback of this style of speculative parsing is in error
    /// presentation. Even if the lookahead is the "correct" parse, the error
    /// that is shown is that of the "fallback" parse. To use the same example
    /// as the turbofish above, take the following unfinished "turbofish":
    ///
    /// ```text
    /// let _ = f<&'a fn(), for<'a> serde::>();
    /// ```
    ///
    /// If this is parsed as generic arguments, we can provide the error message
    ///
    /// ```text
    /// error: expected identifier
    ///  --> src.rs:L:C
    ///   |
    /// L | let _ = f<&'a fn(), for<'a> serde::>();
    ///   |                                    ^
    /// ```
    ///
    /// but if parsed using the above speculative parsing, it falls back to
    /// assuming that the `<` is a less-than when it fails to parse the
    /// generic arguments, and tries to interpret the `&'a` as the start of a
    /// labelled loop, resulting in the much less helpful error
    ///
    /// ```text
    /// error: expected `:`
    ///  --> src.rs:L:C
    ///   |
    /// L | let _ = f<&'a fn(), for<'a> serde::>();
    ///   |               ^^
    /// ```
    ///
    /// This can be mitigated with various heuristics (two examples: show both
    /// forks' parse errors, or show the one that consumed more tokens), but
    /// when you can control the grammar, sticking to something that can be
    /// parsed LL(3) and without the LL(*) speculative parsing this makes
    /// possible, displaying reasonable errors becomes much more simple.
    ///
    /// [RFC#2544]: https://github.com/rust-lang/rfcs/pull/2544
    /// [`PathSegment`]: ../../struct.PathSegment.html
    ///
    /// # Performance
    ///
    /// This method performs a cheap fixed amount of work that does not depend
    /// on how far apart the two streams are positioned.
    ///
    /// # Panics
    ///
    /// The forked stream in the argument of `advance_to` must have been
    /// obtained by forking `self`. Attempting to advance to any other stream
    /// will cause a panic.
    fn advance_to(&self, fork: &Self);
}

impl<'a> Speculative for ParseBuffer<'a> {
    fn advance_to(&self, fork: &Self) {
        if !private::same_scope(self.cursor(), fork.cursor()) {
            panic!("Fork was not derived from the advancing parse stream");
        }

        // See comment on `cell` in the struct definition.
        self.cell
            .set(unsafe { mem::transmute::<Cursor, Cursor<'static>>(fork.cursor()) })
    }
}
<|endoftext|>


<commit_before>use std::clone::Clone;
use std::collections::HashMap;
use std::convert::AsRef;
use std::convert::Into;
use std::error::Error;
use std::rc::Rc;

use crate::ast::Position;
use crate::ast::PositionedItem;
use crate::build::ir::Val;
use crate::error;

pub fn find_in_fieldlist(
    target: &str,
    fs: &Vec<(PositionedItem<String>, Rc<Val>)>,
) -> Option<Rc<Val>> {
    for (key, val) in fs.iter().cloned() {
        if target == &key.val {
            return Some(val.clone());
        }
    }
    return None;
}

/// Defines a set of values in a parsed file.
pub type ValueMap = HashMap<PositionedItem<String>, Rc<Val>>;

/// Defines a scope for execution in ucg.
///
/// Scopes in ucg are defined by the currently executing file and
/// the complex data types in that file. (Tuple, List, Modules, and the
/// left operands for dot selectors).
///
/// UCG Scopes do not descend up into their parent scopes so we do not maintain a stack
/// for those.
#[derive(Debug, PartialEq, Clone)]
pub struct Scope {
    pub import_stack: Vec<String>,
    pub env: Rc<Val>,
    pub curr_val: Option<Rc<Val>>,
    pub build_output: ValueMap,
    pub search_curr_val: bool,
}

impl Scope {
    // Construct a new scope with environment variables.
    pub fn new(env: Rc<Val>) -> Self {
        Self {
            import_stack: Vec::new(),
            env: env,
            // CurrVal represents the currently processing value.
            // (eg: Tuple, List. left side of a dot selection.)
            curr_val: None,
            build_output: HashMap::new(),
            search_curr_val: false,
        }
    }

    pub fn use_curr_val(mut self) -> Self {
        self.search_curr_val = true;
        self
    }

    /// Spawn a child scope based on the current scope but without the current
    /// val set.
    pub fn spawn_child(&self) -> Self {
        Self {
            import_stack: self.import_stack.clone(),
            env: self.env.clone(),
            // Children start with no current val
            curr_val: None,
            build_output: self.build_output.clone(),
            search_curr_val: false,
        }
    }

    pub fn spawn_clean(&self) -> Self {
        Self {
            import_stack: self.import_stack.clone(),
            env: self.env.clone(),
            // Children start with no current val
            curr_val: None,
            build_output: HashMap::new(),
            search_curr_val: false,
        }
    }

    /// Push an import onto the import stack.
    pub fn push_import<S: Into<String>>(&mut self, path: S) {
        self.import_stack.push(path.into());
    }

    pub fn prepend_import_stack(&mut self, imports: &Vec<String>) {
        let mut new_stack = self.import_stack.clone();
        new_stack.append(imports.clone().as_mut());
        self.import_stack = new_stack;
    }

    /// Set the current value for our execution context.
    pub fn set_curr_val(mut self, val: Rc<Val>) -> Self {
        self.curr_val = Some(val);
        self
    }

    /// Lookup up a list index in the current value
    pub fn lookup_idx(&self, pos: &Position, idx: &Val) -> Result<Rc<Val>, Box<dyn Error>> {
        if self.search_curr_val && self.curr_val.is_some() {
            if let &Val::List(ref fs) = self.curr_val.as_ref().unwrap().as_ref() {
                return Self::lookup_in_list(pos, idx, fs);
            }
        }
        Err(Box::new(error::BuildError::new(
            "Not a list in index lookup.",
            error::ErrorType::TypeFail,
            pos.clone(),
        )))
    }

    /// Lookup a symbol in the current execution context.
    ///
    /// The lookup rules are simple.
    ///
    /// * `env` is always an environment variable lookup.
    /// * `self` is always the current value. This symbol is only
    ///    valid when the current value is a tuple.
    /// * everything else is looked up in the currently accumulated build output
    ///   for this execution context.
    pub fn lookup_sym(&self, sym: &PositionedItem<String>, is_symbol: bool) -> Option<Rc<Val>> {
        if &sym.val == "env" && is_symbol {
            return Some(self.env.clone());
        }
        if &sym.val == "self" && is_symbol {
            return self.curr_val.clone();
        }
        if self.search_curr_val && self.curr_val.is_some() {
            match self.curr_val.as_ref().unwrap().as_ref() {
                &Val::Env(ref fs) => {
                    for (name, val) in fs.iter() {
                        if name == &sym.val {
                            return Some(Rc::new(Val::Str(val.clone())));
                        }
                    }
                }
                &Val::Tuple(ref fs) => match Self::lookup_in_tuple(&sym.pos, &sym.val, fs) {
                    Ok(v) => return Some(v),
                    Err(_) => {
                        // noop
                    }
                },
                &Val::List(ref fs) => {
                    match Self::lookup_in_list(&sym.pos, &Val::Str(sym.val.clone()), fs) {
                        Ok(v) => return Some(v),
                        Err(_) => {
                            // noop
                        }
                    }
                }
                _ => {
                    // noop
                }
            };
        }
        if self.build_output.contains_key(sym) {
            return Some(self.build_output[sym].clone());
        }
        None
    }

    fn lookup_in_tuple(
        pos: &Position,
        field: &str,
        fs: &Vec<(PositionedItem<String>, Rc<Val>)>,
    ) -> Result<Rc<Val>, Box<dyn Error>> {
        if let Some(vv) = find_in_fieldlist(&field, fs) {
            Ok(vv)
        } else {
            Err(Box::new(error::BuildError::new(
                format!("Unable to {} match element in tuple.", field,),
                error::ErrorType::NoSuchSymbol,
                pos.clone(),
            )))
        }
    }

    fn lookup_in_list(
        pos: &Position,
        field: &Val,
        elems: &Vec<Rc<Val>>,
    ) -> Result<Rc<Val>, Box<dyn Error>> {
        let idx = match field {
            &Val::Int(i) => i as usize,
            &Val::Str(ref s) => s.parse::<usize>()?,
            _ => {
                return Err(Box::new(error::BuildError::new(
                    format!("Invalid idx type {} for list lookup", field),
                    error::ErrorType::TypeFail,
                    pos.clone(),
                )));
            }
        };
        if idx < elems.len() {
            Ok(elems[idx].clone())
        } else {
            Err(Box::new(error::BuildError::new(
                format!("idx {} out of bounds in list", idx),
                error::ErrorType::NoSuchSymbol,
                pos.clone(),
            )))
        }
    }
}
<commit_msg>REFACTOR: Improve the typesafety of lookup_sym.<commit_after>use std::clone::Clone;
use std::collections::HashMap;
use std::convert::AsRef;
use std::convert::Into;
use std::error::Error;
use std::rc::Rc;

use crate::ast::Position;
use crate::ast::PositionedItem;
use crate::build::ir::Val;
use crate::error;

pub fn find_in_fieldlist(
    target: &str,
    fs: &Vec<(PositionedItem<String>, Rc<Val>)>,
) -> Option<Rc<Val>> {
    for (key, val) in fs.iter().cloned() {
        if target == &key.val {
            return Some(val.clone());
        }
    }
    return None;
}

/// Defines a set of values in a parsed file.
pub type ValueMap = HashMap<PositionedItem<String>, Rc<Val>>;

/// Defines a scope for execution in ucg.
///
/// Scopes in ucg are defined by the currently executing file and
/// the complex data types in that file. (Tuple, List, Modules, and the
/// left operands for dot selectors).
///
/// UCG Scopes do not descend up into their parent scopes so we do not maintain a stack
/// for those.
#[derive(Debug, PartialEq, Clone)]
pub struct Scope {
    pub import_stack: Vec<String>,
    pub env: Rc<Val>,
    pub curr_val: Option<Rc<Val>>,
    pub build_output: ValueMap,
    pub search_curr_val: bool,
}

impl Scope {
    // Construct a new scope with environment variables.
    pub fn new(env: Rc<Val>) -> Self {
        Self {
            import_stack: Vec::new(),
            env: env,
            // CurrVal represents the currently processing value.
            // (eg: Tuple, List. left side of a dot selection.)
            curr_val: None,
            build_output: HashMap::new(),
            search_curr_val: false,
        }
    }

    pub fn use_curr_val(mut self) -> Self {
        self.search_curr_val = true;
        self
    }

    /// Spawn a child scope based on the current scope but without the current
    /// val set.
    pub fn spawn_child(&self) -> Self {
        Self {
            import_stack: self.import_stack.clone(),
            env: self.env.clone(),
            // Children start with no current val
            curr_val: None,
            build_output: self.build_output.clone(),
            search_curr_val: false,
        }
    }

    pub fn spawn_clean(&self) -> Self {
        Self {
            import_stack: self.import_stack.clone(),
            env: self.env.clone(),
            // Children start with no current val
            curr_val: None,
            build_output: HashMap::new(),
            search_curr_val: false,
        }
    }

    /// Push an import onto the import stack.
    pub fn push_import<S: Into<String>>(&mut self, path: S) {
        self.import_stack.push(path.into());
    }

    pub fn prepend_import_stack(&mut self, imports: &Vec<String>) {
        let mut new_stack = self.import_stack.clone();
        new_stack.append(imports.clone().as_mut());
        self.import_stack = new_stack;
    }

    /// Set the current value for our execution context.
    pub fn set_curr_val(mut self, val: Rc<Val>) -> Self {
        self.curr_val = Some(val);
        self
    }

    /// Lookup up a list index in the current value
    pub fn lookup_idx(&self, pos: &Position, idx: &Val) -> Result<Rc<Val>, Box<dyn Error>> {
        if self.search_curr_val && self.curr_val.is_some() {
            if let &Val::List(ref fs) = self.curr_val.as_ref().unwrap().as_ref() {
                return Self::lookup_in_list(pos, idx, fs);
            }
        }
        Err(Box::new(error::BuildError::new(
            "Not a list in index lookup.",
            error::ErrorType::TypeFail,
            pos.clone(),
        )))
    }

    /// Lookup a symbol in the current execution context.
    ///
    /// The lookup rules are simple.
    ///
    /// * `env` is always an environment variable lookup.
    /// * `self` is always the current value. This symbol is only
    ///    valid when the current value is a tuple.
    /// * everything else is looked up in the currently accumulated build output
    ///   for this execution context.
    pub fn lookup_sym(&self, sym: &PositionedItem<String>, is_symbol: bool) -> Option<Rc<Val>> {
        if &sym.val == "env" && is_symbol {
            return Some(self.env.clone());
        }
        if &sym.val == "self" && is_symbol {
            return self.curr_val.clone();
        }
        if self.search_curr_val && self.curr_val.is_some() {
            match self.curr_val.as_ref().unwrap().as_ref() {
                Val::Env(ref fs) => {
                    for (name, val) in fs.iter() {
                        if name == &sym.val {
                            return Some(Rc::new(Val::Str(val.clone())));
                        }
                    }
                }
                Val::Tuple(ref fs) => match Self::lookup_in_tuple(&sym.pos, &sym.val, fs) {
                    Ok(v) => return Some(v),
                    Err(_) => {
                        // noop
                    }
                },
                Val::List(ref fs) => {
                    match Self::lookup_in_list(&sym.pos, &Val::Str(sym.val.clone()), fs) {
                        Ok(v) => return Some(v),
                        Err(_) => {
                            // noop
                        }
                    }
                }
                Val::Boolean(_)
                | Val::Empty
                | Val::Float(_)
                | Val::Int(_)
                | Val::Module(_)
                | Val::Str(_)
                | Val::Func(_) => {
                    // noop
                }
            };
        }
        if self.build_output.contains_key(sym) {
            return Some(self.build_output[sym].clone());
        }
        None
    }

    fn lookup_in_tuple(
        pos: &Position,
        field: &str,
        fs: &Vec<(PositionedItem<String>, Rc<Val>)>,
    ) -> Result<Rc<Val>, Box<dyn Error>> {
        if let Some(vv) = find_in_fieldlist(&field, fs) {
            Ok(vv)
        } else {
            Err(Box::new(error::BuildError::new(
                format!("Unable to {} match element in tuple.", field,),
                error::ErrorType::NoSuchSymbol,
                pos.clone(),
            )))
        }
    }

    fn lookup_in_list(
        pos: &Position,
        field: &Val,
        elems: &Vec<Rc<Val>>,
    ) -> Result<Rc<Val>, Box<dyn Error>> {
        let idx = match field {
            &Val::Int(i) => i as usize,
            &Val::Str(ref s) => s.parse::<usize>()?,
            _ => {
                return Err(Box::new(error::BuildError::new(
                    format!("Invalid idx type {} for list lookup", field),
                    error::ErrorType::TypeFail,
                    pos.clone(),
                )));
            }
        };
        if idx < elems.len() {
            Ok(elems[idx].clone())
        } else {
            Err(Box::new(error::BuildError::new(
                format!("idx {} out of bounds in list", idx),
                error::ErrorType::NoSuchSymbol,
                pos.clone(),
            )))
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
<commit_msg>Add geev<commit_after>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
use std::mem;
use std::ptr;
use libc::c_int;
use num::complex::{
    Complex,
};
use error::Error;
use ll::*;
use Matrix;
use Vector;
use scalar::Scalar;
use types::Compute;
use util::ColMem;

pub trait Geev<Eigenvalues>: Sized {
    fn geev(a: &mut Matrix<Self>, values: &mut Vector<Eigenvalues>,
        left: Option<&mut Matrix<Self>>, right: Option<&mut Matrix<Self>>) -> Result<(), Error> {

        let job_l = match &left {
            &Some(_) => Compute::Value,
            _ => Compute::None,
        };

        let job_r = match &right {
            &Some(_) => Compute::Value,
            _ => Compute::None,
        };

        let work_len = try!(Geev::work_len(a, job_l, job_r));
        let mut work: Vec<_> = Vec::with_capacity(work_len as usize);
        unsafe {
            work.set_len(work_len as usize);
        }

        Geev::work(a, values, left, right, &mut work[..])
    }
    fn work(a: &mut Matrix<Self>, values: &mut Vector<Eigenvalues>,
        left: Option<&mut Matrix<Self>>, right: Option<&mut Matrix<Self>>, work: &mut [Self]) -> Result<(), Error>;
    fn work_len(a: &mut Matrix<Self>, left: Compute, right: Compute) -> Result<usize, Error>;
}

macro_rules! real_eigen_impl(($($t: ident), +) => ($(
    impl Geev<Complex<$t>> for $t {
        fn work(a: &mut Matrix<Self>, values: &mut Vector<Complex<$t>>,
            left: Option<&mut Matrix<Self>>, right: Option<&mut Matrix<Self>>, work: &mut [Self]) -> Result<(), Error> {

            let mut info: c_int = 0;
            let n = a.rows();
            if n != a.cols() {
                return Err(Error::DimensionMismatch);
            }
            let mut a_mem = ColMem::new(a.order(), a);

            let (job_l, lead_l, ptr_l) = match left {
                Some(m) => (Compute::Value, m.rows(), m.as_mut_ptr()),
                None => (Compute::None, 1, ptr::null::<$t>() as *mut _),
            };

            let (job_r, lead_r, ptr_r) = match right {
                Some(m) => (Compute::Value, m.rows(), m.as_mut_ptr()),
                None => (Compute::None, 1, ptr::null::<$t>() as *mut _),
            };

            //TODO: this is really bad
            let (real, imag) = unsafe {
                let start = values.as_mut_ptr();
                let mid = start.offset(n as isize);
                (start as *mut $t, mid as *mut $t)
            };

            unsafe {
                prefix!($t, geev_)(
                    job_l.as_i8().as_mut(), job_r.as_i8().as_mut(),
                    n.as_mut(),
                    a_mem.as_mut_ptr(), a_mem.lead().as_mut(),
                    real, imag,
                    ptr_l, lead_l.as_mut(),
                    ptr_r, lead_r.as_mut(),
                    work.as_mut_ptr(), (work.len() as c_int).as_mut(),
                    &mut info as *mut c_int);
            };

            match info {
                0 => Ok(()),
                x if x < 0 => Err(Error::IllegalParameter(-x as usize)),
                x => Err(Error::DiagonalElementZero(x as usize)),
            }
        }

        fn work_len(a: &mut Matrix<Self>, left: Compute, right: Compute) -> Result<usize, Error> {
            let mut info: c_int = 0;
            let mut len_info: $t = unsafe { mem::zeroed() };
            let len_ptr = (&mut len_info) as *mut $t;

            let n = a.rows();
            if n != a.cols() {
                return Err(Error::DimensionMismatch);
            }
            let lda = n;

            unsafe {
                prefix!($t, geev_)(
                    left.as_i8().as_mut(), right.as_i8().as_mut(),
                    n.as_mut(),
                    a.as_mut_ptr(), lda.as_mut(),
                    ptr::null::<$t>() as *mut _, ptr::null::<$t>() as *mut _,
                    ptr::null::<$t>() as *mut _, n.as_mut(),
                    ptr::null::<$t>() as *mut _, n.as_mut(),
                    len_ptr, (-1 as c_int).as_mut(),
                    &mut info as *mut c_int);
            };

            match info {
                0 => Ok(len_info.as_work()),
                x if x < 0 => Err(Error::IllegalParameter(-x as usize)),
                x => Err(Error::DiagonalElementZero(x as usize)),
            }
        }
    }
)+));

real_eigen_impl!(f32, f64);

#[cfg(test)]
mod geev_tests {
    use eigenvalues::Geev;
    use matrix::tests::M;
    use types::Order::*;

    #[test]
    fn real() {
        let mut a = M(RowMajor, 2i32, 2i32, vec![2.0f64, 7.0, -1.0, -6.0]);
        let mut v = Vec::with_capacity(2);
        unsafe { v.set_len(2) };

        Geev::geev(&mut a, &mut v, None, None).unwrap();

        assert_eq!(v, vec![]);
    }
}

<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use autocxx::prelude::*;

include_cpp! {
    // C++ headers we want to include.
    #include "s2/r2rect.h"
    #include "extras.h"
    // Safety policy. We are marking that this whole C++ inclusion is unsafe
    // which means the functions themselves do not need to be marked
    // as unsafe. Other policies are possible.
    safety!(unsafe)
    // What types and functions we want to generate
    generate!("R1Interval")
    generate!("R2Rect")
    generate!("describe_point")
}

// Everything that we care about is inlined, so we don't have to do
// anything fancy to build or link any external code.
fn main() {
    // Create a couple of R1Intervals using their pre-existing C++
    // constructors. Actually these will be cxx::UniquePtr<R1Interval>s.
    let i1 = ffi::R1Interval::new(1.0f64, 2.0f64).within_unique_ptr();
    let i2 = ffi::R1Interval::new(5.0f64, 6.0f64).within_unique_ptr();
    // Create a rect, passing references to the intervals.
    // Note this is 'make_unique1' because R2Rect has multiple
    // overloaded constructors. 'cargo expand' is useful here,
    // and there's work afoot to make this work nicely with
    // rust-analyzer to give IDE autocompletion.
    let r = ffi::R2Rect::new(&i1, &i2).within_unique_ptr();
    // Call a method on one of these objects. As it happens,
    // this returns a
    // UniquePtr< ... opaque object representing a point ...>.
    let center = r.GetCenter();
    // As the object is too complex for autocxx to understand,
    // we can't do much with it except to send it into other
    // C++ APIs. We'll make our own which describes the point.
    // This will return a std::string, which autocxx will
    // convert to a UniquePtr<CxxString>. We can convert that
    // back to a Rust string and print it, so long as we
    // take care to decide how to deal with non-UTF8
    // characters (hence the unwrap).
    println!(
        "Center of rectangle is {}",
        ffi::describe_point(center).to_str().unwrap()
    );
}
<commit_msg>Fix example.<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use autocxx::prelude::*;

include_cpp! {
    // C++ headers we want to include.
    #include "s2/r2rect.h"
    #include "extras.h"
    // Safety policy. We are marking that this whole C++ inclusion is unsafe
    // which means the functions themselves do not need to be marked
    // as unsafe. Other policies are possible.
    safety!(unsafe)
    // What types and functions we want to generate
    generate!("R1Interval")
    generate!("R2Rect")
    generate!("describe_point")
}

// Everything that we care about is inlined, so we don't have to do
// anything fancy to build or link any external code.
fn main() {
    // Create a couple of R1Intervals using their pre-existing C++
    // constructors. Actually these will be cxx::UniquePtr<R1Interval>s.
    let i1 = ffi::R1Interval::new(1.0f64, 2.0f64).within_unique_ptr();
    let i2 = ffi::R1Interval::new(5.0f64, 6.0f64).within_unique_ptr();
    // Create a rect, passing references to the intervals.
    // Note this is 'new1' because R2Rect has multiple
    // overloaded constructors. 'cargo expand', `cargo doc`
    // or a rust-analyzer IDE is useful here.
    let r = ffi::R2Rect::new1(&i1, &i2).within_unique_ptr();
    // Call a method on one of these objects. As it happens,
    // this returns a
    // UniquePtr< ... opaque object representing a point ...>.
    let center = r.GetCenter();
    // As the object is too complex for autocxx to understand,
    // we can't do much with it except to send it into other
    // C++ APIs. We'll make our own which describes the point.
    // This will return a std::string, which autocxx will
    // convert to a UniquePtr<CxxString>. We can convert that
    // back to a Rust string and print it, so long as we
    // take care to decide how to deal with non-UTF8
    // characters (hence the unwrap).
    println!(
        "Center of rectangle is {}",
        ffi::describe_point(center).to_str().unwrap()
    );
}
<|endoftext|>


<commit_before>#![crate_name = "uu_cksum"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Michael Gehring <mg@ebfe.org>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate getopts;

#[macro_use]
extern crate uucore;

use getopts::Options;
use std::fs::File;
use std::io::{self, stdin, Read, Write, BufReader};
use std::mem;
use std::path::Path;

use crc_table::CRC_TABLE;

mod crc_table;

static NAME: &'static str = "cksum";
static VERSION: &'static str = env!("CARGO_PKG_VERSION");

#[inline]
fn crc_update(crc: u32, input: u8) -> u32 {
    (crc << 8) ^ CRC_TABLE[((crc >> 24) as usize ^ input as usize) & 0xFF]
}

#[inline]
fn crc_final(mut crc: u32, mut length: usize) -> u32 {
    while length != 0 {
        crc = crc_update(crc, length as u8);
        length >>= 8;
    }

    !crc
}

#[inline]
fn cksum(fname: &str) -> io::Result<(u32, usize)> {
    let mut crc = 0u32;
    let mut size = 0usize;

    let file;
    let mut rd : Box<Read> = match fname {
        "-" => {
            Box::new(stdin())
        }
        _ => {
            file = try!(File::open(&Path::new(fname)));
            Box::new(BufReader::new(file))
        }
    };

    let mut bytes: [u8; 1024 * 1024] = unsafe { mem::uninitialized() };
    loop {
        match rd.read(&mut bytes) {
            Ok(num_bytes) => {
                if num_bytes == 0 {
                    return Ok((crc_final(crc, size), size));
                }
                for &b in bytes[..num_bytes].iter() {
                    crc = crc_update(crc, b);
                }
                size += num_bytes;
            }
            Err(err) => return Err(err)
        }
    }
}

pub fn uumain(args: Vec<String>) -> i32 {
    let mut opts = Options::new();
    opts.optflag("h", "help", "display this help and exit");
    opts.optflag("V", "version", "output version information and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(err) => panic!("{}", err),
    };

    if matches.opt_present("help") {
        let msg = format!("{0} {1}

Usage:
  {0} [OPTIONS] [FILE]...

Print CRC and size for each file.", NAME, VERSION);

        print!("{}", opts.usage(&msg));
        return 0;
    }

    if matches.opt_present("version") {
        println!("{} {}", NAME, VERSION);
        return 0;
    }

    let files = matches.free;

    if files.is_empty() {
        match cksum("-") {
            Ok((crc, size)) => println!("{} {}", crc, size),
            Err(err) => {
                show_error!("{}", err);
                return 2;
            }
        }
        return 0;
    }

    let mut exit_code = 0;
    for fname in &files {
        match cksum(fname.as_ref()) {
            Ok((crc, size)) => println!("{} {} {}", crc, size, fname),
            Err(err) => {
                show_error!("'{}' {}", fname, err);
                exit_code = 2;
            }
        }
    }

    exit_code
}
<commit_msg>cksum: resolve msvc unsafe issue<commit_after>#![crate_name = "uu_cksum"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Michael Gehring <mg@ebfe.org>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate getopts;

#[macro_use]
extern crate uucore;

use getopts::Options;
use std::fs::File;
use std::io::{self, stdin, Read, Write, BufReader};
#[cfg(not(windows))]
use std::mem;
use std::path::Path;

use crc_table::CRC_TABLE;

mod crc_table;

static NAME: &'static str = "cksum";
static VERSION: &'static str = env!("CARGO_PKG_VERSION");

#[inline]
fn crc_update(crc: u32, input: u8) -> u32 {
    (crc << 8) ^ CRC_TABLE[((crc >> 24) as usize ^ input as usize) & 0xFF]
}

#[inline]
fn crc_final(mut crc: u32, mut length: usize) -> u32 {
    while length != 0 {
        crc = crc_update(crc, length as u8);
        length >>= 8;
    }

    !crc
}

#[cfg(windows)]
fn init_byte_array() -> Vec<u8> {
    vec![0; 1024 * 1024]
}

#[cfg(not(windows))]
fn init_byte_array() -> [u8; 1024*1024] {
    unsafe { mem::uninitialized() }
}

#[inline]
fn cksum(fname: &str) -> io::Result<(u32, usize)> {
    let mut crc = 0u32;
    let mut size = 0usize;

    let file;
    let mut rd : Box<Read> = match fname {
        "-" => {
            Box::new(stdin())
        }
        _ => {
            file = try!(File::open(&Path::new(fname)));
            Box::new(BufReader::new(file))
        }
    };

    let mut bytes = init_byte_array();
    loop {
        match rd.read(&mut bytes) {
            Ok(num_bytes) => {
                if num_bytes == 0 {
                    return Ok((crc_final(crc, size), size));
                }
                for &b in bytes[..num_bytes].iter() {
                    crc = crc_update(crc, b);
                }
                size += num_bytes;
            }
            Err(err) => return Err(err)
        }
    }
    //Ok((0 as u32,0 as usize))
}

pub fn uumain(args: Vec<String>) -> i32 {
    let mut opts = Options::new();
    opts.optflag("h", "help", "display this help and exit");
    opts.optflag("V", "version", "output version information and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(err) => panic!("{}", err),
    };

    if matches.opt_present("help") {
        let msg = format!("{0} {1}

Usage:
  {0} [OPTIONS] [FILE]...

Print CRC and size for each file.", NAME, VERSION);

        print!("{}", opts.usage(&msg));
        return 0;
    }

    if matches.opt_present("version") {
        println!("{} {}", NAME, VERSION);
        return 0;
    }

    let files = matches.free;

    if files.is_empty() {
        match cksum("-") {
            Ok((crc, size)) => println!("{} {}", crc, size),
            Err(err) => {
                show_error!("{}", err);
                return 2;
            }
        }
        return 0;
    }

    let mut exit_code = 0;
    for fname in &files {
        match cksum(fname.as_ref()) {
            Ok((crc, size)) => println!("{} {} {}", crc, size, fname),
            Err(err) => {
                show_error!("'{}' {}", fname, err);
                exit_code = 2;
            }
        }
    }

    exit_code
}
<|endoftext|>