<commit_before>use std::f32;
use std::ops::Index;
use std::cmp::PartialOrd;
use Vector;
use na::Point3;
use ray::Ray;
use stats;
use num::Bounded;
use na::BaseNum;

pub type Bounds3f = Bounds3<f32>;

/// Axis Aligned Bounding Box
#[derive(Debug, Copy, Clone)]
pub struct Bounds3<T> {
    pub p_min: Point3<T>,
    pub p_max: Point3<T>,
}

impl<T> Bounds3<T>
    where T: BaseNum + Bounded + PartialOrd + Into<f32>
{
    pub fn new() -> Bounds3<T> {
        let min = T::min_value();
        let max = T::max_value();
        Bounds3 {
            p_min: Point3::new(max, max, max),
            p_max: Point3::new(min, min, min),
        }
    }

    pub fn from_point(point: &Point3<T>) -> Bounds3<T> {
        Bounds3 {
            p_min: *point,
            p_max: *point,
        }
    }

    pub fn from_points(min: &Point3<T>, max: &Point3<T>) -> Bounds3<T> {
        assert!(min.x <= max.x && min.y <= max.y && min.z <= max.z,
                "Invalid bounds");
        Bounds3 {
            p_min: *min,
            p_max: *max,
        }
    }

    pub fn corner(&self, corner: usize) -> Point3<T> {
        Point3::new(self[corner & 1].x,
                    self[if corner & 2 != 0 { 1 } else { 0 }].y,
                    self[if corner & 4 != 0 { 1 } else { 0 }].y)
    }

    pub fn extend(&mut self, p: Point3<T>) {
        if p.x < self.p_min.x {
            self.p_min.x = p.x
        }
        if p.y < self.p_min.y {
            self.p_min.y = p.y
        }
        if p.z < self.p_min.z {
            self.p_min.z = p.z
        }
        if p.x > self.p_max.x {
            self.p_max.x = p.x
        }
        if p.y > self.p_max.y {
            self.p_max.y = p.y
        }
        if p.z > self.p_max.z {
            self.p_max.z = p.z
        }
    }

    pub fn maximum_extent(&self) -> Axis {
        let v = self.p_max - self.p_min;
        if v.x > v.y {
            if v.x > v.z { Axis::X } else { Axis::Z }
        } else if v.y > v.z {
            Axis::Y
        } else {
            Axis::Z
        }
    }

    pub fn union(bbox1: &Bounds3<T>, bbox2: &Bounds3<T>) -> Bounds3<T> {
        let min = Point3::new(min(bbox1.p_min.x, bbox2.p_min.x),
                              min(bbox1.p_min.y, bbox2.p_min.y),
                              min(bbox1.p_min.z, bbox2.p_min.z));
        let max = Point3::new(max(bbox1.p_max.x, bbox2.p_max.x),
                              max(bbox1.p_max.y, bbox2.p_max.y),
                              max(bbox1.p_max.z, bbox2.p_max.z));

        Bounds3 {
            p_min: min,
            p_max: max,
        }
    }

    pub fn union_point(bbox: &Bounds3<T>, p: &Point3<T>) -> Bounds3<T> {
        let mut b = *bbox;
        b.extend(*p);
        b
    }

    pub fn intersect_p(&self, ray: &mut Ray) -> bool {
        let invdir = Vector::new(1.0 / ray.d.x, 1.0 / ray.d.y, 1.0 / ray.d.z);
        let sign = [(ray.d.x < 0.0) as usize, (ray.d.y < 0.0) as usize, (ray.d.z < 0.0) as usize];

        self.intersect_p_fast(ray, &invdir, &sign)
    }

    pub fn intersect_p_fast(&self,
                            ray: &mut Ray,
                            inv_dir: &Vector,
                            dir_is_neg: &[usize; 3])
                            -> bool {
        stats::inc_fast_bbox_isect();
        // Check intersection with X and Y slab
        let mut tmin = (self[dir_is_neg[0]].x.into() - ray.o.x) * inv_dir.x;
        let mut tmax = (self[1 - dir_is_neg[0]].x.into() - ray.o.x) * inv_dir.x;
        let tymin = (self[dir_is_neg[1]].y.into() - ray.o.y) * inv_dir.y;
        let tymax = (self[1 - dir_is_neg[1]].y.into() - ray.o.y) * inv_dir.y;
        if (tmin > tymax) || (tymin > tmax) {
            return false;
        }
        if tymin > tmin {
            tmin = tymin;
        }
        if tymax < tmax {
            tmax = tymax;
        }
        // Check intersection with Z slab
        let tzmin = (self[dir_is_neg[2]].z.into() - ray.o.z) * inv_dir.z;
        let tzmax = (self[1 - dir_is_neg[2]].z.into() - ray.o.z) * inv_dir.z;
        if (tmin > tzmax) || (tzmin > tmax) {
            return false;
        }
        if tzmin > tmin {
            tmin = tzmin;
        }
        if tzmax < tmax {
            tmax = tzmax;
        }

        tmin < ray.t_max && tmax > ray.t_min
    }
}

impl<T> Index<usize> for Bounds3<T> {
    type Output = Point3<T>;

    fn index(&self, i: usize) -> &Point3<T> {
        match i {
            0 => &self.p_min,
            1 => &self.p_max,
            _ => panic!("Invalid index!"),
        }
    }
}

fn min<T: PartialOrd>(a: T, b: T) -> T {
    if a.lt(&b) { a } else { b }
}

fn max<T: PartialOrd>(a: T, b: T) -> T {
    if a.gt(&b) { a } else { b }
}

#[derive(Copy, Clone, Debug)]
pub enum Axis {
    X,
    Y,
    Z,
}

impl Index<Axis> for Point3<f32> {
    type Output = f32;

    fn index(&self, axis: Axis) -> &f32 {
        match axis {
            Axis::X => &self.x,
            Axis::Y => &self.y,
            Axis::Z => &self.z,
        }
    }
}
<commit_msg>Add linear interpolation of a Point inside a Bounds3<commit_after>use std::f32;
use std::ops::Index;
use std::cmp::PartialOrd;
use {Vector, Point, lerp};
use na::Point3;
use ray::Ray;
use stats;
use num::Bounded;
use na::BaseNum;

pub type Bounds3f = Bounds3<f32>;

/// Axis Aligned Bounding Box
#[derive(Debug, Copy, Clone)]
pub struct Bounds3<T> {
    pub p_min: Point3<T>,
    pub p_max: Point3<T>,
}

impl<T> Bounds3<T>
    where T: BaseNum + Bounded + PartialOrd + Into<f32>
{
    pub fn new() -> Bounds3<T> {
        let min = T::min_value();
        let max = T::max_value();
        Bounds3 {
            p_min: Point3::new(max, max, max),
            p_max: Point3::new(min, min, min),
        }
    }

    pub fn from_point(point: &Point3<T>) -> Bounds3<T> {
        Bounds3 {
            p_min: *point,
            p_max: *point,
        }
    }

    pub fn from_points(min: &Point3<T>, max: &Point3<T>) -> Bounds3<T> {
        assert!(min.x <= max.x && min.y <= max.y && min.z <= max.z,
                "Invalid bounds");
        Bounds3 {
            p_min: *min,
            p_max: *max,
        }
    }

    pub fn corner(&self, corner: usize) -> Point3<T> {
        Point3::new(self[corner & 1].x,
                    self[if corner & 2 != 0 { 1 } else { 0 }].y,
                    self[if corner & 4 != 0 { 1 } else { 0 }].y)
    }

    pub fn extend(&mut self, p: Point3<T>) {
        if p.x < self.p_min.x {
            self.p_min.x = p.x
        }
        if p.y < self.p_min.y {
            self.p_min.y = p.y
        }
        if p.z < self.p_min.z {
            self.p_min.z = p.z
        }
        if p.x > self.p_max.x {
            self.p_max.x = p.x
        }
        if p.y > self.p_max.y {
            self.p_max.y = p.y
        }
        if p.z > self.p_max.z {
            self.p_max.z = p.z
        }
    }

    pub fn maximum_extent(&self) -> Axis {
        let v = self.p_max - self.p_min;
        if v.x > v.y {
            if v.x > v.z { Axis::X } else { Axis::Z }
        } else if v.y > v.z {
            Axis::Y
        } else {
            Axis::Z
        }
    }

    pub fn union(bbox1: &Bounds3<T>, bbox2: &Bounds3<T>) -> Bounds3<T> {
        let min = Point3::new(min(bbox1.p_min.x, bbox2.p_min.x),
                              min(bbox1.p_min.y, bbox2.p_min.y),
                              min(bbox1.p_min.z, bbox2.p_min.z));
        let max = Point3::new(max(bbox1.p_max.x, bbox2.p_max.x),
                              max(bbox1.p_max.y, bbox2.p_max.y),
                              max(bbox1.p_max.z, bbox2.p_max.z));

        Bounds3 {
            p_min: min,
            p_max: max,
        }
    }

    pub fn union_point(bbox: &Bounds3<T>, p: &Point3<T>) -> Bounds3<T> {
        let mut b = *bbox;
        b.extend(*p);
        b
    }

    pub fn intersect_p(&self, ray: &mut Ray) -> bool {
        let invdir = Vector::new(1.0 / ray.d.x, 1.0 / ray.d.y, 1.0 / ray.d.z);
        let sign = [(ray.d.x < 0.0) as usize, (ray.d.y < 0.0) as usize, (ray.d.z < 0.0) as usize];

        self.intersect_p_fast(ray, &invdir, &sign)
    }

    pub fn intersect_p_fast(&self,
                            ray: &mut Ray,
                            inv_dir: &Vector,
                            dir_is_neg: &[usize; 3])
                            -> bool {
        stats::inc_fast_bbox_isect();
        // Check intersection with X and Y slab
        let mut tmin = (self[dir_is_neg[0]].x.into() - ray.o.x) * inv_dir.x;
        let mut tmax = (self[1 - dir_is_neg[0]].x.into() - ray.o.x) * inv_dir.x;
        let tymin = (self[dir_is_neg[1]].y.into() - ray.o.y) * inv_dir.y;
        let tymax = (self[1 - dir_is_neg[1]].y.into() - ray.o.y) * inv_dir.y;
        if (tmin > tymax) || (tymin > tmax) {
            return false;
        }
        if tymin > tmin {
            tmin = tymin;
        }
        if tymax < tmax {
            tmax = tymax;
        }
        // Check intersection with Z slab
        let tzmin = (self[dir_is_neg[2]].z.into() - ray.o.z) * inv_dir.z;
        let tzmax = (self[1 - dir_is_neg[2]].z.into() - ray.o.z) * inv_dir.z;
        if (tmin > tzmax) || (tzmin > tmax) {
            return false;
        }
        if tzmin > tmin {
            tmin = tzmin;
        }
        if tzmax < tmax {
            tmax = tzmax;
        }

        tmin < ray.t_max && tmax > ray.t_min
    }

    /// Linearly interpolate a point inside the bounds
    pub fn lerp(&self, t: &Point3<T>) -> Point3<T> {
        Point3::new(lerp(t.x, self.p_min.x, self.p_max.x),
                    lerp(t.y, self.p_min.y, self.p_max.y),
                    lerp(t.z, self.p_min.z, self.p_max.z))
    }
}

impl<T> Index<usize> for Bounds3<T> {
    type Output = Point3<T>;

    fn index(&self, i: usize) -> &Point3<T> {
        match i {
            0 => &self.p_min,
            1 => &self.p_max,
            _ => panic!("Invalid index!"),
        }
    }
}

fn min<T: PartialOrd>(a: T, b: T) -> T {
    if a.lt(&b) { a } else { b }
}

fn max<T: PartialOrd>(a: T, b: T) -> T {
    if a.gt(&b) { a } else { b }
}

#[derive(Copy, Clone, Debug)]
pub enum Axis {
    X,
    Y,
    Z,
}

impl Index<Axis> for Point3<f32> {
    type Output = f32;

    fn index(&self, axis: Axis) -> &f32 {
        match axis {
            Axis::X => &self.x,
            Axis::Y => &self.y,
            Axis::Z => &self.z,
        }
    }
}
<|endoftext|>


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

#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![comment = "A mathematics library for computer graphics."]
#![license = "ASL2"]

#![feature(globs)]
#![feature(macro_rules)]

//! Computer graphics-centric math.
//!
//! This crate provides useful mathematical primitives and operations on them.
//! It is organized into one module per primitive. The core structures are
//! vectors and matrices. A strongly-typed interface is provided, to prevent
//! mixing units or violating mathematical invariants.
//!
//! Transformations are not usually done directly on matrices, but go through
//! transformation objects that can be converted to matrices. Rotations go
//! through the `Basis` types, which are guaranteed to be orthogonal matrices.
//! Despite this, one can directly create a limited rotation matrix using the
//! `look_at`, `from_angle`, `from_euler`, and `from_axis_angle` methods.
//! These are provided for convenience.

// Re-exports

pub use array::{Array1, Array2, FixedArray};

pub use matrix::Matrix;
pub use matrix::{Matrix2, Matrix3, Matrix4};
pub use matrix::{ToMatrix2, ToMatrix3, ToMatrix4};
pub use quaternion::{Quaternion, ToQuaternion};
pub use vector::{Vector, EuclideanVector};
pub use vector::{Vector2, Vector3, Vector4};
pub use vector::dot;

pub use angle::{rad, deg};
pub use angle::{Angle, Rad, Deg};
pub use angle::{ToRad, ToDeg};
pub use angle::bisect;
pub use angle::{sin, cos, tan, sin_cos};
pub use angle::{cot, sec, csc};
pub use angle::{acos, asin, atan, atan2};
pub use plane::Plane;
pub use point::{Point, Point2, Point3};
pub use line::{Line, Line2, Line3};
pub use ray::{Ray, Ray2, Ray3};
pub use rotation::{Rotation, Rotation2, Rotation3};
pub use rotation::{Basis3, Basis2};
pub use rotation::{ToBasis2, ToBasis3};
pub use transform::{Transform, Transform3};
pub use transform::{Decomposed, AffineMatrix3};

pub use projection::{perspective, frustum, ortho};
pub use projection::{Projection, PerspectiveFov, Perspective, Ortho};

pub use aabb::{Aabb, Aabb2, Aabb3, Aabb3};
pub use cylinder::Cylinder;
pub use frustum::{Frustum, FrustumPoints};
pub use intersect::Intersect;
pub use obb::{Obb2, Obb3};
pub use sphere::Sphere;

pub use approx::ApproxEq;
pub use num::{PartialOrd, BaseNum, BaseInt, BaseFloat};

// Modules

mod array;

mod matrix;
mod quaternion;
mod vector;

mod angle;
mod plane;
mod point;
mod line;
mod ray;
mod rotation;
mod transform;

mod projection;

mod aabb;
mod cylinder;
mod frustum;
mod intersect;
mod obb;
mod sphere;

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

#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![comment = "A mathematics library for computer graphics."]
#![license = "ASL2"]

#![feature(globs)]
#![feature(macro_rules)]

//! Computer graphics-centric math.
//!
//! This crate provides useful mathematical primitives and operations on them.
//! It is organized into one module per primitive. The core structures are
//! vectors and matrices. A strongly-typed interface is provided, to prevent
//! mixing units or violating mathematical invariants.
//!
//! Transformations are not usually done directly on matrices, but go through
//! transformation objects that can be converted to matrices. Rotations go
//! through the `Basis` types, which are guaranteed to be orthogonal matrices.
//! Despite this, one can directly create a limited rotation matrix using the
//! `look_at`, `from_angle`, `from_euler`, and `from_axis_angle` methods.
//! These are provided for convenience.

// Re-exports

pub use array::{Array1, Array2, FixedArray};

pub use matrix::Matrix;
pub use matrix::{Matrix2, Matrix3, Matrix4};
pub use matrix::{ToMatrix2, ToMatrix3, ToMatrix4};
pub use quaternion::{Quaternion, ToQuaternion};
pub use vector::{Vector, EuclideanVector};
pub use vector::{Vector2, Vector3, Vector4};
pub use vector::dot;

pub use angle::{rad, deg};
pub use angle::{Angle, Rad, Deg};
pub use angle::{ToRad, ToDeg};
pub use angle::bisect;
pub use angle::{sin, cos, tan, sin_cos};
pub use angle::{cot, sec, csc};
pub use angle::{acos, asin, atan, atan2};
pub use plane::Plane;
pub use point::{Point, Point2, Point3};
pub use line::{Line, Line2, Line3};
pub use ray::{Ray, Ray2, Ray3};
pub use rotation::{Rotation, Rotation2, Rotation3};
pub use rotation::{Basis3, Basis2};
pub use rotation::{ToBasis2, ToBasis3};
pub use transform::{Transform, Transform3};
pub use transform::{Decomposed, AffineMatrix3};

pub use projection::{perspective, frustum, ortho};
pub use projection::{Projection, PerspectiveFov, Perspective, Ortho};

pub use aabb::{Aabb, Aabb2, Aabb3};
pub use cylinder::Cylinder;
pub use frustum::{Frustum, FrustumPoints};
pub use intersect::Intersect;
pub use obb::{Obb2, Obb3};
pub use sphere::Sphere;

pub use approx::ApproxEq;
pub use num::{PartialOrd, BaseNum, BaseInt, BaseFloat};

// Modules

mod array;

mod matrix;
mod quaternion;
mod vector;

mod angle;
mod plane;
mod point;
mod line;
mod ray;
mod rotation;
mod transform;

mod projection;

mod aabb;
mod cylinder;
mod frustum;
mod intersect;
mod obb;
mod sphere;

mod approx;
mod num;
<|endoftext|>


<commit_before>
//! Various methods for computing with vectors.

use {
    Line,
    Matrix2d,
    Ray,
    Rectangle,
    Vec2d,
    Triangle
};
use modular_index::{previous};

/// Multiplies two matrices.
#[inline(always)]
pub fn multiply(m: &[f64, ..6], b: &[f64, ..6]) -> Matrix2d {
    [m[0]*b[0]+m[1]*b[3]+m[2]*0.0,  m[0]*b[1]+m[1]*b[4]+m[2]*0.0,  m[0]*b[2]+m[1]*b[5]+m[2]*1.0,
     m[3]*b[0]+m[4]*b[3]+m[5]*0.0,  m[3]*b[1]+m[4]*b[4]+m[5]*0.0,  m[3]*b[2]+m[4]*b[5]+m[5]*1.0]
}

/// Creates a translation matrix.
#[inline(always)]
pub fn translate(x: f64, y: f64) -> Matrix2d {
    [1.0, 0.0, x,
     0.0, 1.0, y]
}

/// Creates a rotation matrix.
#[inline(always)]
pub fn rotate_radians(angle: f64) -> Matrix2d {
    let c = angle.cos();
    let s = angle.sin();
    [c, -s, 0.0,
     s,  c, 0.0]
}

/// Orients x axis to look at point.
///
/// Leaves x axis unchanged if the point to look at is the origin.
#[inline(always)]
pub fn orient(x: f64, y: f64) -> Matrix2d {
    let len = x * x + y * y;
    if len == 0.0 {
         return [1.0, 0.0, 0.0,
                 0.0, 1.0, 0.0];
    }

    let len = len.sqrt();
    let c = x / len;
    let s = y / len;
    [c, -s, 0.0,
     s,  c, 0.0]
}

/// Create a scale matrix.
#[inline(always)]
pub fn scale(sx: f64, sy: f64) -> Matrix2d {
    [sx, 0.0, 0.0,
     0.0, sy, 0.0]
}

/// Create a shear matrix.
#[inline(always)]
pub fn shear(sx: f64, sy: f64) -> Matrix2d {
    [1.0, sx, 0.0,
     sy, 1.0, 0.0]
}

/// Create an identity matrix.
#[inline(always)]
pub fn identity() -> Matrix2d {
    [1.0, 0.0, 0.0,
     0.0, 1.0, 0.0]
}

/// Compute the shortest vector from point to ray.
/// A ray stores starting point and directional vector.
#[inline(always)]
pub fn separation(ray: Ray, x: f64, y: f64) -> Vec2d {
    // Get the directional vector.
    let (dir_x, dir_y) = (ray[2], ray[3]);
    // Get displacement vector from point.
    let (dx, dy) = (ray[0] - x, ray[1] - y);
    // Compute the component of position in ray direction.
    let dot = dir_x * x + dir_y * y;
    // The directional vector multiplied with the dot gives us a parallel vector.
    // When we subtract this from the displacement we get a vector normal to the ray.
    // This is the shortest vector from the point to the ray.
    [dx - dot * dir_x, dy - dot * dir_y]
}

/// Returns the least separation out of four.
/// Each seperation can be computed using `separation` function.
/// The separation returned can be used to solve collision of rectangles.
#[inline(always)]
pub fn least_separation_4(sep1: Vec2d, sep2: Vec2d, sep3: Vec2d, sep4: Vec2d) -> Vec2d {
    let dot1 = sep1[0] * sep1[0] + sep1[1] * sep1[1];
    let dot2 = sep2[0] * sep2[0] + sep2[1] * sep2[1];
    let dot3 = sep3[0] * sep3[0] + sep3[1] * sep3[1];
    let dot4 = sep4[0] * sep4[0] + sep4[1] * sep4[1];
    // Search for the smallest dot product.
    if dot1 < dot2 {
        if dot3 < dot4 {
            if dot1 < dot3 { sep1 } else { sep3 }
        } else {
            if dot1 < dot4 { sep1 } else { sep4 }
        }
    } else {
        if dot3 < dot4 {
            if dot2 < dot3 { sep2 } else { sep3 }
        } else {
            if dot2 < dot4 { sep2 } else { sep4 }
        }
    }
}

/// Shrinks a rectangle by a factor on all sides.
#[inline(always)]
pub fn margin_rectangle(rect: &Rectangle, m: f64) -> Rectangle {
    let w = rect[2] - 2.0 * m;
    let h = rect[3] - 2.0 * m;
    let (x, w) = if w < 0.0 { (rect[0] + 0.5 * rect[2], 0.0) } else { (rect[0] + m, w) };
    let (y, h) = if h < 0.0 { (rect[1] + 0.5 * rect[3], 0.0) } else { (rect[1] + m, h) };
    [x, y, w, h]
}

/// Computes a relative rectangle using the rectangle as a tile.
#[inline(always)]
pub fn relative_rectangle(rect: &Rectangle, x: f64, y: f64) -> Rectangle {
    [rect[0] + x * rect[2], rect[1] + y * rect[3], rect[2], rect[3]]
}

/// Computes modular offset safely for numbers.
#[inline(always)]
pub fn modular_offset<T: Add<T, T> + Rem<T, T>>(n: &T, i: &T, off: &T) -> T {
    (*i + (*off % *n + *n)) % *n
}

#[test]
fn test_modular_offset() {
    assert_eq!(modular_offset(&3.0_f64, &0.0_f64, &-1.0_f64), 2.0_f64);
    assert_eq!(modular_offset(&3.0_f64, &1.0_f64, &-1.0_f64), 0.0_f64);
    assert_eq!(modular_offset(&3.0_f64, &2.0_f64, &-1.0_f64), 1.0_f64);
    assert_eq!(modular_offset(&3.0_f64, &3.0_f64, &-1.0_f64), 2.0_f64);

    assert_eq!(modular_offset(&3.0_f64, &0.0_f64, &1.0_f64), 1.0_f64);
    assert_eq!(modular_offset(&3.0_f64, &1.0_f64, &1.0_f64), 2.0_f64);
    assert_eq!(modular_offset(&3.0_f64, &2.0_f64, &1.0_f64), 0.0_f64);
    assert_eq!(modular_offset(&3.0_f64, &3.0_f64, &1.0_f64), 1.0_f64);
}

/// Computes the area and centroid of a simple polygon.
///
/// A simple polygon is one that does not intersect itself.
/// Source: http://en.wikipedia.org/wiki/Polygon_area#Simple_polygons
pub fn area_centroid(polygon: &[f64]) -> (f64, Vec2d) {
    let n = polygon.len() / 2;
    let mut sum = 0.0_f64;
    let (mut cx, mut cy) = (0.0_f64, 0.0_f64);
    for i in range(0, n) {
        let (qx, qy) = (polygon[i * 2], polygon[i * 2 + 1]);
        let p_i = previous(n, i);
        let (px, py) = (polygon[p_i * 2], polygon[p_i * 2 + 1]);
        let cross = px * qy - qx * py;
        cx += (px + qx) * cross;
        cy += (py + qy) * cross;
        sum += cross;
    }

    let area = 0.5 * sum;
    // 'cx / (6.0 * area)' = 'cx / (3.0 * sum)'
    let centroid = [cx / (3.0 * sum), cy / (3.0 * sum)];
    (area, centroid)
}

/// Computes area of a simple polygon.
///
/// A simple polygon is one that does not intersect itself.
#[inline(always)]
pub fn area(polygon: &[f64]) -> f64 {
    let (res, _) = area_centroid(polygon);
    res
}

/// Computes centroid of a simple polygon.
///
/// A simple polygon is one that does not intersect itself.
#[inline(always)]
pub fn centroid(polygon: &[f64]) -> Vec2d {
    let (_, res) = area_centroid(polygon);
    res
}

/// Returns a number that tells which side it is relative to a line.
///
/// Computes the cross product of the vector that gives the line
/// with the vector between point and starting point of line.
/// One side of the line has opposite sign of the other.
#[inline(always)]
pub fn line_side(line: &Line, x: f64, y: f64) -> f64 {
    let (ax, ay) = (line[0], line[1]);
    let (bx, by) = (line[2], line[3]);
    (bx - ax) * (y - ay) - (by - ay) * (x - ax)
}

/// Returns true if point is inside triangle.
///
/// This is done by computing a `side` number for each edge.
/// If the number is inside if it is on the same side for all edges.
/// Might break for very small triangles.
pub fn inside_triangle(triangle: &Triangle, x: f64, y: f64) -> bool {
    let (ax, ay) = (triangle[0], triangle[1]);
    let (bx, by) = (triangle[2], triangle[3]);
    let (cx, cy) = (triangle[4], triangle[5]);

    let ab_side = line_side(&([ax, ay, bx, by]), x, y);
    let bc_side = line_side(&([bx, by, cx, cy]), x, y);
    let ca_side = line_side(&([cx, cy, ax, ay]), x, y);

    let ab_positive = ab_side.is_positive();
    let bc_positive = bc_side.is_positive();
    let ca_positive = ca_side.is_positive();

    ab_positive == bc_positive
    && bc_positive == ca_positive
}

#[test]
fn test_triangle() {
    // Triangle counter clock-wise.
    let tri_1 = [0.0, 0.0, 1.0, 0.0, 1.0, 1.0];
    // Triangle clock-wise.
    let tri_2 = [0.0, 0.0, 1.0, 1.0, 1.0, 0.0];
    let (x, y) = (0.5, 0.25);
    assert_eq!(inside_triangle(&tri_1, x, y), true);
    assert_eq!(inside_triangle(&tri_2, x, y), true);
}
<commit_msg>Added `triangle_face` function to `vecmath`<commit_after>
//! Various methods for computing with vectors.

use {
    Line,
    Matrix2d,
    Ray,
    Rectangle,
    Vec2d,
    Triangle
};
use modular_index::{previous};

/// Multiplies two matrices.
#[inline(always)]
pub fn multiply(m: &[f64, ..6], b: &[f64, ..6]) -> Matrix2d {
    [m[0]*b[0]+m[1]*b[3]+m[2]*0.0,  m[0]*b[1]+m[1]*b[4]+m[2]*0.0,  m[0]*b[2]+m[1]*b[5]+m[2]*1.0,
     m[3]*b[0]+m[4]*b[3]+m[5]*0.0,  m[3]*b[1]+m[4]*b[4]+m[5]*0.0,  m[3]*b[2]+m[4]*b[5]+m[5]*1.0]
}

/// Creates a translation matrix.
#[inline(always)]
pub fn translate(x: f64, y: f64) -> Matrix2d {
    [1.0, 0.0, x,
     0.0, 1.0, y]
}

/// Creates a rotation matrix.
#[inline(always)]
pub fn rotate_radians(angle: f64) -> Matrix2d {
    let c = angle.cos();
    let s = angle.sin();
    [c, -s, 0.0,
     s,  c, 0.0]
}

/// Orients x axis to look at point.
///
/// Leaves x axis unchanged if the point to look at is the origin.
#[inline(always)]
pub fn orient(x: f64, y: f64) -> Matrix2d {
    let len = x * x + y * y;
    if len == 0.0 {
         return [1.0, 0.0, 0.0,
                 0.0, 1.0, 0.0];
    }

    let len = len.sqrt();
    let c = x / len;
    let s = y / len;
    [c, -s, 0.0,
     s,  c, 0.0]
}

/// Create a scale matrix.
#[inline(always)]
pub fn scale(sx: f64, sy: f64) -> Matrix2d {
    [sx, 0.0, 0.0,
     0.0, sy, 0.0]
}

/// Create a shear matrix.
#[inline(always)]
pub fn shear(sx: f64, sy: f64) -> Matrix2d {
    [1.0, sx, 0.0,
     sy, 1.0, 0.0]
}

/// Create an identity matrix.
#[inline(always)]
pub fn identity() -> Matrix2d {
    [1.0, 0.0, 0.0,
     0.0, 1.0, 0.0]
}

/// Compute the shortest vector from point to ray.
/// A ray stores starting point and directional vector.
#[inline(always)]
pub fn separation(ray: Ray, x: f64, y: f64) -> Vec2d {
    // Get the directional vector.
    let (dir_x, dir_y) = (ray[2], ray[3]);
    // Get displacement vector from point.
    let (dx, dy) = (ray[0] - x, ray[1] - y);
    // Compute the component of position in ray direction.
    let dot = dir_x * x + dir_y * y;
    // The directional vector multiplied with the dot gives us a parallel vector.
    // When we subtract this from the displacement we get a vector normal to the ray.
    // This is the shortest vector from the point to the ray.
    [dx - dot * dir_x, dy - dot * dir_y]
}

/// Returns the least separation out of four.
/// Each seperation can be computed using `separation` function.
/// The separation returned can be used to solve collision of rectangles.
#[inline(always)]
pub fn least_separation_4(sep1: Vec2d, sep2: Vec2d, sep3: Vec2d, sep4: Vec2d) -> Vec2d {
    let dot1 = sep1[0] * sep1[0] + sep1[1] * sep1[1];
    let dot2 = sep2[0] * sep2[0] + sep2[1] * sep2[1];
    let dot3 = sep3[0] * sep3[0] + sep3[1] * sep3[1];
    let dot4 = sep4[0] * sep4[0] + sep4[1] * sep4[1];
    // Search for the smallest dot product.
    if dot1 < dot2 {
        if dot3 < dot4 {
            if dot1 < dot3 { sep1 } else { sep3 }
        } else {
            if dot1 < dot4 { sep1 } else { sep4 }
        }
    } else {
        if dot3 < dot4 {
            if dot2 < dot3 { sep2 } else { sep3 }
        } else {
            if dot2 < dot4 { sep2 } else { sep4 }
        }
    }
}

/// Shrinks a rectangle by a factor on all sides.
#[inline(always)]
pub fn margin_rectangle(rect: &Rectangle, m: f64) -> Rectangle {
    let w = rect[2] - 2.0 * m;
    let h = rect[3] - 2.0 * m;
    let (x, w) = if w < 0.0 { (rect[0] + 0.5 * rect[2], 0.0) } else { (rect[0] + m, w) };
    let (y, h) = if h < 0.0 { (rect[1] + 0.5 * rect[3], 0.0) } else { (rect[1] + m, h) };
    [x, y, w, h]
}

/// Computes a relative rectangle using the rectangle as a tile.
#[inline(always)]
pub fn relative_rectangle(rect: &Rectangle, x: f64, y: f64) -> Rectangle {
    [rect[0] + x * rect[2], rect[1] + y * rect[3], rect[2], rect[3]]
}

/// Computes modular offset safely for numbers.
#[inline(always)]
pub fn modular_offset<T: Add<T, T> + Rem<T, T>>(n: &T, i: &T, off: &T) -> T {
    (*i + (*off % *n + *n)) % *n
}

#[test]
fn test_modular_offset() {
    assert_eq!(modular_offset(&3.0_f64, &0.0_f64, &-1.0_f64), 2.0_f64);
    assert_eq!(modular_offset(&3.0_f64, &1.0_f64, &-1.0_f64), 0.0_f64);
    assert_eq!(modular_offset(&3.0_f64, &2.0_f64, &-1.0_f64), 1.0_f64);
    assert_eq!(modular_offset(&3.0_f64, &3.0_f64, &-1.0_f64), 2.0_f64);

    assert_eq!(modular_offset(&3.0_f64, &0.0_f64, &1.0_f64), 1.0_f64);
    assert_eq!(modular_offset(&3.0_f64, &1.0_f64, &1.0_f64), 2.0_f64);
    assert_eq!(modular_offset(&3.0_f64, &2.0_f64, &1.0_f64), 0.0_f64);
    assert_eq!(modular_offset(&3.0_f64, &3.0_f64, &1.0_f64), 1.0_f64);
}

/// Computes the area and centroid of a simple polygon.
///
/// A simple polygon is one that does not intersect itself.
/// Source: http://en.wikipedia.org/wiki/Polygon_area#Simple_polygons
pub fn area_centroid(polygon: &[f64]) -> (f64, Vec2d) {
    let n = polygon.len() / 2;
    let mut sum = 0.0_f64;
    let (mut cx, mut cy) = (0.0_f64, 0.0_f64);
    for i in range(0, n) {
        let (qx, qy) = (polygon[i * 2], polygon[i * 2 + 1]);
        let p_i = previous(n, i);
        let (px, py) = (polygon[p_i * 2], polygon[p_i * 2 + 1]);
        let cross = px * qy - qx * py;
        cx += (px + qx) * cross;
        cy += (py + qy) * cross;
        sum += cross;
    }

    let area = 0.5 * sum;
    // 'cx / (6.0 * area)' = 'cx / (3.0 * sum)'
    let centroid = [cx / (3.0 * sum), cy / (3.0 * sum)];
    (area, centroid)
}

/// Computes area of a simple polygon.
///
/// A simple polygon is one that does not intersect itself.
#[inline(always)]
pub fn area(polygon: &[f64]) -> f64 {
    let (res, _) = area_centroid(polygon);
    res
}

/// Computes centroid of a simple polygon.
///
/// A simple polygon is one that does not intersect itself.
#[inline(always)]
pub fn centroid(polygon: &[f64]) -> Vec2d {
    let (_, res) = area_centroid(polygon);
    res
}

/// Returns a number that tells which side it is relative to a line.
///
/// Computes the cross product of the vector that gives the line
/// with the vector between point and starting point of line.
/// One side of the line has opposite sign of the other.
#[inline(always)]
pub fn line_side(line: &Line, x: f64, y: f64) -> f64 {
    let (ax, ay) = (line[0], line[1]);
    let (bx, by) = (line[2], line[3]);
    (bx - ax) * (y - ay) - (by - ay) * (x - ax)
}

/// Returns true if point is inside triangle.
///
/// This is done by computing a `side` number for each edge.
/// If the number is inside if it is on the same side for all edges.
/// Might break for very small triangles.
pub fn inside_triangle(triangle: &Triangle, x: f64, y: f64) -> bool {
    let (ax, ay) = (triangle[0], triangle[1]);
    let (bx, by) = (triangle[2], triangle[3]);
    let (cx, cy) = (triangle[4], triangle[5]);

    let ab_side = line_side(&([ax, ay, bx, by]), x, y);
    let bc_side = line_side(&([bx, by, cx, cy]), x, y);
    let ca_side = line_side(&([cx, cy, ax, ay]), x, y);

    let ab_positive = ab_side.is_positive();
    let bc_positive = bc_side.is_positive();
    let ca_positive = ca_side.is_positive();

    ab_positive == bc_positive
    && bc_positive == ca_positive
}

/// Returns true if triangle is clockwise.
///
/// This is done by computing which side the third vertex is relative to
/// the line starting from the first vertex to second vertex.
pub fn triangle_face(triangle: &Triangle) -> bool {
    let (ax, ay) = (triangle[0], triangle[1]);
    let (bx, by) = (triangle[2], triangle[3]);
    let (cx, cy) = (triangle[4], triangle[5]);

    let ab_side = line_side(&([ax, ay, bx, by]), cx, cy);

    ab_side.is_negative()
}

#[test]
fn test_triangle() {
    // Triangle counter clock-wise.
    let tri_1 = [0.0, 0.0, 1.0, 0.0, 1.0, 1.0];
    // Triangle clock-wise.
    let tri_2 = [0.0, 0.0, 1.0, 1.0, 1.0, 0.0];
    let (x, y) = (0.5, 0.25);
    assert_eq!(inside_triangle(&tri_1, x, y), true);
    assert_eq!(inside_triangle(&tri_2, x, y), true);
    assert_eq!(triangle_face(&tri_1), false);
    assert_eq!(triangle_face(&tri_2), true);
}
<|endoftext|>


<commit_before>use std::io::Read;

use hyper::status::StatusCode;
use rustc_serialize::json;
use url::{ParseError, Url};
use url::form_urlencoded::serialize_owned;

use error::Error;
use http;

#[derive(Debug)]
#[derive(RustcDecodable)]
pub struct Response {
    pub action: String,
    pub node: Node,
    pub prev_node: Option<Node>,
}

#[derive(Debug)]
#[derive(RustcDecodable)]
pub struct Node {
    pub created_index: Option<u64>,
    pub dir: Option<bool>,
    pub expiration: Option<String>,
    pub key: Option<String>,
    pub modified_index: Option<u64>,
    pub nodes: Option<Vec<Node>>,
    pub ttl: Option<i64>,
    pub value: Option<String>,
}

#[derive(Debug)]
pub struct Client {
    root_url: String,
}

impl Client {
    pub fn new(root_url: &str) -> Result<Client, ParseError> {
        let url = try!(Url::parse(root_url));
        let client = Client {
            root_url: format!("{}", url.serialize()),
        };

        Ok(client)
    }

    pub fn default() -> Client {
        Client {
            root_url: "http://127.0.0.1:2379/".to_string(),
        }
    }

    pub fn get(&self, key: &str) -> Result<Response, EtcdError> {
        Err(EtcdError)
    }

    pub fn create(&self, key: &str, value: &str, ttl: Option<u64>) -> Result<Response, Error> {
        let url = self.build_url(key);
        let mut options = vec![];

        options.push(("value".to_string(), value.to_string()));
        options.push(("prevExist".to_string(), "false".to_string()));

        if ttl.is_some() {
            options.push(("ttl".to_string(), format!("{}", ttl.unwrap())));
        }

        let body = serialize_owned(&options);

        match http::put(url, body) {
            Ok(mut response) => {
                let mut response_body = String::new();

                response.read_to_string(&mut response_body).unwrap();

                println!("{:?} - {:?} - {:?}", response.status, response.headers, response_body);

                match response.status {
                    StatusCode::Created => Ok(json::decode(&response_body).unwrap()),
                    _ => Err(Error::Etcd(json::decode(&response_body).unwrap())),
                }
            },
            Err(error) => Err(Error::Http(error)),
        }
    }

    pub fn delete(&self, key: &str, recursive: bool) -> Result<Response, Error> {
        let url = self.build_url(key);
        let mut options = vec![];

        options.push(("recursive".to_string(), format!("{}", recursive)));

        let body = serialize_owned(&options);

        match http::delete(url, body) {
            Ok(mut response) => {
                let mut response_body = String::new();

                response.read_to_string(&mut response_body).unwrap();

                println!("{:?} - {:?} - {:?}", response.status, response.headers, response_body);

                match response.status {
                    StatusCode::Ok => Ok(json::decode(&response_body).unwrap()),
                    _ => Err(Error::Etcd(json::decode(&response_body).unwrap())),
                }
            },
            Err(error) => Err(Error::Http(error)),
        }
    }

    // private

    fn build_url(&self, path: &str) -> String {
        format!("{}v2/keys{}", self.root_url, path)
    }

}

#[cfg(test)]
mod create_tests {
    use super::Client;
    use error::Error;

    #[test]
    fn create() {
        let client = Client::new("http://etcd:2379").unwrap();

        let response = client.create("/foo", "bar", Some(100)).ok().unwrap();

        assert_eq!(response.action, "create".to_string());
        assert_eq!(response.node.value.unwrap(), "bar".to_string());
        assert_eq!(response.node.ttl.unwrap(), 100);
    }

    #[test]
    fn already_created() {
        let client = Client::new("http://etcd:2379").unwrap();

        assert!(client.create("/foo", "bar", None).is_ok());

        match client.create("/foo", "bar", None).err().unwrap() {
            Error::Etcd(error) => assert_eq!(error.message, "Key already exists".to_string()),
            _ => panic!("expected EtcdError due to pre-existing key"),
        };
    }
}

#[cfg(test)]
mod delete_tests {
    use super::Client;

    #[test]
    fn delete() {
        let client = Client::new("http://etcd:2379").unwrap();

        client.create("/foo", "bar", Some(100)).ok().unwrap();

        let response = client.delete("/foo", false).ok().unwrap();

        assert_eq!(response.action, "delete");
    }
}

#[cfg(test)]
mod mkdir_tests {
    use super::Client;

    #[test]
    fn mkdir() {
        let client = Client::default();

        assert!(client.mkdir("/foo", None).ok().unwrap().node.dir.unwrap());
    }

    #[test]
    fn mkdir_failure() {
        let client = Client::default();

        assert!(client.mkdir("/foo", None).is_ok());
        assert!(client.mkdir("/foo", None).is_err());
    }
}

#[cfg(test)]
mod get_tests {
    use super::Client;

    #[test]
    fn set_and_get_key() {
        let client = Client::default();

        assert!(client.set("/foo", "bar", None, None, None).is_ok());
        assert_eq!(client.get("/foo").ok().unwrap().node.value.unwrap(), "bar");
    }
}
<commit_msg>Remove unfinished code, compact all tests into one.<commit_after>use std::io::Read;

use hyper::status::StatusCode;
use rustc_serialize::json;
use url::{ParseError, Url};
use url::form_urlencoded::serialize_owned;

use error::Error;
use http;

#[derive(Debug)]
#[derive(RustcDecodable)]
pub struct Response {
    pub action: String,
    pub node: Node,
    pub prev_node: Option<Node>,
}

#[derive(Debug)]
#[derive(RustcDecodable)]
pub struct Node {
    pub created_index: Option<u64>,
    pub dir: Option<bool>,
    pub expiration: Option<String>,
    pub key: Option<String>,
    pub modified_index: Option<u64>,
    pub nodes: Option<Vec<Node>>,
    pub ttl: Option<i64>,
    pub value: Option<String>,
}

#[derive(Debug)]
pub struct Client {
    root_url: String,
}

impl Client {
    pub fn new(root_url: &str) -> Result<Client, ParseError> {
        let url = try!(Url::parse(root_url));
        let client = Client {
            root_url: format!("{}", url.serialize()),
        };

        Ok(client)
    }

    pub fn default() -> Client {
        Client {
            root_url: "http://127.0.0.1:2379/".to_string(),
        }
    }

    pub fn create(&self, key: &str, value: &str, ttl: Option<u64>) -> Result<Response, Error> {
        let url = self.build_url(key);
        let mut options = vec![];

        options.push(("value".to_string(), value.to_string()));
        options.push(("prevExist".to_string(), "false".to_string()));

        if ttl.is_some() {
            options.push(("ttl".to_string(), format!("{}", ttl.unwrap())));
        }

        let body = serialize_owned(&options);

        match http::put(url, body) {
            Ok(mut response) => {
                let mut response_body = String::new();

                response.read_to_string(&mut response_body).unwrap();

                println!("{:?} - {:?} - {:?}", response.status, response.headers, response_body);

                match response.status {
                    StatusCode::Created => Ok(json::decode(&response_body).unwrap()),
                    _ => Err(Error::Etcd(json::decode(&response_body).unwrap())),
                }
            },
            Err(error) => Err(Error::Http(error)),
        }
    }

    pub fn delete(&self, key: &str, recursive: bool) -> Result<Response, Error> {
        let url = self.build_url(key);
        let mut options = vec![];

        options.push(("recursive".to_string(), format!("{}", recursive)));

        let body = serialize_owned(&options);

        match http::delete(url, body) {
            Ok(mut response) => {
                let mut response_body = String::new();

                response.read_to_string(&mut response_body).unwrap();

                println!("{:?} - {:?} - {:?}", response.status, response.headers, response_body);

                match response.status {
                    StatusCode::Ok => Ok(json::decode(&response_body).unwrap()),
                    _ => Err(Error::Etcd(json::decode(&response_body).unwrap())),
                }
            },
            Err(error) => Err(Error::Http(error)),
        }
    }

    // private

    fn build_url(&self, path: &str) -> String {
        format!("{}v2/keys{}", self.root_url, path)
    }

}

#[cfg(test)]
mod client_tests {
    use super::Client;
    use error::Error;

    #[test]
    fn lifecycle() {
        let client = Client::new("http://etcd:2379").unwrap();

        // Create a key

        let create_response = client.create("/foo", "bar", Some(100)).ok().unwrap();

        assert_eq!(create_response.action, "create".to_string());
        assert_eq!(create_response.node.value.unwrap(), "bar".to_string());
        assert_eq!(create_response.node.ttl.unwrap(), 100);

        // Creating a key fails if it already exists

        match client.create("/foo", "bar", None).err().unwrap() {
            Error::Etcd(error) => assert_eq!(error.message, "Key already exists".to_string()),
            _ => panic!("expected EtcdError due to pre-existing key"),
        };

        // Deleting a key

        let delete_response = client.delete("/foo", false).ok().unwrap();

        assert_eq!(delete_response.action, "delete");
    }
}
<|endoftext|>


<commit_before><commit_msg>Avoid resetting camera when reloading the same scene<commit_after><|endoftext|>


<commit_before>use hb;
use std::ops::{Deref, DerefMut};
use std::borrow::Borrow;

/// A type to represent 4-byte SFNT tags.
///
/// Tables, features, etc. in OpenType and many other font formats use SFNT tags as identifiers.
/// These are 4-bytes long and usually each byte represents an ASCII value. `Tag` provides methods
/// to create such identifiers from individual `chars` or a `str` slice and to get the string
/// representation of a `Tag`.
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
pub struct Tag(pub hb::hb_tag_t);

impl Tag {
    /// Create a `Tag` from its four-char textual representation.
    ///
    /// # Examples
    ///
    /// ```
    /// use harfbuzz_rs::Tag;
    /// let cmap_tag = Tag::new('c', 'm', 'a', 'p');
    /// assert_eq!(cmap_tag.to_string(), "cmap")
    /// ```
    ///
    pub fn new(a: char, b: char, c: char, d: char) -> Self {
        Tag(((a as u32) << 24) | ((b as u32) << 16) | ((c as u32) << 8) | (d as u32))
    }

    fn tag_to_string(self) -> String {
        let mut buf: [u8; 4] = [0; 4];
        unsafe { hb::hb_tag_to_string(self.0, buf.as_mut_ptr() as *mut _) };
        String::from_utf8_lossy(&buf).into()
    }
}

use std::fmt;
use std::fmt::{Debug, Display, Formatter};
impl Debug for Tag {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let string = self.tag_to_string();
        let mut chars = string.chars().chain(std::iter::repeat('\u{FFFD}'));
        write!(
            f,
            "Tag({:?}, {:?}, {:?}, {:?})",
            chars.next().unwrap(),
            chars.next().unwrap(),
            chars.next().unwrap(),
            chars.next().unwrap()
        )
    }
}

impl Display for Tag {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}", self.tag_to_string())
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
/// An Error generated when a `Tag` fails to parse from a `&str` with the `from_str` function.
pub enum TagFromStrErr {
    /// The string contains non-ASCII characters.
    NonAscii,
    /// The string has length zero.
    ZeroLengthString,
}

use std;
use std::str::FromStr;

impl FromStr for Tag {
    type Err = TagFromStrErr;
    /// Parses a `Tag` from a `&str` that contains four or less ASCII characters. When the string's
    /// length is smaller than 4 it is extended with `' '` (Space) characters. The remaining bytes
    /// of strings longer than 4 bytes are ignored.
    ///
    /// # Examples
    ///
    /// ```
    /// use harfbuzz_rs::Tag;
    /// use std::str::FromStr;
    /// let tag1 = Tag::from_str("ABCD").unwrap();
    /// let tag2 = Tag::new('A', 'B', 'C', 'D');
    /// assert_eq!(tag1, tag2);
    /// ```
    ///
    fn from_str(s: &str) -> Result<Tag, TagFromStrErr> {
        if s.is_ascii() == false {
            return Err(TagFromStrErr::NonAscii);
        }
        if s.len() == 0 {
            return Err(TagFromStrErr::ZeroLengthString);
        }
        let len = std::cmp::max(s.len(), 4) as i32;
        unsafe { Ok(Tag(hb::hb_tag_from_string(s.as_ptr() as *mut _, len))) }
    }
}

pub struct Language(pub hb::hb_language_t);

impl Default for Language {
    fn default() -> Language {
        Language(unsafe { hb::hb_language_get_default() })
    }
}

impl Debug for Language {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "Language(\"{}\")", self)
    }
}

use std::ffi::CStr;
impl Display for Language {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let string = unsafe {
            let char_ptr = hb::hb_language_to_string(self.0);
            if char_ptr.is_null() {
                return Err(fmt::Error);
            }
            CStr::from_ptr(char_ptr)
                .to_str()
                .expect("String representation of language is not valid utf8.")
        };
        write!(f, "{}", string)
    }
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct InvalidLanguage;

impl FromStr for Language {
    type Err = InvalidLanguage;
    fn from_str(s: &str) -> Result<Language, InvalidLanguage> {
        let len = std::cmp::min(s.len(), std::i32::MAX as _) as i32;
        let lang = unsafe { hb::hb_language_from_string(s.as_ptr() as *mut _, len) };
        if lang.is_null() {
            Err(InvalidLanguage {})
        } else {
            Ok(Language(lang))
        }
    }
}

/// A trait which is implemented for all harffbuzz wrapper structs. It exposes common functionality
/// for converting from and to the underlying raw harfbuzz pointers that are useful for ffi.
pub trait HarfbuzzObject: Sized {
    /// Type of the raw harfbuzz object.
    type Raw;

    /// Creates a reference from a harfbuzz object pointer.
    ///
    /// Unsafe because a raw pointer may be accessed. The reference count is not changed. Should not
    /// be called directly by a library user.
    ///
    /// Use the Owned and Shared abstractions instead.
    unsafe fn from_raw<'a>(val: *const Self::Raw) -> &'a Self {
        &*(val as *const Self)
    }

    /// Creates a mutable reference from a harfbuzz object pointer.
    ///
    /// Unsafe because a raw pointer may be accessed. The reference count is not changed. Should not
    /// be called directly by a library user.
    ///
    /// Use the Owned and Shared abstractions instead.
    unsafe fn from_raw_mut<'a>(val: *mut Self::Raw) -> &'a mut Self {
        &mut *(val as *mut Self)
    }

    /// Returns the underlying harfbuzz object pointer.
    ///
    /// The caller must ensure, that this pointer is not used after `self`'s destruction.
    fn as_raw(&self) -> *mut Self::Raw {
        (((self as *const Self) as *mut Self) as *mut Self::Raw)
    }

    /// Increases the reference count of the HarfBuzz object.
    ///
    /// Wraps a `hb_TYPE_reference()` call.
    unsafe fn reference(&self);

    /// Decreases the reference count of the HarfBuzz object and destroys it if the reference count
    /// reaches zero.
    ///
    /// Wraps a `hb_TYPE_destroy()` call.
    unsafe fn dereference(&self);
}

/// A smart pointer that wraps an atomically reference counted HarfBuzz object.
///
/// Usually you don't create a `Shared` yourself, but get it from another function in this crate.
/// You can just use the methods of the wrapped object through its `Deref` implementation.
///
/// A `Shared` is a safe wrapper for reference counted HarfBuzz objects and provides shared immutable
/// access to its inner object. As HarfBuzz' objects are all thread-safe `Shared` implements `Send`
/// and `Sync`.
///
/// Tries to mirror the stdlib `Arc` interface where applicable as HarfBuzz' reference counting has
/// similar semantics.
#[derive(Debug, PartialEq, Eq)]
pub struct Shared<T: HarfbuzzObject> {
    pointer: *mut T::Raw,
}

impl<T: HarfbuzzObject> Shared<T> {
    /// Creates a `Shared` from a raw harfbuzz pointer.
    ///
    /// Transfers ownership. _Use of the original pointer is now forbidden!_ Unsafe because
    /// dereferencing a raw pointer is necessary.
    pub unsafe fn from_raw(raw: *mut T::Raw) -> Self {
        Shared { pointer: raw }
    }

    /// Converts `self` into the underlying harfbuzz object pointer value. The resulting pointer
    /// has to be manually destroyed using `hb_TYPE_destroy` or be converted back into the wrapper
    /// using the `from_raw` function to avoid leaking memory.
    pub fn into_raw(shared: Shared<T>) -> *mut T::Raw {
        let result = shared.pointer;
        std::mem::forget(shared);
        result
    }

    pub fn from_ref(reference: &T) -> Self {
        unsafe {
            reference.reference();
            Shared::from_raw(reference.as_raw())
        }
    }
}

impl<T: HarfbuzzObject> Clone for Shared<T> {
    fn clone(&self) -> Self {
        unsafe {
            self.reference();
            Self::from_raw(self.pointer)
        }
    }
}

impl<T: HarfbuzzObject> Deref for Shared<T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { T::from_raw(self.pointer) }
    }
}

impl<T: HarfbuzzObject> Borrow<T> for Shared<T> {
    fn borrow(&self) -> &T {
        self
    }
}

impl<T: HarfbuzzObject> From<Owned<T>> for Shared<T> {
    fn from(t: Owned<T>) -> Self {
        let ptr = t.pointer;
        std::mem::forget(t);
        unsafe { Shared::from_raw(ptr) }
    }
}

impl<T: HarfbuzzObject> Drop for Shared<T> {
    fn drop(&mut self) {
        unsafe { self.dereference() }
    }
}

unsafe impl<T: HarfbuzzObject + Sync + Send> Send for Shared<T> {}
unsafe impl<T: HarfbuzzObject + Sync + Send> Sync for Shared<T> {}

/// A smart pointer that wraps a singly owned harfbuzz object.
///
/// Usually you don't create a `Owned` yourself, but get it from another function in this crate.
/// You can just use the methods of the wrapped object through its `Deref` implementation.
///
/// A `Owned` is used to wrap freshly created owned HarfBuzz objects. It permits mutable, non-shared
/// access to the enclosed HarfBuzz value so it can be used e.g. to set up a `Font` or `Face` after
/// its creation.
///
/// When you are finished mutating the inner value, you usually want to pass it to other HarfBuzz
/// functions that expect shared access. Thus you need to convert the `Owned` to a `Shared` pointer
/// using `.into()`. Note however that once a value is
/// converted to  a `Shared<T>`, it will not possible to mutate it anymore.
#[derive(Debug, PartialEq, Eq)]
pub struct Owned<T: HarfbuzzObject> {
    pointer: *mut T::Raw,
}

impl<T: HarfbuzzObject> Owned<T> {
    /// Creates a `Owned` safely wrapping a raw harfbuzz pointer.
    ///
    /// This fully transfers ownership. _Use of the original pointer is now forbidden!_ Unsafe
    /// because a dereference of a raw pointer is necessary.
    ///
    /// Use this only to wrap freshly created HarfBuzz object that is not shared!
    pub unsafe fn from_raw(raw: *mut T::Raw) -> Self {
        Owned { pointer: raw }
    }

    /// Converts `self` into the underlying harfbuzz object pointer value. The resulting pointer
    /// has to be manually destroyed using `hb_TYPE_destroy` or be converted back into the wrapper
    /// using the `from_raw` function to avoid leaking memory.
    pub fn into_raw(owned: Owned<T>) -> *mut T::Raw {
        let result = owned.pointer;
        std::mem::forget(owned);
        result
    }
}

impl<T: HarfbuzzObject> Drop for Owned<T> {
    fn drop(&mut self) {
        unsafe { self.dereference() }
    }
}

impl<T: HarfbuzzObject> Deref for Owned<T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { T::from_raw(self.pointer) }
    }
}

impl<T: HarfbuzzObject> DerefMut for Owned<T> {
    fn deref_mut(&mut self) -> &mut T {
        unsafe { T::from_raw_mut(self.pointer) }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::str::FromStr;
    use std::rc::Rc;
    use std::cell::Cell;
    use std::mem;

    #[test]
    fn test_tag_debugging() {
        let tag = Tag::from_str("ABCD").unwrap();
        assert_eq!("ABCD", format!("{}", tag));
        assert_eq!("Tag('A', 'B', 'C', 'D')", format!("{:?}", tag));
    }

    #[test]
    fn test_tag_creation() {
        assert!(Tag::from_str("∞BCD").is_err());
        assert!(Tag::from_str("").is_err());
        assert_eq!(Tag::from_str("ABCDE"), Tag::from_str("ABCD"));
        assert_eq!(Tag::from_str("abWd").unwrap(), Tag::new('a', 'b', 'W', 'd'));
    }

    #[test]
    fn test_language() {
        assert_eq!(Language::default().to_string(), "c");
        assert_eq!(Language::from_str("ger").unwrap().to_string(), "ger");
        assert_eq!(Language::from_str("ge!").unwrap().to_string(), "ge");
        assert_eq!(Language::from_str("German").unwrap().to_string(), "german");
    }

    #[derive(Debug)]
    struct ReferenceCounter {
        rc: Cell<isize>,
    }

    impl HarfbuzzObject for ReferenceCounter {
        type Raw = Cell<isize>;

        unsafe fn reference(&self) {
            println!("referencing {:?}", self);
            let rc = self.rc.get();
            self.rc.set(rc + 1);
        }

        unsafe fn dereference(&self) {
            println!("dereferencing {:?}", self);
            let rc = self.rc.get();
            self.rc.set(rc - 1);
        }
    }

    #[test]
    fn reference_counting_shared() {
        // Mimic a C-API that returns a pointer to a reference counted value.
        let object = Rc::new(ReferenceCounter { rc: Cell::new(1) });
        let raw = Rc::into_raw(object.clone()) as *mut _;

        let arc: Shared<ReferenceCounter> = unsafe { Shared::from_raw(raw) };
        assert_eq!(object.rc.get(), 1);
        {
            let arc2 = Shared::clone(&arc);
            assert_eq!(object.rc.get(), 2);
            mem::drop(arc2);
        }
        assert_eq!(object.rc.get(), 1);
        mem::drop(arc);
        assert_eq!(object.rc.get(), 0);

        // don't leak memory
        let _ = unsafe { Rc::from_raw(raw) };
    }
}
<commit_msg>Improve docs<commit_after>use hb;
use std::ops::{Deref, DerefMut};
use std::borrow::Borrow;

/// A type to represent 4-byte SFNT tags.
///
/// Tables, features, etc. in OpenType and many other font formats use SFNT tags as identifiers.
/// These are 4-bytes long and usually each byte represents an ASCII value. `Tag` provides methods
/// to create such identifiers from individual `chars` or a `str` slice and to get the string
/// representation of a `Tag`.
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
pub struct Tag(pub hb::hb_tag_t);

impl Tag {
    /// Create a `Tag` from its four-char textual representation.
    ///
    /// # Examples
    ///
    /// ```
    /// use harfbuzz_rs::Tag;
    /// let cmap_tag = Tag::new('c', 'm', 'a', 'p');
    /// assert_eq!(cmap_tag.to_string(), "cmap")
    /// ```
    ///
    pub fn new(a: char, b: char, c: char, d: char) -> Self {
        Tag(((a as u32) << 24) | ((b as u32) << 16) | ((c as u32) << 8) | (d as u32))
    }

    fn tag_to_string(self) -> String {
        let mut buf: [u8; 4] = [0; 4];
        unsafe { hb::hb_tag_to_string(self.0, buf.as_mut_ptr() as *mut _) };
        String::from_utf8_lossy(&buf).into()
    }
}

use std::fmt;
use std::fmt::{Debug, Display, Formatter};
impl Debug for Tag {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let string = self.tag_to_string();
        let mut chars = string.chars().chain(std::iter::repeat('\u{FFFD}'));
        write!(
            f,
            "Tag({:?}, {:?}, {:?}, {:?})",
            chars.next().unwrap(),
            chars.next().unwrap(),
            chars.next().unwrap(),
            chars.next().unwrap()
        )
    }
}

impl Display for Tag {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}", self.tag_to_string())
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
/// An Error generated when a `Tag` fails to parse from a `&str` with the `from_str` function.
pub enum TagFromStrErr {
    /// The string contains non-ASCII characters.
    NonAscii,
    /// The string has length zero.
    ZeroLengthString,
}

use std;
use std::str::FromStr;

impl FromStr for Tag {
    type Err = TagFromStrErr;
    /// Parses a `Tag` from a `&str` that contains four or less ASCII characters. When the string's
    /// length is smaller than 4 it is extended with `' '` (Space) characters. The remaining bytes
    /// of strings longer than 4 bytes are ignored.
    ///
    /// # Examples
    ///
    /// ```
    /// use harfbuzz_rs::Tag;
    /// use std::str::FromStr;
    /// let tag1 = Tag::from_str("ABCD").unwrap();
    /// let tag2 = Tag::new('A', 'B', 'C', 'D');
    /// assert_eq!(tag1, tag2);
    /// ```
    ///
    fn from_str(s: &str) -> Result<Tag, TagFromStrErr> {
        if s.is_ascii() == false {
            return Err(TagFromStrErr::NonAscii);
        }
        if s.len() == 0 {
            return Err(TagFromStrErr::ZeroLengthString);
        }
        let len = std::cmp::max(s.len(), 4) as i32;
        unsafe { Ok(Tag(hb::hb_tag_from_string(s.as_ptr() as *mut _, len))) }
    }
}

pub struct Language(pub hb::hb_language_t);

impl Default for Language {
    fn default() -> Language {
        Language(unsafe { hb::hb_language_get_default() })
    }
}

impl Debug for Language {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "Language(\"{}\")", self)
    }
}

use std::ffi::CStr;
impl Display for Language {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let string = unsafe {
            let char_ptr = hb::hb_language_to_string(self.0);
            if char_ptr.is_null() {
                return Err(fmt::Error);
            }
            CStr::from_ptr(char_ptr)
                .to_str()
                .expect("String representation of language is not valid utf8.")
        };
        write!(f, "{}", string)
    }
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct InvalidLanguage;

impl FromStr for Language {
    type Err = InvalidLanguage;
    fn from_str(s: &str) -> Result<Language, InvalidLanguage> {
        let len = std::cmp::min(s.len(), std::i32::MAX as _) as i32;
        let lang = unsafe { hb::hb_language_from_string(s.as_ptr() as *mut _, len) };
        if lang.is_null() {
            Err(InvalidLanguage {})
        } else {
            Ok(Language(lang))
        }
    }
}

/// A trait which is implemented for all harffbuzz wrapper structs. It exposes common functionality
/// for converting from and to the underlying raw harfbuzz pointers that are useful for ffi.
pub trait HarfbuzzObject: Sized {
    /// Type of the raw harfbuzz object.
    type Raw;

    /// Creates a reference from a harfbuzz object pointer.
    ///
    /// Unsafe because a raw pointer may be accessed. The reference count is not changed. Should not
    /// be called directly by a library user.
    ///
    /// Use the Owned and Shared abstractions instead.
    unsafe fn from_raw<'a>(val: *const Self::Raw) -> &'a Self {
        &*(val as *const Self)
    }

    /// Creates a mutable reference from a harfbuzz object pointer.
    ///
    /// Unsafe because a raw pointer may be accessed. The reference count is not changed. Should not
    /// be called directly by a library user.
    ///
    /// Use the Owned and Shared abstractions instead.
    unsafe fn from_raw_mut<'a>(val: *mut Self::Raw) -> &'a mut Self {
        &mut *(val as *mut Self)
    }

    /// Returns the underlying harfbuzz object pointer.
    ///
    /// The caller must ensure, that this pointer is not used after `self`'s destruction.
    fn as_raw(&self) -> *mut Self::Raw {
        (((self as *const Self) as *mut Self) as *mut Self::Raw)
    }

    /// Increases the reference count of the HarfBuzz object.
    ///
    /// Wraps a `hb_TYPE_reference()` call.
    unsafe fn reference(&self);

    /// Decreases the reference count of the HarfBuzz object and destroys it if the reference count
    /// reaches zero.
    ///
    /// Wraps a `hb_TYPE_destroy()` call.
    unsafe fn dereference(&self);
}

/// A smart pointer that wraps an atomically reference counted HarfBuzz object.
///
/// Usually you don't create a `Shared` yourself, but get it from another function in this crate.
/// You can just use the methods of the wrapped object through its `Deref` implementation.
///
/// A `Shared` is a safe wrapper for reference counted HarfBuzz objects and provides shared immutable
/// access to its inner object. As HarfBuzz' objects are all thread-safe `Shared` implements `Send`
/// and `Sync`.
///
/// Tries to mirror the stdlib `Arc` interface where applicable as HarfBuzz' reference counting has
/// similar semantics.
#[derive(Debug, PartialEq, Eq)]
pub struct Shared<T: HarfbuzzObject> {
    pointer: *mut T::Raw,
}

impl<T: HarfbuzzObject> Shared<T> {
    /// Creates a `Shared` from a raw harfbuzz pointer.
    ///
    /// Transfers ownership. _Use of the original pointer is now forbidden!_ Unsafe because
    /// dereferencing a raw pointer is necessary.
    pub unsafe fn from_raw(raw: *mut T::Raw) -> Self {
        Shared { pointer: raw }
    }

    /// Converts `self` into the underlying harfbuzz object pointer value. The resulting pointer
    /// has to be manually destroyed using `hb_TYPE_destroy` or be converted back into the wrapper
    /// using the `from_raw` function to avoid leaking memory.
    pub fn into_raw(shared: Shared<T>) -> *mut T::Raw {
        let result = shared.pointer;
        std::mem::forget(shared);
        result
    }

    pub fn from_ref(reference: &T) -> Self {
        unsafe {
            reference.reference();
            Shared::from_raw(reference.as_raw())
        }
    }
}

impl<T: HarfbuzzObject> Clone for Shared<T> {
    fn clone(&self) -> Self {
        unsafe {
            self.reference();
            Self::from_raw(self.pointer)
        }
    }
}

impl<T: HarfbuzzObject> Deref for Shared<T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { T::from_raw(self.pointer) }
    }
}

impl<T: HarfbuzzObject> Borrow<T> for Shared<T> {
    fn borrow(&self) -> &T {
        self
    }
}

impl<T: HarfbuzzObject> From<Owned<T>> for Shared<T> {
    fn from(t: Owned<T>) -> Self {
        let ptr = t.pointer;
        std::mem::forget(t);
        unsafe { Shared::from_raw(ptr) }
    }
}

impl<T: HarfbuzzObject> Drop for Shared<T> {
    fn drop(&mut self) {
        unsafe { self.dereference() }
    }
}

unsafe impl<T: HarfbuzzObject + Sync + Send> Send for Shared<T> {}
unsafe impl<T: HarfbuzzObject + Sync + Send> Sync for Shared<T> {}

/// A smart pointer that wraps a singly owned harfbuzz object.
///
/// A `Owned` is used to wrap freshly created owned HarfBuzz objects. It permits mutable, non-shared
/// access to the enclosed HarfBuzz value so it can be used e.g. to set up a `Font` or `Face` after
/// its creation.
///
/// There is no safe way to construct an `Owned` pointer and usually you don't need to create a
/// `Owned` yourself, but get it from another function in this crate.
/// You can just use the methods of the wrapped object through its `Deref` implementation.
///
/// Interaction with `Shared`
/// -------------------------
/// When you are finished mutating the inner value, you usually want to pass it to other HarfBuzz
/// functions that expect shared access. Thus you need to convert the `Owned` to a `Shared` pointer
/// using `.into()`. Note however that once a value is
/// converted to  a `Shared<T>`, it will not possible to mutate it anymore.
#[derive(Debug, PartialEq, Eq)]
pub struct Owned<T: HarfbuzzObject> {
    pointer: *mut T::Raw,
}

impl<T: HarfbuzzObject> Owned<T> {
    /// Creates a `Owned` safely wrapping a raw harfbuzz pointer.
    ///
    /// This fully transfers ownership. _Use of the original pointer is now forbidden!_ Unsafe
    /// because a dereference of a raw pointer is necessary.
    ///
    /// Use this only to wrap freshly created HarfBuzz object that is not shared!
    pub unsafe fn from_raw(raw: *mut T::Raw) -> Self {
        Owned { pointer: raw }
    }

    /// Converts `self` into the underlying harfbuzz object pointer value. The resulting pointer
    /// has to be manually destroyed using `hb_TYPE_destroy` or be converted back into the wrapper
    /// using the `from_raw` function to avoid leaking memory.
    pub fn into_raw(owned: Owned<T>) -> *mut T::Raw {
        let result = owned.pointer;
        std::mem::forget(owned);
        result
    }
}

impl<T: HarfbuzzObject> Drop for Owned<T> {
    fn drop(&mut self) {
        unsafe { self.dereference() }
    }
}

impl<T: HarfbuzzObject> Deref for Owned<T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { T::from_raw(self.pointer) }
    }
}

impl<T: HarfbuzzObject> DerefMut for Owned<T> {
    fn deref_mut(&mut self) -> &mut T {
        unsafe { T::from_raw_mut(self.pointer) }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::str::FromStr;
    use std::rc::Rc;
    use std::cell::Cell;
    use std::mem;

    #[test]
    fn test_tag_debugging() {
        let tag = Tag::from_str("ABCD").unwrap();
        assert_eq!("ABCD", format!("{}", tag));
        assert_eq!("Tag('A', 'B', 'C', 'D')", format!("{:?}", tag));
    }

    #[test]
    fn test_tag_creation() {
        assert!(Tag::from_str("∞BCD").is_err());
        assert!(Tag::from_str("").is_err());
        assert_eq!(Tag::from_str("ABCDE"), Tag::from_str("ABCD"));
        assert_eq!(Tag::from_str("abWd").unwrap(), Tag::new('a', 'b', 'W', 'd'));
    }

    #[test]
    fn test_language() {
        assert_eq!(Language::default().to_string(), "c");
        assert_eq!(Language::from_str("ger").unwrap().to_string(), "ger");
        assert_eq!(Language::from_str("ge!").unwrap().to_string(), "ge");
        assert_eq!(Language::from_str("German").unwrap().to_string(), "german");
    }

    #[derive(Debug)]
    struct ReferenceCounter {
        rc: Cell<isize>,
    }

    impl HarfbuzzObject for ReferenceCounter {
        type Raw = Cell<isize>;

        unsafe fn reference(&self) {
            println!("referencing {:?}", self);
            let rc = self.rc.get();
            self.rc.set(rc + 1);
        }

        unsafe fn dereference(&self) {
            println!("dereferencing {:?}", self);
            let rc = self.rc.get();
            self.rc.set(rc - 1);
        }
    }

    #[test]
    fn reference_counting_shared() {
        // Mimic a C-API that returns a pointer to a reference counted value.
        let object = Rc::new(ReferenceCounter { rc: Cell::new(1) });
        let raw = Rc::into_raw(object.clone()) as *mut _;

        let arc: Shared<ReferenceCounter> = unsafe { Shared::from_raw(raw) };
        assert_eq!(object.rc.get(), 1);
        {
            let arc2 = Shared::clone(&arc);
            assert_eq!(object.rc.get(), 2);
            mem::drop(arc2);
        }
        assert_eq!(object.rc.get(), 1);
        mem::drop(arc);
        assert_eq!(object.rc.get(), 0);

        // don't leak memory
        let _ = unsafe { Rc::from_raw(raw) };
    }
}
<|endoftext|>


<commit_before>#![feature(never_type)]
#![feature(const_panic)]
#![feature(control_flow_enum)]

#[macro_use]
extern crate bitflags;

use rustc_data_structures::stable_hasher::{HashStable, StableHasher};

bitflags! {
    /// Flags that we track on types. These flags are propagated upwards
    /// through the type during type construction, so that we can quickly check
    /// whether the type has various kinds of types in it without recursing
    /// over the type itself.
    pub struct TypeFlags: u32 {
        // Does this have parameters? Used to determine whether substitution is
        // required.
        /// Does this have `Param`?
        const HAS_TY_PARAM                = 1 << 0;
        /// Does this have `ReEarlyBound`?
        const HAS_RE_PARAM                = 1 << 1;
        /// Does this have `ConstKind::Param`?
        const HAS_CT_PARAM                = 1 << 2;

        const NEEDS_SUBST                 = TypeFlags::HAS_TY_PARAM.bits
                                          | TypeFlags::HAS_RE_PARAM.bits
                                          | TypeFlags::HAS_CT_PARAM.bits;

        /// Does this have `Infer`?
        const HAS_TY_INFER                = 1 << 3;
        /// Does this have `ReVar`?
        const HAS_RE_INFER                = 1 << 4;
        /// Does this have `ConstKind::Infer`?
        const HAS_CT_INFER                = 1 << 5;

        /// Does this have inference variables? Used to determine whether
        /// inference is required.
        const NEEDS_INFER                 = TypeFlags::HAS_TY_INFER.bits
                                          | TypeFlags::HAS_RE_INFER.bits
                                          | TypeFlags::HAS_CT_INFER.bits;

        /// Does this have `Placeholder`?
        const HAS_TY_PLACEHOLDER          = 1 << 6;
        /// Does this have `RePlaceholder`?
        const HAS_RE_PLACEHOLDER          = 1 << 7;
        /// Does this have `ConstKind::Placeholder`?
        const HAS_CT_PLACEHOLDER          = 1 << 8;

        /// `true` if there are "names" of regions and so forth
        /// that are local to a particular fn/inferctxt
        const HAS_FREE_LOCAL_REGIONS      = 1 << 9;

        /// `true` if there are "names" of types and regions and so forth
        /// that are local to a particular fn
        const HAS_FREE_LOCAL_NAMES        = TypeFlags::HAS_TY_PARAM.bits
                                          | TypeFlags::HAS_CT_PARAM.bits
                                          | TypeFlags::HAS_TY_INFER.bits
                                          | TypeFlags::HAS_CT_INFER.bits
                                          | TypeFlags::HAS_TY_PLACEHOLDER.bits
                                          | TypeFlags::HAS_CT_PLACEHOLDER.bits
                                          | TypeFlags::HAS_FREE_LOCAL_REGIONS.bits;

        /// Does this have `Projection`?
        const HAS_TY_PROJECTION           = 1 << 10;
        /// Does this have `Opaque`?
        const HAS_TY_OPAQUE               = 1 << 11;
        /// Does this have `ConstKind::Unevaluated`?
        const HAS_CT_PROJECTION           = 1 << 12;

        /// Could this type be normalized further?
        const HAS_PROJECTION              = TypeFlags::HAS_TY_PROJECTION.bits
                                          | TypeFlags::HAS_TY_OPAQUE.bits
                                          | TypeFlags::HAS_CT_PROJECTION.bits;

        /// Is an error type/const reachable?
        const HAS_ERROR                   = 1 << 13;

        /// Does this have any region that "appears free" in the type?
        /// Basically anything but `ReLateBound` and `ReErased`.
        const HAS_FREE_REGIONS            = 1 << 14;

        /// Does this have any `ReLateBound` regions? Used to check
        /// if a global bound is safe to evaluate.
        const HAS_RE_LATE_BOUND           = 1 << 15;

        /// Does this have any `ReErased` regions?
        const HAS_RE_ERASED               = 1 << 16;

        /// Does this value have parameters/placeholders/inference variables which could be
        /// replaced later, in a way that would change the results of `impl` specialization?
        const STILL_FURTHER_SPECIALIZABLE = 1 << 17;
    }
}

rustc_index::newtype_index! {
    /// A [De Bruijn index][dbi] is a standard means of representing
    /// regions (and perhaps later types) in a higher-ranked setting. In
    /// particular, imagine a type like this:
    ///
    ///     for<'a> fn(for<'b> fn(&'b isize, &'a isize), &'a char)
    ///     ^          ^            |          |           |
    ///     |          |            |          |           |
    ///     |          +------------+ 0        |           |
    ///     |                                  |           |
    ///     +----------------------------------+ 1         |
    ///     |                                              |
    ///     +----------------------------------------------+ 0
    ///
    /// In this type, there are two binders (the outer fn and the inner
    /// fn). We need to be able to determine, for any given region, which
    /// fn type it is bound by, the inner or the outer one. There are
    /// various ways you can do this, but a De Bruijn index is one of the
    /// more convenient and has some nice properties. The basic idea is to
    /// count the number of binders, inside out. Some examples should help
    /// clarify what I mean.
    ///
    /// Let's start with the reference type `&'b isize` that is the first
    /// argument to the inner function. This region `'b` is assigned a De
    /// Bruijn index of 0, meaning "the innermost binder" (in this case, a
    /// fn). The region `'a` that appears in the second argument type (`&'a
    /// isize`) would then be assigned a De Bruijn index of 1, meaning "the
    /// second-innermost binder". (These indices are written on the arrays
    /// in the diagram).
    ///
    /// What is interesting is that De Bruijn index attached to a particular
    /// variable will vary depending on where it appears. For example,
    /// the final type `&'a char` also refers to the region `'a` declared on
    /// the outermost fn. But this time, this reference is not nested within
    /// any other binders (i.e., it is not an argument to the inner fn, but
    /// rather the outer one). Therefore, in this case, it is assigned a
    /// De Bruijn index of 0, because the innermost binder in that location
    /// is the outer fn.
    ///
    /// [dbi]: https://en.wikipedia.org/wiki/De_Bruijn_index
    pub struct DebruijnIndex {
        DEBUG_FORMAT = "DebruijnIndex({})",
        const INNERMOST = 0,
    }
}

impl DebruijnIndex {
    /// Returns the resulting index when this value is moved into
    /// `amount` number of new binders. So, e.g., if you had
    ///
    ///    for<'a> fn(&'a x)
    ///
    /// and you wanted to change it to
    ///
    ///    for<'a> fn(for<'b> fn(&'a x))
    ///
    /// you would need to shift the index for `'a` into a new binder.
    #[must_use]
    pub fn shifted_in(self, amount: u32) -> DebruijnIndex {
        DebruijnIndex::from_u32(self.as_u32() + amount)
    }

    /// Update this index in place by shifting it "in" through
    /// `amount` number of binders.
    pub fn shift_in(&mut self, amount: u32) {
        *self = self.shifted_in(amount);
    }

    /// Returns the resulting index when this value is moved out from
    /// `amount` number of new binders.
    #[must_use]
    pub fn shifted_out(self, amount: u32) -> DebruijnIndex {
        DebruijnIndex::from_u32(self.as_u32() - amount)
    }

    /// Update in place by shifting out from `amount` binders.
    pub fn shift_out(&mut self, amount: u32) {
        *self = self.shifted_out(amount);
    }

    /// Adjusts any De Bruijn indices so as to make `to_binder` the
    /// innermost binder. That is, if we have something bound at `to_binder`,
    /// it will now be bound at INNERMOST. This is an appropriate thing to do
    /// when moving a region out from inside binders:
    ///
    /// ```
    ///             for<'a>   fn(for<'b>   for<'c>   fn(&'a u32), _)
    /// // Binder:  D3           D2        D1            ^^
    /// ```
    ///
    /// Here, the region `'a` would have the De Bruijn index D3,
    /// because it is the bound 3 binders out. However, if we wanted
    /// to refer to that region `'a` in the second argument (the `_`),
    /// those two binders would not be in scope. In that case, we
    /// might invoke `shift_out_to_binder(D3)`. This would adjust the
    /// De Bruijn index of `'a` to D1 (the innermost binder).
    ///
    /// If we invoke `shift_out_to_binder` and the region is in fact
    /// bound by one of the binders we are shifting out of, that is an
    /// error (and should fail an assertion failure).
    pub fn shifted_out_to_binder(self, to_binder: DebruijnIndex) -> Self {
        self.shifted_out(to_binder.as_u32() - INNERMOST.as_u32())
    }
}

impl<CTX> HashStable<CTX> for DebruijnIndex {
    fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
        self.as_u32().hash_stable(ctx, hasher);
    }
}
<commit_msg>Fix typo in `DebruijnIndex` documentation<commit_after>#![feature(never_type)]
#![feature(const_panic)]
#![feature(control_flow_enum)]

#[macro_use]
extern crate bitflags;

use rustc_data_structures::stable_hasher::{HashStable, StableHasher};

bitflags! {
    /// Flags that we track on types. These flags are propagated upwards
    /// through the type during type construction, so that we can quickly check
    /// whether the type has various kinds of types in it without recursing
    /// over the type itself.
    pub struct TypeFlags: u32 {
        // Does this have parameters? Used to determine whether substitution is
        // required.
        /// Does this have `Param`?
        const HAS_TY_PARAM                = 1 << 0;
        /// Does this have `ReEarlyBound`?
        const HAS_RE_PARAM                = 1 << 1;
        /// Does this have `ConstKind::Param`?
        const HAS_CT_PARAM                = 1 << 2;

        const NEEDS_SUBST                 = TypeFlags::HAS_TY_PARAM.bits
                                          | TypeFlags::HAS_RE_PARAM.bits
                                          | TypeFlags::HAS_CT_PARAM.bits;

        /// Does this have `Infer`?
        const HAS_TY_INFER                = 1 << 3;
        /// Does this have `ReVar`?
        const HAS_RE_INFER                = 1 << 4;
        /// Does this have `ConstKind::Infer`?
        const HAS_CT_INFER                = 1 << 5;

        /// Does this have inference variables? Used to determine whether
        /// inference is required.
        const NEEDS_INFER                 = TypeFlags::HAS_TY_INFER.bits
                                          | TypeFlags::HAS_RE_INFER.bits
                                          | TypeFlags::HAS_CT_INFER.bits;

        /// Does this have `Placeholder`?
        const HAS_TY_PLACEHOLDER          = 1 << 6;
        /// Does this have `RePlaceholder`?
        const HAS_RE_PLACEHOLDER          = 1 << 7;
        /// Does this have `ConstKind::Placeholder`?
        const HAS_CT_PLACEHOLDER          = 1 << 8;

        /// `true` if there are "names" of regions and so forth
        /// that are local to a particular fn/inferctxt
        const HAS_FREE_LOCAL_REGIONS      = 1 << 9;

        /// `true` if there are "names" of types and regions and so forth
        /// that are local to a particular fn
        const HAS_FREE_LOCAL_NAMES        = TypeFlags::HAS_TY_PARAM.bits
                                          | TypeFlags::HAS_CT_PARAM.bits
                                          | TypeFlags::HAS_TY_INFER.bits
                                          | TypeFlags::HAS_CT_INFER.bits
                                          | TypeFlags::HAS_TY_PLACEHOLDER.bits
                                          | TypeFlags::HAS_CT_PLACEHOLDER.bits
                                          | TypeFlags::HAS_FREE_LOCAL_REGIONS.bits;

        /// Does this have `Projection`?
        const HAS_TY_PROJECTION           = 1 << 10;
        /// Does this have `Opaque`?
        const HAS_TY_OPAQUE               = 1 << 11;
        /// Does this have `ConstKind::Unevaluated`?
        const HAS_CT_PROJECTION           = 1 << 12;

        /// Could this type be normalized further?
        const HAS_PROJECTION              = TypeFlags::HAS_TY_PROJECTION.bits
                                          | TypeFlags::HAS_TY_OPAQUE.bits
                                          | TypeFlags::HAS_CT_PROJECTION.bits;

        /// Is an error type/const reachable?
        const HAS_ERROR                   = 1 << 13;

        /// Does this have any region that "appears free" in the type?
        /// Basically anything but `ReLateBound` and `ReErased`.
        const HAS_FREE_REGIONS            = 1 << 14;

        /// Does this have any `ReLateBound` regions? Used to check
        /// if a global bound is safe to evaluate.
        const HAS_RE_LATE_BOUND           = 1 << 15;

        /// Does this have any `ReErased` regions?
        const HAS_RE_ERASED               = 1 << 16;

        /// Does this value have parameters/placeholders/inference variables which could be
        /// replaced later, in a way that would change the results of `impl` specialization?
        const STILL_FURTHER_SPECIALIZABLE = 1 << 17;
    }
}

rustc_index::newtype_index! {
    /// A [De Bruijn index][dbi] is a standard means of representing
    /// regions (and perhaps later types) in a higher-ranked setting. In
    /// particular, imagine a type like this:
    ///
    ///     for<'a> fn(for<'b> fn(&'b isize, &'a isize), &'a char)
    ///     ^          ^            |          |           |
    ///     |          |            |          |           |
    ///     |          +------------+ 0        |           |
    ///     |                                  |           |
    ///     +----------------------------------+ 1         |
    ///     |                                              |
    ///     +----------------------------------------------+ 0
    ///
    /// In this type, there are two binders (the outer fn and the inner
    /// fn). We need to be able to determine, for any given region, which
    /// fn type it is bound by, the inner or the outer one. There are
    /// various ways you can do this, but a De Bruijn index is one of the
    /// more convenient and has some nice properties. The basic idea is to
    /// count the number of binders, inside out. Some examples should help
    /// clarify what I mean.
    ///
    /// Let's start with the reference type `&'b isize` that is the first
    /// argument to the inner function. This region `'b` is assigned a De
    /// Bruijn index of 0, meaning "the innermost binder" (in this case, a
    /// fn). The region `'a` that appears in the second argument type (`&'a
    /// isize`) would then be assigned a De Bruijn index of 1, meaning "the
    /// second-innermost binder". (These indices are written on the arrows
    /// in the diagram).
    ///
    /// What is interesting is that De Bruijn index attached to a particular
    /// variable will vary depending on where it appears. For example,
    /// the final type `&'a char` also refers to the region `'a` declared on
    /// the outermost fn. But this time, this reference is not nested within
    /// any other binders (i.e., it is not an argument to the inner fn, but
    /// rather the outer one). Therefore, in this case, it is assigned a
    /// De Bruijn index of 0, because the innermost binder in that location
    /// is the outer fn.
    ///
    /// [dbi]: https://en.wikipedia.org/wiki/De_Bruijn_index
    pub struct DebruijnIndex {
        DEBUG_FORMAT = "DebruijnIndex({})",
        const INNERMOST = 0,
    }
}

impl DebruijnIndex {
    /// Returns the resulting index when this value is moved into
    /// `amount` number of new binders. So, e.g., if you had
    ///
    ///    for<'a> fn(&'a x)
    ///
    /// and you wanted to change it to
    ///
    ///    for<'a> fn(for<'b> fn(&'a x))
    ///
    /// you would need to shift the index for `'a` into a new binder.
    #[must_use]
    pub fn shifted_in(self, amount: u32) -> DebruijnIndex {
        DebruijnIndex::from_u32(self.as_u32() + amount)
    }

    /// Update this index in place by shifting it "in" through
    /// `amount` number of binders.
    pub fn shift_in(&mut self, amount: u32) {
        *self = self.shifted_in(amount);
    }

    /// Returns the resulting index when this value is moved out from
    /// `amount` number of new binders.
    #[must_use]
    pub fn shifted_out(self, amount: u32) -> DebruijnIndex {
        DebruijnIndex::from_u32(self.as_u32() - amount)
    }

    /// Update in place by shifting out from `amount` binders.
    pub fn shift_out(&mut self, amount: u32) {
        *self = self.shifted_out(amount);
    }

    /// Adjusts any De Bruijn indices so as to make `to_binder` the
    /// innermost binder. That is, if we have something bound at `to_binder`,
    /// it will now be bound at INNERMOST. This is an appropriate thing to do
    /// when moving a region out from inside binders:
    ///
    /// ```
    ///             for<'a>   fn(for<'b>   for<'c>   fn(&'a u32), _)
    /// // Binder:  D3           D2        D1            ^^
    /// ```
    ///
    /// Here, the region `'a` would have the De Bruijn index D3,
    /// because it is the bound 3 binders out. However, if we wanted
    /// to refer to that region `'a` in the second argument (the `_`),
    /// those two binders would not be in scope. In that case, we
    /// might invoke `shift_out_to_binder(D3)`. This would adjust the
    /// De Bruijn index of `'a` to D1 (the innermost binder).
    ///
    /// If we invoke `shift_out_to_binder` and the region is in fact
    /// bound by one of the binders we are shifting out of, that is an
    /// error (and should fail an assertion failure).
    pub fn shifted_out_to_binder(self, to_binder: DebruijnIndex) -> Self {
        self.shifted_out(to_binder.as_u32() - INNERMOST.as_u32())
    }
}

impl<CTX> HashStable<CTX> for DebruijnIndex {
    fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
        self.as_u32().hash_stable(ctx, hasher);
    }
}
<|endoftext|>