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

use std::mem::transmute;
use std::fmt;
use std::num::Zero;

use approx::ApproxEq;
use intersect::Intersect;
use num::BaseFloat;
use point::{Point, Point3};
use ray::Ray3;
use vector::{Vector3, Vector4};
use vector::{Vector, EuclideanVector};

/// A 3-dimensional plane formed from the equation: `A*x + B*y + C*z - D = 0`.
///
/// # Fields
///
/// - `n`: a unit vector representing the normal of the plane where:
///   - `n.x`: corresponds to `A` in the plane equation
///   - `n.y`: corresponds to `B` in the plane equation
///   - `n.z`: corresponds to `C` in the plane equation
/// - `d`: the distance value, corresponding to `D` in the plane equation
///
/// # Notes
///
/// The `A*x + B*y + C*z - D = 0` form is preferred over the other common
/// alternative, `A*x + B*y + C*z + D = 0`, because it tends to avoid
/// superfluous negations (see _Real Time Collision Detection_, p. 55).
#[deriving(Clone, PartialEq)]
pub struct Plane<S> {
    pub n: Vector3<S>,
    pub d: S,
}

impl<S: BaseFloat> Plane<S> {
    /// Construct a plane from a normal vector and a scalar distance. The
    /// plane will be perpendicular to `n`, and `d` units offset from the
    /// origin.
    pub fn new(n: Vector3<S>, d: S) -> Plane<S> {
        Plane { n: n, d: d }
    }

    /// # Arguments
    ///
    /// - `a`: the `x` component of the normal
    /// - `b`: the `y` component of the normal
    /// - `c`: the `z` component of the normal
    /// - `d`: the plane's distance value
    pub fn from_abcd(a: S, b: S, c: S, d: S) -> Plane<S> {
        Plane { n: Vector3::new(a, b, c), d: d }
    }

    /// Construct a plane from the components of a four-dimensional vector
    pub fn from_vector4(v: Vector4<S>) -> Plane<S> {
        unsafe { transmute(v) }
    }

    /// Constructs a plane that passes through the the three points `a`, `b` and `c`
    pub fn from_points(a: Point3<S>, b: Point3<S>, c: Point3<S>) -> Option<Plane<S>> {
        // create two vectors that run parallel to the plane
        let v0 = b.sub_p(&a);
        let v1 = c.sub_p(&a);

        // find the normal vector that is perpendicular to v1 and v2
        let mut n = v0.cross(&v1);

        if n.approx_eq(&Vector3::zero()) { None }
        else {
            // compute the normal and the distance to the plane
            n.normalize_self();
            let d = -a.dot(&n);

            Some(Plane::new(n, d))
        }
    }
}

impl<S: BaseFloat> Intersect<Option<Point3<S>>> for (Plane<S>, Ray3<S>) {
    fn intersection(&self) -> Option<Point3<S>> {
        match *self {
            (ref p, ref r) => {
                let t = -(p.d + r.origin.dot(&p.n)) / r.direction.dot(&p.n);
                if t < Zero::zero() { None }
                else { Some(r.origin.add_v(&r.direction.mul_s(t))) }
            }
        }
    }
}

impl<S: BaseFloat> Intersect<Option<Ray3<S>>> for (Plane<S>, Plane<S>) {
    fn intersection(&self) -> Option<Ray3<S>> {
        fail!("Not yet implemented");
    }
}

impl<S: BaseFloat> Intersect<Option<Point3<S>>> for (Plane<S>, Plane<S>, Plane<S>) {
    fn intersection(&self) -> Option<Point3<S>> {
        fail!("Not yet implemented");
    }
}

impl<S: BaseFloat + ApproxEq<S>>
ApproxEq<S> for Plane<S> {
    #[inline]
    fn approx_eq_eps(&self, other: &Plane<S>, epsilon: &S) -> bool {
        self.n.approx_eq_eps(&other.n, epsilon) &&
        self.d.approx_eq_eps(&other.d, epsilon)
    }
}

impl<S: BaseFloat> fmt::Show for Plane<S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:f}x + {:f}y + {:f}z - {:f} = 0",
               self.n.x, self.n.y, self.n.z, self.d)
    }
}
<commit_msg>Fix transmute build failure<commit_after>// Copyright 2013-2014 The CGMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::fmt;
use std::num::Zero;

use approx::ApproxEq;
use intersect::Intersect;
use num::BaseFloat;
use point::{Point, Point3};
use ray::Ray3;
use vector::{Vector3, Vector4};
use vector::{Vector, EuclideanVector};

/// A 3-dimensional plane formed from the equation: `A*x + B*y + C*z - D = 0`.
///
/// # Fields
///
/// - `n`: a unit vector representing the normal of the plane where:
///   - `n.x`: corresponds to `A` in the plane equation
///   - `n.y`: corresponds to `B` in the plane equation
///   - `n.z`: corresponds to `C` in the plane equation
/// - `d`: the distance value, corresponding to `D` in the plane equation
///
/// # Notes
///
/// The `A*x + B*y + C*z - D = 0` form is preferred over the other common
/// alternative, `A*x + B*y + C*z + D = 0`, because it tends to avoid
/// superfluous negations (see _Real Time Collision Detection_, p. 55).
#[deriving(Clone, PartialEq)]
pub struct Plane<S> {
    pub n: Vector3<S>,
    pub d: S,
}

impl<S: BaseFloat> Plane<S> {
    /// Construct a plane from a normal vector and a scalar distance. The
    /// plane will be perpendicular to `n`, and `d` units offset from the
    /// origin.
    pub fn new(n: Vector3<S>, d: S) -> Plane<S> {
        Plane { n: n, d: d }
    }

    /// # Arguments
    ///
    /// - `a`: the `x` component of the normal
    /// - `b`: the `y` component of the normal
    /// - `c`: the `z` component of the normal
    /// - `d`: the plane's distance value
    pub fn from_abcd(a: S, b: S, c: S, d: S) -> Plane<S> {
        Plane { n: Vector3::new(a, b, c), d: d }
    }

    /// Construct a plane from the components of a four-dimensional vector
    pub fn from_vector4(v: Vector4<S>) -> Plane<S> {
        match v {
            Vector4 { x, y, z, w } => Plane { n: Vector3::new(x, y, z), d: w },
        }
    }

    /// Constructs a plane that passes through the the three points `a`, `b` and `c`
    pub fn from_points(a: Point3<S>, b: Point3<S>, c: Point3<S>) -> Option<Plane<S>> {
        // create two vectors that run parallel to the plane
        let v0 = b.sub_p(&a);
        let v1 = c.sub_p(&a);

        // find the normal vector that is perpendicular to v1 and v2
        let mut n = v0.cross(&v1);

        if n.approx_eq(&Vector3::zero()) { None }
        else {
            // compute the normal and the distance to the plane
            n.normalize_self();
            let d = -a.dot(&n);

            Some(Plane::new(n, d))
        }
    }
}

impl<S: BaseFloat> Intersect<Option<Point3<S>>> for (Plane<S>, Ray3<S>) {
    fn intersection(&self) -> Option<Point3<S>> {
        match *self {
            (ref p, ref r) => {
                let t = -(p.d + r.origin.dot(&p.n)) / r.direction.dot(&p.n);
                if t < Zero::zero() { None }
                else { Some(r.origin.add_v(&r.direction.mul_s(t))) }
            }
        }
    }
}

impl<S: BaseFloat> Intersect<Option<Ray3<S>>> for (Plane<S>, Plane<S>) {
    fn intersection(&self) -> Option<Ray3<S>> {
        fail!("Not yet implemented");
    }
}

impl<S: BaseFloat> Intersect<Option<Point3<S>>> for (Plane<S>, Plane<S>, Plane<S>) {
    fn intersection(&self) -> Option<Point3<S>> {
        fail!("Not yet implemented");
    }
}

impl<S: BaseFloat + ApproxEq<S>>
ApproxEq<S> for Plane<S> {
    #[inline]
    fn approx_eq_eps(&self, other: &Plane<S>, epsilon: &S) -> bool {
        self.n.approx_eq_eps(&other.n, epsilon) &&
        self.d.approx_eq_eps(&other.d, epsilon)
    }
}

impl<S: BaseFloat> fmt::Show for Plane<S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:f}x + {:f}y + {:f}z - {:f} = 0",
               self.n.x, self.n.y, self.n.z, self.d)
    }
}
<|endoftext|>


<commit_before>//! [Church pairs](https://en.wikipedia.org/wiki/Church_encoding#Church_pairs)

use term::{Term, Error, abs};
use term::Term::*;
use term::Error::*;
use church::booleans::{tru, fls};

/// Produces a Church-encoded pair; applying it to two other terms puts them inside it.
///
/// PAIR := λxyz.z x y = λ λ λ 1 3 2
///
/// # Example
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::church::pairs::pair;
/// use lambda_calculus::church::numerals::{zero, one};
///
/// let pair01 = app!(pair(), zero(), one());
///
/// assert_eq!(pair01.fst_ref(), Ok(&zero()));
/// assert_eq!(pair01.snd_ref(), Ok(&one()));
/// # }
/// ```
pub fn pair() -> Term {
    abs(abs(abs(
        app!(Var(1), Var(3), Var(2))
    )))
}

/// Applied to a Church-encoded pair `(a, b)` it yields `a`.
///
/// FST := λp.p TRUE = λ 1 TRUE
///
/// # Example
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::church::pairs::{pair, fst};
/// use lambda_calculus::church::numerals::{zero, one};
/// use lambda_calculus::reduction::beta;
/// use lambda_calculus::reduction::Order::*;
///
/// let pair_0_1 = app!(pair(), zero(), one());
///
/// assert_eq!(beta(fst().app(pair_0_1), NOR, 0, false), zero());
/// # }
/// ```
pub fn fst() -> Term { abs(Var(1).app(tru())) }

/// Applied to a Church-encoded pair `(a, b)` it yields `b`.
///
/// SND := λp.p FALSE = λ 1 FALSE
///
/// # Example
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::church::pairs::{pair, snd};
/// use lambda_calculus::church::numerals::{zero, one};
/// use lambda_calculus::reduction::beta;
/// use lambda_calculus::reduction::Order::*;
///
/// let pair_0_1 = app!(pair(), zero(), one());
///
/// assert_eq!(beta(snd().app(pair_0_1), NOR, 0, false), one());
/// # }
/// ```
pub fn snd() -> Term { abs(Var(1).app(fls())) }

impl Term {
    /// Checks whether `self` is a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert!(pair01.is_pair());
    /// # }
    /// ```
    pub fn is_pair(&self) -> bool {
        self.unpair_ref().is_ok()
    }

    /// Splits a Church-encoded pair into a pair of terms, consuming `self`.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.unpair(), Ok((zero(), one())));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn unpair(self) -> Result<(Term, Term), Error> {
        let candidate = if let Abs(abstracted) = self { *abstracted } else { self };

        if let Ok((wrapped_a, b)) = candidate.unapp() {
            Ok((try!(wrapped_a.rhs()), b))
        } else {
            Err(NotAPair)
        }
    }

    /// Splits a Church-encoded pair into a pair of references to its underlying terms.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.unpair_ref(), Ok((&zero(), &one())));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn unpair_ref(&self) -> Result<(&Term, &Term), Error> {
        let candidate = if let Abs(ref abstracted) = *self { abstracted } else { self };

        if let Ok((wrapped_a, b)) = candidate.unapp_ref() {
            Ok((try!(wrapped_a.rhs_ref()), b))
        } else {
            Err(NotAPair)
        }
    }

    /// Splits a Church-encoded pair into a pair of mutable references to its underlying terms.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let mut pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.unpair_mut(), Ok((&mut zero(), &mut one())));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn unpair_mut(&mut self) -> Result<(&mut Term, &mut Term), Error> {
        let mut candidate = if let Abs(ref mut abstracted) = *self { abstracted } else { self };

        if let Ok((wrapped_a, b)) = candidate.unapp_mut() {
            Ok((try!(wrapped_a.rhs_mut()), b))
        } else {
            Err(NotAPair)
        }
    }

    /// Returns the first term from a Church-encoded pair, consuming `self`.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.fst(), Ok(zero()));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn fst(self) -> Result<Term, Error> {
        Ok(try!(self.unpair()).0)
    }

    /// Returns a reference to the first term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.fst_ref(), Ok(&zero()));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn fst_ref(&self) -> Result<&Term, Error> {
        Ok(try!(self.unpair_ref()).0)
    }

    /// Returns a mutable reference to the first term of a Church-encoded pair.
    /// Returns a reference to the first term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let mut pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.fst_mut(), Ok(&mut zero()));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn fst_mut(&mut self) -> Result<&mut Term, Error> {
        Ok(try!(self.unpair_mut()).0)
    }

    /// Returns the second term from a Church-encoded pair, consuming `self`.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.snd(), Ok(one()));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn snd(self) -> Result<Term, Error> {
        Ok(try!(self.unpair()).1)
    }

    /// Returns a reference to the second term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.snd_ref(), Ok(&one()));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn snd_ref(&self) -> Result<&Term, Error> {
        Ok(try!(self.unpair_ref()).1)
    }

    /// Returns a mutable reference to the second term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let mut pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.snd_mut(), Ok(&mut one()));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn snd_mut(&mut self) -> Result<&mut Term, Error> {
        Ok(try!(self.unpair_mut()).1)
    }
}

impl From<(Term, Term)> for Term {
    fn from((t1, t2): (Term, Term)) -> Self {
        abs(app!(Var(1), t1, t2))
    }
}
<commit_msg>remove unnecessary mutability<commit_after>//! [Church pairs](https://en.wikipedia.org/wiki/Church_encoding#Church_pairs)

use term::{Term, Error, abs};
use term::Term::*;
use term::Error::*;
use church::booleans::{tru, fls};

/// Produces a Church-encoded pair; applying it to two other terms puts them inside it.
///
/// PAIR := λxyz.z x y = λ λ λ 1 3 2
///
/// # Example
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::church::pairs::pair;
/// use lambda_calculus::church::numerals::{zero, one};
///
/// let pair01 = app!(pair(), zero(), one());
///
/// assert_eq!(pair01.fst_ref(), Ok(&zero()));
/// assert_eq!(pair01.snd_ref(), Ok(&one()));
/// # }
/// ```
pub fn pair() -> Term {
    abs(abs(abs(
        app!(Var(1), Var(3), Var(2))
    )))
}

/// Applied to a Church-encoded pair `(a, b)` it yields `a`.
///
/// FST := λp.p TRUE = λ 1 TRUE
///
/// # Example
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::church::pairs::{pair, fst};
/// use lambda_calculus::church::numerals::{zero, one};
/// use lambda_calculus::reduction::beta;
/// use lambda_calculus::reduction::Order::*;
///
/// let pair_0_1 = app!(pair(), zero(), one());
///
/// assert_eq!(beta(fst().app(pair_0_1), NOR, 0, false), zero());
/// # }
/// ```
pub fn fst() -> Term { abs(Var(1).app(tru())) }

/// Applied to a Church-encoded pair `(a, b)` it yields `b`.
///
/// SND := λp.p FALSE = λ 1 FALSE
///
/// # Example
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::church::pairs::{pair, snd};
/// use lambda_calculus::church::numerals::{zero, one};
/// use lambda_calculus::reduction::beta;
/// use lambda_calculus::reduction::Order::*;
///
/// let pair_0_1 = app!(pair(), zero(), one());
///
/// assert_eq!(beta(snd().app(pair_0_1), NOR, 0, false), one());
/// # }
/// ```
pub fn snd() -> Term { abs(Var(1).app(fls())) }

impl Term {
    /// Checks whether `self` is a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert!(pair01.is_pair());
    /// # }
    /// ```
    pub fn is_pair(&self) -> bool {
        self.unpair_ref().is_ok()
    }

    /// Splits a Church-encoded pair into a pair of terms, consuming `self`.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.unpair(), Ok((zero(), one())));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn unpair(self) -> Result<(Term, Term), Error> {
        let candidate = if let Abs(abstracted) = self { *abstracted } else { self };

        if let Ok((wrapped_a, b)) = candidate.unapp() {
            Ok((try!(wrapped_a.rhs()), b))
        } else {
            Err(NotAPair)
        }
    }

    /// Splits a Church-encoded pair into a pair of references to its underlying terms.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.unpair_ref(), Ok((&zero(), &one())));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn unpair_ref(&self) -> Result<(&Term, &Term), Error> {
        let candidate = if let Abs(ref abstracted) = *self { abstracted } else { self };

        if let Ok((wrapped_a, b)) = candidate.unapp_ref() {
            Ok((try!(wrapped_a.rhs_ref()), b))
        } else {
            Err(NotAPair)
        }
    }

    /// Splits a Church-encoded pair into a pair of mutable references to its underlying terms.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let mut pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.unpair_mut(), Ok((&mut zero(), &mut one())));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn unpair_mut(&mut self) -> Result<(&mut Term, &mut Term), Error> {
        let candidate = if let Abs(ref mut abstracted) = *self { abstracted } else { self };

        if let Ok((wrapped_a, b)) = candidate.unapp_mut() {
            Ok((try!(wrapped_a.rhs_mut()), b))
        } else {
            Err(NotAPair)
        }
    }

    /// Returns the first term from a Church-encoded pair, consuming `self`.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.fst(), Ok(zero()));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn fst(self) -> Result<Term, Error> {
        Ok(try!(self.unpair()).0)
    }

    /// Returns a reference to the first term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.fst_ref(), Ok(&zero()));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn fst_ref(&self) -> Result<&Term, Error> {
        Ok(try!(self.unpair_ref()).0)
    }

    /// Returns a mutable reference to the first term of a Church-encoded pair.
    /// Returns a reference to the first term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let mut pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.fst_mut(), Ok(&mut zero()));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn fst_mut(&mut self) -> Result<&mut Term, Error> {
        Ok(try!(self.unpair_mut()).0)
    }

    /// Returns the second term from a Church-encoded pair, consuming `self`.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.snd(), Ok(one()));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn snd(self) -> Result<Term, Error> {
        Ok(try!(self.unpair()).1)
    }

    /// Returns a reference to the second term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.snd_ref(), Ok(&one()));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn snd_ref(&self) -> Result<&Term, Error> {
        Ok(try!(self.unpair_ref()).1)
    }

    /// Returns a mutable reference to the second term of a Church-encoded pair.
    ///
    /// # Example
    /// ```
    /// # #[macro_use] extern crate lambda_calculus;
    /// # fn main() {
    /// use lambda_calculus::church::pairs::pair;
    /// use lambda_calculus::church::numerals::{zero, one};
    ///
    /// let mut pair01 = app!(pair(), zero(), one());
    ///
    /// assert_eq!(pair01.snd_mut(), Ok(&mut one()));
    /// # }
    /// ```
    /// # Errors
    ///
    /// The function will return an error if `self` is not a Church pair.
    pub fn snd_mut(&mut self) -> Result<&mut Term, Error> {
        Ok(try!(self.unpair_mut()).1)
    }
}

impl From<(Term, Term)> for Term {
    fn from((t1, t2): (Term, Term)) -> Self {
        abs(app!(Var(1), t1, t2))
    }
}
<|endoftext|>


<commit_before>use std::convert::From;

use binding::class::{instance_variable_get, instance_variable_set, object_class};
use binding::util::call_method;
use types::Value;
use util::create_arguments;

use super::any_object::AnyObject;
use super::class::Class;

/// `Object`
///
/// Trait consists methods of Ruby `Object` class. Every struct like `Array`, `Hash` etc implements
/// this trait.
pub trait Object: From<Value> {
    /// Usually this function just returns a `value` of current object.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::types::Value;
    /// use ruru::traits::Object;
    ///
    /// struct Array {
    ///     value: Value
    /// }
    ///
    /// impl From<Value> for Array {
    ///     fn from(value: Value) -> Self {
    ///         Array {
    ///             value: value
    ///         }
    ///     }
    /// }
    ///
    /// impl Object for Array {
    ///     fn value(&self) -> Value {
    ///         self.value
    ///     }
    /// }
    /// ```
    fn value(&self) -> Value;

    /// Returns a `Class` struct of current object
    ///
    /// # Examples
    /// ```
    /// use ruru::{Array, VM};
    /// use ruru::traits::Object;
    /// # VM::init();
    ///
    /// assert_eq!(Array::new().class(), Array::new().class());
    /// ```
    fn class(&self) -> Class {
        let class = object_class(self.value());

        Class::from(class)
    }

    /// Calls a given method on an object similarly to Ruby `Object#send` method
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use ruru::{Array, Fixnum, RString, VM};
    /// use ruru::traits::Object;
    /// # VM::init();
    ///
    /// let array = Array::new().push(Fixnum::new(1));
    /// let array_to_str =
    ///     array
    ///         .send("to_s", vec![])
    ///         .to::<RString>()
    ///         .to_string();
    ///
    /// assert_eq!(array_to_str, "[1]".to_string());
    /// ```
    fn send(&self, method: &str, arguments: Vec<AnyObject>) -> AnyObject {
        let (argc, argv) = create_arguments(arguments);

        let result = call_method(self.value(), method, argc, argv.as_ptr());

        AnyObject::from(result)
    }

    /// Converts struct to `AnyObject`
    ///
    /// See docs for `AnyObject` class for more details.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use ruru::{Array, Fixnum, VM};
    /// use ruru::traits::Object;
    /// # VM::init();
    ///
    /// let array = Array::new().push(Fixnum::new(1));
    /// let args = vec![Fixnum::new(1).to_any_object()];
    /// let index =
    ///     array
    ///         .send("find_index", args)
    ///         .to::<Fixnum>()
    ///         .to_i64();
    ///
    /// assert_eq!(index, 0);
    /// ```
    fn to_any_object(&self) -> AnyObject {
        AnyObject::from(self.value())
    }

    /// Sets an instance variable for object
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use ruru::{AnyObject, Class, Fixnum, VM};
    /// use ruru::types::Argc;
    /// use ruru::traits::Object;
    ///
    /// #[no_mangle]
    /// pub extern fn counter_initialize(_: Argc,
    ///                                  _: *const AnyObject,
    ///                                  mut itself: AnyObject) -> AnyObject {
    ///     itself.instance_variable_set("@state", Fixnum::new(0))
    /// }
    ///
    /// #[no_mangle]
    /// pub extern fn counter_increment(_: Argc,
    ///                                 _: *const AnyObject,
    ///                                 mut itself: AnyObject) -> AnyObject {
    ///     let state = itself.instance_variable_get("@state").to::<Fixnum>().to_i64();
    ///
    ///     itself.instance_variable_set("@state", Fixnum::new(state + 1))
    /// }
    ///
    /// #[no_mangle]
    /// pub extern fn counter_state(_: Argc, _: *const AnyObject, itself: AnyObject) -> Fixnum {
    ///     itself.instance_variable_get("@state").to::<Fixnum>()
    /// }
    ///
    /// fn main() {
    ///     # VM::init();
    ///     let counter = Class::new("Counter").define(|itself| {
    ///         itself.def("initialize", counter_initialize);
    ///         itself.def("increment!", counter_increment);
    ///         itself.def("state", counter_state);
    ///     }).new_instance(vec![]);
    ///
    ///     counter.send("increment!", vec![]);
    ///
    ///     let new_state = counter.send("state", vec![]).to::<Fixnum>().to_i64();
    ///
    ///     assert_eq!(new_state, 1);
    /// }
    /// ```
    fn instance_variable_get(&self, variable: &str) -> AnyObject {
        let result = instance_variable_get(self.value(), variable);

        AnyObject::from(result)
    }

    /// Gets an instance variable of object
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use ruru::{AnyObject, Class, Fixnum, VM};
    /// use ruru::types::Argc;
    /// use ruru::traits::Object;
    ///
    /// #[no_mangle]
    /// pub extern fn counter_initialize(_: Argc,
    ///                                  _: *const AnyObject,
    ///                                  mut itself: AnyObject) -> AnyObject {
    ///     itself.instance_variable_set("@state", Fixnum::new(0))
    /// }
    ///
    /// #[no_mangle]
    /// pub extern fn counter_increment(_: Argc,
    ///                                 _: *const AnyObject,
    ///                                 mut itself: AnyObject) -> AnyObject {
    ///     let state = itself.instance_variable_get("@state").to::<Fixnum>().to_i64();
    ///
    ///     itself.instance_variable_set("@state", Fixnum::new(state + 1))
    /// }
    ///
    /// #[no_mangle]
    /// pub extern fn counter_state(_: Argc, _: *const AnyObject, itself: AnyObject) -> Fixnum {
    ///     itself.instance_variable_get("@state").to::<Fixnum>()
    /// }
    ///
    /// fn main() {
    ///     # VM::init();
    ///     let counter = Class::new("Counter").define(|itself| {
    ///         itself.def("initialize", counter_initialize);
    ///         itself.def("increment!", counter_increment);
    ///         itself.def("state", counter_state);
    ///     }).new_instance(vec![]);
    ///
    ///     counter.send("increment!", vec![]);
    ///
    ///     let new_state = counter.send("state", vec![]).to::<Fixnum>().to_i64();
    ///
    ///     assert_eq!(new_state, 1);
    /// }
    /// ```
    fn instance_variable_set<T: Object>(&mut self, variable: &str, value: T) -> AnyObject {
        let result = instance_variable_set(self.value(), variable, value.value());

        AnyObject::from(result)
    }
}
<commit_msg>Add Object.is_nil()<commit_after>use std::convert::From;

use binding::class::{instance_variable_get, instance_variable_set, object_class};
use binding::util::call_method;
use types::Value;
use util::create_arguments;

use super::any_object::AnyObject;
use super::class::Class;

/// `Object`
///
/// Trait consists methods of Ruby `Object` class. Every struct like `Array`, `Hash` etc implements
/// this trait.
pub trait Object: From<Value> {
    /// Usually this function just returns a `value` of current object.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::types::Value;
    /// use ruru::traits::Object;
    ///
    /// struct Array {
    ///     value: Value
    /// }
    ///
    /// impl From<Value> for Array {
    ///     fn from(value: Value) -> Self {
    ///         Array {
    ///             value: value
    ///         }
    ///     }
    /// }
    ///
    /// impl Object for Array {
    ///     fn value(&self) -> Value {
    ///         self.value
    ///     }
    /// }
    /// ```
    fn value(&self) -> Value;

    /// Returns a `Class` struct of current object
    ///
    /// # Examples
    /// ```
    /// use ruru::{Array, VM};
    /// use ruru::traits::Object;
    /// # VM::init();
    ///
    /// assert_eq!(Array::new().class(), Array::new().class());
    /// ```
    fn class(&self) -> Class {
        let class = object_class(self.value());

        Class::from(class)
    }

    /// Calls a given method on an object similarly to Ruby `Object#send` method
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use ruru::{Array, Fixnum, RString, VM};
    /// use ruru::traits::Object;
    /// # VM::init();
    ///
    /// let array = Array::new().push(Fixnum::new(1));
    /// let array_to_str =
    ///     array
    ///         .send("to_s", vec![])
    ///         .to::<RString>()
    ///         .to_string();
    ///
    /// assert_eq!(array_to_str, "[1]".to_string());
    /// ```
    fn send(&self, method: &str, arguments: Vec<AnyObject>) -> AnyObject {
        let (argc, argv) = create_arguments(arguments);

        let result = call_method(self.value(), method, argc, argv.as_ptr());

        AnyObject::from(result)
    }

    /// Checks weather the object is `nil`
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Hash, NilClass, VM};
    /// use ruru::traits::Object;
    /// # VM::init();
    ///
    /// assert!(NilClass::new().is_nil());
    /// assert!(!Hash::new().is_nil());
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// nil.nil? == true
    /// {}.nil? == false
    /// ```
    fn is_nil(&self) -> bool {
        self.value().is_nil()
    }

    /// Converts struct to `AnyObject`
    ///
    /// See docs for `AnyObject` class for more details.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use ruru::{Array, Fixnum, VM};
    /// use ruru::traits::Object;
    /// # VM::init();
    ///
    /// let array = Array::new().push(Fixnum::new(1));
    /// let args = vec![Fixnum::new(1).to_any_object()];
    /// let index =
    ///     array
    ///         .send("find_index", args)
    ///         .to::<Fixnum>()
    ///         .to_i64();
    ///
    /// assert_eq!(index, 0);
    /// ```
    fn to_any_object(&self) -> AnyObject {
        AnyObject::from(self.value())
    }

    /// Sets an instance variable for object
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use ruru::{AnyObject, Class, Fixnum, VM};
    /// use ruru::types::Argc;
    /// use ruru::traits::Object;
    ///
    /// #[no_mangle]
    /// pub extern fn counter_initialize(_: Argc,
    ///                                  _: *const AnyObject,
    ///                                  mut itself: AnyObject) -> AnyObject {
    ///     itself.instance_variable_set("@state", Fixnum::new(0))
    /// }
    ///
    /// #[no_mangle]
    /// pub extern fn counter_increment(_: Argc,
    ///                                 _: *const AnyObject,
    ///                                 mut itself: AnyObject) -> AnyObject {
    ///     let state = itself.instance_variable_get("@state").to::<Fixnum>().to_i64();
    ///
    ///     itself.instance_variable_set("@state", Fixnum::new(state + 1))
    /// }
    ///
    /// #[no_mangle]
    /// pub extern fn counter_state(_: Argc, _: *const AnyObject, itself: AnyObject) -> Fixnum {
    ///     itself.instance_variable_get("@state").to::<Fixnum>()
    /// }
    ///
    /// fn main() {
    ///     # VM::init();
    ///     let counter = Class::new("Counter").define(|itself| {
    ///         itself.def("initialize", counter_initialize);
    ///         itself.def("increment!", counter_increment);
    ///         itself.def("state", counter_state);
    ///     }).new_instance(vec![]);
    ///
    ///     counter.send("increment!", vec![]);
    ///
    ///     let new_state = counter.send("state", vec![]).to::<Fixnum>().to_i64();
    ///
    ///     assert_eq!(new_state, 1);
    /// }
    /// ```
    fn instance_variable_get(&self, variable: &str) -> AnyObject {
        let result = instance_variable_get(self.value(), variable);

        AnyObject::from(result)
    }

    /// Gets an instance variable of object
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use ruru::{AnyObject, Class, Fixnum, VM};
    /// use ruru::types::Argc;
    /// use ruru::traits::Object;
    ///
    /// #[no_mangle]
    /// pub extern fn counter_initialize(_: Argc,
    ///                                  _: *const AnyObject,
    ///                                  mut itself: AnyObject) -> AnyObject {
    ///     itself.instance_variable_set("@state", Fixnum::new(0))
    /// }
    ///
    /// #[no_mangle]
    /// pub extern fn counter_increment(_: Argc,
    ///                                 _: *const AnyObject,
    ///                                 mut itself: AnyObject) -> AnyObject {
    ///     let state = itself.instance_variable_get("@state").to::<Fixnum>().to_i64();
    ///
    ///     itself.instance_variable_set("@state", Fixnum::new(state + 1))
    /// }
    ///
    /// #[no_mangle]
    /// pub extern fn counter_state(_: Argc, _: *const AnyObject, itself: AnyObject) -> Fixnum {
    ///     itself.instance_variable_get("@state").to::<Fixnum>()
    /// }
    ///
    /// fn main() {
    ///     # VM::init();
    ///     let counter = Class::new("Counter").define(|itself| {
    ///         itself.def("initialize", counter_initialize);
    ///         itself.def("increment!", counter_increment);
    ///         itself.def("state", counter_state);
    ///     }).new_instance(vec![]);
    ///
    ///     counter.send("increment!", vec![]);
    ///
    ///     let new_state = counter.send("state", vec![]).to::<Fixnum>().to_i64();
    ///
    ///     assert_eq!(new_state, 1);
    /// }
    /// ```
    fn instance_variable_set<T: Object>(&mut self, variable: &str, value: T) -> AnyObject {
        let result = instance_variable_set(self.value(), variable, value.value());

        AnyObject::from(result)
    }
}
<|endoftext|>


<commit_before>use std::error;
use clap::{Arg, App, SubCommand, AppSettings};

use config;
use output;

use super::{DeployCommand, RunTaskCommand, ScheduleTaskPutCommand, ScheduleTaskDeleteCommand, ParamsExecCommand, ParamsGetCommand, ParamsListCommand, ParamsPutCommand, ParamsDeleteCommand};

pub struct MainCommand {
}

impl MainCommand {

  pub fn run() -> Result<(), Box<error::Error>> {

    let matches = App::new("Racco")
                    .version("0.1.0")
                    .author("Daichi Sakai. <daisaru11@gmail.com>")
                    .about("Deployment toolkit for AWS ECS")
                    .arg(Arg::with_name("config")
                            .short("c")
                            .long("config")
                            .value_name("FILE")
                            .help("Specifies configuration file")
                            .takes_value(true))
                    .subcommand(SubCommand::with_name("deploy")
                        .about("Deploys ECS service")
                        .arg(Arg::with_name("NAME")
                            .help("Name of the entry in config")
                            .index(1))
                    )
                    .subcommand(SubCommand::with_name("run-task")
                        .about("Runs single ESC task")
                        .arg(Arg::with_name("NAME")
                            .help("Name of the entry in config")
                            .required(true)
                            .index(1))
                    )
                    .subcommand(SubCommand::with_name("schedule-task")
                        .about("Deploys ECS task scheduled by Cloudwatch events")
                        .subcommand(SubCommand::with_name("put")
                            .about("Puts a scheduled task")
                            .arg(Arg::with_name("NAME")
                                .help("Name of the entry in config")
                                .required(true)
                                .index(1))
                        )
                        .subcommand(SubCommand::with_name("delete")
                            .about("Deletes a scheduled task")
                            .arg(Arg::with_name("NAME")
                                .help("Name of the entry in config")
                                .required(true)
                                .index(1))
                        )
                    )
                    .subcommand(SubCommand::with_name("params")
                        .about("Manages parameters")
                        .subcommand(SubCommand::with_name("get")
                            .about("Gets a parameter")
                            .arg(Arg::with_name("NAME")
                               .help("Name of the parameter")
                               .required(true)
                               .index(1))
                        )
                        .subcommand(SubCommand::with_name("list")
                            .about("Lists parameters")
                        )
                        .subcommand(SubCommand::with_name("put")
                            .about("Puts a parameter")
                            .arg(Arg::with_name("NAME")
                               .help("Name of the parameter")
                               .required(true)
                               .index(1))
                            .arg(Arg::with_name("VALUE")
                               .help("Value of the parameter")
                               .required(true)
                               .index(2))
                        )
                        .subcommand(SubCommand::with_name("delete")
                            .about("Deletes a parameter")
                            .arg(Arg::with_name("NAME")
                               .help("Name of the parameter")
                               .required(true)
                               .index(1))
                        )
                        .subcommand(SubCommand::with_name("exec")
                            .setting(AppSettings::AllowLeadingHyphen)
                            .about("Executes a command with the exported parameters as env variables")
                            .arg(Arg::with_name("PROGRAM")
                                .help("Program to be executed")
                                .required(true)
                                .index(1))
                            .arg(Arg::with_name("ARGS")
                                .help("Arguments passed to the program")
                                .multiple(true)
                                .index(2)
                                )
                        )
                    )
                    .get_matches()
                    ;

    info!("start racco");

    let arg_conf = matches.value_of("config").unwrap_or("racco.yml");
    info!("config file: {}", arg_conf);

    match config::command::Config::from_file(arg_conf) {
        Err(error) => {
            error!("invalid config: {}", error)
        }
        Ok(config) => {

            // deploy
            if let Some(sub_matches) = matches.subcommand_matches("deploy") {

                info!("start deploy");

                let cmd = DeployCommand::from_args(&config, sub_matches);
                match cmd.run() {
                    Ok(_) => {
                    },
                    Err(error) => {
                        error!("deploy failed: {}", error)
                    }
                }

                info!("end deploy");
            }

            // run-task
            if let Some(sub_matches) = matches.subcommand_matches("run-task") {

                info!("start run-task");

                let cmd = RunTaskCommand::from_args(&config, sub_matches);
                match cmd.run() {
                    Ok(_) => {
                    },
                    Err(error) => {
                        output::PrintLine::error(&format!("Failed: {}", error));
                    }
                }

                info!("end run-task");
            }

            // schedule-task
            if let Some(sub0_matches) = matches.subcommand_matches("schedule-task") {
                if let Some(sub1_matches) = sub0_matches.subcommand_matches("put") {
                    info!("start schedule-task put");

                    let cmd = ScheduleTaskPutCommand::from_args(&config, sub1_matches);
                    match cmd.run() {
                        Ok(_) => {
                        },
                        Err(error) => {
                            output::PrintLine::error(&format!("Failed: {}", error));
                        }
                    }

                    info!("end schdule-task put");
                }
                if let Some(sub1_matches) = sub0_matches.subcommand_matches("delete") {
                    info!("start schedule-task delete");

                    let cmd = ScheduleTaskDeleteCommand::from_args(&config, sub1_matches);
                    match cmd.run() {
                        Ok(_) => {
                        },
                        Err(error) => {
                            output::PrintLine::error(&format!("Failed: {}", error));
                        }
                    }

                    info!("end schedule-task delete");
                }
            }

            // params
            if let Some(sub0_matches) = matches.subcommand_matches("params") {
                if let Some(sub1_matches) = sub0_matches.subcommand_matches("get") {
                    info!("start params get");

                    let cmd = ParamsGetCommand::from_args(&config, sub1_matches);
                    match cmd.run() {
                        Ok(_) => {
                        },
                        Err(error) => {
                            output::PrintLine::error(&format!("Failed: {}", error));
                        }
                    }

                    info!("end params get");
                }
                if let Some(sub1_matches) = sub0_matches.subcommand_matches("list") {
                    info!("start params list");

                    let cmd = ParamsListCommand::from_args(&config, sub1_matches);
                    match cmd.run() {
                        Ok(_) => {
                        },
                        Err(error) => {
                            output::PrintLine::error(&format!("Failed: {}", error));
                        }
                    }

                    info!("end params list");
                }
                if let Some(sub1_matches) = sub0_matches.subcommand_matches("put") {
                    info!("start params put");

                    let cmd = ParamsPutCommand::from_args(&config, sub1_matches);
                    match cmd.run() {
                        Ok(_) => {
                        },
                        Err(error) => {
                            output::PrintLine::error(&format!("Failed: {}", error));
                        }
                    }

                    info!("end params put");
                }
                if let Some(sub1_matches) = sub0_matches.subcommand_matches("delete") {
                    info!("start params delete");

                    let cmd = ParamsDeleteCommand::from_args(&config, sub1_matches);
                    match cmd.run() {
                        Ok(_) => {
                        },
                        Err(error) => {
                            output::PrintLine::error(&format!("Failed: {}", error));
                        }
                    }

                    info!("end params delete");
                }
                if let Some(sub1_matches) = sub0_matches.subcommand_matches("exec") {
                    info!("start params exec");

                    let cmd = ParamsExecCommand::from_args(&config, sub1_matches);
                    match cmd.run() {
                        Ok(_) => {
                        },
                        Err(error) => {
                            output::PrintLine::error(&format!("Failed: {}", error));
                        }
                    }

                    info!("end params exec");
                }
            }

        },
    };

    info!("end racco");

    Ok(())
  }
}
<commit_msg>change the argument name of config to large capitals<commit_after>use std::error;
use clap::{Arg, App, SubCommand, AppSettings};

use config;
use output;

use super::{DeployCommand, RunTaskCommand, ScheduleTaskPutCommand, ScheduleTaskDeleteCommand, ParamsExecCommand, ParamsGetCommand, ParamsListCommand, ParamsPutCommand, ParamsDeleteCommand};

pub struct MainCommand {
}

impl MainCommand {

  pub fn run() -> Result<(), Box<error::Error>> {

    let matches = App::new("Racco")
                    .version("0.1.0")
                    .author("Daichi Sakai. <daisaru11@gmail.com>")
                    .about("Deployment toolkit for AWS ECS")
                    .arg(Arg::with_name("CONFIG")
                            .short("c")
                            .long("config")
                            .value_name("FILE")
                            .help("Specifies configuration file")
                            .takes_value(true))
                    .subcommand(SubCommand::with_name("deploy")
                        .about("Deploys ECS service")
                        .arg(Arg::with_name("NAME")
                            .help("Name of the entry in config")
                            .index(1))
                    )
                    .subcommand(SubCommand::with_name("run-task")
                        .about("Runs single ESC task")
                        .arg(Arg::with_name("NAME")
                            .help("Name of the entry in config")
                            .required(true)
                            .index(1))
                    )
                    .subcommand(SubCommand::with_name("schedule-task")
                        .about("Deploys ECS task scheduled by Cloudwatch events")
                        .subcommand(SubCommand::with_name("put")
                            .about("Puts a scheduled task")
                            .arg(Arg::with_name("NAME")
                                .help("Name of the entry in config")
                                .required(true)
                                .index(1))
                        )
                        .subcommand(SubCommand::with_name("delete")
                            .about("Deletes a scheduled task")
                            .arg(Arg::with_name("NAME")
                                .help("Name of the entry in config")
                                .required(true)
                                .index(1))
                        )
                    )
                    .subcommand(SubCommand::with_name("params")
                        .about("Manages parameters")
                        .subcommand(SubCommand::with_name("get")
                            .about("Gets a parameter")
                            .arg(Arg::with_name("NAME")
                               .help("Name of the parameter")
                               .required(true)
                               .index(1))
                        )
                        .subcommand(SubCommand::with_name("list")
                            .about("Lists parameters")
                        )
                        .subcommand(SubCommand::with_name("put")
                            .about("Puts a parameter")
                            .arg(Arg::with_name("NAME")
                               .help("Name of the parameter")
                               .required(true)
                               .index(1))
                            .arg(Arg::with_name("VALUE")
                               .help("Value of the parameter")
                               .required(true)
                               .index(2))
                        )
                        .subcommand(SubCommand::with_name("delete")
                            .about("Deletes a parameter")
                            .arg(Arg::with_name("NAME")
                               .help("Name of the parameter")
                               .required(true)
                               .index(1))
                        )
                        .subcommand(SubCommand::with_name("exec")
                            .setting(AppSettings::AllowLeadingHyphen)
                            .about("Executes a command with the exported parameters as env variables")
                            .arg(Arg::with_name("PROGRAM")
                                .help("Program to be executed")
                                .required(true)
                                .index(1))
                            .arg(Arg::with_name("ARGS")
                                .help("Arguments passed to the program")
                                .multiple(true)
                                .index(2)
                                )
                        )
                    )
                    .get_matches()
                    ;

    info!("start racco");

    let arg_conf = matches.value_of("CONFIG").unwrap_or("racco.yml");
    info!("config file: {}", arg_conf);

    match config::command::Config::from_file(arg_conf) {
        Err(error) => {
            error!("invalid config: {}", error)
        }
        Ok(config) => {

            // deploy
            if let Some(sub_matches) = matches.subcommand_matches("deploy") {

                info!("start deploy");

                let cmd = DeployCommand::from_args(&config, sub_matches);
                match cmd.run() {
                    Ok(_) => {
                    },
                    Err(error) => {
                        error!("deploy failed: {}", error)
                    }
                }

                info!("end deploy");
            }

            // run-task
            if let Some(sub_matches) = matches.subcommand_matches("run-task") {

                info!("start run-task");

                let cmd = RunTaskCommand::from_args(&config, sub_matches);
                match cmd.run() {
                    Ok(_) => {
                    },
                    Err(error) => {
                        output::PrintLine::error(&format!("Failed: {}", error));
                    }
                }

                info!("end run-task");
            }

            // schedule-task
            if let Some(sub0_matches) = matches.subcommand_matches("schedule-task") {
                if let Some(sub1_matches) = sub0_matches.subcommand_matches("put") {
                    info!("start schedule-task put");

                    let cmd = ScheduleTaskPutCommand::from_args(&config, sub1_matches);
                    match cmd.run() {
                        Ok(_) => {
                        },
                        Err(error) => {
                            output::PrintLine::error(&format!("Failed: {}", error));
                        }
                    }

                    info!("end schdule-task put");
                }
                if let Some(sub1_matches) = sub0_matches.subcommand_matches("delete") {
                    info!("start schedule-task delete");

                    let cmd = ScheduleTaskDeleteCommand::from_args(&config, sub1_matches);
                    match cmd.run() {
                        Ok(_) => {
                        },
                        Err(error) => {
                            output::PrintLine::error(&format!("Failed: {}", error));
                        }
                    }

                    info!("end schedule-task delete");
                }
            }

            // params
            if let Some(sub0_matches) = matches.subcommand_matches("params") {
                if let Some(sub1_matches) = sub0_matches.subcommand_matches("get") {
                    info!("start params get");

                    let cmd = ParamsGetCommand::from_args(&config, sub1_matches);
                    match cmd.run() {
                        Ok(_) => {
                        },
                        Err(error) => {
                            output::PrintLine::error(&format!("Failed: {}", error));
                        }
                    }

                    info!("end params get");
                }
                if let Some(sub1_matches) = sub0_matches.subcommand_matches("list") {
                    info!("start params list");

                    let cmd = ParamsListCommand::from_args(&config, sub1_matches);
                    match cmd.run() {
                        Ok(_) => {
                        },
                        Err(error) => {
                            output::PrintLine::error(&format!("Failed: {}", error));
                        }
                    }

                    info!("end params list");
                }
                if let Some(sub1_matches) = sub0_matches.subcommand_matches("put") {
                    info!("start params put");

                    let cmd = ParamsPutCommand::from_args(&config, sub1_matches);
                    match cmd.run() {
                        Ok(_) => {
                        },
                        Err(error) => {
                            output::PrintLine::error(&format!("Failed: {}", error));
                        }
                    }

                    info!("end params put");
                }
                if let Some(sub1_matches) = sub0_matches.subcommand_matches("delete") {
                    info!("start params delete");

                    let cmd = ParamsDeleteCommand::from_args(&config, sub1_matches);
                    match cmd.run() {
                        Ok(_) => {
                        },
                        Err(error) => {
                            output::PrintLine::error(&format!("Failed: {}", error));
                        }
                    }

                    info!("end params delete");
                }
                if let Some(sub1_matches) = sub0_matches.subcommand_matches("exec") {
                    info!("start params exec");

                    let cmd = ParamsExecCommand::from_args(&config, sub1_matches);
                    match cmd.run() {
                        Ok(_) => {
                        },
                        Err(error) => {
                            output::PrintLine::error(&format!("Failed: {}", error));
                        }
                    }

                    info!("end params exec");
                }
            }

        },
    };

    info!("end racco");

    Ok(())
  }
}
<|endoftext|>


<commit_before>use command::{Command, Query};
use commandlinable::Escape;

#[derive(Clone, Debug)]
pub struct CommandLine {
    command: Command,
    arguments: Query,
}

impl CommandLine {
    pub fn new(command: Command, query: Query) -> CommandLine {
        CommandLine {
            command: command,
            arguments: query,
        }
    }

    /// Get command enum constant to construct command line query.
    pub fn get_command(&mut self) -> Command {
        self.command.clone()
    }

    /// Get vectorize `("key", "value")` pairs to construct command line query.
    pub fn get_argument(&mut self) -> Query {
        self.arguments.clone()
    }

    /// Set vectorize `("key", "value")` pairs to construct command line query.
    pub fn set_argument(&mut self, arguments: Query) {
        self.arguments = arguments
    }

    /// Create command line style command query.
    ///
    /// `vec![("key","value")]` interprets to `"--key value"`.
    /// And two or more value pair are concatinate with ` `(a space).
    pub fn make_command(&mut self) -> String {
        let mut output = String::new();
        for query in self.arguments.to_owned() {
            let (key, value) = query;
            if output.len() >= 1 {
                output.push_str(" ");
            }
            let format_string = format!("--{} {}", &*key, Escape(&*value));
            output.push_str(format_string.as_str());
        }
        output
    }

    ///
    /// Create Groonga command line style command.
    pub fn encode(&mut self) -> String {
        format!("{} {}", self.get_command(), self.make_command())
            .trim()
            .to_string()
    }
}

#[cfg(test)]
mod test {
    use super::CommandLine;
    use select::SelectCommand;
    use load::{LoadCommand, InputType};
    use status::StatusCommand;
    use dump::DumpCommand;
    use delete::DeleteCommand;
    use table_create::TableCreateCommand;
    use types::table_flag_type::TableFlagType;
    use column_create::ColumnCreateCommand;
    use types::data_type::DataType;

    #[test]
    fn test_select() {
        let (command, query) = SelectCommand::new("Test".to_string())
            .filter("output_column @ \"type_safe\"".to_string())
            .build();
        let command_line = CommandLine::new(command, query).encode();
        let cli_encoded = "select --table Test --filter \'output_column @ \"type_safe\"\'";
        assert_eq!(cli_encoded.to_string(), command_line);
    }

    #[test]
    fn test_load() {
        let load_data: &'static str = r#"[
{"_key":"http://example.org/","title":"This is test record 1!"},
]"#;
        let (command, query, values) = LoadCommand::new("Test".to_string(), load_data.to_string())
            .input_type(InputType::Json)
            .build();
        let command_line = CommandLine::new(command, query).encode();
        let cli_encoded = "load --table Test --input_type json";
        assert_eq!(cli_encoded.to_string(), command_line);
        assert_eq!(load_data.to_string(), values);
    }

    #[test]
    fn test_status() {
        let (command, query) = StatusCommand::new().build();
        let command_line = CommandLine::new(command, query).encode();
        let cli_encoded = "status";
        assert_eq!(cli_encoded.to_string(), command_line);
    }

    #[test]
    fn test_dump() {
        let (command, query) = DumpCommand::new()
            .tables(vec!["Books".to_string(), "Categories".to_string()])
            .build();
        let command_line = CommandLine::new(command, query).encode();
        let cli_encoded = "dump --tables Books,Categories";
        assert_eq!(cli_encoded.to_string(), command_line);
    }

    #[test]
    fn test_delete() {
        let (command, query) = DeleteCommand::new("Books".to_string())
            .filter("author == unknown".to_string())
            .build();
        let command_line = CommandLine::new(command, query).encode();
        let cli_encoded = "delete --table Books --filter \'author == unknown\'";
        assert_eq!(cli_encoded.to_string(), command_line);
    }

    #[test]
    fn test_table_create() {
        let (command, query) = TableCreateCommand::new("Test".to_string())
            .flags(vec![(TableFlagType::PatKey), (TableFlagType::KeyWithSIS)])
            .build();
        let command_line = CommandLine::new(command, query).encode();
        let url_encoded = "table_create --name Test --flags TABLE_PAT_KEY|KEY_WITH_SIS";
        assert_eq!(url_encoded.to_string(), command_line);
    }

    #[test]
    fn test_column_create() {
        let (command, query) = ColumnCreateCommand::new("Test".to_string(), "element".to_string())
            .column_type(DataType::LongText)
            .build();
        let command_line = CommandLine::new(command, query).encode();
        let cli_encoded = "column_create --table Test --name element --type LongText";
        assert_eq!(cli_encoded.to_string(), command_line);
    }
}
<commit_msg>command_line: Try to use Cow<commit_after>use command::{Command, Query};
use commandlinable::Escape;
use std::borrow::Cow;

#[derive(Clone, Debug)]
pub struct CommandLine {
    command: Command,
    arguments: Query,
}

impl CommandLine {
    pub fn new(command: Command, query: Query) -> CommandLine {
        CommandLine {
            command: command,
            arguments: query,
        }
    }

    /// Get command enum constant to construct command line query.
    pub fn get_command(&mut self) -> Cow<Command> {
        Cow::Borrowed(&self.command)
    }

    /// Get vectorize `("key", "value")` pairs to construct command line query.
    pub fn get_argument(&mut self) -> Cow<Query> {
        Cow::Borrowed(&self.arguments)
    }

    /// Set vectorize `("key", "value")` pairs to construct command line query.
    pub fn set_argument(&mut self, arguments: Query) {
        self.arguments = arguments
    }

    /// Create command line style command query.
    ///
    /// `vec![("key","value")]` interprets to `"--key value"`.
    /// And two or more value pair are concatinate with ` `(a space).
    pub fn make_command<'a>(&mut self) -> Cow<'a, str> {
        let mut output = String::new();
        for query in self.arguments.to_owned() {
            let (key, value) = query;
            if output.len() >= 1 {
                output.push_str(" ");
            }
            let format_string = format!("--{} {}", &*key, Escape(&*value));
            output.push_str(format_string.as_str());
        }
        Cow::Owned(output)
    }

    ///
    /// Create Groonga command line style command.
    pub fn encode(&mut self) -> String {
        format!("{} {}", self.get_command().into_owned(), self.make_command().into_owned())
            .trim()
            .to_string()
    }
}

#[cfg(test)]
mod test {
    use super::CommandLine;
    use select::SelectCommand;
    use load::{LoadCommand, InputType};
    use status::StatusCommand;
    use dump::DumpCommand;
    use delete::DeleteCommand;
    use table_create::TableCreateCommand;
    use types::table_flag_type::TableFlagType;
    use column_create::ColumnCreateCommand;
    use types::data_type::DataType;

    #[test]
    fn test_select() {
        let (command, query) = SelectCommand::new("Test".to_string())
            .filter("output_column @ \"type_safe\"".to_string())
            .build();
        let command_line = CommandLine::new(command, query).encode();
        let cli_encoded = "select --table Test --filter \'output_column @ \"type_safe\"\'";
        assert_eq!(cli_encoded.to_string(), command_line);
    }

    #[test]
    fn test_load() {
        let load_data: &'static str = r#"[
{"_key":"http://example.org/","title":"This is test record 1!"},
]"#;
        let (command, query, values) = LoadCommand::new("Test".to_string(), load_data.to_string())
            .input_type(InputType::Json)
            .build();
        let command_line = CommandLine::new(command, query).encode();
        let cli_encoded = "load --table Test --input_type json";
        assert_eq!(cli_encoded.to_string(), command_line);
        assert_eq!(load_data.to_string(), values);
    }

    #[test]
    fn test_status() {
        let (command, query) = StatusCommand::new().build();
        let command_line = CommandLine::new(command, query).encode();
        let cli_encoded = "status";
        assert_eq!(cli_encoded.to_string(), command_line);
    }

    #[test]
    fn test_dump() {
        let (command, query) = DumpCommand::new()
            .tables(vec!["Books".to_string(), "Categories".to_string()])
            .build();
        let command_line = CommandLine::new(command, query).encode();
        let cli_encoded = "dump --tables Books,Categories";
        assert_eq!(cli_encoded.to_string(), command_line);
    }

    #[test]
    fn test_delete() {
        let (command, query) = DeleteCommand::new("Books".to_string())
            .filter("author == unknown".to_string())
            .build();
        let command_line = CommandLine::new(command, query).encode();
        let cli_encoded = "delete --table Books --filter \'author == unknown\'";
        assert_eq!(cli_encoded.to_string(), command_line);
    }

    #[test]
    fn test_table_create() {
        let (command, query) = TableCreateCommand::new("Test".to_string())
            .flags(vec![(TableFlagType::PatKey), (TableFlagType::KeyWithSIS)])
            .build();
        let command_line = CommandLine::new(command, query).encode();
        let url_encoded = "table_create --name Test --flags TABLE_PAT_KEY|KEY_WITH_SIS";
        assert_eq!(url_encoded.to_string(), command_line);
    }

    #[test]
    fn test_column_create() {
        let (command, query) = ColumnCreateCommand::new("Test".to_string(), "element".to_string())
            .column_type(DataType::LongText)
            .build();
        let command_line = CommandLine::new(command, query).encode();
        let cli_encoded = "column_create --table Test --name element --type LongText";
        assert_eq!(cli_encoded.to_string(), command_line);
    }
}
<|endoftext|>


<commit_before>use crate::config::types::*;
use clap::{value_t, values_t, ArgMatches};
use coveralls_api::CiService;
use log::error;
use regex::Regex;
use std::env;
use std::path::PathBuf;
use std::time::Duration;

pub(super) fn get_list(args: &ArgMatches, key: &str) -> Vec<String> {
    args.values_of_lossy(key).unwrap_or_else(Vec::new)
}

pub(super) fn get_line_cov(args: &ArgMatches) -> bool {
    let cover_lines = args.is_present("line");
    let cover_branches = args.is_present("branch");

    cover_lines || !(cover_lines || cover_branches)
}

pub(super) fn get_branch_cov(args: &ArgMatches) -> bool {
    let cover_lines = args.is_present("line");
    let cover_branches = args.is_present("branch");

    cover_branches || !(cover_lines || cover_branches)
}

pub(super) fn get_manifest(args: &ArgMatches) -> PathBuf {
    if let Some(path) = args.value_of("manifest-path") {
        let path = PathBuf::from(path);
        if path.is_relative() {
            return env::current_dir().unwrap().join(path).canonicalize().unwrap();
        }
        return path;
    }

    let mut manifest = env::current_dir().unwrap();

    if let Some(path) = args.value_of("root") {
        manifest.push(path);
    }

    manifest.push("Cargo.toml");
    manifest.canonicalize().unwrap_or(manifest)
}

pub(super) fn get_root(args: &ArgMatches) -> Option<String> {
    args.value_of("root").map(ToString::to_string)
}

pub(super) fn get_ci(args: &ArgMatches) -> Option<CiService> {
    value_t!(args, "ciserver", Ci).map(|x| x.0).ok()
}

pub(super) fn get_coveralls(args: &ArgMatches) -> Option<String> {
    args.value_of("coveralls").map(ToString::to_string)
}

pub(super) fn get_report_uri(args: &ArgMatches) -> Option<String> {
    args.value_of("report-uri").map(ToString::to_string)
}

pub(super) fn get_outputs(args: &ArgMatches) -> Vec<OutputFile> {
    values_t!(args.values_of("out"), OutputFile).unwrap_or(vec![])
}

pub(super) fn get_output_directory(args: &ArgMatches) -> PathBuf {
    if let Some(path) = args.value_of("output-dir") {
        return PathBuf::from(path);
    }
    env::current_dir().unwrap()
}

pub(super) fn get_run_types(args: &ArgMatches) -> Vec<RunType> {
    values_t!(args.values_of("run-types"), RunType).unwrap_or(vec![RunType::Tests])
}

pub(super) fn get_excluded(args: &ArgMatches) -> Vec<Regex> {
    let mut files = vec![];

    for temp_str in &get_list(args, "exclude-files") {
        let s = &temp_str.replace(".", r"\.").replace("*", ".*");

        if let Ok(re) = Regex::new(s) {
            files.push(re);
        } else {
            error!("Invalid regex: {}", temp_str);
        }
    }

    files
}

pub(super) fn get_timeout(args: &ArgMatches) -> Duration {
    if args.is_present("timeout") {
        let duration = value_t!(args.value_of("timeout"), u64).unwrap_or(60);
        Duration::from_secs(duration)
    } else {
        Duration::from_secs(60)
    }
}
<commit_msg>get_manifest: Reformat canonicalization chain<commit_after>use crate::config::types::*;
use clap::{value_t, values_t, ArgMatches};
use coveralls_api::CiService;
use log::error;
use regex::Regex;
use std::env;
use std::path::PathBuf;
use std::time::Duration;

pub(super) fn get_list(args: &ArgMatches, key: &str) -> Vec<String> {
    args.values_of_lossy(key).unwrap_or_else(Vec::new)
}

pub(super) fn get_line_cov(args: &ArgMatches) -> bool {
    let cover_lines = args.is_present("line");
    let cover_branches = args.is_present("branch");

    cover_lines || !(cover_lines || cover_branches)
}

pub(super) fn get_branch_cov(args: &ArgMatches) -> bool {
    let cover_lines = args.is_present("line");
    let cover_branches = args.is_present("branch");

    cover_branches || !(cover_lines || cover_branches)
}

pub(super) fn get_manifest(args: &ArgMatches) -> PathBuf {
    if let Some(path) = args.value_of("manifest-path") {
        let path = PathBuf::from(path);
        if path.is_relative() {
            return env::current_dir()
                .unwrap()
                .join(path)
                .canonicalize()
                .unwrap();
        }
        return path;
    }

    let mut manifest = env::current_dir().unwrap();

    if let Some(path) = args.value_of("root") {
        manifest.push(path);
    }

    manifest.push("Cargo.toml");
    manifest.canonicalize().unwrap_or(manifest)
}

pub(super) fn get_root(args: &ArgMatches) -> Option<String> {
    args.value_of("root").map(ToString::to_string)
}

pub(super) fn get_ci(args: &ArgMatches) -> Option<CiService> {
    value_t!(args, "ciserver", Ci).map(|x| x.0).ok()
}

pub(super) fn get_coveralls(args: &ArgMatches) -> Option<String> {
    args.value_of("coveralls").map(ToString::to_string)
}

pub(super) fn get_report_uri(args: &ArgMatches) -> Option<String> {
    args.value_of("report-uri").map(ToString::to_string)
}

pub(super) fn get_outputs(args: &ArgMatches) -> Vec<OutputFile> {
    values_t!(args.values_of("out"), OutputFile).unwrap_or(vec![])
}

pub(super) fn get_output_directory(args: &ArgMatches) -> PathBuf {
    if let Some(path) = args.value_of("output-dir") {
        return PathBuf::from(path);
    }
    env::current_dir().unwrap()
}

pub(super) fn get_run_types(args: &ArgMatches) -> Vec<RunType> {
    values_t!(args.values_of("run-types"), RunType).unwrap_or(vec![RunType::Tests])
}

pub(super) fn get_excluded(args: &ArgMatches) -> Vec<Regex> {
    let mut files = vec![];

    for temp_str in &get_list(args, "exclude-files") {
        let s = &temp_str.replace(".", r"\.").replace("*", ".*");

        if let Ok(re) = Regex::new(s) {
            files.push(re);
        } else {
            error!("Invalid regex: {}", temp_str);
        }
    }

    files
}

pub(super) fn get_timeout(args: &ArgMatches) -> Duration {
    if args.is_present("timeout") {
        let duration = value_t!(args.value_of("timeout"), u64).unwrap_or(60);
        Duration::from_secs(duration)
    } else {
        Duration::from_secs(60)
    }
}
<|endoftext|>


<commit_before>use std::str::Chars;

/// Peekable iterator over a char sequence.
///
/// Next characters can be peeked via `nth_char` method,
/// and position can be shifted forward via `bump` method.
pub(crate) struct Cursor<'a> {
    initial_len: usize,
    chars: Chars<'a>,
    #[cfg(debug_assertions)]
    prev: char,
}

pub(crate) const EOF_CHAR: char = '\0';

impl<'a> Cursor<'a> {
    pub(crate) fn new(input: &'a str) -> Cursor<'a> {
        Cursor {
            initial_len: input.len(),
            chars: input.chars(),
            #[cfg(debug_assertions)]
            prev: EOF_CHAR,
        }
    }

    /// For debug assertions only
    /// Returns the last eaten symbol (or '\0' in release builds).
    pub(crate) fn prev(&self) -> char {
        #[cfg(debug_assertions)]
        {
            self.prev
        }

        #[cfg(not(debug_assertions))]
        {
            '\0'
        }
    }

    /// Returns nth character relative to the current cursor position.
    /// If requested position doesn't exist, `EOF_CHAR` is returned.
    /// However, getting `EOF_CHAR` doesn't always mean actual end of file,
    /// it should be checked with `is_eof` method.
    fn nth_char(&self, n: usize) -> char {
        self.chars().nth(n).unwrap_or(EOF_CHAR)
    }

    /// Peeks the next symbol from the input stream without consuming it.
    pub(crate) fn first(&self) -> char {
        self.nth_char(0)
    }

    /// Peeks the second symbol from the input stream without consuming it.
    pub(crate) fn second(&self) -> char {
        self.nth_char(1)
    }

    /// Checks if there is nothing more to consume.
    pub(crate) fn is_eof(&self) -> bool {
        self.chars.as_str().is_empty()
    }

    /// Returns amount of already consumed symbols.
    pub(crate) fn len_consumed(&self) -> usize {
        self.initial_len - self.chars.as_str().len()
    }

    /// Returns a `Chars` iterator over the remaining characters.
    fn chars(&self) -> Chars<'a> {
        self.chars.clone()
    }

    /// Moves to the next character.
    pub(crate) fn bump(&mut self) -> Option<char> {
        let c = self.chars.next()?;

        #[cfg(debug_assertions)]
        {
            self.prev = c;
        }

        Some(c)
    }
}
<commit_msg>Edit cursor.prev() method docs in lexer<commit_after>use std::str::Chars;

/// Peekable iterator over a char sequence.
///
/// Next characters can be peeked via `nth_char` method,
/// and position can be shifted forward via `bump` method.
pub(crate) struct Cursor<'a> {
    initial_len: usize,
    chars: Chars<'a>,
    #[cfg(debug_assertions)]
    prev: char,
}

pub(crate) const EOF_CHAR: char = '\0';

impl<'a> Cursor<'a> {
    pub(crate) fn new(input: &'a str) -> Cursor<'a> {
        Cursor {
            initial_len: input.len(),
            chars: input.chars(),
            #[cfg(debug_assertions)]
            prev: EOF_CHAR,
        }
    }

    /// Returns the last eaten symbol (or `'\0'` in release builds).
    /// (For debug assertions only.)
    pub(crate) fn prev(&self) -> char {
        #[cfg(debug_assertions)]
        {
            self.prev
        }

        #[cfg(not(debug_assertions))]
        {
            '\0'
        }
    }

    /// Returns nth character relative to the current cursor position.
    /// If requested position doesn't exist, `EOF_CHAR` is returned.
    /// However, getting `EOF_CHAR` doesn't always mean actual end of file,
    /// it should be checked with `is_eof` method.
    fn nth_char(&self, n: usize) -> char {
        self.chars().nth(n).unwrap_or(EOF_CHAR)
    }

    /// Peeks the next symbol from the input stream without consuming it.
    pub(crate) fn first(&self) -> char {
        self.nth_char(0)
    }

    /// Peeks the second symbol from the input stream without consuming it.
    pub(crate) fn second(&self) -> char {
        self.nth_char(1)
    }

    /// Checks if there is nothing more to consume.
    pub(crate) fn is_eof(&self) -> bool {
        self.chars.as_str().is_empty()
    }

    /// Returns amount of already consumed symbols.
    pub(crate) fn len_consumed(&self) -> usize {
        self.initial_len - self.chars.as_str().len()
    }

    /// Returns a `Chars` iterator over the remaining characters.
    fn chars(&self) -> Chars<'a> {
        self.chars.clone()
    }

    /// Moves to the next character.
    pub(crate) fn bump(&mut self) -> Option<char> {
        let c = self.chars.next()?;

        #[cfg(debug_assertions)]
        {
            self.prev = c;
        }

        Some(c)
    }
}
<|endoftext|>


<commit_before>pub enum Flag {
    Set(&'static str),
    Clear(&'static str),
    NotAffected(&'static str),
    Undefined,
}

pub struct FlagsDesc {
    pub x: Flag,
    pub n: Flag,
    pub z: Flag,
    pub v: Flag,
    pub c: Flag,
}

const FLAGS_ARC: FlagsDesc = FlagsDesc {
    x: Flag::Set("X - Set the same as carry"),
    n: Flag::Set("N - Set if the result is negative; cleared otherwise."),
    z: Flag::Set("Z — Set if the result is zero; cleared otherwise."),
    v: Flag::Set("V — Set if an overflow is generated; cleared otherwise."),
    c: Flag::Set("C — Set if a carry is generated; cleared otherwise."),
};

const FLAGS_ABCD: FlagsDesc = FlagsDesc {
    x: Flag::Set("X - Set the same as carry"),
    n: Flag::Undefined,
    z: Flag::Clear("Z — Cleared if the result is nonzero; unchanged otherwise"),
    v: Flag::Undefined,
    c: Flag::Set("C — Set if a decimal carry was generated; cleared otherwise."),
};

pub struct Description {
    pub description: &'static str,
    pub operation: &'static str,
    pub assembler: &'static [&'static str],
    pub attributes: &'static str,
    pub flags: &'static FlagsDesc,
}

pub const ABCD_DESC: Description = Description {
    description: "Adds the source operand to the destination operand along with the extend bit, and stores the result in the destination location. The addition is performed using binary- coded decimal arithmetic. The operands, which are packed binary-coded decimal numbers, can be addressed in two different ways\n
        1. Data Register to Data Register: The operands are contained in the data registers specified in the instruction.\n
        2. Memory to Memory: The operands are addressed with the predecrement addressing mode using the address registers specified in the instruction.\n
        This operation is a byte operation only.",
    operation: "Source10 + Destination10 + X → Destination",
    assembler: &["Add < ea > ,Dn", "Add Dn, < ea >"],
    attributes: "Byte, Word, Long",
    flags: &FLAGS_ABCD,
};

pub const ADD_DESC: Description = Description {
    description: "Adds the source operand to the destination operand using binary addition and stores the result in the destination location. The size of the operation may be specified as byte, word, or long. The mode of the instruction indicates which operand is the source and which is the destination, as well as the operand size.",
    operation: "Source + Destination → Destination",
    assembler: &["Add < ea > ,Dn", "Add Dn, < ea >"],
    attributes: "Byte, Word, Long",
    flags: &FLAGS_ARC,
};

<commit_msg>Added some more descriptions<commit_after>pub enum Flag {
    Set(&'static str),
    Clear(&'static str),
    NotAffected(&'static str),
    Undefined,
}

pub struct FlagsDesc {
    pub x: Flag,
    pub n: Flag,
    pub z: Flag,
    pub v: Flag,
    pub c: Flag,
}

const FLAGS_ARC: FlagsDesc = FlagsDesc {
    x: Flag::Set("X - Set the same as carry"),
    n: Flag::Set("N - Set if the result is negative; cleared otherwise."),
    z: Flag::Set("Z — Set if the result is zero; cleared otherwise."),
    v: Flag::Set("V — Set if an overflow is generated; cleared otherwise."),
    c: Flag::Set("C — Set if a carry is generated; cleared otherwise."),
};

const FLAGS_X: FlagsDesc = FlagsDesc {
    x: Flag::Set("X - Set the same as carry"),
    n: Flag::Set("N - Set if the result is negative; cleared otherwise."),
    z: Flag::Set("Z — Cleared if the result is non-zero; unchanged otherwise."),
    v: Flag::Set("V — Set if an overflow is generated; cleared otherwise."),
    c: Flag::Set("C — Set if a carry is generated; cleared otherwise."),
};

const FLAGS_ABCD: FlagsDesc = FlagsDesc {
    x: Flag::Set("X - Set the same as carry"),
    n: Flag::Undefined,
    z: Flag::Clear("Z — Cleared if the result is nonzero; unchanged otherwise"),
    v: Flag::Undefined,
    c: Flag::Set("C — Set if a decimal carry was generated; cleared otherwise."),
};

const FLAGS_AND: FlagsDesc = FlagsDesc {
    x: Flag::NotAffected("X - Not Affected"),
    n: Flag::Set("N — Set if the most significant bit of the result is set; cleared otherwise."),
    z: Flag::Set("Z — Set if the result is zero; cleared otherwise."),
    v: Flag::Clear("V — Always cleared."),
    c: Flag::Clear("C — Always cleared."),
};

pub struct Description {
    pub description: &'static str,
    pub operation: &'static str,
    pub assembler: &'static [&'static str],
    pub attributes: &'static str,
    pub flags: &'static FlagsDesc,
}

pub const ABCD_DESC: Description = Description {
    description: "Adds the source operand to the destination operand along with the extend bit, and stores the result in the destination location. The addition is performed using binary- coded decimal arithmetic. The operands, which are packed binary-coded decimal numbers, can be addressed in two different ways\n
        1. Data Register to Data Register: The operands are contained in the data registers specified in the instruction.\n
        2. Memory to Memory: The operands are addressed with the predecrement addressing mode using the address registers specified in the instruction.\n
        This operation is a byte operation only.",
    operation: "Source10 + Destination10 + X → Destination",
    assembler: &["abcd < ea > ,Dn", "Add Dn, < ea >"],
    attributes: "Byte, Word, Long",
    flags: &FLAGS_ABCD,
};

pub const ADD_DESC: Description = Description {
    description: "Adds the source operand to the destination operand using binary addition and stores the result in the destination location. The size of the operation may be specified as byte, word, or long. The mode of the instruction indicates which operand is the source and which is the destination, as well as the operand size.",
    operation: "Source + Destination → Destination",
    assembler: &["Add < ea > ,Dn", "Add Dn, < ea >"],
    attributes: "Byte, Word, Long",
    flags: &FLAGS_ARC,
};

pub const ADDQ_DESC: Description = Description {
    description: "Adds an immediate value of one to eight to the operand at the destination location. The size of the operation may be specified as byte, word, or long. Word and long operations are also allowed on the address registers. When adding to address registers, the condition codes are not altered, and the entire destination address register is used regardless of the operation size.",
    operation: "Immidate + Destination → Destination",
    assembler: &["addq # < data > , < ea >"],
    attributes: "Byte, Word, Long",
    flags: &FLAGS_ARC,
};

pub const ADDX_DESC: Description = Description {
    description: "Adds the source operand and the extend bit to the destination operand and stores the result in the destination location. The operands can be addressed in two different ways:
                    1. Data register to data register—The data registers specified in the instruction contain the operands.
                    2. Memory to memory—The address registers specified in the instruction address the operands using the predecrement addressing mode.
                    The size of the operation can be specified as byte, word, or long.";
    operation: "Source + Destination + X → Destination",
    assembler: &["addx Dy,Dx", "addx -(Ay),-(Ax)"],
    attributes: "Byte, Word, Long",
    flags: &FLAGS_X,
};

pub const AND_DESC: Description = Description {
    description: "Performs an AND operation of the source operand with the destination operand and stores the result in the destination location. The size of the operation can be specified as byte, word, or long. The contents of an address register may not be used as an operand.",
    operation: "Source & Destination → Destination",
    assembler: &["and < ea > ,Dn", "Add Dn, < ea >"],
    attributes: "Byte, Word, Long",
    flags: &FLAGS_AND,
};

<|endoftext|>


<commit_before>use std::{convert};
use std::io::{Cursor, Read};

use byteorder;
use byteorder::{ReadBytesExt};

#[derive(Debug, PartialEq, Eq)]
pub enum DeserializationError {
    UnexpectedTag,
    ShortData,
    ExtraData,
    IntegerOverflow,
}

impl convert::From<byteorder::Error> for DeserializationError {
    fn from(e: byteorder::Error) -> DeserializationError {
        return match e {
            byteorder::Error::UnexpectedEOF => DeserializationError::ShortData,
            _ => panic!("Unexpected error!"),
        }
    }
}

pub type DeserializationResult<T> = Result<T, DeserializationError>;

pub struct Deserializer {
    reader: Cursor<Vec<u8>>,
}

impl Deserializer {
    pub fn new(data: Vec<u8>) -> Deserializer {
        return Deserializer{
            reader: Cursor::new(data),
        }
    }

    fn _read_length(&mut self) -> DeserializationResult<usize> {
        let b = try!(self.reader.read_u8());
        // TODO: handle lengths greater than 128
        assert!(b & 0x80 == 0);
        return Ok((b & 0x7f) as usize);
    }

    fn _read_with_tag<T, F>(&mut self, expected_tag: u8, body: F) -> DeserializationResult<T>
            where F: Fn(Vec<u8>) -> DeserializationResult<T> {
        // TODO: only some of the bits in the first byte are for the tag
        let tag = try!(self.reader.read_u8());
        if tag != expected_tag {
            return Err(DeserializationError::UnexpectedTag);
        }
        let length = try!(self._read_length());
        let mut data = vec![0; length];
        let n = self.reader.read(&mut data).unwrap();
        if n != length {
            return Err(DeserializationError::ShortData);
        }
        return body(data);
    }

    pub fn finish(self) -> DeserializationResult<()> {
        if self.reader.position() as usize != self.reader.get_ref().len() {
            return Err(DeserializationError::ExtraData);
        }
        return Ok(());
    }

    pub fn read_int(&mut self) -> DeserializationResult<i64> {
        return self._read_with_tag(2, |data| {
            if data.len() > 8 {
                return Err(DeserializationError::IntegerOverflow);
            }
            let mut ret = 0;
            for b in data.iter() {
                ret <<= 8;
                ret |= *b as i64;
            }
            // Shift up and down in order to sign extend the result.
            ret <<= 64 - data.len() * 8;
            ret >>= 64 - data.len() * 8;
            return Ok(ret);
        });
    }
}

pub fn from_vec<F, T>(data: Vec<u8>, f: F) -> DeserializationResult<T>
        where F: Fn(&mut Deserializer) -> DeserializationResult<T> {
    let mut deserializer = Deserializer::new(data);
    let result = try!(f(&mut deserializer));
    try!(deserializer.finish());
    return Ok(result);
}

#[cfg(test)]
mod tests {
    use std::{fmt};

    use super::{Deserializer, DeserializationError, DeserializationResult, from_vec};

    fn assert_deserializes<T, F>(values: Vec<(DeserializationResult<T>, Vec<u8>)>, f: F)
            where T: Eq + fmt::Debug, F: Fn(&mut Deserializer) -> DeserializationResult<T> {
        for (expected, value) in values {
            let result = from_vec(value, &f);
            assert_eq!(result, expected);
        }
    }
    #[test]
    fn test_read_extra_data() {
        assert_deserializes(vec![
            (Err(DeserializationError::ExtraData), b"\x00".to_vec()),
        ], |_| {
            return Ok(());
        });
    }

    #[test]
    fn test_read_int() {
        assert_deserializes(vec![
            (Ok(0), b"\x02\x01\x00".to_vec()),
            (Ok(127), b"\x02\x01\x7f".to_vec()),
            (Ok(128), b"\x02\x02\x00\x80".to_vec()),
            (Ok(256), b"\x02\x02\x01\x00".to_vec()),
            (Ok(-128), b"\x02\x01\x80".to_vec()),
            (Ok(-129), b"\x02\x02\xff\x7f".to_vec()),
            (Err(DeserializationError::UnexpectedTag), b"\x03".to_vec()),
            (Err(DeserializationError::ShortData), b"\x02\x02\x00".to_vec()),
            (Err(DeserializationError::ShortData), b"".to_vec()),
            (Err(DeserializationError::ShortData), b"\x02".to_vec()),
            (
                Err(DeserializationError::IntegerOverflow),
                b"\x02\x09\x02\x00\x00\x00\x00\x00\x00\x00\x00".to_vec()
            ),
        ], |deserializer| {
            return deserializer.read_int();
        });
    }
}
<commit_msg>put this comment in the right place<commit_after>use std::{convert};
use std::io::{Cursor, Read};

use byteorder;
use byteorder::{ReadBytesExt};

#[derive(Debug, PartialEq, Eq)]
pub enum DeserializationError {
    UnexpectedTag,
    ShortData,
    ExtraData,
    IntegerOverflow,
}

impl convert::From<byteorder::Error> for DeserializationError {
    fn from(e: byteorder::Error) -> DeserializationError {
        return match e {
            byteorder::Error::UnexpectedEOF => DeserializationError::ShortData,
            _ => panic!("Unexpected error!"),
        }
    }
}

pub type DeserializationResult<T> = Result<T, DeserializationError>;

pub struct Deserializer {
    reader: Cursor<Vec<u8>>,
}

impl Deserializer {
    pub fn new(data: Vec<u8>) -> Deserializer {
        return Deserializer{
            reader: Cursor::new(data),
        }
    }

    fn _read_length(&mut self) -> DeserializationResult<usize> {
        let b = try!(self.reader.read_u8());
        // TODO: handle lengths greater than 128
        assert!(b & 0x80 == 0);
        return Ok((b & 0x7f) as usize);
    }

    fn _read_with_tag<T, F>(&mut self, expected_tag: u8, body: F) -> DeserializationResult<T>
            where F: Fn(Vec<u8>) -> DeserializationResult<T> {
        let tag = try!(self.reader.read_u8());
        // TODO: only some of the bits in the first byte are for the tag
        if tag != expected_tag {
            return Err(DeserializationError::UnexpectedTag);
        }
        let length = try!(self._read_length());
        let mut data = vec![0; length];
        let n = self.reader.read(&mut data).unwrap();
        if n != length {
            return Err(DeserializationError::ShortData);
        }
        return body(data);
    }

    pub fn finish(self) -> DeserializationResult<()> {
        if self.reader.position() as usize != self.reader.get_ref().len() {
            return Err(DeserializationError::ExtraData);
        }
        return Ok(());
    }

    pub fn read_int(&mut self) -> DeserializationResult<i64> {
        return self._read_with_tag(2, |data| {
            if data.len() > 8 {
                return Err(DeserializationError::IntegerOverflow);
            }
            let mut ret = 0;
            for b in data.iter() {
                ret <<= 8;
                ret |= *b as i64;
            }
            // Shift up and down in order to sign extend the result.
            ret <<= 64 - data.len() * 8;
            ret >>= 64 - data.len() * 8;
            return Ok(ret);
        });
    }
}

pub fn from_vec<F, T>(data: Vec<u8>, f: F) -> DeserializationResult<T>
        where F: Fn(&mut Deserializer) -> DeserializationResult<T> {
    let mut deserializer = Deserializer::new(data);
    let result = try!(f(&mut deserializer));
    try!(deserializer.finish());
    return Ok(result);
}

#[cfg(test)]
mod tests {
    use std::{fmt};

    use super::{Deserializer, DeserializationError, DeserializationResult, from_vec};

    fn assert_deserializes<T, F>(values: Vec<(DeserializationResult<T>, Vec<u8>)>, f: F)
            where T: Eq + fmt::Debug, F: Fn(&mut Deserializer) -> DeserializationResult<T> {
        for (expected, value) in values {
            let result = from_vec(value, &f);
            assert_eq!(result, expected);
        }
    }
    #[test]
    fn test_read_extra_data() {
        assert_deserializes(vec![
            (Err(DeserializationError::ExtraData), b"\x00".to_vec()),
        ], |_| {
            return Ok(());
        });
    }

    #[test]
    fn test_read_int() {
        assert_deserializes(vec![
            (Ok(0), b"\x02\x01\x00".to_vec()),
            (Ok(127), b"\x02\x01\x7f".to_vec()),
            (Ok(128), b"\x02\x02\x00\x80".to_vec()),
            (Ok(256), b"\x02\x02\x01\x00".to_vec()),
            (Ok(-128), b"\x02\x01\x80".to_vec()),
            (Ok(-129), b"\x02\x02\xff\x7f".to_vec()),
            (Err(DeserializationError::UnexpectedTag), b"\x03".to_vec()),
            (Err(DeserializationError::ShortData), b"\x02\x02\x00".to_vec()),
            (Err(DeserializationError::ShortData), b"".to_vec()),
            (Err(DeserializationError::ShortData), b"\x02".to_vec()),
            (
                Err(DeserializationError::IntegerOverflow),
                b"\x02\x09\x02\x00\x00\x00\x00\x00\x00\x00\x00".to_vec()
            ),
        ], |deserializer| {
            return deserializer.read_int();
        });
    }
}
<|endoftext|>