<commit_before>//! # Documentation: FAQ
//!
//! 1. [Comparisons](#comparisons)
//!    1. [How does `clap` compare to structopt?](#how-does-clap-compare-to-structopt)
//!    2. [What are some reasons to use `clap`? (The Pitch)](#what-are-some-reasons-to-use-clap-the-pitch)
//!    3. [What are some reasons *not* to use `clap`? (The Anti Pitch)](#what-are-some-reasons-not-to-use-clap-the-anti-pitch)
//!    4. [Reasons to use `clap`](#reasons-to-use-clap)
//! 2. [How many approaches are there to create a parser?](#how-many-approaches-are-there-to-create-a-parser)
//! 3. [When should I use the builder vs derive APIs?](#when-should-i-use-the-builder-vs-derive-apis)
//! 4. [Why is there a default subcommand of help?](#why-is-there-a-default-subcommand-of-help)
//!
//! ### Comparisons
//!
//! First, let me say that these comparisons are highly subjective, and not meant
//! in a critical or harsh manner. All the argument parsing libraries out there (to
//! include `clap`) have their own strengths and weaknesses. Sometimes it just
//! comes down to personal taste when all other factors are equal. When in doubt,
//! try them all and pick one that you enjoy :) There's plenty of room in the Rust
//! community for multiple implementations!
//!
//! For less detailed but more broad comparisons, see
//! [argparse-benchmarks](https://github.com/rust-cli/argparse-benchmarks-rs).
//!
//! #### How does `clap` compare to [structopt](https://github.com/TeXitoi/structopt)?
//!
//! Simple! `clap` *is* `structopt`.  `structopt` started as a derive API built on
//! top of clap v2.  With clap v3, we've forked structopt and integrated it
//! directly into clap.  structopt is in
//! [maintenance mode](https://github.com/TeXitoi/structopt/issues/516#issuecomment-989566094)
//! with the release of `clap_derive`.
//!
//! The benefits of integrating `structopt` and `clap` are:
//! - Easier cross-linking in documentation
//! - [Documentation parity](../examples)
//! - Tighter design feedback loop, ensuring all new features are designed with
//!   derives in mind and easier to change `clap` in response to `structopt` bugs.
//! - Clearer endorsement of `structopt`
//!
//! See also
//! - [`clap` v3 CHANGELOG](../CHANGELOG.md#300---2021-12-31)
//! - [`structopt` migration guide](../CHANGELOG.md#migrate-structopt)
//!
//! #### What are some reasons to use `clap`? (The Pitch)
//!
//! `clap` is as fast, and as lightweight as possible while still giving all the features you'd expect from a modern argument parser. In fact, for the amount and type of features `clap` offers it remains about as fast as `getopts`. If you use `clap` when just need some simple arguments parsed, you'll find it's a walk in the park. `clap` also makes it possible to represent extremely complex, and advanced requirements, without too much thought. `clap` aims to be intuitive, easy to use, and fully capable for wide variety use cases and needs.
//!
//! #### What are some reasons *not* to use `clap`? (The Anti Pitch)
//!
//! Depending on the style in which you choose to define the valid arguments, `clap` can be very verbose. `clap` also offers so many finetuning knobs and dials, that learning everything can seem overwhelming. I strive to keep the simple cases simple, but when turning all those custom dials it can get complex. `clap` is also opinionated about parsing. Even though so much can be tweaked and tuned with `clap` (and I'm adding more all the time), there are still certain features which `clap` implements in specific ways which may be contrary to some users use-cases.
//!
//! #### Reasons to use `clap`
//!
//!  * You want all the nice CLI features your users may expect, yet you don't want to implement them all yourself. You'd like to focus your application, not argument parsing.
//!  * In addition to the point above; you don't want to sacrifice performance to get all those nice features
//!  * You have complex requirements/conflicts between your various valid args.
//!  * You want to use subcommands (although other libraries also support subcommands, they are not nearly as feature rich as those provided by `clap`)
//!  * You want some sort of custom validation built into the argument parsing process, instead of as part of your application (which allows for earlier failures, better error messages, more cohesive experience, etc.)
//!
//! ### How many approaches are there to create a parser?
//!
//! The following APIs are supported:
//! - [Derive][crate::_derive::_tutorial]
//! - [Builder][crate::_tutorial]
//!
//! Previously, we supported:
//! - [YAML](https://github.com/clap-rs/clap/issues/3087)
//! - [docopt](http://docopt.org/)-inspired [usage parser](https://github.com/clap-rs/clap/issues/3086)
//! - [`clap_app!`](https://github.com/clap-rs/clap/issues/2835)
//!
//! There are also experiments with other APIs:
//! - [fncmd](https://github.com/yuhr/fncmd): function attribute
//! - [clap-serde](https://github.com/aobatact/clap-serde): create an `Command` from a deserializer
//!
//! ### When should I use the builder vs derive APIs?
//!
//! Our default answer is to use the [Derive API][crate::_derive::_tutorial]:
//! - Easier to read, write, and modify
//! - Easier to keep the argument declaration and reading of argument in sync
//! - Easier to reuse, e.g. [clap-verbosity-flag](https://crates.io/crates/clap-verbosity-flag)
//!
//! The [Builder API][crate::_tutorial] is a lower-level API that someone might want to use for
//! - Faster compile times if you aren't already using other procedural macros
//! - More flexibility, e.g. you can look up an [arguments values][crate::ArgMatches::get_many],
//!   their [ordering with other arguments][crate::ArgMatches::indices_of], and [what set
//!   them][crate::ArgMatches::value_source].  The Derive API can only report values and not
//!   indices of or other data.
//!
//! You can [interop between Derive and Builder APIs][crate::_derive#mixing-builder-and-derive-apis].
//!
//! ### Why is there a default subcommand of help?
//!
//! There is only a default subcommand of `help` when other subcommands have been defined manually. So it's opt-in(ish), being that you only get a `help` subcommand if you're actually using subcommands.
//!
//! Also, if the user defined a `help` subcommand themselves, the auto-generated one wouldn't be added (meaning it's only generated if the user hasn't defined one themselves).
//!
<commit_msg>docs: Quality improvements to FAQ docs<commit_after>//! # Documentation: FAQ
//!
//! 1. [Comparisons](#comparisons)
//!    1. [How does `clap` compare to structopt?](#how-does-clap-compare-to-structopt)
//!    2. [What are some reasons to use `clap`? (The Pitch)](#what-are-some-reasons-to-use-clap-the-pitch)
//!    3. [What are some reasons *not* to use `clap`? (The Anti Pitch)](#what-are-some-reasons-not-to-use-clap-the-anti-pitch)
//!    4. [Reasons to use `clap`](#reasons-to-use-clap)
//! 2. [How many approaches are there to create a parser?](#how-many-approaches-are-there-to-create-a-parser)
//! 3. [When should I use the builder vs derive APIs?](#when-should-i-use-the-builder-vs-derive-apis)
//! 4. [Why is there a default subcommand of help?](#why-is-there-a-default-subcommand-of-help)
//!
//! ### Comparisons
//!
//! First, let me say that these comparisons are highly subjective, and not meant
//! in a critical or harsh manner. All the argument parsing libraries out there (to
//! include `clap`) have their own strengths and weaknesses. Sometimes it just
//! comes down to personal taste when all other factors are equal. When in doubt,
//! try them all and pick one that you enjoy :). There's plenty of room in the Rust
//! community for multiple implementations!
//!
//! For less detailed but more broad comparisons, see
//! [argparse-benchmarks](https://github.com/rust-cli/argparse-benchmarks-rs).
//!
//! #### How does `clap` compare to [structopt](https://github.com/TeXitoi/structopt)?
//!
//! Simple! `clap` *is* `structopt`.  `structopt` started as a derive API built on
//! top of clap v2.  With clap v3, we've forked structopt and integrated it
//! directly into clap.  structopt is in
//! [maintenance mode](https://github.com/TeXitoi/structopt/issues/516#issuecomment-989566094)
//! with the release of `clap_derive`.
//!
//! The benefits of integrating `structopt` and `clap` are:
//! - Easier cross-linking in documentation
//! - [Documentation parity](../examples)
//! - Tighter design feedback loop, ensuring all new features are designed with
//!   derives in mind and easier to change `clap` in response to `structopt` bugs.
//! - Clearer endorsement of `structopt`
//!
//! See also
//! - [`clap` v3 CHANGELOG](../CHANGELOG.md#300---2021-12-31)
//! - [`structopt` migration guide](../CHANGELOG.md#migrate-structopt)
//!
//! #### What are some reasons to use `clap`? (The Pitch)
//!
//! `clap` is as fast, and as lightweight as possible while still giving all the features you'd expect from a modern argument parser. In fact, for the amount and type of features `clap` offers it remains about as fast as `getopts`. If you use `clap`, when you just need some simple arguments parsed, you'll find it's a walk in the park. `clap` also makes it possible to represent extremely complex and advanced requirements without too much thought. `clap` aims to be intuitive, easy to use, and fully capable for wide variety use cases and needs.
//!
//! #### What are some reasons *not* to use `clap`? (The Anti Pitch)
//!
//! Depending on the style in which you choose to define the valid arguments, `clap` can be very verbose. `clap` also offers so many finetuning knobs and dials, that learning everything can seem overwhelming. I strive to keep the simple cases simple, but when turning all those custom dials it can get complex. `clap` is also opinionated about parsing. Even though so much can be tweaked and tuned with `clap` (and I'm adding more all the time), there are still certain features which `clap` implements in specific ways that may be contrary to some users' use-cases.
//!
//! #### Reasons to use `clap`
//!
//!  * You want all the nice CLI features your users may expect, yet you don't want to implement them all yourself. You'd like to focus on your application, not argument parsing.
//!  * In addition to the point above, you don't want to sacrifice performance to get all those nice features.
//!  * You have complex requirements/conflicts between your various valid args.
//!  * You want to use subcommands (although other libraries also support subcommands, they are not nearly as feature rich as those provided by `clap`).
//!  * You want some sort of custom validation built into the argument parsing process, instead of as part of your application (which allows for earlier failures, better error messages, more cohesive experience, etc.).
//!
//! ### How many approaches are there to create a parser?
//!
//! The following APIs are supported:
//! - [Derive][crate::_derive::_tutorial]
//! - [Builder][crate::_tutorial]
//!
//! Previously, we supported:
//! - [YAML](https://github.com/clap-rs/clap/issues/3087)
//! - [docopt](http://docopt.org/)-inspired [usage parser](https://github.com/clap-rs/clap/issues/3086)
//! - [`clap_app!`](https://github.com/clap-rs/clap/issues/2835)
//!
//! There are also experiments with other APIs:
//! - [fncmd](https://github.com/yuhr/fncmd): function attribute
//! - [clap-serde](https://github.com/aobatact/clap-serde): create an `Command` from a deserializer
//!
//! ### When should I use the builder vs derive APIs?
//!
//! Our default answer is to use the [Derive API][crate::_derive::_tutorial]:
//! - Easier to read, write, and modify
//! - Easier to keep the argument declaration and reading of argument in sync
//! - Easier to reuse, e.g. [clap-verbosity-flag](https://crates.io/crates/clap-verbosity-flag)
//!
//! The [Builder API][crate::_tutorial] is a lower-level API that someone might want to use for
//! - Faster compile times if you aren't already using other procedural macros
//! - More flexibility, e.g. you can look up an [arguments values][crate::ArgMatches::get_many],
//!   their [ordering with other arguments][crate::ArgMatches::indices_of], and [what set
//!   them][crate::ArgMatches::value_source].  The Derive API can only report values and not
//!   indices of or other data.
//!
//! You can [interop between Derive and Builder APIs][crate::_derive#mixing-builder-and-derive-apis].
//!
//! ### Why is there a default subcommand of help?
//!
//! There is only a default subcommand of `help` when other subcommands have been defined manually. So it's opt-in(ish), being that you only get a `help` subcommand if you're actually using subcommands.
//!
//! Also, if the user defined a `help` subcommand themselves, the auto-generated one wouldn't be added (meaning it's only generated if the user hasn't defined one themselves).
//!
<|endoftext|>


<commit_before>// Copyright 2013-2014 The CGMath Developers. For a full listing of the authors,
// refer to the Cargo.toml 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.

//! Axis-aligned bounding boxes
//!
//! An AABB is a geometric object which encompasses a set of points and is not
//! rotated. It is either a rectangle or a rectangular prism (depending on the
//! dimension) where the slope of every line is either 0 or undefined. These
//! are useful for very cheap collision detection.

use std::fmt;

use cgmath::{EuclideanSpace, Point2, Point3};
use cgmath::{VectorSpace, Array, Vector2, Vector3};
use cgmath::{BaseNum, BaseFloat, ElementWise};

use {Ray2, Ray3, Plane};
use bound::{Bound, Relation};
use intersect::Continuous;

pub trait MinMax {
    fn min(a: Self, b: Self) -> Self;
    fn max(a: Self, b: Self) -> Self;
}

impl<S> MinMax for Point2<S>
    where S: BaseNum
{
    fn min(a: Point2<S>, b: Point2<S>) -> Point2<S> {
        Point2::new(a.x.partial_min(b.x), a.y.partial_min(b.y))
    }

    fn max(a: Point2<S>, b: Point2<S>) -> Point2<S> {
        Point2::new(a.x.partial_max(b.x), a.y.partial_max(b.y))
    }
}

impl<S> MinMax for Point3<S>
    where S: BaseNum
{
    fn min(a: Point3<S>, b: Point3<S>) -> Point3<S> {
        Point3::new(a.x.partial_min(b.x),
                    a.y.partial_min(b.y),
                    a.z.partial_min(b.z))
    }

    fn max(a: Point3<S>, b: Point3<S>) -> Point3<S> {
        Point3::new(a.x.partial_max(b.x),
                    a.y.partial_max(b.y),
                    a.z.partial_max(b.z))
    }
}

pub trait Aabb<S: BaseNum,
               V: VectorSpace<Scalar = S> + ElementWise + Array<Element = S>,
               P: EuclideanSpace<Scalar = S, Diff = V>>: Sized {
    /// Create a new AABB using two points as opposing corners.
    fn new(p1: P, p2: P) -> Self;

    /// Return a shared reference to the point nearest to (-inf, -inf).
    fn min(&self) -> P;

    /// Return a shared reference to the point nearest to (inf, inf).
    fn max(&self) -> P;

    /// Return the dimensions of this AABB.
    #[inline]
    fn dim(&self) -> V {
        self.max() - self.min()
    }

    /// Return the volume this AABB encloses.
    #[inline]
    fn volume(&self) -> S {
        self.dim().product()
    }

    /// Return the center point of this AABB.
    #[inline]
    fn center(&self) -> P {
        let two = S::one() + S::one();
        self.min() + self.dim() / two
    }

    /// Tests whether a point is cointained in the box, inclusive for min corner
    /// and exclusive for the max corner.
    #[inline]
    fn contains(&self, p: P) -> bool;

    /// Returns a new AABB that is grown to include the given point.
    fn grow(&self, p: P) -> Self
        where P: MinMax
    {
        Aabb::new(MinMax::min(self.min(), p), MinMax::max(self.max(), p))
    }

    /// Add a vector to every point in the AABB, returning a new AABB.
    fn add_v(&self, v: V) -> Self {
        Aabb::new(self.min() + v, self.max() + v)
    }

    /// Multiply every point in the AABB by a scalar, returning a new AABB.
    fn mul_s(&self, s: S) -> Self {
        Aabb::new(self.min() * s, self.max() * s)
    }

    /// Multiply every point in the AABB by a vector, returning a new AABB.
    fn mul_v(&self, v: V) -> Self {
        let min = P::from_vec(self.min().to_vec().mul_element_wise(v));
        let max = P::from_vec(self.max().to_vec().mul_element_wise(v));
        Aabb::new(min, max)
    }
}

/// A two-dimensional AABB, aka a rectangle.
#[derive(Copy, Clone, PartialEq)]
#[cfg_attr(feature = "eders", derive(Serialize, Deserialize))]
pub struct Aabb2<S> {
    pub min: Point2<S>,
    pub max: Point2<S>,
}

impl<S: BaseNum> Aabb2<S> {
    /// Construct a new axis-aligned bounding box from two points.
    #[inline]
    pub fn new(p1: Point2<S>, p2: Point2<S>) -> Aabb2<S> {
        Aabb2 {
            min: Point2::new(p1.x.partial_min(p2.x), p1.y.partial_min(p2.y)),
            max: Point2::new(p1.x.partial_max(p2.x), p1.y.partial_max(p2.y)),
        }
    }

    /// Compute corners.
    #[inline]
    pub fn to_corners(&self) -> [Point2<S>; 4] {
        [self.min,
         Point2::new(self.max.x, self.min.y),
         Point2::new(self.min.x, self.max.y),
         self.max]
    }
}

impl<S: BaseNum> Aabb<S, Vector2<S>, Point2<S>> for Aabb2<S> {
    #[inline]
    fn new(p1: Point2<S>, p2: Point2<S>) -> Aabb2<S> {
        Aabb2::new(p1, p2)
    }

    #[inline]
    fn min(&self) -> Point2<S> {
        self.min
    }

    #[inline]
    fn max(&self) -> Point2<S> {
        self.max
    }

    #[inline]
    fn contains(&self, p: Point2<S>) -> bool {
        let v_min = p - self.min();
        let v_max = self.max() - p;
        v_min.x >= S::zero() && v_min.y >= S::zero() && v_max.x > S::zero() && v_max.y > S::zero()
    }
}

impl<S: BaseNum> fmt::Debug for Aabb2<S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[{:?} - {:?}]", self.min, self.max)
    }
}

/// A three-dimensional AABB, aka a rectangular prism.
#[derive(Copy, Clone, PartialEq)]
#[cfg_attr(feature = "eders", derive(Serialize, Deserialize))]
pub struct Aabb3<S> {
    pub min: Point3<S>,
    pub max: Point3<S>,
}

impl<S: BaseNum> Aabb3<S> {
    /// Construct a new axis-aligned bounding box from two points.
    #[inline]
    pub fn new(p1: Point3<S>, p2: Point3<S>) -> Aabb3<S> {
        Aabb3 {
            min: Point3::new(p1.x.partial_min(p2.x),
                             p1.y.partial_min(p2.y),
                             p1.z.partial_min(p2.z)),
            max: Point3::new(p1.x.partial_max(p2.x),
                             p1.y.partial_max(p2.y),
                             p1.z.partial_max(p2.z)),
        }
    }

    /// Compute corners.
    #[inline]
    pub fn to_corners(&self) -> [Point3<S>; 8] {
        [self.min,
         Point3::new(self.max.x, self.min.y, self.min.z),
         Point3::new(self.min.x, self.max.y, self.min.z),
         Point3::new(self.max.x, self.max.y, self.min.z),
         Point3::new(self.min.x, self.min.y, self.max.z),
         Point3::new(self.max.x, self.min.y, self.max.z),
         Point3::new(self.min.x, self.max.y, self.max.z),
         self.max]
    }
}

impl<S: BaseNum> Aabb<S, Vector3<S>, Point3<S>> for Aabb3<S> {
    #[inline]
    fn new(p1: Point3<S>, p2: Point3<S>) -> Aabb3<S> {
        Aabb3::new(p1, p2)
    }

    #[inline]
    fn min(&self) -> Point3<S> {
        self.min
    }

    #[inline]
    fn max(&self) -> Point3<S> {
        self.max
    }

    #[inline]
    fn contains(&self, p: Point3<S>) -> bool {
        let v_min = p - self.min();
        let v_max = self.max() - p;
        v_min.x >= S::zero() && v_min.y >= S::zero() && v_min.z >= S::zero() &&
        v_max.x > S::zero() && v_max.y > S::zero() && v_max.z > S::zero()
    }
}

impl<S: BaseNum> fmt::Debug for Aabb3<S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[{:?} - {:?}]", self.min, self.max)
    }
}

impl<S: BaseFloat> Continuous<Point2<S>> for (Ray2<S>, Aabb2<S>) {
    fn intersection(&self) -> Option<Point2<S>> {
        let (ref ray, ref aabb) = *self;

        let mut tmin = S::neg_infinity();
        let mut tmax = S::infinity();

        if ray.direction.x != S::zero() {
            let tx1 = (aabb.min.x - ray.origin.x) / ray.direction.x;
            let tx2 = (aabb.max.x - ray.origin.x) / ray.direction.x;
            tmin = tmin.max(tx1.min(tx2));
            tmax = tmax.min(tx1.max(tx2));
        }

        if ray.direction.y != S::zero() {
            let ty1 = (aabb.min.y - ray.origin.y) / ray.direction.y;
            let ty2 = (aabb.max.y - ray.origin.y) / ray.direction.y;
            tmin = tmin.max(ty1.min(ty2));
            tmax = tmax.min(ty1.max(ty2));
        }

        if tmin < S::zero() && tmax < S::zero() {
            None
        } else if tmax >= tmin {
            if tmin >= S::zero() {
                Some(Point2::new(ray.origin.x + ray.direction.x * tmin,
                                 ray.origin.y + ray.direction.y * tmin))
            } else {
                Some(Point2::new(ray.origin.x + ray.direction.x * tmax,
                                 ray.origin.y + ray.direction.y * tmax))
            }
        } else {
            None
        }
    }
}

impl<S: BaseFloat> Continuous<Point3<S>> for (Ray3<S>, Aabb3<S>) {
    fn intersection(&self) -> Option<Point3<S>> {
        let (ref ray, ref aabb) = *self;

        let inv_dir = Vector3::new(S::one(), S::one(), S::one()).div_element_wise(ray.direction);

        let mut t1 = (aabb.min.x - ray.origin.x) * inv_dir.x;
        let mut t2 = (aabb.max.x - ray.origin.x) * inv_dir.x;

        let mut tmin = t1.min(t2);
        let mut tmax = t1.max(t2);

        for i in 1..3 {
            t1 = (aabb.min[i] - ray.origin[i]) * inv_dir[i];
            t2 = (aabb.max[i] - ray.origin[i]) * inv_dir[i];

            tmin = tmin.max(t1.min(t2));
            tmax = tmax.min(t1.max(t2));
        }

        if tmin < S::zero() && tmax < S::zero() {
            None
        } else if tmax >= tmin {
            if tmin >= S::zero() {
                Some(Point3::new(ray.origin.x + ray.direction.x * tmin,
                                 ray.origin.y + ray.direction.y * tmin,
                                 ray.origin.z + ray.direction.z * tmin))
            } else {
                Some(Point3::new(ray.origin.x + ray.direction.x * tmax,
                                 ray.origin.y + ray.direction.y * tmax,
                                 ray.origin.z + ray.direction.z * tmax))
            }
        } else {
            None
        }
    }
}

impl<S: BaseFloat + 'static> Bound<S> for Aabb3<S> {
    fn relate_plane(self, plane: Plane<S>) -> Relation {
        let corners = self.to_corners();
        let first = corners[0].relate_plane(plane);
        for p in corners[1..].iter() {
            if p.relate_plane(plane) != first {
                return Relation::Cross;
            }
        }
        first
    }
}
<commit_msg>Add: implement Discrete for (Aabb2, Aabb2)<commit_after>// Copyright 2013-2014 The CGMath Developers. For a full listing of the authors,
// refer to the Cargo.toml 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.

//! Axis-aligned bounding boxes
//!
//! An AABB is a geometric object which encompasses a set of points and is not
//! rotated. It is either a rectangle or a rectangular prism (depending on the
//! dimension) where the slope of every line is either 0 or undefined. These
//! are useful for very cheap collision detection.

use std::fmt;

use cgmath::{EuclideanSpace, Point2, Point3};
use cgmath::{VectorSpace, Array, Vector2, Vector3};
use cgmath::{BaseNum, BaseFloat, ElementWise};

use {Ray2, Ray3, Plane};
use bound::{Bound, Relation};
use intersect::{Continuous, Discrete};

pub trait MinMax {
    fn min(a: Self, b: Self) -> Self;
    fn max(a: Self, b: Self) -> Self;
}

impl<S> MinMax for Point2<S>
    where S: BaseNum
{
    fn min(a: Point2<S>, b: Point2<S>) -> Point2<S> {
        Point2::new(a.x.partial_min(b.x), a.y.partial_min(b.y))
    }

    fn max(a: Point2<S>, b: Point2<S>) -> Point2<S> {
        Point2::new(a.x.partial_max(b.x), a.y.partial_max(b.y))
    }
}

impl<S> MinMax for Point3<S>
    where S: BaseNum
{
    fn min(a: Point3<S>, b: Point3<S>) -> Point3<S> {
        Point3::new(a.x.partial_min(b.x),
                    a.y.partial_min(b.y),
                    a.z.partial_min(b.z))
    }

    fn max(a: Point3<S>, b: Point3<S>) -> Point3<S> {
        Point3::new(a.x.partial_max(b.x),
                    a.y.partial_max(b.y),
                    a.z.partial_max(b.z))
    }
}

pub trait Aabb<S: BaseNum,
               V: VectorSpace<Scalar = S> + ElementWise + Array<Element = S>,
               P: EuclideanSpace<Scalar = S, Diff = V>>: Sized {
    /// Create a new AABB using two points as opposing corners.
    fn new(p1: P, p2: P) -> Self;

    /// Return a shared reference to the point nearest to (-inf, -inf).
    fn min(&self) -> P;

    /// Return a shared reference to the point nearest to (inf, inf).
    fn max(&self) -> P;

    /// Return the dimensions of this AABB.
    #[inline]
    fn dim(&self) -> V {
        self.max() - self.min()
    }

    /// Return the volume this AABB encloses.
    #[inline]
    fn volume(&self) -> S {
        self.dim().product()
    }

    /// Return the center point of this AABB.
    #[inline]
    fn center(&self) -> P {
        let two = S::one() + S::one();
        self.min() + self.dim() / two
    }

    /// Tests whether a point is cointained in the box, inclusive for min corner
    /// and exclusive for the max corner.
    #[inline]
    fn contains(&self, p: P) -> bool;

    /// Returns a new AABB that is grown to include the given point.
    fn grow(&self, p: P) -> Self
        where P: MinMax
    {
        Aabb::new(MinMax::min(self.min(), p), MinMax::max(self.max(), p))
    }

    /// Add a vector to every point in the AABB, returning a new AABB.
    fn add_v(&self, v: V) -> Self {
        Aabb::new(self.min() + v, self.max() + v)
    }

    /// Multiply every point in the AABB by a scalar, returning a new AABB.
    fn mul_s(&self, s: S) -> Self {
        Aabb::new(self.min() * s, self.max() * s)
    }

    /// Multiply every point in the AABB by a vector, returning a new AABB.
    fn mul_v(&self, v: V) -> Self {
        let min = P::from_vec(self.min().to_vec().mul_element_wise(v));
        let max = P::from_vec(self.max().to_vec().mul_element_wise(v));
        Aabb::new(min, max)
    }
}

/// A two-dimensional AABB, aka a rectangle.
#[derive(Copy, Clone, PartialEq)]
#[cfg_attr(feature = "eders", derive(Serialize, Deserialize))]
pub struct Aabb2<S> {
    pub min: Point2<S>,
    pub max: Point2<S>,
}

impl<S: BaseNum> Aabb2<S> {
    /// Construct a new axis-aligned bounding box from two points.
    #[inline]
    pub fn new(p1: Point2<S>, p2: Point2<S>) -> Aabb2<S> {
        Aabb2 {
            min: Point2::new(p1.x.partial_min(p2.x), p1.y.partial_min(p2.y)),
            max: Point2::new(p1.x.partial_max(p2.x), p1.y.partial_max(p2.y)),
        }
    }

    /// Compute corners.
    #[inline]
    pub fn to_corners(&self) -> [Point2<S>; 4] {
        [self.min,
         Point2::new(self.max.x, self.min.y),
         Point2::new(self.min.x, self.max.y),
         self.max]
    }
}

impl<S: BaseNum> Aabb<S, Vector2<S>, Point2<S>> for Aabb2<S> {
    #[inline]
    fn new(p1: Point2<S>, p2: Point2<S>) -> Aabb2<S> {
        Aabb2::new(p1, p2)
    }

    #[inline]
    fn min(&self) -> Point2<S> {
        self.min
    }

    #[inline]
    fn max(&self) -> Point2<S> {
        self.max
    }

    #[inline]
    fn contains(&self, p: Point2<S>) -> bool {
        let v_min = p - self.min();
        let v_max = self.max() - p;
        v_min.x >= S::zero() && v_min.y >= S::zero() && v_max.x > S::zero() && v_max.y > S::zero()
    }
}

impl<S: BaseNum> fmt::Debug for Aabb2<S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[{:?} - {:?}]", self.min, self.max)
    }
}

/// A three-dimensional AABB, aka a rectangular prism.
#[derive(Copy, Clone, PartialEq)]
#[cfg_attr(feature = "eders", derive(Serialize, Deserialize))]
pub struct Aabb3<S> {
    pub min: Point3<S>,
    pub max: Point3<S>,
}

impl<S: BaseNum> Aabb3<S> {
    /// Construct a new axis-aligned bounding box from two points.
    #[inline]
    pub fn new(p1: Point3<S>, p2: Point3<S>) -> Aabb3<S> {
        Aabb3 {
            min: Point3::new(p1.x.partial_min(p2.x),
                             p1.y.partial_min(p2.y),
                             p1.z.partial_min(p2.z)),
            max: Point3::new(p1.x.partial_max(p2.x),
                             p1.y.partial_max(p2.y),
                             p1.z.partial_max(p2.z)),
        }
    }

    /// Compute corners.
    #[inline]
    pub fn to_corners(&self) -> [Point3<S>; 8] {
        [self.min,
         Point3::new(self.max.x, self.min.y, self.min.z),
         Point3::new(self.min.x, self.max.y, self.min.z),
         Point3::new(self.max.x, self.max.y, self.min.z),
         Point3::new(self.min.x, self.min.y, self.max.z),
         Point3::new(self.max.x, self.min.y, self.max.z),
         Point3::new(self.min.x, self.max.y, self.max.z),
         self.max]
    }
}

impl<S: BaseNum> Aabb<S, Vector3<S>, Point3<S>> for Aabb3<S> {
    #[inline]
    fn new(p1: Point3<S>, p2: Point3<S>) -> Aabb3<S> {
        Aabb3::new(p1, p2)
    }

    #[inline]
    fn min(&self) -> Point3<S> {
        self.min
    }

    #[inline]
    fn max(&self) -> Point3<S> {
        self.max
    }

    #[inline]
    fn contains(&self, p: Point3<S>) -> bool {
        let v_min = p - self.min();
        let v_max = self.max() - p;
        v_min.x >= S::zero() && v_min.y >= S::zero() && v_min.z >= S::zero() &&
        v_max.x > S::zero() && v_max.y > S::zero() && v_max.z > S::zero()
    }
}

impl<S: BaseNum> fmt::Debug for Aabb3<S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[{:?} - {:?}]", self.min, self.max)
    }
}

impl<S: BaseFloat> Continuous<Point2<S>> for (Ray2<S>, Aabb2<S>) {
    fn intersection(&self) -> Option<Point2<S>> {
        let (ref ray, ref aabb) = *self;

        let mut tmin = S::neg_infinity();
        let mut tmax = S::infinity();

        if ray.direction.x != S::zero() {
            let tx1 = (aabb.min.x - ray.origin.x) / ray.direction.x;
            let tx2 = (aabb.max.x - ray.origin.x) / ray.direction.x;
            tmin = tmin.max(tx1.min(tx2));
            tmax = tmax.min(tx1.max(tx2));
        }

        if ray.direction.y != S::zero() {
            let ty1 = (aabb.min.y - ray.origin.y) / ray.direction.y;
            let ty2 = (aabb.max.y - ray.origin.y) / ray.direction.y;
            tmin = tmin.max(ty1.min(ty2));
            tmax = tmax.min(ty1.max(ty2));
        }

        if tmin < S::zero() && tmax < S::zero() {
            None
        } else if tmax >= tmin {
            if tmin >= S::zero() {
                Some(Point2::new(ray.origin.x + ray.direction.x * tmin,
                                 ray.origin.y + ray.direction.y * tmin))
            } else {
                Some(Point2::new(ray.origin.x + ray.direction.x * tmax,
                                 ray.origin.y + ray.direction.y * tmax))
            }
        } else {
            None
        }
    }
}

impl<S: BaseFloat> Continuous<Point3<S>> for (Ray3<S>, Aabb3<S>) {
    fn intersection(&self) -> Option<Point3<S>> {
        let (ref ray, ref aabb) = *self;

        let inv_dir = Vector3::new(S::one(), S::one(), S::one()).div_element_wise(ray.direction);

        let mut t1 = (aabb.min.x - ray.origin.x) * inv_dir.x;
        let mut t2 = (aabb.max.x - ray.origin.x) * inv_dir.x;

        let mut tmin = t1.min(t2);
        let mut tmax = t1.max(t2);

        for i in 1..3 {
            t1 = (aabb.min[i] - ray.origin[i]) * inv_dir[i];
            t2 = (aabb.max[i] - ray.origin[i]) * inv_dir[i];

            tmin = tmin.max(t1.min(t2));
            tmax = tmax.min(t1.max(t2));
        }

        if tmin < S::zero() && tmax < S::zero() {
            None
        } else if tmax >= tmin {
            if tmin >= S::zero() {
                Some(Point3::new(ray.origin.x + ray.direction.x * tmin,
                                 ray.origin.y + ray.direction.y * tmin,
                                 ray.origin.z + ray.direction.z * tmin))
            } else {
                Some(Point3::new(ray.origin.x + ray.direction.x * tmax,
                                 ray.origin.y + ray.direction.y * tmax,
                                 ray.origin.z + ray.direction.z * tmax))
            }
        } else {
            None
        }
    }
}

impl<S: BaseFloat> Discrete for (Aabb2<S>, Aabb2<S>) {
    // TODO: i don't like current implementation
    fn intersects(&self) -> bool {
        let (ref a, ref b) = *self;

        if (a.max().x <= b.min().x) || (a.min().x >= b.max().x) || (a.max().y <= b.min().y) ||
           (a.min().y >= b.min().y) {
            return false;
        }
        true
    }
}

impl<S: BaseFloat + 'static> Bound<S> for Aabb3<S> {
    fn relate_plane(self, plane: Plane<S>) -> Relation {
        let corners = self.to_corners();
        let first = corners[0].relate_plane(plane);
        for p in corners[1..].iter() {
            if p.relate_plane(plane) != first {
                return Relation::Cross;
            }
        }
        first
    }
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;
use std::convert::From;
use ::parse::{IrcMsg, ParseError};

pub enum PushError {
	Full,
}

pub enum RecvError {
	MoreData,
	Parse(ParseError),
}

impl From<ParseError> for RecvError {
	fn from(e: ParseError) -> RecvError {
		RecvError::Parse(e)
	}
}

pub struct IrcMsgBuffer {
	capacity: usize,
	data: VecDeque<u8>,
}

impl IrcMsgBuffer {
	// Later, we'll use a doubly-mapped circular buffer
	pub fn new(capacity: usize) -> IrcMsgBuffer {
		IrcMsgBuffer {
			capacity: capacity,
			data: VecDeque::with_capacity(capacity),
		}
	}

	pub fn push(&mut self, buffer: &[u8]) -> Result<(), PushError> {
		if self.data.len() + buffer.len() > self.capacity {
			return Err(PushError::Full);
		}
		self.data.extend(buffer.iter().cloned());
		Ok(())
	}

	pub fn recv(&mut self) -> Result<IrcMsg, RecvError> {
		let mut bytes = 0;
		let mut found_eol = false;

		for &byte in self.data.iter() {
			if byte == b'\n' {
				found_eol = true;
				break;
			}
			bytes += 1;
		}

		if !found_eol {
			return Err(RecvError::MoreData);
		}

		let buffer: Vec<u8> = self.data.iter().take(bytes).cloned().collect();
		for _ in 0..bytes {
			self.data.pop_front();
		}

		Ok(try!(IrcMsg::new(buffer)))
	}
}<commit_msg>fix recv::IrcMsgBuffer<commit_after>use std::collections::VecDeque;
use std::convert::From;
use ::parse::{IrcMsg, ParseError};

pub enum PushError {
	Full,
}

pub enum RecvError {
	MoreData,
	Parse(ParseError),
}

impl From<ParseError> for RecvError {
	fn from(e: ParseError) -> RecvError {
		RecvError::Parse(e)
	}
}

pub struct IrcMsgBuffer {
	capacity: usize,
	data: VecDeque<u8>,
}

impl IrcMsgBuffer {
	// Later, we'll use a doubly-mapped circular buffer
	pub fn new(capacity: usize) -> IrcMsgBuffer {
		IrcMsgBuffer {
			capacity: capacity,
			data: VecDeque::with_capacity(capacity),
		}
	}

	pub fn push(&mut self, buffer: &[u8]) -> Result<(), PushError> {
		if self.data.len() + buffer.len() > self.capacity {
			return Err(PushError::Full);
		}
		self.data.extend(buffer.iter().cloned());
		Ok(())
	}

	pub fn recv(&mut self) -> Result<IrcMsg, RecvError> {
		let mut bytes = 0;
		let mut found_eol = false;

		for &byte in self.data.iter() {
			bytes += 1;
			if byte == b'\n' {
				found_eol = true;
				break;
			}
		}

		if !found_eol {
			return Err(RecvError::MoreData);
		}

		let buffer: Vec<u8> = self.data.iter().take(bytes).cloned().collect();
		for _ in 0..bytes {
			self.data.pop_front();
		}
		Ok(try!(IrcMsg::new(buffer)))
	}
}<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use hir::def_id::DefId;
use util::nodemap::{NodeMap, DefIdMap};
use syntax::ast;
use syntax::ext::base::MacroKind;
use syntax_pos::Span;
use hir;
use ty;

#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum CtorKind {
    /// Constructor function automatically created by a tuple struct/variant.
    Fn,
    /// Constructor constant automatically created by a unit struct/variant.
    Const,
    /// Unusable name in value namespace created by a struct variant.
    Fictive,
}

#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum Def {
    // Type namespace
    Mod(DefId),
    Struct(DefId), // DefId refers to NodeId of the struct itself
    Union(DefId),
    Enum(DefId),
    Variant(DefId),
    Trait(DefId),
    TyAlias(DefId),
    TyForeign(DefId),
    TraitAlias(DefId),
    AssociatedTy(DefId),
    PrimTy(hir::PrimTy),
    TyParam(DefId),
    SelfTy(Option<DefId> /* trait */, Option<DefId> /* impl */),

    // Value namespace
    Fn(DefId),
    Const(DefId),
    Static(DefId, bool /* is_mutbl */),
    StructCtor(DefId, CtorKind), // DefId refers to NodeId of the struct's constructor
    VariantCtor(DefId, CtorKind),
    Method(DefId),
    AssociatedConst(DefId),

    Local(ast::NodeId),
    Upvar(ast::NodeId,  // node id of closed over local
          usize,        // index in the freevars list of the closure
          ast::NodeId), // expr node that creates the closure
    Label(ast::NodeId),

    // Macro namespace
    Macro(DefId, MacroKind),

    GlobalAsm(DefId),

    // Both namespaces
    Err,
}

/// The result of resolving a path before lowering to HIR.
/// `base_def` is definition of resolved part of the
/// path, `unresolved_segments` is the number of unresolved
/// segments.
///     module::Type::AssocX::AssocY::MethodOrAssocType
///     ^~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
///     base_def      unresolved_segments = 3
///
///     <T as Trait>::AssocX::AssocY::MethodOrAssocType
///           ^~~~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~
///           base_def        unresolved_segments = 2
#[derive(Copy, Clone, Debug)]
pub struct PathResolution {
    base_def: Def,
    unresolved_segments: usize,
}

impl PathResolution {
    pub fn new(def: Def) -> Self {
        PathResolution { base_def: def, unresolved_segments: 0 }
    }

    pub fn with_unresolved_segments(def: Def, mut unresolved_segments: usize) -> Self {
        if def == Def::Err { unresolved_segments = 0 }
        PathResolution { base_def: def, unresolved_segments: unresolved_segments }
    }

    #[inline]
    pub fn base_def(&self) -> Def {
        self.base_def
    }

    #[inline]
    pub fn unresolved_segments(&self) -> usize {
        self.unresolved_segments
    }

    pub fn kind_name(&self) -> &'static str {
        if self.unresolved_segments != 0 {
            "associated item"
        } else {
            self.base_def.kind_name()
        }
    }
}

/// Definition mapping
pub type DefMap = NodeMap<PathResolution>;

/// This is the replacement export map. It maps a module to all of the exports
/// within.
pub type ExportMap = DefIdMap<Vec<Export>>;

#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct Export {
    /// The name of the target.
    pub ident: ast::Ident,
    /// The definition of the target.
    pub def: Def,
    /// The span of the target definition.
    pub span: Span,
    /// The visibility of the export.
    /// We include non-`pub` exports for hygienic macros that get used from extern crates.
    pub vis: ty::Visibility,
    /// True if from a `use` or and `extern crate`.
    pub is_import: bool,
}

impl CtorKind {
    pub fn from_ast(vdata: &ast::VariantData) -> CtorKind {
        match *vdata {
            ast::VariantData::Tuple(..) => CtorKind::Fn,
            ast::VariantData::Unit(..) => CtorKind::Const,
            ast::VariantData::Struct(..) => CtorKind::Fictive,
        }
    }
    pub fn from_hir(vdata: &hir::VariantData) -> CtorKind {
        match *vdata {
            hir::VariantData::Tuple(..) => CtorKind::Fn,
            hir::VariantData::Unit(..) => CtorKind::Const,
            hir::VariantData::Struct(..) => CtorKind::Fictive,
        }
    }
}

impl Def {
    pub fn def_id(&self) -> DefId {
        match *self {
            Def::Fn(id) | Def::Mod(id) | Def::Static(id, _) |
            Def::Variant(id) | Def::VariantCtor(id, ..) | Def::Enum(id) |
            Def::TyAlias(id) | Def::TraitAlias(id) |
            Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) |
            Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
            Def::AssociatedConst(id) | Def::Macro(id, ..) |
            Def::GlobalAsm(id) | Def::TyForeign(id) => {
                id
            }

            Def::Local(..) |
            Def::Upvar(..) |
            Def::Label(..)  |
            Def::PrimTy(..) |
            Def::SelfTy(..) |
            Def::Err => {
                bug!("attempted .def_id() on invalid def: {:?}", self)
            }
        }
    }

    /// A human readable kind name
    pub fn kind_name(&self) -> &'static str {
        match *self {
            Def::Fn(..) => "function",
            Def::Mod(..) => "module",
            Def::Static(..) => "static",
            Def::Variant(..) => "variant",
            Def::VariantCtor(.., CtorKind::Fn) => "tuple variant",
            Def::VariantCtor(.., CtorKind::Const) => "unit variant",
            Def::VariantCtor(.., CtorKind::Fictive) => "struct variant",
            Def::Enum(..) => "enum",
            Def::TyAlias(..) => "type alias",
            Def::TraitAlias(..) => "trait alias",
            Def::AssociatedTy(..) => "associated type",
            Def::Struct(..) => "struct",
            Def::StructCtor(.., CtorKind::Fn) => "tuple struct",
            Def::StructCtor(.., CtorKind::Const) => "unit struct",
            Def::StructCtor(.., CtorKind::Fictive) => bug!("impossible struct constructor"),
            Def::Union(..) => "union",
            Def::Trait(..) => "trait",
            Def::TyForeign(..) => "foreign type",
            Def::Method(..) => "method",
            Def::Const(..) => "constant",
            Def::AssociatedConst(..) => "associated constant",
            Def::TyParam(..) => "type parameter",
            Def::PrimTy(..) => "builtin type",
            Def::Local(..) => "local variable",
            Def::Upvar(..) => "closure capture",
            Def::Label(..) => "label",
            Def::SelfTy(..) => "self type",
            Def::Macro(..) => "macro",
            Def::GlobalAsm(..) => "global asm",
            Def::Err => "unresolved item",
        }
    }
}
<commit_msg>Clarify where `is_import` is used.<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use hir::def_id::DefId;
use util::nodemap::{NodeMap, DefIdMap};
use syntax::ast;
use syntax::ext::base::MacroKind;
use syntax_pos::Span;
use hir;
use ty;

#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum CtorKind {
    /// Constructor function automatically created by a tuple struct/variant.
    Fn,
    /// Constructor constant automatically created by a unit struct/variant.
    Const,
    /// Unusable name in value namespace created by a struct variant.
    Fictive,
}

#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum Def {
    // Type namespace
    Mod(DefId),
    Struct(DefId), // DefId refers to NodeId of the struct itself
    Union(DefId),
    Enum(DefId),
    Variant(DefId),
    Trait(DefId),
    TyAlias(DefId),
    TyForeign(DefId),
    TraitAlias(DefId),
    AssociatedTy(DefId),
    PrimTy(hir::PrimTy),
    TyParam(DefId),
    SelfTy(Option<DefId> /* trait */, Option<DefId> /* impl */),

    // Value namespace
    Fn(DefId),
    Const(DefId),
    Static(DefId, bool /* is_mutbl */),
    StructCtor(DefId, CtorKind), // DefId refers to NodeId of the struct's constructor
    VariantCtor(DefId, CtorKind),
    Method(DefId),
    AssociatedConst(DefId),

    Local(ast::NodeId),
    Upvar(ast::NodeId,  // node id of closed over local
          usize,        // index in the freevars list of the closure
          ast::NodeId), // expr node that creates the closure
    Label(ast::NodeId),

    // Macro namespace
    Macro(DefId, MacroKind),

    GlobalAsm(DefId),

    // Both namespaces
    Err,
}

/// The result of resolving a path before lowering to HIR.
/// `base_def` is definition of resolved part of the
/// path, `unresolved_segments` is the number of unresolved
/// segments.
///     module::Type::AssocX::AssocY::MethodOrAssocType
///     ^~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
///     base_def      unresolved_segments = 3
///
///     <T as Trait>::AssocX::AssocY::MethodOrAssocType
///           ^~~~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~
///           base_def        unresolved_segments = 2
#[derive(Copy, Clone, Debug)]
pub struct PathResolution {
    base_def: Def,
    unresolved_segments: usize,
}

impl PathResolution {
    pub fn new(def: Def) -> Self {
        PathResolution { base_def: def, unresolved_segments: 0 }
    }

    pub fn with_unresolved_segments(def: Def, mut unresolved_segments: usize) -> Self {
        if def == Def::Err { unresolved_segments = 0 }
        PathResolution { base_def: def, unresolved_segments: unresolved_segments }
    }

    #[inline]
    pub fn base_def(&self) -> Def {
        self.base_def
    }

    #[inline]
    pub fn unresolved_segments(&self) -> usize {
        self.unresolved_segments
    }

    pub fn kind_name(&self) -> &'static str {
        if self.unresolved_segments != 0 {
            "associated item"
        } else {
            self.base_def.kind_name()
        }
    }
}

/// Definition mapping
pub type DefMap = NodeMap<PathResolution>;

/// This is the replacement export map. It maps a module to all of the exports
/// within.
pub type ExportMap = DefIdMap<Vec<Export>>;

#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct Export {
    /// The name of the target.
    pub ident: ast::Ident,
    /// The definition of the target.
    pub def: Def,
    /// The span of the target definition.
    pub span: Span,
    /// The visibility of the export.
    /// We include non-`pub` exports for hygienic macros that get used from extern crates.
    pub vis: ty::Visibility,
    /// True if from a `use` or and `extern crate`.
    /// Used in rustdoc.
    pub is_import: bool,
}

impl CtorKind {
    pub fn from_ast(vdata: &ast::VariantData) -> CtorKind {
        match *vdata {
            ast::VariantData::Tuple(..) => CtorKind::Fn,
            ast::VariantData::Unit(..) => CtorKind::Const,
            ast::VariantData::Struct(..) => CtorKind::Fictive,
        }
    }
    pub fn from_hir(vdata: &hir::VariantData) -> CtorKind {
        match *vdata {
            hir::VariantData::Tuple(..) => CtorKind::Fn,
            hir::VariantData::Unit(..) => CtorKind::Const,
            hir::VariantData::Struct(..) => CtorKind::Fictive,
        }
    }
}

impl Def {
    pub fn def_id(&self) -> DefId {
        match *self {
            Def::Fn(id) | Def::Mod(id) | Def::Static(id, _) |
            Def::Variant(id) | Def::VariantCtor(id, ..) | Def::Enum(id) |
            Def::TyAlias(id) | Def::TraitAlias(id) |
            Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) |
            Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
            Def::AssociatedConst(id) | Def::Macro(id, ..) |
            Def::GlobalAsm(id) | Def::TyForeign(id) => {
                id
            }

            Def::Local(..) |
            Def::Upvar(..) |
            Def::Label(..)  |
            Def::PrimTy(..) |
            Def::SelfTy(..) |
            Def::Err => {
                bug!("attempted .def_id() on invalid def: {:?}", self)
            }
        }
    }

    /// A human readable kind name
    pub fn kind_name(&self) -> &'static str {
        match *self {
            Def::Fn(..) => "function",
            Def::Mod(..) => "module",
            Def::Static(..) => "static",
            Def::Variant(..) => "variant",
            Def::VariantCtor(.., CtorKind::Fn) => "tuple variant",
            Def::VariantCtor(.., CtorKind::Const) => "unit variant",
            Def::VariantCtor(.., CtorKind::Fictive) => "struct variant",
            Def::Enum(..) => "enum",
            Def::TyAlias(..) => "type alias",
            Def::TraitAlias(..) => "trait alias",
            Def::AssociatedTy(..) => "associated type",
            Def::Struct(..) => "struct",
            Def::StructCtor(.., CtorKind::Fn) => "tuple struct",
            Def::StructCtor(.., CtorKind::Const) => "unit struct",
            Def::StructCtor(.., CtorKind::Fictive) => bug!("impossible struct constructor"),
            Def::Union(..) => "union",
            Def::Trait(..) => "trait",
            Def::TyForeign(..) => "foreign type",
            Def::Method(..) => "method",
            Def::Const(..) => "constant",
            Def::AssociatedConst(..) => "associated constant",
            Def::TyParam(..) => "type parameter",
            Def::PrimTy(..) => "builtin type",
            Def::Local(..) => "local variable",
            Def::Upvar(..) => "closure capture",
            Def::Label(..) => "label",
            Def::SelfTy(..) => "self type",
            Def::Macro(..) => "macro",
            Def::GlobalAsm(..) => "global asm",
            Def::Err => "unresolved item",
        }
    }
}
<|endoftext|>


<commit_before>// Parse ANSI attr code

use regex::Regex;
use curses::get_color_pair;
use ncurses::*;
use std::sync::Mutex;

pub fn parse_ansi(text: &str) -> (String, Vec<(usize, attr_t)>) {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"\x1b\[[0-9;]*[mK]").unwrap();
        static ref LAST_ATTR: Mutex<Option<attr_t>> = Mutex::new(None);
    }

    let mut strip_string = String::new();
    let mut colors = Vec::new();
    let mut last_attr = LAST_ATTR.lock().unwrap();

    // assume parse_ansi is called linewise.
    // Because ANSI color code can affect text of next lines. We will save the last attribute and
    // add it to the newest line if no new color is specified.
    match RE.find(text) {
        Some((start, _)) if start <= 0 => {}
        Some(_) | None => {
            last_attr.map(|attr| {
                colors.push((0, attr));
            });
        }
    }

    let mut last = 0;
    for (start, end) in RE.find_iter(text) {
        strip_string.push_str(&text[last..start]);
        last = end;

        let attr = interpret_code(&text[start..end]);
        attr.map(|attr| {
            colors.push((strip_string.len(), attr));
        });
        *last_attr = attr;
    }

    strip_string.push_str(&text[last..text.len()]);

    (strip_string, colors)
}

fn interpret_code(code: &str) -> Option<attr_t> {
    if &code[code.len()-1..code.len()] == "K"{
        return None;
    }

    let mut state256 = 0;
    let mut attr = 0;
    let mut fg = -1;
    let mut bg = -1;
    let mut use_fg = true;

    let code = &code[2..code.len()-1]; // ^[[1;30;40m -> 1;30;40
    if code.len() == 0 {
        return None;
    }

    for num in code.split(';').map(|x| x.parse::<i16>()) {
        match state256 {
            0 => {
                match num.unwrap_or(0) {
                    0 => {attr = 0;}
                    1 => {attr |= A_BOLD();}
                    4 => {attr |= A_UNDERLINE();}
                    5 => {attr |= A_BLINK();}
                    7 => {attr |= A_REVERSE();}
                    8 => {attr |= A_INVIS();}
                    38 => {
                        use_fg = true;
                        state256 += 1;
                    }
                    48 => {
                        use_fg = false;
                        state256 += 1;
                    }
                    39 => {
                        fg = -1;
                    }
                    49 => {
                        bg = -1;
                    }
                    num if num >= 30 && num <= 37 => {
                        fg = num - 30;
                    }
                    num if num >= 40 && num <= 47 => {
                        bg = num - 40;
                    }
                    _ => {
                    }
                }
            }
            1 => {
                match num.unwrap_or(0) {
                    5 => { state256 += 1; }
                    _ => { state256 = 0; }
                }
            }
            2 => {
                if use_fg {
                    fg = num.unwrap_or(-1);
                } else {
                    bg = num.unwrap_or(-1);
                }
            }
            _ => {}
        }
    }

    if fg != -1 || bg != -1 {
        attr |= get_color_pair(fg, bg);
    }

    Some(attr)
}
<commit_msg>[ansi] fix: wrong boundary for unicode characters<commit_after>// Parse ANSI attr code

use regex::Regex;
use curses::get_color_pair;
use ncurses::*;
use std::sync::Mutex;

pub fn parse_ansi(text: &str) -> (String, Vec<(usize, attr_t)>) {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"\x1b\[[0-9;]*[mK]").unwrap();
        static ref LAST_ATTR: Mutex<Option<attr_t>> = Mutex::new(None);
    }

    let mut strip_string = String::new();
    let mut colors = Vec::new();
    let mut last_attr = LAST_ATTR.lock().unwrap();

    // assume parse_ansi is called linewise.
    // Because ANSI color code can affect text of next lines. We will save the last attribute and
    // add it to the newest line if no new color is specified.
    match RE.find(text) {
        Some((start, _)) if start <= 0 => {}
        Some(_) | None => {
            last_attr.map(|attr| {
                colors.push((0, attr));
            });
        }
    }

    let mut num_chars = 0;
    let mut last = 0;
    for (start, end) in RE.find_iter(text) {
        strip_string.push_str(&text[last..start]);
        num_chars += (&text[last..start]).chars().count();

        last = end;

        let attr = interpret_code(&text[start..end]);
        attr.map(|attr| {
            colors.push((num_chars, attr));
        });
        *last_attr = attr;
    }

    strip_string.push_str(&text[last..text.len()]);

    (strip_string, colors)
}

fn interpret_code(code: &str) -> Option<attr_t> {
    if &code[code.len()-1..code.len()] == "K"{
        return None;
    }

    let mut state256 = 0;
    let mut attr = 0;
    let mut fg = -1;
    let mut bg = -1;
    let mut use_fg = true;

    let code = &code[2..code.len()-1]; // ^[[1;30;40m -> 1;30;40
    if code.len() == 0 {
        return None;
    }

    for num in code.split(';').map(|x| x.parse::<i16>()) {
        match state256 {
            0 => {
                match num.unwrap_or(0) {
                    0 => {attr = 0;}
                    1 => {attr |= A_BOLD();}
                    4 => {attr |= A_UNDERLINE();}
                    5 => {attr |= A_BLINK();}
                    7 => {attr |= A_REVERSE();}
                    8 => {attr |= A_INVIS();}
                    38 => {
                        use_fg = true;
                        state256 += 1;
                    }
                    48 => {
                        use_fg = false;
                        state256 += 1;
                    }
                    39 => {
                        fg = -1;
                    }
                    49 => {
                        bg = -1;
                    }
                    num if num >= 30 && num <= 37 => {
                        fg = num - 30;
                    }
                    num if num >= 40 && num <= 47 => {
                        bg = num - 40;
                    }
                    _ => {
                    }
                }
            }
            1 => {
                match num.unwrap_or(0) {
                    5 => { state256 += 1; }
                    _ => { state256 = 0; }
                }
            }
            2 => {
                if use_fg {
                    fg = num.unwrap_or(-1);
                } else {
                    bg = num.unwrap_or(-1);
                }
            }
            _ => {}
        }
    }

    if fg != -1 || bg != -1 {
        attr |= get_color_pair(fg, bg);
    }

    Some(attr)
}
<|endoftext|>


<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::io;

pub fn general() {
    io::println("Usage: rustpkg [options] <cmd> [args..]

Where <cmd> is one of:
    build, clean, do, info, install, list, prefer, test, uninstall, unprefer

Options:

    -h, --help                  Display this message
    --sysroot PATH              Override the system root
    <cmd> -h, <cmd> --help      Display help for <cmd>");
}

pub fn build() {
    io::println("rustpkg build [options..] [package-ID]

Build the given package ID if specified. With no package ID argument,
build the package in the current directory. In that case, the current
directory must be a direct child of an `src` directory in a workspace.

Options:
    -c, --cfg      Pass a cfg flag to the package script
    --no-link      Compile and assemble, but don't link (like -c in rustc)
    --no-trans     Parse and translate, but don't generate any code
    --pretty       Pretty-print the code, but don't generate output
    --parse-only   Parse the code, but don't typecheck or generate code
    -S             Generate assembly code, but don't assemble or link it
    -S --emit-llvm Generate LLVM assembly code
    --emit-llvm    Generate LLVM bitcode
    --linker PATH  Use a linker other than the system linker
    --link-args [ARG..] Extra arguments to pass to the linker
    --opt-level=n  Set the optimization level (0 <= n <= 3)
    -O             Equivalent to --opt-level=2
    --save-temps   Don't delete temporary files
    --target TRIPLE Set the target triple
    --target-cpu CPU Set the target CPU
    -Z FLAG        Enable an experimental rustc feature (see `rustc --help`)");
}

pub fn clean() {
    io::println("rustpkg clean

Remove all build files in the work cache for the package in the current
directory.");
}

pub fn do_cmd() {
    io::println("rustpkg do <cmd>

Runs a command in the package script. You can listen to a command
by tagging a function with the attribute `#[pkg_do(cmd)]`.");
}

pub fn info() {
    io::println("rustpkg [options..] info

Probe the package script in the current directory for information.

Options:
    -j, --json      Output the result as JSON");
}

pub fn list() {
    io::println("rustpkg list

List all installed packages.");
}

pub fn install() {
    io::println("rustpkg install [options..] [package-ID]

Install the given package ID if specified. With no package ID
argument, install the package in the current directory.
In that case, the current directory must be a direct child of a
`src` directory in a workspace.

Examples:
    rustpkg install
    rustpkg install github.com/mozilla/servo
    rustpkg install github.com/mozilla/servo#0.1.2

Options:
    -c, --cfg      Pass a cfg flag to the package script
    --emit-llvm    Generate LLVM bitcode
    --linker PATH  Use a linker other than the system linker
    --link-args [ARG..] Extra arguments to pass to the linker
    --opt-level=n  Set the optimization level (0 <= n <= 3)
    -O             Equivalent to --opt-level=2
    --save-temps   Don't delete temporary files
    --target TRIPLE Set the target triple
    --target-cpu CPU Set the target CPU
    -Z FLAG        Enable an experimental rustc feature (see `rustc --help`)");
}

pub fn uninstall() {
    io::println("rustpkg uninstall <id|name>[@version]

Remove a package by id or name and optionally version. If the package(s)
is/are depended on by another package then they cannot be removed.");
}

pub fn prefer() {
    io::println("rustpkg [options..] prefer <id|name>[@version]

By default all binaries are given a unique name so that multiple versions can
coexist. The prefer command will symlink the uniquely named binary to
the binary directory under its bare name. If version is not supplied, the
latest version of the package will be preferred.

Example:
    export PATH=$PATH:/home/user/.rustpkg/bin
    rustpkg prefer machine@1.2.4
    machine -v
    ==> v1.2.4
    rustpkg prefer machine@0.4.6
    machine -v
    ==> v0.4.6");
}

pub fn unprefer() {
    io::println("rustpkg [options..] unprefer <id|name>[@version]

Remove all symlinks from the store to the binary directory for a package
name and optionally version. If version is not supplied, the latest version
of the package will be unpreferred. See `rustpkg prefer -h` for more
information.");
}

pub fn test() {
    io::println("rustpkg [options..] test

Build all targets described in the package script in the current directory
with the test flag. The test bootstraps will be run afterwards and the output
and exit code will be redirected.

Options:
    -c, --cfg      Pass a cfg flag to the package script");
}

pub fn init() {
    io::println("rustpkg init name

This makes a new workspace for working on a project named name.
");
}
<commit_msg>Fix usage for rustpkg init<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::io;

pub fn general() {
    io::println("Usage: rustpkg [options] <cmd> [args..]

Where <cmd> is one of:
    build, clean, do, info, install, list, prefer, test, uninstall, unprefer

Options:

    -h, --help                  Display this message
    --sysroot PATH              Override the system root
    <cmd> -h, <cmd> --help      Display help for <cmd>");
}

pub fn build() {
    io::println("rustpkg build [options..] [package-ID]

Build the given package ID if specified. With no package ID argument,
build the package in the current directory. In that case, the current
directory must be a direct child of an `src` directory in a workspace.

Options:
    -c, --cfg      Pass a cfg flag to the package script
    --no-link      Compile and assemble, but don't link (like -c in rustc)
    --no-trans     Parse and translate, but don't generate any code
    --pretty       Pretty-print the code, but don't generate output
    --parse-only   Parse the code, but don't typecheck or generate code
    -S             Generate assembly code, but don't assemble or link it
    -S --emit-llvm Generate LLVM assembly code
    --emit-llvm    Generate LLVM bitcode
    --linker PATH  Use a linker other than the system linker
    --link-args [ARG..] Extra arguments to pass to the linker
    --opt-level=n  Set the optimization level (0 <= n <= 3)
    -O             Equivalent to --opt-level=2
    --save-temps   Don't delete temporary files
    --target TRIPLE Set the target triple
    --target-cpu CPU Set the target CPU
    -Z FLAG        Enable an experimental rustc feature (see `rustc --help`)");
}

pub fn clean() {
    io::println("rustpkg clean

Remove all build files in the work cache for the package in the current
directory.");
}

pub fn do_cmd() {
    io::println("rustpkg do <cmd>

Runs a command in the package script. You can listen to a command
by tagging a function with the attribute `#[pkg_do(cmd)]`.");
}

pub fn info() {
    io::println("rustpkg [options..] info

Probe the package script in the current directory for information.

Options:
    -j, --json      Output the result as JSON");
}

pub fn list() {
    io::println("rustpkg list

List all installed packages.");
}

pub fn install() {
    io::println("rustpkg install [options..] [package-ID]

Install the given package ID if specified. With no package ID
argument, install the package in the current directory.
In that case, the current directory must be a direct child of a
`src` directory in a workspace.

Examples:
    rustpkg install
    rustpkg install github.com/mozilla/servo
    rustpkg install github.com/mozilla/servo#0.1.2

Options:
    -c, --cfg      Pass a cfg flag to the package script
    --emit-llvm    Generate LLVM bitcode
    --linker PATH  Use a linker other than the system linker
    --link-args [ARG..] Extra arguments to pass to the linker
    --opt-level=n  Set the optimization level (0 <= n <= 3)
    -O             Equivalent to --opt-level=2
    --save-temps   Don't delete temporary files
    --target TRIPLE Set the target triple
    --target-cpu CPU Set the target CPU
    -Z FLAG        Enable an experimental rustc feature (see `rustc --help`)");
}

pub fn uninstall() {
    io::println("rustpkg uninstall <id|name>[@version]

Remove a package by id or name and optionally version. If the package(s)
is/are depended on by another package then they cannot be removed.");
}

pub fn prefer() {
    io::println("rustpkg [options..] prefer <id|name>[@version]

By default all binaries are given a unique name so that multiple versions can
coexist. The prefer command will symlink the uniquely named binary to
the binary directory under its bare name. If version is not supplied, the
latest version of the package will be preferred.

Example:
    export PATH=$PATH:/home/user/.rustpkg/bin
    rustpkg prefer machine@1.2.4
    machine -v
    ==> v1.2.4
    rustpkg prefer machine@0.4.6
    machine -v
    ==> v0.4.6");
}

pub fn unprefer() {
    io::println("rustpkg [options..] unprefer <id|name>[@version]

Remove all symlinks from the store to the binary directory for a package
name and optionally version. If version is not supplied, the latest version
of the package will be unpreferred. See `rustpkg prefer -h` for more
information.");
}

pub fn test() {
    io::println("rustpkg [options..] test

Build all targets described in the package script in the current directory
with the test flag. The test bootstraps will be run afterwards and the output
and exit code will be redirected.

Options:
    -c, --cfg      Pass a cfg flag to the package script");
}

pub fn init() {
    io::println("rustpkg init

This will turn the current working directory into a workspace. The first
command you run when starting off a new project.
");
}
<|endoftext|>


<commit_before>// (c) 2016 Productize SPRL <joost@productize.be>

use std::fmt;
use std::result;
use std::str::FromStr;

use str_error;
use Result;

// like Into trait but works from a ref avoiding consumption or expensive clone
pub trait IntoSexp {
    fn into_sexp(&self) -> Sexp;
}

#[derive(Debug, Clone)]
pub enum Sexp {
    String(String),
    List(Vec<Sexp>),
    Empty,
}

/*

Following the KiCad file formats specification chapter 4.4 - Identifiers and Strings:
A string may not contain an actual newline or carriage return, but it may use an escape sequence to encode a
newline, such as \n.
If a string has any of the following conditions, then it must be quoted with a leading and trailing double quote
character, otherwise it is acceptable to not quote the string:
1. has one or more of the following 4 separator bytes: ASCII space, tab, '(', or ')'.
2. has one or more of the following bytes: '%', '{', or '}'.
3. has a length of zero bytes, and you need a place holder for the field, then use "".
4. includes a byte of '-', and this byte is not in the first position of the string.
*/

pub fn encode_string(s:&str) -> String {
    fn rule_4(s:&str) -> bool {
        s.contains('-') && s.len() > 1 && s.as_bytes()[0] != 45
    }
    if s.contains('(') || s.contains(' ') || s.contains(')') || s.contains('\t') || s.contains('{') || s.contains('}') || s.contains('}') || s.contains('%') || s.is_empty() || rule_4(s) {
        format!("\"{}\"", s)
    } else {
        String::from(s)
    }
}

impl Sexp {

    pub fn new_empty() -> Sexp {
        Sexp::Empty
    }

    pub fn from<T:IntoSexp>(t:&T) -> Sexp {
        t.into_sexp()
    }

    pub fn list(&self) -> Result<&Vec<Sexp> > {
        match *self {
            Sexp::List(ref v) => Ok(v),
            _ => str_error(format!("not a list: {}", self))
        }
    }

    pub fn string(&self) -> Result<&String> {
        match *self {
            Sexp::String(ref s) => Ok(s),
            _ => str_error(format!("not a string: {}", self))
        }
    }

    pub fn f(&self) -> Result<f64> {
        let s = try!(self.string());
        match f64::from_str(s) {
            Ok(f) => Ok(f),
            _ => str_error("Error parsing float".to_string())
        }
    }

    pub fn i(&self) -> Result<i64> {
        let s = try!(self.string());
        match i64::from_str(s) {
            Ok(f) => Ok(f),
            _ => str_error("Error parsing int".to_string())
        }
    }

    pub fn list_name(&self) -> Result<&String> {
        let l = try!(self.list());
        let l = &l[..];
        let a = try!(l[0].string());
        Ok(a)
    }

    pub fn slice_atom(&self, s:&str) -> Result<&[Sexp]> {
        let v = try!(self.list());
        let v2 =&v[..];
        let st = try!(v2[0].string());
        if st != s {
            return str_error(format!("list {} doesn't start with {}, but with {}", self, s, st))
        };
        Ok(&v[1..])
    }

    pub fn named_value(&self, s:&str) -> Result<&Sexp> {
        let v = try!(self.list());
        if v.len() != 2 {
            return str_error(format!("list {} is not a named_value", s))
        }
        let l = try!(self.slice_atom(s));
        Ok(&l[0])
    }

    pub fn named_value_i(&self, s:&str) -> Result<i64> {
        try!(self.named_value(s)).i()
    }

    pub fn named_value_f(&self, s:&str) -> Result<f64> {
        try!(self.named_value(s)).f()
    }

    pub fn named_value_string(&self, s:&str) -> Result<&String> {
        try!(self.named_value(s)).string()
    }

    pub fn slice_atom_num(&self, s:&str, num:usize) -> Result<&[Sexp]> {
        let v = try!(self.list());
        let v2 =&v[..];
        let st = try!(v2[0].string());
        if st != s {
            return str_error(format!("list doesn't start with {}, but with {}", s, st))
        };
        if v.len() != (num+1) {
            return str_error(format!("list ({}) doesn't have {} elements but {}", s, num, v.len()-1))
        }
        Ok(&v[1..])
    }
}

impl fmt::Display for Sexp {
    fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
        match *self {
            Sexp::String(ref s) => {
                write!(f, "{}", encode_string(s))
            },
            Sexp::List(ref v) => {
                try!(write!(f, "("));
                let l = v.len();
                for (i,x) in v.iter().enumerate() {
                    if i < l-1 {
                        try!(write!(f, "{} ", x));
                    } else {
                        try!(write!(f, "{}", x));
                    }
                }
                write!(f, ")")
            },
            Sexp::Empty => Ok(())
        }
    }
}
<commit_msg>add extra constructors<commit_after>// (c) 2016 Productize SPRL <joost@productize.be>

use std::fmt;
use std::result;
use std::str::FromStr;

use str_error;
use Result;

// like Into trait but works from a ref avoiding consumption or expensive clone
pub trait IntoSexp {
    fn into_sexp(&self) -> Sexp;
}

#[derive(Debug, Clone)]
pub enum Sexp {
    String(String),
    List(Vec<Sexp>),
    Empty,
}

/*

Following the KiCad file formats specification chapter 4.4 - Identifiers and Strings:
A string may not contain an actual newline or carriage return, but it may use an escape sequence to encode a
newline, such as \n.
If a string has any of the following conditions, then it must be quoted with a leading and trailing double quote
character, otherwise it is acceptable to not quote the string:
1. has one or more of the following 4 separator bytes: ASCII space, tab, '(', or ')'.
2. has one or more of the following bytes: '%', '{', or '}'.
3. has a length of zero bytes, and you need a place holder for the field, then use "".
4. includes a byte of '-', and this byte is not in the first position of the string.
*/

pub fn encode_string(s:&str) -> String {
    fn rule_4(s:&str) -> bool {
        s.contains('-') && s.len() > 1 && s.as_bytes()[0] != 45
    }
    if s.contains('(') || s.contains(' ') || s.contains(')') || s.contains('\t') || s.contains('{') || s.contains('}') || s.contains('}') || s.contains('%') || s.is_empty() || rule_4(s) {
        format!("\"{}\"", s)
    } else {
        String::from(s)
    }
}

impl Sexp {

    pub fn new_empty() -> Sexp {
        Sexp::Empty
    }

    pub fn new_string(s:&str) -> Sexp {
        Sexp::String(s.to_string())
    }

    pub fn new_list(v:Vec<Sexp>) -> Sexp {
        Sexp::List(v)
    }

    pub fn from<T:IntoSexp>(t:&T) -> Sexp {
        t.into_sexp()
    }

    pub fn list(&self) -> Result<&Vec<Sexp> > {
        match *self {
            Sexp::List(ref v) => Ok(v),
            _ => str_error(format!("not a list: {}", self))
        }
    }

    pub fn string(&self) -> Result<&String> {
        match *self {
            Sexp::String(ref s) => Ok(s),
            _ => str_error(format!("not a string: {}", self))
        }
    }

    pub fn f(&self) -> Result<f64> {
        let s = try!(self.string());
        match f64::from_str(s) {
            Ok(f) => Ok(f),
            _ => str_error("Error parsing float".to_string())
        }
    }

    pub fn i(&self) -> Result<i64> {
        let s = try!(self.string());
        match i64::from_str(s) {
            Ok(f) => Ok(f),
            _ => str_error("Error parsing int".to_string())
        }
    }

    pub fn list_name(&self) -> Result<&String> {
        let l = try!(self.list());
        let l = &l[..];
        let a = try!(l[0].string());
        Ok(a)
    }

    pub fn slice_atom(&self, s:&str) -> Result<&[Sexp]> {
        let v = try!(self.list());
        let v2 =&v[..];
        let st = try!(v2[0].string());
        if st != s {
            return str_error(format!("list {} doesn't start with {}, but with {}", self, s, st))
        };
        Ok(&v[1..])
    }

    pub fn named_value(&self, s:&str) -> Result<&Sexp> {
        let v = try!(self.list());
        if v.len() != 2 {
            return str_error(format!("list {} is not a named_value", s))
        }
        let l = try!(self.slice_atom(s));
        Ok(&l[0])
    }

    pub fn named_value_i(&self, s:&str) -> Result<i64> {
        try!(self.named_value(s)).i()
    }

    pub fn named_value_f(&self, s:&str) -> Result<f64> {
        try!(self.named_value(s)).f()
    }

    pub fn named_value_string(&self, s:&str) -> Result<&String> {
        try!(self.named_value(s)).string()
    }

    pub fn slice_atom_num(&self, s:&str, num:usize) -> Result<&[Sexp]> {
        let v = try!(self.list());
        let v2 =&v[..];
        let st = try!(v2[0].string());
        if st != s {
            return str_error(format!("list doesn't start with {}, but with {}", s, st))
        };
        if v.len() != (num+1) {
            return str_error(format!("list ({}) doesn't have {} elements but {}", s, num, v.len()-1))
        }
        Ok(&v[1..])
    }
}

impl fmt::Display for Sexp {
    fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
        match *self {
            Sexp::String(ref s) => {
                write!(f, "{}", encode_string(s))
            },
            Sexp::List(ref v) => {
                try!(write!(f, "("));
                let l = v.len();
                for (i,x) in v.iter().enumerate() {
                    if i < l-1 {
                        try!(write!(f, "{} ", x));
                    } else {
                        try!(write!(f, "{}", x));
                    }
                }
                write!(f, ")")
            },
            Sexp::Empty => Ok(())
        }
    }
}
<|endoftext|>


<commit_before>use ritual::cli;
use ritual::config::{Config, CrateProperties, GlobalConfig};
use ritual::cpp_data::CppPath;
use ritual::cpp_type::{CppBuiltInNumericType, CppType};
use ritual::rust_info::{NameType, RustPathScope};
use ritual::rust_type::RustPath;
use ritual_common::cpp_build_config::{CppBuildConfigData, CppLibraryType};
use ritual_common::errors::{bail, err_msg, FancyUnwrap, Result, ResultExt};
use ritual_common::file_utils::repo_dir_path;
use ritual_common::string_utils::CaseOperations;
use ritual_common::{target, toml};
use std::env;
use std::path::PathBuf;

mod after_cpp_parser;

pub const CPP_STD_VERSION: &str = "0.0.0";
pub const STD_HEADERS_PATH_ENV_VAR_NAME: &str = "RITUAL_STD_HEADERS";

fn create_config() -> Result<Config> {
    let mut crate_properties = CrateProperties::new("cpp_std", CPP_STD_VERSION);
    let mut custom_fields = toml::value::Table::new();
    let mut package_data = toml::value::Table::new();
    package_data.insert(
        "authors".to_string(),
        toml::Value::Array(vec![toml::Value::String(
            "Pavel Strakhov <ri@idzaaus.org>".to_string(),
        )]),
    );
    package_data.insert(
        "description".to_string(),
        toml::Value::String("Bindings for C++ standard library".into()),
    );
    // TODO: doc url
    //package_data.insert("documentation".to_string(), toml::Value::String(doc_url));
    package_data.insert(
        "repository".to_string(),
        toml::Value::String("https://github.com/rust-qt/ritual".to_string()),
    );
    package_data.insert(
        "license".to_string(),
        toml::Value::String("MIT OR Apache-2.0".to_string()),
    );
    package_data.insert(
        "keywords".to_string(),
        toml::Value::Array(vec![
            toml::Value::String("ffi".to_string()),
            toml::Value::String("ritual".to_string()),
        ]),
    );
    package_data.insert(
        "categories".to_string(),
        toml::Value::Array(vec![toml::Value::String(
            "external-ffi-bindings".to_string(),
        )]),
    );

    custom_fields.insert("package".to_string(), toml::Value::Table(package_data));
    crate_properties.set_custom_fields(custom_fields);

    let mut config = Config::new(crate_properties);
    config.set_cpp_lib_version("11");

    config.set_crate_template_path(repo_dir_path("ritual/src/bin/std_ritual/crate_template")?);

    /* TODO:  "array", "bitset", "deque", "forward_list", "list", "map", "queue", "set", "stack",
        "unordered_map", "unordered_set", "ios", "istream", "iostream", "fstream", "sstream",
        "atomic", "condition_variable", "future", "mutex", "thread", "algorithm", "chrono",
        "codecvt", "complex", "exception", "functional", "initializer_list", "iterator", "limits",
         "locale", "memory", "new", "numeric", "random", "ratio", "regex", "stdexcept",
         "system_error", "tuple", "typeindex", "typeinfo", "type_traits", "utility", "valarray",
    */
    let headers = ["string", "vector"];

    for header in &headers[..] {
        config.add_include_directive(header);
    }

    let include_path = PathBuf::from(
        env::var(STD_HEADERS_PATH_ENV_VAR_NAME)
            .with_context(|_| format!("missing env var: {}", STD_HEADERS_PATH_ENV_VAR_NAME))?,
    );
    if !include_path.exists() {
        bail!("std headers path doesn't exist: {}", include_path.display());
    }
    config.add_target_include_path(include_path);

    config.set_cpp_parser_path_hook(|path| {
        if path.items().iter().any(|item| item.name.starts_with('_')) {
            return Ok(false);
        }

        /*
                let string = path.to_templateless_string();
                let blocked = &[
                    // not in C++ standard
                    "__gnu_cxx",
                ];
                if blocked.contains(&string.as_str()) {
                    return Ok(false);
                }
        */

        Ok(true)
    });

    config.add_after_cpp_parser_hook(after_cpp_parser::hook);

    let namespace = CppPath::from_good_str("std");
    config.set_rust_path_scope_hook(move |path| {
        if path == &namespace {
            return Ok(Some(RustPathScope {
                path: RustPath::from_good_str("cpp_std"),
                prefix: None,
            }));
        }
        Ok(None)
    });

    config.set_rust_path_hook(move |path, name_type, _data| {
        if path.to_templateless_string() == "std::basic_string" {
            let args = path
                .last()
                .template_arguments
                .as_ref()
                .ok_or_else(|| err_msg("std::basic_string must have template arguments"))?;
            let arg = args
                .get(0)
                .ok_or_else(|| err_msg("std::basic_string: first argument is missing"))?;

            let rust_name = match arg {
                CppType::BuiltInNumeric(CppBuiltInNumericType::Char) => "String",
                CppType::BuiltInNumeric(CppBuiltInNumericType::Char16) => "U16String",
                CppType::BuiltInNumeric(CppBuiltInNumericType::Char32) => "U32String",
                CppType::BuiltInNumeric(CppBuiltInNumericType::WChar) => "WString",
                _ => {
                    return Ok(None);
                }
            };

            let name = match name_type {
                NameType::Type => format!("cpp_std::{}", rust_name),
                NameType::Module => format!("cpp_std::{}", rust_name.to_snake_case()),
                _ => bail!("unexpected name type for std::basic_string"),
            };
            return Ok(Some(RustPath::from_good_str(&name)));
        }
        Ok(None)
    });

    config.add_cpp_parser_argument("-std=c++11");
    let mut data = CppBuildConfigData::new();
    data.set_library_type(CppLibraryType::Static);
    config
        .cpp_build_config_mut()
        .add(target::Condition::True, data);
    Ok(config)
}

fn main() {
    let mut config = GlobalConfig::new();
    config.set_all_crate_names(vec!["cpp_std".into()]);
    config.set_create_config_hook(|_crate_name| create_config());

    cli::run_from_args(config).fancy_unwrap();
}
<commit_msg>bump cpp_std version<commit_after>use ritual::cli;
use ritual::config::{Config, CrateProperties, GlobalConfig};
use ritual::cpp_data::CppPath;
use ritual::cpp_type::{CppBuiltInNumericType, CppType};
use ritual::rust_info::{NameType, RustPathScope};
use ritual::rust_type::RustPath;
use ritual_common::cpp_build_config::{CppBuildConfigData, CppLibraryType};
use ritual_common::errors::{bail, err_msg, FancyUnwrap, Result, ResultExt};
use ritual_common::file_utils::repo_dir_path;
use ritual_common::string_utils::CaseOperations;
use ritual_common::{target, toml};
use std::env;
use std::path::PathBuf;

mod after_cpp_parser;

pub const CPP_STD_VERSION: &str = "0.1.0";
pub const STD_HEADERS_PATH_ENV_VAR_NAME: &str = "RITUAL_STD_HEADERS";

fn create_config() -> Result<Config> {
    let mut crate_properties = CrateProperties::new("cpp_std", CPP_STD_VERSION);
    let mut custom_fields = toml::value::Table::new();
    let mut package_data = toml::value::Table::new();
    package_data.insert(
        "authors".to_string(),
        toml::Value::Array(vec![toml::Value::String(
            "Pavel Strakhov <ri@idzaaus.org>".to_string(),
        )]),
    );
    package_data.insert(
        "description".to_string(),
        toml::Value::String("Bindings for C++ standard library".into()),
    );
    // TODO: doc url
    //package_data.insert("documentation".to_string(), toml::Value::String(doc_url));
    package_data.insert(
        "repository".to_string(),
        toml::Value::String("https://github.com/rust-qt/ritual".to_string()),
    );
    package_data.insert(
        "license".to_string(),
        toml::Value::String("MIT OR Apache-2.0".to_string()),
    );
    package_data.insert(
        "keywords".to_string(),
        toml::Value::Array(vec![
            toml::Value::String("ffi".to_string()),
            toml::Value::String("ritual".to_string()),
        ]),
    );
    package_data.insert(
        "categories".to_string(),
        toml::Value::Array(vec![toml::Value::String(
            "external-ffi-bindings".to_string(),
        )]),
    );

    custom_fields.insert("package".to_string(), toml::Value::Table(package_data));
    crate_properties.set_custom_fields(custom_fields);

    let mut config = Config::new(crate_properties);
    config.set_cpp_lib_version("11");

    config.set_crate_template_path(repo_dir_path("ritual/src/bin/std_ritual/crate_template")?);

    /* TODO:  "array", "bitset", "deque", "forward_list", "list", "map", "queue", "set", "stack",
        "unordered_map", "unordered_set", "ios", "istream", "iostream", "fstream", "sstream",
        "atomic", "condition_variable", "future", "mutex", "thread", "algorithm", "chrono",
        "codecvt", "complex", "exception", "functional", "initializer_list", "iterator", "limits",
         "locale", "memory", "new", "numeric", "random", "ratio", "regex", "stdexcept",
         "system_error", "tuple", "typeindex", "typeinfo", "type_traits", "utility", "valarray",
    */
    let headers = ["string", "vector"];

    for header in &headers[..] {
        config.add_include_directive(header);
    }

    let include_path = PathBuf::from(
        env::var(STD_HEADERS_PATH_ENV_VAR_NAME)
            .with_context(|_| format!("missing env var: {}", STD_HEADERS_PATH_ENV_VAR_NAME))?,
    );
    if !include_path.exists() {
        bail!("std headers path doesn't exist: {}", include_path.display());
    }
    config.add_target_include_path(include_path);

    config.set_cpp_parser_path_hook(|path| {
        if path.items().iter().any(|item| item.name.starts_with('_')) {
            return Ok(false);
        }

        /*
                let string = path.to_templateless_string();
                let blocked = &[
                    // not in C++ standard
                    "__gnu_cxx",
                ];
                if blocked.contains(&string.as_str()) {
                    return Ok(false);
                }
        */

        Ok(true)
    });

    config.add_after_cpp_parser_hook(after_cpp_parser::hook);

    let namespace = CppPath::from_good_str("std");
    config.set_rust_path_scope_hook(move |path| {
        if path == &namespace {
            return Ok(Some(RustPathScope {
                path: RustPath::from_good_str("cpp_std"),
                prefix: None,
            }));
        }
        Ok(None)
    });

    config.set_rust_path_hook(move |path, name_type, _data| {
        if path.to_templateless_string() == "std::basic_string" {
            let args = path
                .last()
                .template_arguments
                .as_ref()
                .ok_or_else(|| err_msg("std::basic_string must have template arguments"))?;
            let arg = args
                .get(0)
                .ok_or_else(|| err_msg("std::basic_string: first argument is missing"))?;

            let rust_name = match arg {
                CppType::BuiltInNumeric(CppBuiltInNumericType::Char) => "String",
                CppType::BuiltInNumeric(CppBuiltInNumericType::Char16) => "U16String",
                CppType::BuiltInNumeric(CppBuiltInNumericType::Char32) => "U32String",
                CppType::BuiltInNumeric(CppBuiltInNumericType::WChar) => "WString",
                _ => {
                    return Ok(None);
                }
            };

            let name = match name_type {
                NameType::Type => format!("cpp_std::{}", rust_name),
                NameType::Module => format!("cpp_std::{}", rust_name.to_snake_case()),
                _ => bail!("unexpected name type for std::basic_string"),
            };
            return Ok(Some(RustPath::from_good_str(&name)));
        }
        Ok(None)
    });

    config.add_cpp_parser_argument("-std=c++11");
    let mut data = CppBuildConfigData::new();
    data.set_library_type(CppLibraryType::Static);
    config
        .cpp_build_config_mut()
        .add(target::Condition::True, data);
    Ok(config)
}

fn main() {
    let mut config = GlobalConfig::new();
    config.set_all_crate_names(vec!["cpp_std".into()]);
    config.set_create_config_hook(|_crate_name| create_config());

    cli::run_from_args(config).fancy_unwrap();
}
<|endoftext|>


<commit_before>use proc_macro2::Span;

pub trait IntoSpans<S> {
    // Not public API.
    #[doc(hidden)]
    fn into_spans(self) -> S;
}

impl IntoSpans<[Span; 1]> for Span {
    fn into_spans(self) -> [Span; 1] {
        [self]
    }
}

impl IntoSpans<[Span; 2]> for Span {
    fn into_spans(self) -> [Span; 2] {
        [self, self]
    }
}

impl IntoSpans<[Span; 3]> for Span {
    fn into_spans(self) -> [Span; 3] {
        [self, self, self]
    }
}

impl IntoSpans<Self> for [Span; 1] {
    fn into_spans(self) -> Self {
        self
    }
}

impl IntoSpans<Self> for [Span; 2] {
    fn into_spans(self) -> Self {
        self
    }
}

impl IntoSpans<Self> for [Span; 3] {
    fn into_spans(self) -> Self {
        self
    }
}

#[cfg(feature = "parsing")]
pub trait FromSpans: Sized {
    fn from_spans(spans: &[Span]) -> Self;
}

#[cfg(feature = "parsing")]
impl FromSpans for [Span; 1] {
    fn from_spans(spans: &[Span]) -> Self {
        [spans[0]]
    }
}

#[cfg(feature = "parsing")]
impl FromSpans for [Span; 2] {
    fn from_spans(spans: &[Span]) -> Self {
        [spans[0], spans[1]]
    }
}

#[cfg(feature = "parsing")]
impl FromSpans for [Span; 3] {
    fn from_spans(spans: &[Span]) -> Self {
        [spans[0], spans[1], spans[2]]
    }
}
<commit_msg>Replace Self to support old compilers<commit_after>use proc_macro2::Span;

pub trait IntoSpans<S> {
    // Not public API.
    #[doc(hidden)]
    fn into_spans(self) -> S;
}

impl IntoSpans<[Span; 1]> for Span {
    fn into_spans(self) -> [Span; 1] {
        [self]
    }
}

impl IntoSpans<[Span; 2]> for Span {
    fn into_spans(self) -> [Span; 2] {
        [self, self]
    }
}

impl IntoSpans<[Span; 3]> for Span {
    fn into_spans(self) -> [Span; 3] {
        [self, self, self]
    }
}

impl IntoSpans<[Span; 1]> for [Span; 1] {
    fn into_spans(self) -> [Span; 1] {
        self
    }
}

impl IntoSpans<[Span; 2]> for [Span; 2] {
    fn into_spans(self) -> [Span; 2] {
        self
    }
}

impl IntoSpans<[Span; 3]> for [Span; 3] {
    fn into_spans(self) -> [Span; 3] {
        self
    }
}

#[cfg(feature = "parsing")]
pub trait FromSpans: Sized {
    fn from_spans(spans: &[Span]) -> Self;
}

#[cfg(feature = "parsing")]
impl FromSpans for [Span; 1] {
    fn from_spans(spans: &[Span]) -> Self {
        [spans[0]]
    }
}

#[cfg(feature = "parsing")]
impl FromSpans for [Span; 2] {
    fn from_spans(spans: &[Span]) -> Self {
        [spans[0], spans[1]]
    }
}

#[cfg(feature = "parsing")]
impl FromSpans for [Span; 3] {
    fn from_spans(spans: &[Span]) -> Self {
        [spans[0], spans[1], spans[2]]
    }
}
<|endoftext|>