<commit_before>//! Provides a Quaternion type for properly interpolating rotations

use std::f32;
use std::ops::{Add, Sub, Mul, Div};

use linalg::{self, Vector, Transform, Matrix4};

/// Quaternions describe a rotation in 3d space but can be
/// properly interpolated unlike rotation matrices. The quaternion
/// also provides methods to compute the corresponding rotation
/// transform so that it can be composed with scaling and translation
#[derive(Debug, Copy, Clone)]
pub struct Quaternion {
    pub v: Vector,
    pub w: f32,
}

impl Quaternion {
    /// Construct an identity quaternion
    pub fn identity() -> Quaternion {
        Quaternion { v: Vector::broadcast(0.0), w: 1.0 }
    }
    /// Construct a quaternion from the rotation matrix
    /// Based on Shoemake 1991
    pub fn from_matrix(m: &Matrix4) -> Quaternion {
        let trace = *m.at(0, 0) + *m.at(1, 1) + *m.at(2, 2);
        if trace > 0.0 {
            // Compute w from matrix trace, then the vector
            let mut s = f32::sqrt(trace + 1.0);
            let w = s / 2.0;
            s = 0.5 / s;
            Quaternion { v: Vector::new(s * (*m.at(2, 1) - *m.at(1, 2)), s * (*m.at(0, 2) - *m.at(2, 0)),
                                        s * (*m.at(1, 0) - *m.at(0, 1))),
                         w: w
            }
        } else {
            // Compute largest of x, y or z then the remaining components
            let next = [1, 2, 0];
            let mut q = Vector::broadcast(0.0);
            let mut i = 0;
            if *m.at(1, 1) > *m.at(0, 0) {
                i = 1;
            }
            if *m.at(2, 2) > *m.at(i, i) {
                i = 2;
            }
            let j = next[i];
            let k = next[j];
            let mut s = f32::sqrt((*m.at(i, i) - (*m.at(j, j) + *m.at(k, k))) + 1.0);
            q[i] = s * 0.5;
            if s != 0.0 {
                s = 0.5 / s;
            }
            let w = (*m.at(k, j) - *m.at(j, k)) * s;
            q[j] = (*m.at(j, i) + *m.at(i, j)) * s;
            q[k] = (*m.at(k, i) + *m.at(i, k)) * s;
            Quaternion { v: q, w: w }
        }
    }
    /// Construct the quaternion from the transform
    pub fn from_transform(t: &Transform) -> Quaternion {
        Quaternion::from_matrix(&t.mat)
    }
    /// Get the rotation transform described by this quaternion
    pub fn to_matrix(&self) -> Matrix4 {
        Matrix4::new(
            [1.0 - 2.0 * (f32::powf(self.v.y, 2.0) + f32::powf(self.v.x, 2.0)),
             2.0 * (self.v.x * self.v.y + self.v.z * self.w),
             2.0 * (self.v.x * self.v.z - self.v.y * self.w),
             0.0,

             2.0 * (self.v.x * self.v.y - self.v.z * self.w),
             1.0 - 2.0 * (f32::powf(self.v.x, 2.0) + f32::powf(self.v.z, 2.0)),
             2.0 * (self.v.y * self.v.z + self.v.x * self.w),
             0.0,

             2.0 * (self.v.x * self.v.z + self.v.y * self.w),
             2.0 * (self.v.y * self.v.z - self.v.x * self.w),
             1.0 - 2.0 * (f32::powf(self.v.x, 2.0) + f32::powf(self.v.y, 2.0)),
             0.0,

             0.0, 0.0, 0.0, 1.0
            ])
    }
    /// Get the rotation transform described by this quaternion
    pub fn to_transform(&self) -> Transform {
        Transform::from_mat(&self.to_matrix())
    }
    /// Get the normalized quaternion for this rotation
    pub fn normalized(&self) -> Quaternion {
        *self / f32::sqrt(dot(self, self))
    }
}

/// Compute the dot product of the two quaternions
pub fn dot(a: &Quaternion, b: &Quaternion) -> f32 {
    linalg::dot(&a.v, &b.v) + a.w * b.w
}

/// Use spherical linear interpolation to interpolate between the two quaternions
pub fn slerp(t: f32, a: &Quaternion, b: &Quaternion) -> Quaternion {
    // Check if a and b are nearly parallel. To avoid numerical instability we do
    // regular linear interpolation in this case
    let cos_theta = dot(a, b);
    if cos_theta > 0.9995 {
        ((1.0 - t) * *a + t * *b).normalized()
    } else {
        let theta = f32::acos(linalg::clamp(cos_theta, -1.0, 1.0));
        let theta_t = theta * t;
        let q_perp = (*b - *a * cos_theta).normalized();
        *a * f32::cos(theta_t) + q_perp * f32::sin(theta_t)
    }
}

impl Add for Quaternion {
    type Output = Quaternion;
    /// Add two quaternions
    fn add(self, rhs: Quaternion) -> Quaternion {
        Quaternion { v: self.v + rhs.v, w: self.w + rhs.w }
    }
}

impl Sub for Quaternion {
    type Output = Quaternion;
    /// Subtract two quaternions
    fn sub(self, rhs: Quaternion) -> Quaternion {
        Quaternion { v: self.v - rhs.v, w: self.w - rhs.w }
    }
}

impl Mul<f32> for Quaternion {
    type Output = Quaternion;
    /// Multiply the quaternion by a scalar
    fn mul(self, rhs: f32) -> Quaternion {
        Quaternion { v: self.v * rhs, w: self.w * rhs }
    }
}

impl Mul<Quaternion> for f32 {
    type Output = Quaternion;
    /// Multiply the quaternion by a scalar
    fn mul(self, rhs: Quaternion) -> Quaternion {
        Quaternion { v: self * rhs.v, w: self * rhs.w }
    }
}

impl Div<f32> for Quaternion {
    type Output = Quaternion;
    /// Divide the quaternion by a scalar
    fn div(self, rhs: f32) -> Quaternion {
        Quaternion { v: self.v * rhs, w: self. w * rhs }
    }
}

<commit_msg>Cleaning up dumb typos in quaternion<commit_after>//! Provides a Quaternion type for properly interpolating rotations

use std::f32;
use std::ops::{Add, Sub, Mul, Div};

use linalg::{self, Vector, Transform, Matrix4};

/// Quaternions describe a rotation in 3d space but can be
/// properly interpolated unlike rotation matrices. The quaternion
/// also provides methods to compute the corresponding rotation
/// transform so that it can be composed with scaling and translation
#[derive(Debug, Copy, Clone)]
pub struct Quaternion {
    pub v: Vector,
    pub w: f32,
}

impl Quaternion {
    /// Construct an identity quaternion
    pub fn identity() -> Quaternion {
        Quaternion { v: Vector::broadcast(0.0), w: 1.0 }
    }
    /// Construct a quaternion from the rotation matrix
    /// Based on Shoemake 1991
    pub fn from_matrix(m: &Matrix4) -> Quaternion {
        let trace = *m.at(0, 0) + *m.at(1, 1) + *m.at(2, 2);
        if trace > 0.0 {
            // Compute w from matrix trace, then the vector
            let mut s = f32::sqrt(trace + 1.0);
            let w = s / 2.0;
            s = 0.5 / s;
            Quaternion { v: Vector::new(s * (*m.at(2, 1) - *m.at(1, 2)), s * (*m.at(0, 2) - *m.at(2, 0)),
                                        s * (*m.at(1, 0) - *m.at(0, 1))),
                         w: w
            }
        } else {
            // Compute largest of x, y or z then the remaining components
            let next = [1, 2, 0];
            let mut q = Vector::broadcast(0.0);
            let mut i = 0;
            if *m.at(1, 1) > *m.at(0, 0) {
                i = 1;
            }
            if *m.at(2, 2) > *m.at(i, i) {
                i = 2;
            }
            let j = next[i];
            let k = next[j];
            let mut s = f32::sqrt((*m.at(i, i) - (*m.at(j, j) + *m.at(k, k))) + 1.0);
            q[i] = s * 0.5;
            if s != 0.0 {
                s = 0.5 / s;
            }
            let w = (*m.at(k, j) - *m.at(j, k)) * s;
            q[j] = (*m.at(j, i) + *m.at(i, j)) * s;
            q[k] = (*m.at(k, i) + *m.at(i, k)) * s;
            Quaternion { v: q, w: w }
        }
    }
    /// Construct the quaternion from the transform
    pub fn from_transform(t: &Transform) -> Quaternion {
        Quaternion::from_matrix(&t.mat)
    }
    /// Get the rotation transform described by this quaternion
    pub fn to_matrix(&self) -> Matrix4 {
        Matrix4::new(
            [1.0 - 2.0 * (f32::powf(self.v.y, 2.0) + f32::powf(self.v.z, 2.0)),
             2.0 * (self.v.x * self.v.y + self.v.z * self.w),
             2.0 * (self.v.x * self.v.z - self.v.y * self.w),
             0.0,

             2.0 * (self.v.x * self.v.y - self.v.z * self.w),
             1.0 - 2.0 * (f32::powf(self.v.x, 2.0) + f32::powf(self.v.z, 2.0)),
             2.0 * (self.v.y * self.v.z + self.v.x * self.w),
             0.0,

             2.0 * (self.v.x * self.v.z + self.v.y * self.w),
             2.0 * (self.v.y * self.v.z - self.v.x * self.w),
             1.0 - 2.0 * (f32::powf(self.v.x, 2.0) + f32::powf(self.v.y, 2.0)),
             0.0,

             0.0, 0.0, 0.0, 1.0
            ]).transpose()
    }
    /// Get the rotation transform described by this quaternion
    pub fn to_transform(&self) -> Transform {
        Transform::from_mat(&self.to_matrix())
    }
    /// Get the normalized quaternion for this rotation
    pub fn normalized(&self) -> Quaternion {
        *self / f32::sqrt(dot(self, self))
    }
}

/// Compute the dot product of the two quaternions
pub fn dot(a: &Quaternion, b: &Quaternion) -> f32 {
    linalg::dot(&a.v, &b.v) + a.w * b.w
}

/// Use spherical linear interpolation to interpolate between the two quaternions
pub fn slerp(t: f32, a: &Quaternion, b: &Quaternion) -> Quaternion {
    // Check if a and b are nearly parallel. To avoid numerical instability we do
    // regular linear interpolation in this case
    let cos_theta = dot(a, b);
    if cos_theta > 0.9995 {
        ((1.0 - t) * *a + t * *b).normalized()
    } else {
        let theta = f32::acos(linalg::clamp(cos_theta, -1.0, 1.0));
        let theta_t = theta * t;
        let q_perp = (*b - *a * cos_theta).normalized();
        *a * f32::cos(theta_t) + q_perp * f32::sin(theta_t)
    }
}

impl Add for Quaternion {
    type Output = Quaternion;
    /// Add two quaternions
    fn add(self, rhs: Quaternion) -> Quaternion {
        Quaternion { v: self.v + rhs.v, w: self.w + rhs.w }
    }
}

impl Sub for Quaternion {
    type Output = Quaternion;
    /// Subtract two quaternions
    fn sub(self, rhs: Quaternion) -> Quaternion {
        Quaternion { v: self.v - rhs.v, w: self.w - rhs.w }
    }
}

impl Mul<f32> for Quaternion {
    type Output = Quaternion;
    /// Multiply the quaternion by a scalar
    fn mul(self, rhs: f32) -> Quaternion {
        Quaternion { v: self.v * rhs, w: self.w * rhs }
    }
}

impl Mul<Quaternion> for f32 {
    type Output = Quaternion;
    /// Multiply the quaternion by a scalar
    fn mul(self, rhs: Quaternion) -> Quaternion {
        Quaternion { v: self * rhs.v, w: self * rhs.w }
    }
}

impl Div<f32> for Quaternion {
    type Output = Quaternion;
    /// Divide the quaternion by a scalar
    fn div(self, rhs: f32) -> Quaternion {
        Quaternion { v: self.v / rhs, w: self. w / rhs }
    }
}

<|endoftext|>


<commit_before>//! The transform component, used for positioning objects in the scene.
//!
//! TODO: Document the transform "component", especially how there's no parent/child setup.

use async::engine::{self, EngineMessage};
use async::collections::atomic_array::AtomicArray;
use cell_extras::atomic_ref_cell::*;
use std::fmt::{self, Debug, Formatter};
use std::ptr;
use std::sync::Arc;
use math::*;
use polygon::anchor::AnchorId;

// HACK: This is a temporary upper bound on the number of nodes in a single row until we can
// better support dynamically allocating more space for a row.
const ROW_CAPACITY: usize = 1024;

/// A handle to a node in the scene graph.
pub struct Transform {
    inner: TransformInnerHandle,
}

impl Transform {
    /// Creates a new transform in the scene.
    ///
    /// By default transforms start at the origin of the world with a scale of 1 and are oriented
    /// such that their "forward" is along global -z.
    pub fn new() -> Transform {
        engine::scene_graph(|scene_graph| Transform { inner: scene_graph.create_node() })
    }

    /// Gets the current position of the transform.
    pub fn position(&self) -> Point {
        let data = self.inner.data();
        data.position
    }

    /// Sets the current position of the transform the specified point.
    pub fn set_position(&mut self, position: Point) {
        let mut data = self.inner.data_mut();
        data.position = position;
    }

    /// Moves the transform by the specified offset.
    pub fn translate(&mut self, offset: Vector3) {
        let mut data = self.inner.data_mut();
        data.position += offset;
    }

    /// Gets the current orientation of the transform.
    pub fn orientation(&self) -> Orientation {
        let data = self.inner.data();
        data.orientation
    }

    /// Sets the orientation of the transform.
    pub fn set_orientation(&mut self, orientation: Orientation) {
        let mut data = self.inner.data_mut();
        data.orientation = orientation;
    }

    /// Rotates the transform by the specified offset.
    pub fn rotate(&mut self, offset: Orientation) {
        let mut data = self.inner.data_mut();
        data.orientation += offset;
    }

    /// Rotates the transform by the specified euler angles.
    ///
    /// TODO: Do the number represent clockwise or anitclockwise rotation around each axis? That
    /// might be determined by the math library, but it should be noted in the module docs.
    pub fn rotate_eulers(&mut self, x: f32, y: f32, z: f32) {
        self.rotate(Orientation::from_eulers(x, y, z));
    }

    /// Gets the scale of the transform.
    pub fn scale(&self) -> Vector3 {
        let data = self.inner.data();
        data.scale
    }

    /// Sets the scale of the transform.
    pub fn set_scale(&mut self, scale: Vector3) {
        let mut data = self.inner.data_mut();
        data.scale = scale;
    }

    /// Gets the forward vector for the transform.
    ///
    /// The forward vector for the transform is the global forward (-z) as rotated by the
    /// transform's orientation.
    pub fn forward(&self) -> Vector3 {
        self.orientation() * Vector3::new(0.0, 0.0, -1.0)
    }

    pub fn right(&self) -> Vector3 {
        self.orientation() * Vector3::new(1.0, 0.0, 0.0)
    }

    // TODO: This shouldn't be public, it's only needed by engine internals.
    pub fn inner(&self) -> TransformInnerHandle {
        self.inner.clone()
    }
}

impl Drop for Transform {
    fn drop(&mut self) {
        // TODO: Mark transform and all its children as destroyed in the manager.
        warn_once!("WARNING: Drop hasn't been implemented for Transform yet");
    }
}

impl Debug for Transform {
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), fmt::Error> {
        let data = self.inner.data();
        write!(
            formatter,
            "Transform {{ position: {:?}, orientation: {:?}, scale: {:?} }}",
            data.position,
            data.orientation,
            data.scale,
        )
    }
}

unsafe impl Send for Transform {}

pub struct TransformGraph {
    row: AtomicArray<AtomicRefCell<TransformData>>,
}

impl TransformGraph {
    pub fn new() -> TransformGraph {
        TransformGraph {
            row: AtomicArray::new(ROW_CAPACITY),
        }
    }

    pub fn roots(&self) -> &[AtomicRefCell<TransformData>] {
        self.row.as_slice()
    }

    fn create_node(&self) -> TransformInnerHandle {
        // Create inner transform.
        let inner = Arc::new(TransformInner {
            data: AtomicRefCell::new(ptr::null_mut()),
            anchor: AtomicRefCell::new(None),
        });

        // Create transform data with pointer to inner.
        assert!(self.row.len() < ROW_CAPACITY, "Row 0 exceeded row capacity");
        self.row.push(AtomicRefCell::new(TransformData {
            inner: inner.clone(),

            position: Point::origin(),
            orientation: Orientation::new(),
            scale: Vector3::one(),
        }));

        // Hook up inner's pointer to data.
        {
            let mut data = inner.data.borrow_mut();
            *data = self.row.last().unwrap();
        }

        engine::send_message(EngineMessage::Anchor(inner.clone()));

        inner
    }
}

unsafe impl Send for TransformGraph {}
unsafe impl Sync for TransformGraph {}

#[derive(Debug)]
pub struct TransformInner {
    data: AtomicRefCell<*const AtomicRefCell<TransformData>>,
    anchor: AtomicRefCell<Option<AnchorId>>,
}

impl TransformInner {
    pub fn data(&self) -> AtomicRef<TransformData> {
        let data_ptr = self.data.borrow();
        let data = unsafe { &**data_ptr };
        data.borrow()
    }

    pub fn data_mut(&self) -> AtomicRefMut<TransformData> {
        let data_ptr = self.data.borrow();
        let data = unsafe { &**data_ptr };
        data.borrow_mut()
    }

    pub fn anchor(&self) -> Option<AnchorId> {
        self.anchor.borrow().clone()
    }
}

unsafe impl Send for TransformInner {}
unsafe impl Sync for TransformInner {}

impl TransformInner {
    pub fn set_anchor(&self, anchor: AnchorId) {
        let mut inner_anchor = self.anchor.borrow_mut();
        *inner_anchor = Some(anchor);
    }
}

pub type TransformInnerHandle = Arc<TransformInner>;

#[derive(Debug)]
pub struct TransformData {
    pub inner: TransformInnerHandle,

    pub position: Point,
    pub orientation: Orientation,
    pub scale: Vector3,
}

impl TransformData {
    pub fn anchor(&self) -> Option<AnchorId> {
        *self.inner.anchor.borrow()
    }
}
<commit_msg>Add remaining directional vectors for Transform<commit_after>//! The transform component, used for positioning objects in the scene.
//!
//! TODO: Document the transform "component", especially how there's no parent/child setup.

use async::engine::{self, EngineMessage};
use async::collections::atomic_array::AtomicArray;
use cell_extras::atomic_ref_cell::*;
use std::fmt::{self, Debug, Formatter};
use std::ptr;
use std::sync::Arc;
use math::*;
use polygon::anchor::AnchorId;

// HACK: This is a temporary upper bound on the number of nodes in a single row until we can
// better support dynamically allocating more space for a row.
const ROW_CAPACITY: usize = 1024;

/// A handle to a node in the scene graph.
pub struct Transform {
    inner: TransformInnerHandle,
}

impl Transform {
    /// Creates a new transform in the scene.
    ///
    /// By default transforms start at the origin of the world with a scale of 1 and are oriented
    /// such that their "forward" is along global -z.
    pub fn new() -> Transform {
        engine::scene_graph(|scene_graph| Transform { inner: scene_graph.create_node() })
    }

    /// Gets the current position of the transform.
    pub fn position(&self) -> Point {
        let data = self.inner.data();
        data.position
    }

    /// Sets the current position of the transform the specified point.
    pub fn set_position(&mut self, position: Point) {
        let mut data = self.inner.data_mut();
        data.position = position;
    }

    /// Moves the transform by the specified offset.
    pub fn translate(&mut self, offset: Vector3) {
        let mut data = self.inner.data_mut();
        data.position += offset;
    }

    /// Gets the current orientation of the transform.
    pub fn orientation(&self) -> Orientation {
        let data = self.inner.data();
        data.orientation
    }

    /// Sets the orientation of the transform.
    pub fn set_orientation(&mut self, orientation: Orientation) {
        let mut data = self.inner.data_mut();
        data.orientation = orientation;
    }

    /// Rotates the transform by the specified offset.
    pub fn rotate(&mut self, offset: Orientation) {
        let mut data = self.inner.data_mut();
        data.orientation += offset;
    }

    /// Rotates the transform by the specified euler angles.
    ///
    /// TODO: Do the number represent clockwise or anitclockwise rotation around each axis? That
    /// might be determined by the math library, but it should be noted in the module docs.
    pub fn rotate_eulers(&mut self, x: f32, y: f32, z: f32) {
        self.rotate(Orientation::from_eulers(x, y, z));
    }

    /// Gets the scale of the transform.
    pub fn scale(&self) -> Vector3 {
        let data = self.inner.data();
        data.scale
    }

    /// Sets the scale of the transform.
    pub fn set_scale(&mut self, scale: Vector3) {
        let mut data = self.inner.data_mut();
        data.scale = scale;
    }

    /// Gets the right direction for the transform.
    ///
    /// The right direction for the transform is the global right vector (positive x axis) as
    /// rotated by the transform's orientation. The returned vector will be normalized.
    pub fn right(&self) -> Vector3 {
        self.orientation() * Vector3::right()
    }

    /// Gets the left direction for the transform.
    ///
    /// The left for the transform is the global right vector (negative x axis) as
    /// rotated by the transform's orientation. The returned vector will be normalized.
    pub fn left(&self) -> Vector3 {
        self.orientation() * Vector3::left()
    }

    /// Gets the up direction for the transform.
    ///
    /// The up direction for the transform is the global up vector (positive y axis) as
    /// rotated by the transform's orientation. The returned vector will be normalized.
    pub fn up(&self) -> Vector3 {
        self.orientation() * Vector3::up()
    }

    /// Gets the down direction for the transform.
    ///
    /// The down direction for the transform is the global down vector (negative y axis) as
    /// rotated by the transform's orientation. The returned vector will be normalized.
    pub fn down(&self) -> Vector3 {
        self.orientation() * Vector3::down()
    }

    /// Gets the forward direction for the transform.
    ///
    /// The forward direction for the transform is the global forward vector (negative z axis) as
    /// rotated by the transform's orientation. The returned vector will be normalized.
    pub fn forward(&self) -> Vector3 {
        self.orientation() * Vector3::forward()
    }

    /// Gets the back direction for the transform.
    ///
    /// The back direction for the transform is the global back vector (positive z axis) as
    /// rotated by the transform's orientation. The returned vector will be normalized.
    pub fn back(&self) -> Vector3 {
        self.orientation() * Vector3::back()
    }

    // TODO: This shouldn't be public, it's only needed by engine internals.
    pub fn inner(&self) -> TransformInnerHandle {
        self.inner.clone()
    }
}

impl Drop for Transform {
    fn drop(&mut self) {
        // TODO: Mark transform and all its children as destroyed in the manager.
        warn_once!("WARNING: Drop hasn't been implemented for Transform yet");
    }
}

impl Debug for Transform {
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), fmt::Error> {
        let data = self.inner.data();
        write!(
            formatter,
            "Transform {{ position: {:?}, orientation: {:?}, scale: {:?} }}",
            data.position,
            data.orientation,
            data.scale,
        )
    }
}

unsafe impl Send for Transform {}

pub struct TransformGraph {
    row: AtomicArray<AtomicRefCell<TransformData>>,
}

impl TransformGraph {
    pub fn new() -> TransformGraph {
        TransformGraph {
            row: AtomicArray::new(ROW_CAPACITY),
        }
    }

    pub fn roots(&self) -> &[AtomicRefCell<TransformData>] {
        self.row.as_slice()
    }

    fn create_node(&self) -> TransformInnerHandle {
        // Create inner transform.
        let inner = Arc::new(TransformInner {
            data: AtomicRefCell::new(ptr::null_mut()),
            anchor: AtomicRefCell::new(None),
        });

        // Create transform data with pointer to inner.
        assert!(self.row.len() < ROW_CAPACITY, "Row 0 exceeded row capacity");
        self.row.push(AtomicRefCell::new(TransformData {
            inner: inner.clone(),

            position: Point::origin(),
            orientation: Orientation::new(),
            scale: Vector3::one(),
        }));

        // Hook up inner's pointer to data.
        {
            let mut data = inner.data.borrow_mut();
            *data = self.row.last().unwrap();
        }

        engine::send_message(EngineMessage::Anchor(inner.clone()));

        inner
    }
}

unsafe impl Send for TransformGraph {}
unsafe impl Sync for TransformGraph {}

#[derive(Debug)]
pub struct TransformInner {
    data: AtomicRefCell<*const AtomicRefCell<TransformData>>,
    anchor: AtomicRefCell<Option<AnchorId>>,
}

impl TransformInner {
    pub fn data(&self) -> AtomicRef<TransformData> {
        let data_ptr = self.data.borrow();
        let data = unsafe { &**data_ptr };
        data.borrow()
    }

    pub fn data_mut(&self) -> AtomicRefMut<TransformData> {
        let data_ptr = self.data.borrow();
        let data = unsafe { &**data_ptr };
        data.borrow_mut()
    }

    pub fn anchor(&self) -> Option<AnchorId> {
        self.anchor.borrow().clone()
    }
}

unsafe impl Send for TransformInner {}
unsafe impl Sync for TransformInner {}

impl TransformInner {
    pub fn set_anchor(&self, anchor: AnchorId) {
        let mut inner_anchor = self.anchor.borrow_mut();
        *inner_anchor = Some(anchor);
    }
}

pub type TransformInnerHandle = Arc<TransformInner>;

#[derive(Debug)]
pub struct TransformData {
    pub inner: TransformInnerHandle,

    pub position: Point,
    pub orientation: Orientation,
    pub scale: Vector3,
}

impl TransformData {
    pub fn anchor(&self) -> Option<AnchorId> {
        *self.inner.anchor.borrow()
    }
}
<|endoftext|>


<commit_before>// (C)opyleft 2013-2015 Frank Denis

/*!
 * Bloom filter for Rust
 *
 * This is a simple but fast Bloom filter implementation, that requires only
 * 2 hash functions, generated with SipHash-2-4 using randomized keys.
 */

#![crate_name="bloomfilter"]
#![crate_type = "rlib"]
#![warn(non_camel_case_types, non_upper_case_globals, unused_qualifications)]

extern crate rand;
extern crate bit_vec;

use std::cmp;
use std::f64;
use std::hash::{Hash, Hasher, SipHasher};
use bit_vec::BitVec;

#[cfg(test)]
use rand::Rng;

/// Bloom filter structure
pub struct Bloom {
    bitmap: BitVec,
    bitmap_bits: u64,
    k_num: u32,
    sips: [SipHasher; 2]
}

impl Bloom {
/// Create a new bloom filter structure.
/// bitmap_size is the size in bytes (not bits) that will be allocated in memory
/// items_count is an estimation of the maximum number of items to store.
    pub fn new(bitmap_size: usize, items_count: usize) -> Bloom {
        assert!(bitmap_size > 0 && items_count > 0);
        let bitmap_bits = (bitmap_size as u64) * 8u64;
        let k_num = Bloom::optimal_k_num(bitmap_bits, items_count);
        let bitmap = BitVec::from_elem(bitmap_bits as usize, false);
        let sips = [ Bloom::sip_new(), Bloom::sip_new() ];
        Bloom {
            bitmap: bitmap,
            bitmap_bits: bitmap_bits,
            k_num: k_num,
            sips: sips
        }
    }

/// Create a new bloom filter structure.
/// items_count is an estimation of the maximum number of items to store.
/// fp_p is the wanted rate of false positives, in ]0.0, 1.0[
    pub fn new_for_fp_rate(items_count: usize, fp_p: f64) -> Bloom {
        let bitmap_size = Bloom::compute_bitmap_size(items_count, fp_p);
        Bloom::new(bitmap_size, items_count)
    }

/// Compute a recommended bitmap size for items_count items
/// and a fp_p rate of false positives.
/// fp_p obviously has to be within the ]0.0, 1.0[ range.
    pub fn compute_bitmap_size(items_count: usize, fp_p: f64) -> usize {
        assert!(items_count > 0);
        assert!(fp_p > 0.0 && fp_p < 1.0);
        let log2 = f64::consts::LN_2;
        let log2_2 = log2 * log2;
        ((items_count as f64) * f64::ln(fp_p) / (-8.0 * log2_2)).ceil() as usize
    }

/// Record the presence of an item.
    pub fn set<T>(& mut self, item: T) where T: Hash {
        let mut hashes = [ 0u64, 0u64 ];
        for k_i in (0..self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as usize;
            self.bitmap.set(bit_offset, true);
        }
    }

/// Check if an item is present in the set.
/// There can be false positives, but no false negatives.
    pub fn check<T>(&self, item: T) -> bool where T: Hash {
        let mut hashes = [ 0u64, 0u64 ];
        for k_i in (0..self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as usize;
            if self.bitmap.get(bit_offset).unwrap() == false {
                return false;
            }
        }
        true
    }

/// Record the presence of an item in the set,
/// and return the previous state of this item.
    pub fn check_and_set<T>(&mut self, item: T)
                               -> bool where T: Hash {
        let mut hashes = [ 0u64, 0u64 ];
        let mut found = true;
        for k_i in (0..self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as usize;
            if self.bitmap.get(bit_offset).unwrap() == false {
                found = false;
                self.bitmap.set(bit_offset, true);
            }
        }
        found
    }

/// Return the number of bits in the filter
    pub fn number_of_bits(&self) -> u64 {
        self.bitmap_bits
    }

/// Return the number of hash functions used for `check` and `set`
    pub fn number_of_hash_functions(&self) -> u32 {
        self.k_num
    }

    fn optimal_k_num(bitmap_bits: u64, items_count: usize) -> u32 {
        let m = bitmap_bits as f64;
        let n = items_count as f64;
        let k_num = (m / n * f64::ln(2.0f64)).ceil() as u32;
        cmp::max(k_num, 1)
    }

    fn bloom_hash<T>(&self, hashes: & mut [u64; 2],
                  item: &T, k_i: u32) -> u64 where T: Hash {
        if k_i < 2 {
            let sip = &mut self.sips[k_i as usize].clone();
            item.hash(sip);
            let hash = sip.finish();
            hashes[k_i as usize] = hash;
            hash
        } else {
            hashes[0].wrapping_add((k_i as u64).wrapping_mul(hashes[1]) % 0xffffffffffffffc5)
        }
    }

/// Clear all of the bits in the filter, removing all keys from the set
    pub fn clear(&mut self) {
        self.bitmap.clear()
    }

    fn sip_new() -> SipHasher {
        let mut rng = rand::thread_rng();
        SipHasher::new_with_keys(rand::Rand::rand(& mut rng),
                                 rand::Rand::rand(& mut rng))
    }
}

#[test]
fn bloom_test_set() {
    let mut bloom = Bloom::new(10, 80);
    let key: &Vec<u8> = &rand::thread_rng().gen_iter::<u8>().take(16).collect();
    assert!(bloom.check(key) == false);
    bloom.set(&key);
    assert!(bloom.check(key.clone()) == true);
}

#[test]
fn bloom_test_check_and_set() {
    let mut bloom = Bloom::new(10, 80);
    let key: &Vec<u8> = &rand::thread_rng().gen_iter::<u8>().take(16).collect();
    assert!(bloom.check_and_set(key) == false);
    assert!(bloom.check_and_set(key.clone()) == true);
}

#[test]
fn bloom_test_clear() {
    let mut bloom = Bloom::new(10, 80);
    let key: &Vec<u8> = &rand::thread_rng().gen_iter::<u8>().take(16).collect();
    bloom.set(&key);
    assert!(bloom.check(&key) == true);
    bloom.clear();
    assert!(bloom.check(&key) == false);
}
<commit_msg>Remove  unnecessary parentheses<commit_after>// (C)opyleft 2013-2015 Frank Denis

/*!
 * Bloom filter for Rust
 *
 * This is a simple but fast Bloom filter implementation, that requires only
 * 2 hash functions, generated with SipHash-2-4 using randomized keys.
 */

#![crate_name="bloomfilter"]
#![crate_type = "rlib"]
#![warn(non_camel_case_types, non_upper_case_globals, unused_qualifications)]

extern crate rand;
extern crate bit_vec;

use std::cmp;
use std::f64;
use std::hash::{Hash, Hasher, SipHasher};
use bit_vec::BitVec;

#[cfg(test)]
use rand::Rng;

/// Bloom filter structure
pub struct Bloom {
    bitmap: BitVec,
    bitmap_bits: u64,
    k_num: u32,
    sips: [SipHasher; 2]
}

impl Bloom {
/// Create a new bloom filter structure.
/// bitmap_size is the size in bytes (not bits) that will be allocated in memory
/// items_count is an estimation of the maximum number of items to store.
    pub fn new(bitmap_size: usize, items_count: usize) -> Bloom {
        assert!(bitmap_size > 0 && items_count > 0);
        let bitmap_bits = (bitmap_size as u64) * 8u64;
        let k_num = Bloom::optimal_k_num(bitmap_bits, items_count);
        let bitmap = BitVec::from_elem(bitmap_bits as usize, false);
        let sips = [ Bloom::sip_new(), Bloom::sip_new() ];
        Bloom {
            bitmap: bitmap,
            bitmap_bits: bitmap_bits,
            k_num: k_num,
            sips: sips
        }
    }

/// Create a new bloom filter structure.
/// items_count is an estimation of the maximum number of items to store.
/// fp_p is the wanted rate of false positives, in ]0.0, 1.0[
    pub fn new_for_fp_rate(items_count: usize, fp_p: f64) -> Bloom {
        let bitmap_size = Bloom::compute_bitmap_size(items_count, fp_p);
        Bloom::new(bitmap_size, items_count)
    }

/// Compute a recommended bitmap size for items_count items
/// and a fp_p rate of false positives.
/// fp_p obviously has to be within the ]0.0, 1.0[ range.
    pub fn compute_bitmap_size(items_count: usize, fp_p: f64) -> usize {
        assert!(items_count > 0);
        assert!(fp_p > 0.0 && fp_p < 1.0);
        let log2 = f64::consts::LN_2;
        let log2_2 = log2 * log2;
        ((items_count as f64) * f64::ln(fp_p) / (-8.0 * log2_2)).ceil() as usize
    }

/// Record the presence of an item.
    pub fn set<T>(& mut self, item: T) where T: Hash {
        let mut hashes = [ 0u64, 0u64 ];
        for k_i in 0..self.k_num {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as usize;
            self.bitmap.set(bit_offset, true);
        }
    }

/// Check if an item is present in the set.
/// There can be false positives, but no false negatives.
    pub fn check<T>(&self, item: T) -> bool where T: Hash {
        let mut hashes = [ 0u64, 0u64 ];
        for k_i in 0..self.k_num {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as usize;
            if self.bitmap.get(bit_offset).unwrap() == false {
                return false;
            }
        }
        true
    }

/// Record the presence of an item in the set,
/// and return the previous state of this item.
    pub fn check_and_set<T>(&mut self, item: T)
                               -> bool where T: Hash {
        let mut hashes = [ 0u64, 0u64 ];
        let mut found = true;
        for k_i in 0..self.k_num {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as usize;
            if self.bitmap.get(bit_offset).unwrap() == false {
                found = false;
                self.bitmap.set(bit_offset, true);
            }
        }
        found
    }

/// Return the number of bits in the filter
    pub fn number_of_bits(&self) -> u64 {
        self.bitmap_bits
    }

/// Return the number of hash functions used for `check` and `set`
    pub fn number_of_hash_functions(&self) -> u32 {
        self.k_num
    }

    fn optimal_k_num(bitmap_bits: u64, items_count: usize) -> u32 {
        let m = bitmap_bits as f64;
        let n = items_count as f64;
        let k_num = (m / n * f64::ln(2.0f64)).ceil() as u32;
        cmp::max(k_num, 1)
    }

    fn bloom_hash<T>(&self, hashes: & mut [u64; 2],
                  item: &T, k_i: u32) -> u64 where T: Hash {
        if k_i < 2 {
            let sip = &mut self.sips[k_i as usize].clone();
            item.hash(sip);
            let hash = sip.finish();
            hashes[k_i as usize] = hash;
            hash
        } else {
            hashes[0].wrapping_add((k_i as u64).wrapping_mul(hashes[1]) % 0xffffffffffffffc5)
        }
    }

/// Clear all of the bits in the filter, removing all keys from the set
    pub fn clear(&mut self) {
        self.bitmap.clear()
    }

    fn sip_new() -> SipHasher {
        let mut rng = rand::thread_rng();
        SipHasher::new_with_keys(rand::Rand::rand(& mut rng),
                                 rand::Rand::rand(& mut rng))
    }
}

#[test]
fn bloom_test_set() {
    let mut bloom = Bloom::new(10, 80);
    let key: &Vec<u8> = &rand::thread_rng().gen_iter::<u8>().take(16).collect();
    assert!(bloom.check(key) == false);
    bloom.set(&key);
    assert!(bloom.check(key.clone()) == true);
}

#[test]
fn bloom_test_check_and_set() {
    let mut bloom = Bloom::new(10, 80);
    let key: &Vec<u8> = &rand::thread_rng().gen_iter::<u8>().take(16).collect();
    assert!(bloom.check_and_set(key) == false);
    assert!(bloom.check_and_set(key.clone()) == true);
}

#[test]
fn bloom_test_clear() {
    let mut bloom = Bloom::new(10, 80);
    let key: &Vec<u8> = &rand::thread_rng().gen_iter::<u8>().take(16).collect();
    bloom.set(&key);
    assert!(bloom.check(&key) == true);
    bloom.clear();
    assert!(bloom.check(&key) == false);
}
<|endoftext|>


<commit_before>//! Implementation of `make clean` in rustbuild.
//!
//! Responsible for cleaning out a build directory of all old and stale
//! artifacts to prepare for a fresh build. Currently doesn't remove the
//! `build/cache` directory (download cache) or the `build/$target/llvm`
//! directory unless the `--all` flag is present.

use std::fs;
use std::io::{self, ErrorKind};
use std::path::Path;

use build_helper::t;

use crate::Build;

pub fn clean(build: &Build, all: bool) {
    rm_rf("tmp".as_ref());

    if all {
        rm_rf(&build.out);
    } else {
        rm_rf(&build.out.join("tmp"));
        rm_rf(&build.out.join("dist"));

        for host in &build.hosts {
            let entries = match build.out.join(host.triple).read_dir() {
                Ok(iter) => iter,
                Err(_) => continue,
            };

            for entry in entries {
                let entry = t!(entry);
                if entry.file_name().to_str() == Some("llvm") {
                    continue;
                }
                let path = t!(entry.path().canonicalize());
                rm_rf(&path);
            }
        }
    }
}

fn rm_rf(path: &Path) {
    match path.symlink_metadata() {
        Err(e) => {
            if e.kind() == ErrorKind::NotFound {
                return;
            }
            panic!("failed to get metadata for file {}: {}", path.display(), e);
        }
        Ok(metadata) => {
            if metadata.file_type().is_file() || metadata.file_type().is_symlink() {
                do_op(path, "remove file", |p| fs::remove_file(p));
                return;
            }

            for file in t!(fs::read_dir(path)) {
                rm_rf(&t!(file).path());
            }
            do_op(path, "remove dir", |p| fs::remove_dir(p));
        }
    };
}

fn do_op<F>(path: &Path, desc: &str, mut f: F)
where
    F: FnMut(&Path) -> io::Result<()>,
{
    match f(path) {
        Ok(()) => {}
        // On windows we can't remove a readonly file, and git will often clone files as readonly.
        // As a result, we have some special logic to remove readonly files on windows.
        // This is also the reason that we can't use things like fs::remove_dir_all().
        Err(ref e) if cfg!(windows) && e.kind() == ErrorKind::PermissionDenied => {
            let mut p = t!(path.symlink_metadata()).permissions();
            p.set_readonly(false);
            t!(fs::set_permissions(path, p));
            f(path).unwrap_or_else(|e| {
                panic!("failed to {} {}: {}", desc, path.display(), e);
            })
        }
        Err(e) => {
            panic!("failed to {} {}: {}", desc, path.display(), e);
        }
    }
}
<commit_msg>Rollup merge of #80574 - jyn514:clean-bootstrap, r=Mark-Simulacrum<commit_after>//! Implementation of `make clean` in rustbuild.
//!
//! Responsible for cleaning out a build directory of all old and stale
//! artifacts to prepare for a fresh build. Currently doesn't remove the
//! `build/cache` directory (download cache) or the `build/$target/llvm`
//! directory unless the `--all` flag is present.

use std::fs;
use std::io::{self, ErrorKind};
use std::path::Path;

use build_helper::t;

use crate::Build;

pub fn clean(build: &Build, all: bool) {
    rm_rf("tmp".as_ref());

    if all {
        rm_rf(&build.out);
    } else {
        rm_rf(&build.out.join("tmp"));
        rm_rf(&build.out.join("dist"));
        rm_rf(&build.out.join("bootstrap"));

        for host in &build.hosts {
            let entries = match build.out.join(host.triple).read_dir() {
                Ok(iter) => iter,
                Err(_) => continue,
            };

            for entry in entries {
                let entry = t!(entry);
                if entry.file_name().to_str() == Some("llvm") {
                    continue;
                }
                let path = t!(entry.path().canonicalize());
                rm_rf(&path);
            }
        }
    }
}

fn rm_rf(path: &Path) {
    match path.symlink_metadata() {
        Err(e) => {
            if e.kind() == ErrorKind::NotFound {
                return;
            }
            panic!("failed to get metadata for file {}: {}", path.display(), e);
        }
        Ok(metadata) => {
            if metadata.file_type().is_file() || metadata.file_type().is_symlink() {
                do_op(path, "remove file", |p| fs::remove_file(p));
                return;
            }

            for file in t!(fs::read_dir(path)) {
                rm_rf(&t!(file).path());
            }
            do_op(path, "remove dir", |p| fs::remove_dir(p));
        }
    };
}

fn do_op<F>(path: &Path, desc: &str, mut f: F)
where
    F: FnMut(&Path) -> io::Result<()>,
{
    match f(path) {
        Ok(()) => {}
        // On windows we can't remove a readonly file, and git will often clone files as readonly.
        // As a result, we have some special logic to remove readonly files on windows.
        // This is also the reason that we can't use things like fs::remove_dir_all().
        Err(ref e) if cfg!(windows) && e.kind() == ErrorKind::PermissionDenied => {
            let mut p = t!(path.symlink_metadata()).permissions();
            p.set_readonly(false);
            t!(fs::set_permissions(path, p));
            f(path).unwrap_or_else(|e| {
                panic!("failed to {} {}: {}", desc, path.display(), e);
            })
        }
        Err(e) => {
            panic!("failed to {} {}: {}", desc, path.display(), e);
        }
    }
}
<|endoftext|>


<commit_before>//! A bad shell -- small cross platform module for writing glue code
use std::{
    cell::RefCell,
    env,
    ffi::OsStr,
    fs,
    path::PathBuf,
    process::{Command, Stdio},
};

use anyhow::{bail, Context, Result};

macro_rules! _run {
    ($($expr:expr),*) => {
        run!($($expr),*; echo = true)
    };
    ($($expr:expr),* ; echo = $echo:expr) => {
        $crate::not_bash::run_process(format!($($expr),*), $echo)
    };
}
pub(crate) use _run as run;

pub struct Pushd {
    _p: (),
}

pub fn pushd(path: impl Into<PathBuf>) -> Pushd {
    Env::with(|env| env.pushd(path.into()));
    Pushd { _p: () }
}

impl Drop for Pushd {
    fn drop(&mut self) {
        Env::with(|env| env.popd())
    }
}

pub fn rm(glob: &str) -> Result<()> {
    let cwd = Env::with(|env| env.cwd());
    ls(glob)?.into_iter().try_for_each(|it| fs::remove_file(cwd.join(it)))?;
    Ok(())
}

pub fn ls(glob: &str) -> Result<Vec<PathBuf>> {
    let cwd = Env::with(|env| env.cwd());
    let mut res = Vec::new();
    for entry in fs::read_dir(&cwd)? {
        let entry = entry?;
        if matches(&entry.file_name(), glob) {
            let path = entry.path();
            let path = path.strip_prefix(&cwd).unwrap();
            res.push(path.to_path_buf())
        }
    }
    return Ok(res);

    fn matches(file_name: &OsStr, glob: &str) -> bool {
        assert!(glob.starts_with('*'));
        file_name.to_string_lossy().ends_with(&glob[1..])
    }
}

#[doc(hidden)]
pub fn run_process(cmd: String, echo: bool) -> Result<String> {
    run_process_inner(&cmd, echo).with_context(|| format!("process `{}` failed", cmd))
}

fn run_process_inner(cmd: &str, echo: bool) -> Result<String> {
    let cwd = Env::with(|env| env.cwd());
    let mut args = shelx(cmd);
    let binary = args.remove(0);

    if echo {
        println!("> {}", cmd)
    }

    let output = Command::new(binary)
        .args(args)
        .current_dir(cwd)
        .stdin(Stdio::null())
        .stderr(Stdio::inherit())
        .output()?;
    let stdout = String::from_utf8(output.stdout)?;

    if echo {
        print!("{}", stdout)
    }

    if !output.status.success() {
        bail!("returned non-zero status: {}", output.status)
    }

    Ok(stdout)
}

// FIXME: some real shell lexing here
fn shelx(cmd: &str) -> Vec<String> {
    cmd.split_whitespace().map(|it| it.to_string()).collect()
}

#[derive(Default)]
struct Env {
    pushd_stack: Vec<PathBuf>,
}

impl Env {
    fn with<F: FnOnce(&mut Env) -> T, T>(f: F) -> T {
        thread_local! {
            static ENV: RefCell<Env> = Default::default();
        }
        ENV.with(|it| f(&mut *it.borrow_mut()))
    }

    fn pushd(&mut self, dir: PathBuf) {
        self.pushd_stack.push(dir)
    }
    fn popd(&mut self) {
        self.pushd_stack.pop().unwrap();
    }
    fn cwd(&self) -> PathBuf {
        self.pushd_stack.last().cloned().unwrap_or_else(|| env::current_dir().unwrap())
    }
}
<commit_msg>Cleanup<commit_after>//! A bad shell -- small cross platform module for writing glue code
use std::{
    cell::RefCell,
    env,
    ffi::OsStr,
    fs,
    path::PathBuf,
    process::{Command, Stdio},
};

use anyhow::{bail, Context, Result};

macro_rules! _run {
    ($($expr:expr),*) => {
        run!($($expr),*; echo = true)
    };
    ($($expr:expr),* ; echo = $echo:expr) => {
        $crate::not_bash::run_process(format!($($expr),*), $echo)
    };
}
pub(crate) use _run as run;

pub struct Pushd {
    _p: (),
}

pub fn pushd(path: impl Into<PathBuf>) -> Pushd {
    Env::with(|env| env.pushd(path.into()));
    Pushd { _p: () }
}

impl Drop for Pushd {
    fn drop(&mut self) {
        Env::with(|env| env.popd())
    }
}

pub fn rm(glob: &str) -> Result<()> {
    let cwd = Env::with(|env| env.cwd());
    ls(glob)?.into_iter().try_for_each(|it| fs::remove_file(cwd.join(it)))?;
    Ok(())
}

pub fn ls(glob: &str) -> Result<Vec<PathBuf>> {
    let cwd = Env::with(|env| env.cwd());
    let mut res = Vec::new();
    for entry in fs::read_dir(&cwd)? {
        let entry = entry?;
        if matches(&entry.file_name(), glob) {
            let path = entry.path();
            let path = path.strip_prefix(&cwd).unwrap();
            res.push(path.to_path_buf())
        }
    }
    return Ok(res);

    fn matches(file_name: &OsStr, glob: &str) -> bool {
        assert!(glob.starts_with('*'));
        file_name.to_string_lossy().ends_with(&glob[1..])
    }
}

#[doc(hidden)]
pub fn run_process(cmd: String, echo: bool) -> Result<String> {
    run_process_inner(&cmd, echo).with_context(|| format!("process `{}` failed", cmd))
}

fn run_process_inner(cmd: &str, echo: bool) -> Result<String> {
    let cwd = Env::with(|env| env.cwd());
    let mut args = shelx(cmd);
    let binary = args.remove(0);

    if echo {
        println!("> {}", cmd)
    }

    let output = Command::new(binary)
        .args(args)
        .current_dir(cwd)
        .stdin(Stdio::null())
        .stderr(Stdio::inherit())
        .output()?;
    let stdout = String::from_utf8(output.stdout)?;

    if echo {
        print!("{}", stdout)
    }

    if !output.status.success() {
        bail!("{}", output.status)
    }

    Ok(stdout)
}

// FIXME: some real shell lexing here
fn shelx(cmd: &str) -> Vec<String> {
    cmd.split_whitespace().map(|it| it.to_string()).collect()
}

#[derive(Default)]
struct Env {
    pushd_stack: Vec<PathBuf>,
}

impl Env {
    fn with<F: FnOnce(&mut Env) -> T, T>(f: F) -> T {
        thread_local! {
            static ENV: RefCell<Env> = Default::default();
        }
        ENV.with(|it| f(&mut *it.borrow_mut()))
    }

    fn pushd(&mut self, dir: PathBuf) {
        self.pushd_stack.push(dir)
    }
    fn popd(&mut self) {
        self.pushd_stack.pop().unwrap();
    }
    fn cwd(&self) -> PathBuf {
        self.pushd_stack.last().cloned().unwrap_or_else(|| env::current_dir().unwrap())
    }
}
<|endoftext|>


<commit_before>// The transaction model for handling surface states in Smithay
//
// The caching logic in `cache.rs` provides surfaces with a queue of
// pending states identified with numeric commit ids, allowing the compositor
// to precisely control *when* a state become active. This file is the second
// half: these identified states are grouped into transactions, which allow the
// synchronization of updates accross surfaces.
//
// There are 2 main cases when the state of multiple surfaces must be updated
// atomically:
// - synchronized subsurface must have their state updated at the same time as their parents
// - The upcoming `wp_transaction` protocol
//
// In these situations, the individual states in a surface queue are grouped into a transaction
// and are all applied atomically when the transaction itself is applied. The logic for creating
// new transactions is currently the following:
//
// - Each surface has an implicit "pending" transaction, into which its newly commited state is
//   recorded
// - Furthermore, on commit, the pending transaction of all synchronized child subsurfaces is merged
//   into the current surface's pending transaction, and a new implicit transaction is started for those
//   children (logic is implemented in `handlers.rs`, in `PrivateSurfaceData::commit`).
// - Then, still on commit, if the surface is not a synchronized subsurface, its pending transaction is
//   directly applied
//
// This last step will change once we have support for explicit synchronization (and further in the future,
// of the wp_transaction protocol). Explicit synchronization introduces a notion of blockers: the transaction
// cannot be applied before all blockers are released, and thus must wait for it to be the case.
//
// For thoses situations, the (currently unused) `TransactionQueue` will come into play. It is a per-client
// queue of transactions, that stores and applies them by both respecting their topological order
// (ensuring that for each surface, states are applied in the correct order) and that all transactions
// wait befor all their blockers are resolved to be merged. If a blocker is cancelled, the whole transaction
// it blocks is cancelled as well, and simply dropped. Thanks to the logic of `Cache::apply_state`, the
// associated state will be applied automatically when the next valid transaction is applied, ensuring
// global coherence.

// A significant part of the logic of this module is not yet used,
// but will be once proper transaction & blockers support is
// added to smithay
#![allow(dead_code)]

use std::{
    collections::HashSet,
    sync::{Arc, Mutex},
};

use wayland_server::{protocol::wl_surface::WlSurface, DisplayHandle, Resource};

use crate::wayland::Serial;

use super::tree::PrivateSurfaceData;

pub trait Blocker {
    fn state(&self) -> BlockerState;
}

pub enum BlockerState {
    Pending,
    Released,
    Cancelled,
}

#[derive(Default)]
struct TransactionState {
    surfaces: Vec<(WlSurface, Serial)>,
    blockers: Vec<Box<dyn Blocker + Send>>,
}

impl TransactionState {
    fn insert(&mut self, surface: WlSurface, id: Serial) {
        if let Some(place) = self.surfaces.iter_mut().find(|place| place.0 == surface) {
            // the surface is already in the list, update the serial
            if place.1 < id {
                place.1 = id;
            }
        } else {
            // the surface is not in the list, insert it
            self.surfaces.push((surface, id));
        }
    }
}

enum TransactionInner {
    Data(TransactionState),
    Fused(Arc<Mutex<TransactionInner>>),
}

pub(crate) struct PendingTransaction {
    inner: Arc<Mutex<TransactionInner>>,
}

impl Default for PendingTransaction {
    fn default() -> Self {
        PendingTransaction {
            inner: Arc::new(Mutex::new(TransactionInner::Data(Default::default()))),
        }
    }
}

impl PendingTransaction {
    fn with_inner_state<T, F: FnOnce(&mut TransactionState) -> T>(&self, f: F) -> T {
        let mut next = self.inner.clone();
        loop {
            let tmp = match *next.lock().unwrap() {
                TransactionInner::Data(ref mut state) => return f(state),
                TransactionInner::Fused(ref into) => into.clone(),
            };
            next = tmp;
        }
    }

    pub(crate) fn insert_state(&self, surface: WlSurface, id: Serial) {
        self.with_inner_state(|state| state.insert(surface, id))
    }

    pub(crate) fn add_blocker<B: Blocker + Send + 'static>(&self, blocker: B) {
        self.with_inner_state(|state| state.blockers.push(Box::new(blocker) as Box<_>))
    }

    pub(crate) fn is_same_as(&self, other: &PendingTransaction) -> bool {
        let ptr1 = self.with_inner_state(|state| state as *const _);
        let ptr2 = other.with_inner_state(|state| state as *const _);
        ptr1 == ptr2
    }

    pub(crate) fn merge_into(&self, into: &PendingTransaction) {
        if self.is_same_as(into) {
            // nothing to do
            return;
        }
        // extract our pending surfaces and change our link
        let mut next = self.inner.clone();
        let my_state;
        loop {
            let tmp = {
                let mut guard = next.lock().unwrap();
                match *guard {
                    TransactionInner::Data(ref mut state) => {
                        my_state = std::mem::take(state);
                        *guard = TransactionInner::Fused(into.inner.clone());
                        break;
                    }
                    TransactionInner::Fused(ref into) => into.clone(),
                }
            };
            next = tmp;
        }
        // fuse our surfaces into our new transaction state
        self.with_inner_state(|state| {
            for (surface, id) in my_state.surfaces {
                state.insert(surface, id);
            }
            state.blockers.extend(my_state.blockers);
        });
    }

    pub(crate) fn finalize(mut self) -> Transaction {
        // When finalizing a transaction, this *must* be the last handle to this transaction
        loop {
            let inner = match Arc::try_unwrap(self.inner) {
                Ok(mutex) => mutex.into_inner().unwrap(),
                Err(_) => panic!("Attempting to finalize a transaction but handle is not the last."),
            };
            match inner {
                TransactionInner::Data(TransactionState {
                    surfaces, blockers, ..
                }) => return Transaction { surfaces, blockers },
                TransactionInner::Fused(into) => self.inner = into,
            }
        }
    }
}
pub(crate) struct Transaction {
    surfaces: Vec<(WlSurface, Serial)>,
    blockers: Vec<Box<dyn Blocker + Send>>,
}

impl Transaction {
    /// Computes the global state of the transaction with regard to its blockers
    ///
    /// The logic is:
    ///
    /// - if at least one blocker is cancelled, the transaction is cancelled
    /// - otherwise, if at least one blocker is pending, the transaction is pending
    /// - otherwise, all blockers are released, and the transaction is also released
    pub(crate) fn state(&self) -> BlockerState {
        use BlockerState::*;
        self.blockers
            .iter()
            .fold(Released, |acc, blocker| match (acc, blocker.state()) {
                (Cancelled, _) | (_, Cancelled) => Cancelled,
                (Pending, _) | (_, Pending) => Pending,
                (Released, Released) => Released,
            })
    }

    pub(crate) fn apply(self, dh: &DisplayHandle) {
        for (surface, id) in self.surfaces {
            PrivateSurfaceData::with_states(&surface, |states| {
                states.cached_state.apply_state(id, dh);
            })
        }
    }
}

// This queue should be per-client
#[derive(Default)]
pub(crate) struct TransactionQueue {
    transactions: Vec<Transaction>,
    // we keep the hashset around to reuse allocations
    seen_surfaces: HashSet<u32>,
}

impl TransactionQueue {
    pub(crate) fn append(&mut self, t: Transaction) {
        self.transactions.push(t);
    }

    pub(crate) fn apply_ready<D: 'static>(&mut self, dh: &DisplayHandle) {
        // this is a very non-optimized implementation
        // we just iterate over the queue of transactions, keeping track of which
        // surface we have seen as they encode transaction dependencies
        self.seen_surfaces.clear();
        // manually iterate as we're going to modify the Vec while iterating on it
        let mut i = 0;
        // the loop will terminate, as at every iteration either i is incremented by 1
        // or the lenght of self.transactions is reduced by 1.
        while i <= self.transactions.len() {
            let mut skip = false;
            // does the transaction have any active blocker?
            match self.transactions[i].state() {
                BlockerState::Cancelled => {
                    // this transaction is cancelled, remove it without further processing
                    self.transactions.remove(i);
                    continue;
                }
                BlockerState::Pending => {
                    skip = true;
                }
                BlockerState::Released => {}
            }
            // if not, does this transaction depend on any previous transaction?
            if !skip {
                for (s, _) in &self.transactions[i].surfaces {
                    // TODO: is this alive check still needed?
                    if dh.object_info(s.id()).is_err() {
                        continue;
                    }
                    if self.seen_surfaces.contains(&s.id().protocol_id()) {
                        skip = true;
                        break;
                    }
                }
            }

            if skip {
                // this transaction is not yet ready and should be skipped, add its surfaces to our
                // seen list
                for (s, _) in &self.transactions[i].surfaces {
                    // TODO: is this alive check still needed?
                    if dh.object_info(s.id()).is_err() {
                        continue;
                    }
                    self.seen_surfaces.insert(s.id().protocol_id());
                }
                i += 1;
            } else {
                // this transaction is to be applied, yay!
                self.transactions.remove(i).apply(dh);
            }
        }
    }
}
<commit_msg>WlCompositor Use new IsAlive<commit_after>// The transaction model for handling surface states in Smithay
//
// The caching logic in `cache.rs` provides surfaces with a queue of
// pending states identified with numeric commit ids, allowing the compositor
// to precisely control *when* a state become active. This file is the second
// half: these identified states are grouped into transactions, which allow the
// synchronization of updates accross surfaces.
//
// There are 2 main cases when the state of multiple surfaces must be updated
// atomically:
// - synchronized subsurface must have their state updated at the same time as their parents
// - The upcoming `wp_transaction` protocol
//
// In these situations, the individual states in a surface queue are grouped into a transaction
// and are all applied atomically when the transaction itself is applied. The logic for creating
// new transactions is currently the following:
//
// - Each surface has an implicit "pending" transaction, into which its newly commited state is
//   recorded
// - Furthermore, on commit, the pending transaction of all synchronized child subsurfaces is merged
//   into the current surface's pending transaction, and a new implicit transaction is started for those
//   children (logic is implemented in `handlers.rs`, in `PrivateSurfaceData::commit`).
// - Then, still on commit, if the surface is not a synchronized subsurface, its pending transaction is
//   directly applied
//
// This last step will change once we have support for explicit synchronization (and further in the future,
// of the wp_transaction protocol). Explicit synchronization introduces a notion of blockers: the transaction
// cannot be applied before all blockers are released, and thus must wait for it to be the case.
//
// For thoses situations, the (currently unused) `TransactionQueue` will come into play. It is a per-client
// queue of transactions, that stores and applies them by both respecting their topological order
// (ensuring that for each surface, states are applied in the correct order) and that all transactions
// wait befor all their blockers are resolved to be merged. If a blocker is cancelled, the whole transaction
// it blocks is cancelled as well, and simply dropped. Thanks to the logic of `Cache::apply_state`, the
// associated state will be applied automatically when the next valid transaction is applied, ensuring
// global coherence.

// A significant part of the logic of this module is not yet used,
// but will be once proper transaction & blockers support is
// added to smithay
#![allow(dead_code)]

use std::{
    collections::HashSet,
    sync::{Arc, Mutex},
};

use wayland_server::{protocol::wl_surface::WlSurface, DisplayHandle, Resource};

use crate::{utils::IsAlive, wayland::Serial};

use super::tree::PrivateSurfaceData;

pub trait Blocker {
    fn state(&self) -> BlockerState;
}

pub enum BlockerState {
    Pending,
    Released,
    Cancelled,
}

#[derive(Default)]
struct TransactionState {
    surfaces: Vec<(WlSurface, Serial)>,
    blockers: Vec<Box<dyn Blocker + Send>>,
}

impl TransactionState {
    fn insert(&mut self, surface: WlSurface, id: Serial) {
        if let Some(place) = self.surfaces.iter_mut().find(|place| place.0 == surface) {
            // the surface is already in the list, update the serial
            if place.1 < id {
                place.1 = id;
            }
        } else {
            // the surface is not in the list, insert it
            self.surfaces.push((surface, id));
        }
    }
}

enum TransactionInner {
    Data(TransactionState),
    Fused(Arc<Mutex<TransactionInner>>),
}

pub(crate) struct PendingTransaction {
    inner: Arc<Mutex<TransactionInner>>,
}

impl Default for PendingTransaction {
    fn default() -> Self {
        PendingTransaction {
            inner: Arc::new(Mutex::new(TransactionInner::Data(Default::default()))),
        }
    }
}

impl PendingTransaction {
    fn with_inner_state<T, F: FnOnce(&mut TransactionState) -> T>(&self, f: F) -> T {
        let mut next = self.inner.clone();
        loop {
            let tmp = match *next.lock().unwrap() {
                TransactionInner::Data(ref mut state) => return f(state),
                TransactionInner::Fused(ref into) => into.clone(),
            };
            next = tmp;
        }
    }

    pub(crate) fn insert_state(&self, surface: WlSurface, id: Serial) {
        self.with_inner_state(|state| state.insert(surface, id))
    }

    pub(crate) fn add_blocker<B: Blocker + Send + 'static>(&self, blocker: B) {
        self.with_inner_state(|state| state.blockers.push(Box::new(blocker) as Box<_>))
    }

    pub(crate) fn is_same_as(&self, other: &PendingTransaction) -> bool {
        let ptr1 = self.with_inner_state(|state| state as *const _);
        let ptr2 = other.with_inner_state(|state| state as *const _);
        ptr1 == ptr2
    }

    pub(crate) fn merge_into(&self, into: &PendingTransaction) {
        if self.is_same_as(into) {
            // nothing to do
            return;
        }
        // extract our pending surfaces and change our link
        let mut next = self.inner.clone();
        let my_state;
        loop {
            let tmp = {
                let mut guard = next.lock().unwrap();
                match *guard {
                    TransactionInner::Data(ref mut state) => {
                        my_state = std::mem::take(state);
                        *guard = TransactionInner::Fused(into.inner.clone());
                        break;
                    }
                    TransactionInner::Fused(ref into) => into.clone(),
                }
            };
            next = tmp;
        }
        // fuse our surfaces into our new transaction state
        self.with_inner_state(|state| {
            for (surface, id) in my_state.surfaces {
                state.insert(surface, id);
            }
            state.blockers.extend(my_state.blockers);
        });
    }

    pub(crate) fn finalize(mut self) -> Transaction {
        // When finalizing a transaction, this *must* be the last handle to this transaction
        loop {
            let inner = match Arc::try_unwrap(self.inner) {
                Ok(mutex) => mutex.into_inner().unwrap(),
                Err(_) => panic!("Attempting to finalize a transaction but handle is not the last."),
            };
            match inner {
                TransactionInner::Data(TransactionState {
                    surfaces, blockers, ..
                }) => return Transaction { surfaces, blockers },
                TransactionInner::Fused(into) => self.inner = into,
            }
        }
    }
}
pub(crate) struct Transaction {
    surfaces: Vec<(WlSurface, Serial)>,
    blockers: Vec<Box<dyn Blocker + Send>>,
}

impl Transaction {
    /// Computes the global state of the transaction with regard to its blockers
    ///
    /// The logic is:
    ///
    /// - if at least one blocker is cancelled, the transaction is cancelled
    /// - otherwise, if at least one blocker is pending, the transaction is pending
    /// - otherwise, all blockers are released, and the transaction is also released
    pub(crate) fn state(&self) -> BlockerState {
        use BlockerState::*;
        self.blockers
            .iter()
            .fold(Released, |acc, blocker| match (acc, blocker.state()) {
                (Cancelled, _) | (_, Cancelled) => Cancelled,
                (Pending, _) | (_, Pending) => Pending,
                (Released, Released) => Released,
            })
    }

    pub(crate) fn apply(self, dh: &DisplayHandle) {
        for (surface, id) in self.surfaces {
            PrivateSurfaceData::with_states(&surface, |states| {
                states.cached_state.apply_state(id, dh);
            })
        }
    }
}

// This queue should be per-client
#[derive(Default)]
pub(crate) struct TransactionQueue {
    transactions: Vec<Transaction>,
    // we keep the hashset around to reuse allocations
    seen_surfaces: HashSet<u32>,
}

impl TransactionQueue {
    pub(crate) fn append(&mut self, t: Transaction) {
        self.transactions.push(t);
    }

    pub(crate) fn apply_ready<D: 'static>(&mut self, dh: &DisplayHandle) {
        // this is a very non-optimized implementation
        // we just iterate over the queue of transactions, keeping track of which
        // surface we have seen as they encode transaction dependencies
        self.seen_surfaces.clear();
        // manually iterate as we're going to modify the Vec while iterating on it
        let mut i = 0;
        // the loop will terminate, as at every iteration either i is incremented by 1
        // or the lenght of self.transactions is reduced by 1.
        while i <= self.transactions.len() {
            let mut skip = false;
            // does the transaction have any active blocker?
            match self.transactions[i].state() {
                BlockerState::Cancelled => {
                    // this transaction is cancelled, remove it without further processing
                    self.transactions.remove(i);
                    continue;
                }
                BlockerState::Pending => {
                    skip = true;
                }
                BlockerState::Released => {}
            }
            // if not, does this transaction depend on any previous transaction?
            if !skip {
                for (s, _) in &self.transactions[i].surfaces {
                    // TODO: is this alive check still needed?
                    if !s.alive() {
                        continue;
                    }
                    if self.seen_surfaces.contains(&s.id().protocol_id()) {
                        skip = true;
                        break;
                    }
                }
            }

            if skip {
                // this transaction is not yet ready and should be skipped, add its surfaces to our
                // seen list
                for (s, _) in &self.transactions[i].surfaces {
                    // TODO: is this alive check still needed?
                    if !s.alive() {
                        continue;
                    }
                    self.seen_surfaces.insert(s.id().protocol_id());
                }
                i += 1;
            } else {
                // this transaction is to be applied, yay!
                self.transactions.remove(i).apply(dh);
            }
        }
    }
}
<|endoftext|>


<commit_before>use super::*;

pub trait Vertex: Copy + Eq{}
impl<T> Vertex for T
	where T: Copy + Eq
{}

pub trait Weight: Copy + Eq{}
impl<T> Weight for T
	where T: Copy + Eq
{}

pub trait VertexIter<V>: IntoIterator<Item=V>
	where
		V: Vertex
{}
impl<T,V> VertexIter<V> for T
	where
		T: IntoIterator<Item=V>,
		V: Vertex,
{}

pub trait EdgeIter<V,W>: IntoIterator<Item=BaseEdge<V,W>>
	where
		V: Vertex,
		W: Weight,
{}
impl<T,V,W> EdgeIter<V,W> for T
	where
		T: IntoIterator<Item=BaseEdge<V,W>>,
		V: Vertex,
		W: Weight,
{}

///
/// The basic graph interface.
///
/// This is the main trait for all types graphs.
///
/// The vertices in a graph are identified by their value, and must therefore be unique
/// in the graph.
///
/// The edges in a graph are identified by the vertices they connect and their weight.
/// Edges do not have to be unique, but if there are duplicates (i.e. two or more edges connecting
/// the same vertices with the same weights) then any operation intended for one of the edges
/// may happen on any one of them. E.g. If one of the edges is to be removed, then any
/// one of them will be so.
///
///
///
///
///
pub trait BaseGraph
{
	/// Type of the vertices in the graph.
	type Vertex: Vertex;
	/// Type of the weights in the graph.
	type Weight: Weight;
	/// Type of the collection returned with vertices.
	type VertexIter: VertexIter<Self::Vertex>;
	// Type of the collection returned with edges.
	type EdgeIter: EdgeIter<Self::Vertex, Self::Weight>;

	///
	/// Creates an empty graph. I.e a graph with no vertices and no edges.
	///
	/// Properties:
	///
	/// - `empty().all_vertices().into_iter().next() == None`
	/// - `empty().all_edges().into_iter().next() == None`
	/// - `empty().add_vertex(v) == Ok(())`
	/// - `empty().add_edge(e) == Err(())`
	/// - `empty().remove_vertex(v) == Err(())`
	/// - `empty().remove_edge(e) == Err(())`
	///
	fn empty_graph() -> Self;

	///
	/// Returns copies of all current vertices in the graph.
	///
	fn all_vertices(&self) -> Self::VertexIter;

	///
	/// Returns copies of all current edges in the graph.
	///
	fn all_edges(&self) -> Self::EdgeIter;

	///
	/// Adds the given vertex to graph as long as no equal vertex is already
	/// present i the graph and the graph is capable of storing it.
	///
	/// ###Returns:
	///
	/// - `Ok` if the vertex is valid and has been added.
	/// - `Err` if the vertex is already present in the graph or
	/// the graph doesn't have capacity for it.
	///
	/// ###`Ok` properties :
	///
	/// - All vertices present before the call are also present after it.
	/// - All edges present before the call are also present after it.
	/// - No edge weights are changed.
	/// - No new edges are introduced.
	/// - Only the given vertex is added to the graph.
	///
	/// ###`Err` properties :
	///
	/// - The graph is unchanged.
	///
	///
	fn add_vertex(&mut self, v: Self::Vertex) -> Result<(),()>;

	///
	/// Removes the given vertex from the graph, assuming it is present.
	///
	/// ###Returns:
	///
	/// - `Ok` if the vertex was removed.
	/// - `Err` if the vertex was not present in the graph.
	///
	/// ###`Ok` properties:
	///
	/// - Only the given vertex is removed from the graph.
	/// - Any edge connecting to the removed vertex is also removed.
	/// - All other edges are unchanged.
	/// - No new vertices are introduced.
	/// - No new edges are introduced.
	/// - No edge weights are changed.
	///
	/// ###`Err` properties:
	///
	/// - The graph is unchanged.
	///
	///
	///
	fn remove_vertex(&mut self, v: Self::Vertex) -> Result<(),()>;

	///
	/// Adds the given edge to the graph assuming it connects to valid vertices.
	///
	/// ###Returns
	/// - `Ok` if the edge connects to valid vertices and the edge was added successfully.
	/// - `Err` if the edge connects to invalid vertices or was not added.
	///
	/// ###`Ok` properties:
	///
	/// - Only the given edge is added to the graph.
	/// - Existing edges are unchanged.
	/// - No vertices are introduced or removed.
	///
	/// ###`Err` properties:
	///
	/// - The graph is unchanged.
	///
	fn add_edge(&mut self, e: BaseEdge<Self::Vertex,Self::Weight>) -> Result<(),()>;

	///
	/// Removes the given edge from the graph, assuming it is already present.
	///
	/// ###Returns
	/// - `Ok` if the edge was present before the call and was removed successfully.
	/// - `Err` if the edge was not found in the graph.
	///
	/// ###`Ok` properties:
	///
	/// - Only the given edge is removed.
	/// - No new edges are introduced.
	/// - No edge weights are changed.
	/// - No new vertices are introduced or removed.
	///
	/// ###`Err` properties:
	///
	/// - The graph is unchanged.
	///
	fn remove_edge(&mut self, e: BaseEdge<Self::Vertex,Self::Weight>) -> Result<(),()>;

	///
	/// Creates a graph containing the given vertices and edges. There can be no
	/// duplicate vertices and all edges must connect to the given vertices.
	///
	/// ###Returns:
	///
	/// - `Ok`: If the given graph description is valid, the created graph is returned.
	/// - `Err`: If the given graph description is invalid.
	///
	fn graph(	vertices: Vec<Self::Vertex>,
			 	edges: Vec<(Self::Vertex, Self::Vertex,Self::Weight)>)
		-> Result<Self,()>
		where
			Self: Sized,
	{
		let mut g = Self::empty_graph();

		/* Add all vertices
		 */
		for v in vertices {
			//Make sure the vertex is added
			g.add_vertex(v)?;
		}

		/* Add all edges
		 */
		for (so,si,w) in edges {
			// Make sure the edge is added
			g.add_edge(BaseEdge::new(so,si,w))?;
		}

		Ok(g)
	}

}

<commit_msg>Added BaseGraph.edges_between()<commit_after>use super::*;
use std::iter::FromIterator;

pub trait Vertex: Copy + Eq{}
impl<T> Vertex for T
	where T: Copy + Eq
{}

pub trait Weight: Copy + Eq{}
impl<T> Weight for T
	where T: Copy + Eq
{}

pub trait VertexIter<V>: IntoIterator<Item=V> + FromIterator<V>
	where
		V: Vertex
{}
impl<T,V> VertexIter<V> for T
	where
		T: IntoIterator<Item=V> + FromIterator<V>,
		V: Vertex,
{}

pub trait EdgeIter<V,W>: IntoIterator<Item=BaseEdge<V,W>> + FromIterator<BaseEdge<V,W>>
	where
		V: Vertex,
		W: Weight,
{}
impl<T,V,W> EdgeIter<V,W> for T
	where
		T: IntoIterator<Item=BaseEdge<V,W>> + FromIterator<BaseEdge<V,W>>,
		V: Vertex,
		W: Weight,
{}

///
/// The basic graph interface.
///
/// This is the main trait for all types graphs.
///
/// The vertices in a graph are identified by their value, and must therefore be unique
/// in the graph.
///
/// The edges in a graph are identified by the vertices they connect and their weight.
/// Edges do not have to be unique, but if there are duplicates (i.e. two or more edges connecting
/// the same vertices with the same weights) then any operation intended for one of the edges
/// may happen on any one of them. E.g. If one of the edges is to be removed, then any
/// one of them will be so.
///
///
///
///
///
pub trait BaseGraph
{
	/// Type of the vertices in the graph.
	type Vertex: Vertex;
	/// Type of the weights in the graph.
	type Weight: Weight;
	/// Type of the collection returned with vertices.
	type VertexIter: VertexIter<Self::Vertex>;
	// Type of the collection returned with edges.
	type EdgeIter: EdgeIter<Self::Vertex, Self::Weight>;

	///
	/// Creates an empty graph. I.e a graph with no vertices and no edges.
	///
	/// Properties:
	///
	/// - `empty().all_vertices().into_iter().next() == None`
	/// - `empty().all_edges().into_iter().next() == None`
	/// - `empty().add_vertex(v) == Ok(())`
	/// - `empty().add_edge(e) == Err(())`
	/// - `empty().remove_vertex(v) == Err(())`
	/// - `empty().remove_edge(e) == Err(())`
	///
	fn empty_graph() -> Self;

	///
	/// Returns copies of all current vertices in the graph.
	///
	fn all_vertices(&self) -> Self::VertexIter;

	///
	/// Returns copies of all current edges in the graph.
	///
	fn all_edges(&self) -> Self::EdgeIter;

	///
	/// Adds the given vertex to graph as long as no equal vertex is already
	/// present i the graph and the graph is capable of storing it.
	///
	/// ###Returns:
	///
	/// - `Ok` if the vertex is valid and has been added.
	/// - `Err` if the vertex is already present in the graph or
	/// the graph doesn't have capacity for it.
	///
	/// ###`Ok` properties :
	///
	/// - All vertices present before the call are also present after it.
	/// - All edges present before the call are also present after it.
	/// - No edge weights are changed.
	/// - No new edges are introduced.
	/// - Only the given vertex is added to the graph.
	///
	/// ###`Err` properties :
	///
	/// - The graph is unchanged.
	///
	///
	fn add_vertex(&mut self, v: Self::Vertex) -> Result<(),()>;

	///
	/// Removes the given vertex from the graph, assuming it is present.
	///
	/// ###Returns:
	///
	/// - `Ok` if the vertex was removed.
	/// - `Err` if the vertex was not present in the graph.
	///
	/// ###`Ok` properties:
	///
	/// - Only the given vertex is removed from the graph.
	/// - Any edge connecting to the removed vertex is also removed.
	/// - All other edges are unchanged.
	/// - No new vertices are introduced.
	/// - No new edges are introduced.
	/// - No edge weights are changed.
	///
	/// ###`Err` properties:
	///
	/// - The graph is unchanged.
	///
	///
	///
	fn remove_vertex(&mut self, v: Self::Vertex) -> Result<(),()>;

	///
	/// Adds the given edge to the graph assuming it connects to valid vertices.
	///
	/// ###Returns
	/// - `Ok` if the edge connects to valid vertices and the edge was added successfully.
	/// - `Err` if the edge connects to invalid vertices or was not added.
	///
	/// ###`Ok` properties:
	///
	/// - Only the given edge is added to the graph.
	/// - Existing edges are unchanged.
	/// - No vertices are introduced or removed.
	///
	/// ###`Err` properties:
	///
	/// - The graph is unchanged.
	///
	fn add_edge(&mut self, e: BaseEdge<Self::Vertex,Self::Weight>) -> Result<(),()>;

	///
	/// Removes the given edge from the graph, assuming it is already present.
	///
	/// ###Returns
	/// - `Ok` if the edge was present before the call and was removed successfully.
	/// - `Err` if the edge was not found in the graph.
	///
	/// ###`Ok` properties:
	///
	/// - Only the given edge is removed.
	/// - No new edges are introduced.
	/// - No edge weights are changed.
	/// - No new vertices are introduced or removed.
	///
	/// ###`Err` properties:
	///
	/// - The graph is unchanged.
	///
	fn remove_edge(&mut self, e: BaseEdge<Self::Vertex,Self::Weight>) -> Result<(),()>;

	///
	/// Creates a graph containing the given vertices and edges. There can be no
	/// duplicate vertices and all edges must connect to the given vertices.
	///
	/// ###Returns:
	///
	/// - `Ok`: If the given graph description is valid, the created graph is returned.
	/// - `Err`: If the given graph description is invalid.
	///
	fn graph(	vertices: Vec<Self::Vertex>,
			 	edges: Vec<(Self::Vertex, Self::Vertex,Self::Weight)>)
		-> Result<Self,()>
		where
			Self: Sized,
	{
		let mut g = Self::empty_graph();

		/* Add all vertices
		 */
		for v in vertices {
			//Make sure the vertex is added
			g.add_vertex(v)?;
		}

		/* Add all edges
		 */
		for (so,si,w) in edges {
			// Make sure the edge is added
			g.add_edge(BaseEdge::new(so,si,w))?;
		}

		Ok(g)
	}

	///
	/// Returns all edges that are connect to both the given vertices.
	///
	/// I.e. all edges where e == (v1,v2,_) or e == (v2,v1,_)
	///
	fn edges_between(&self, v1: Self::Vertex, v2: Self::Vertex) -> Self::EdgeIter{
		let all_edges = self.all_edges().into_iter();

		// Filter out any edge that is not connected to both vertices
		let relevant = all_edges.filter(|edge|{
			(edge.source == v1 && edge.sink == v2) ||
				(edge.source == v2 && edge.sink == v1)
		});

		// Return the result
		relevant.collect()
	}

}

<|endoftext|>