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

use std::fmt;
use std::num::{zero, one, cast};

use angle::{Angle, Rad, acos, sin, sin_cos};
use approx::ApproxEq;
use array::{Array, build};
use matrix::{Matrix3, ToMatrix3, ToMatrix4, Matrix4};
use point::{Point3};
use rotation::{Rotation, Rotation3, Basis3, ToBasis3};
use vector::{Vector3, Vector, EuclideanVector};
use partial_ord::PartOrdFloat;

/// A quaternion in scalar/vector form
#[deriving(Clone, Eq)]
pub struct Quaternion<S> { pub s: S, pub v: Vector3<S> }

array!(impl<S> Quaternion<S> -> [S, ..4] _4)

pub trait ToQuaternion<S: Float> {
    fn to_quaternion(&self) -> Quaternion<S>;
}

impl<S: PartOrdFloat<S>>
Quaternion<S> {
    /// Construct a new quaternion from one scalar component and three
    /// imaginary components
    #[inline]
    pub fn new(w: S, xi: S, yj: S, zk: S) -> Quaternion<S> {
        Quaternion::from_sv(w, Vector3::new(xi, yj, zk))
    }

    /// Construct a new quaternion from a scalar and a vector
    #[inline]
    pub fn from_sv(s: S, v: Vector3<S>) -> Quaternion<S> {
        Quaternion { s: s, v: v }
    }

    /// The additive identity, ie: `q = 0 + 0i + 0j + 0i`
    #[inline]
    pub fn zero() -> Quaternion<S> {
        Quaternion::new(zero(), zero(), zero(), zero())
    }

    /// The multiplicative identity, ie: `q = 1 + 0i + 0j + 0i`
    #[inline]
    pub fn identity() -> Quaternion<S> {
        Quaternion::from_sv(one::<S>(), Vector3::zero())
    }

    /// The result of multiplying the quaternion a scalar
    #[inline]
    pub fn mul_s(&self, value: S) -> Quaternion<S> {
        Quaternion::from_sv(self.s * value, self.v.mul_s(value))
    }

    /// The result of dividing the quaternion a scalar
    #[inline]
    pub fn div_s(&self, value: S) -> Quaternion<S> {
        Quaternion::from_sv(self.s / value, self.v.div_s(value))
    }

    /// The result of multiplying the quaternion by a vector
    #[inline]
    pub fn mul_v(&self, vec: &Vector3<S>) -> Vector3<S>  {
        let tmp = self.v.cross(vec).add_v(&vec.mul_s(self.s.clone()));
        self.v.cross(&tmp).mul_s(cast(2).unwrap()).add_v(vec)
    }

    /// The sum of this quaternion and `other`
    #[inline]
    pub fn add_q(&self, other: &Quaternion<S>) -> Quaternion<S> {
        build(|i| self.i(i).add(other.i(i)))
    }

    /// The difference between this quaternion and `other`
    #[inline]
    pub fn sub_q(&self, other: &Quaternion<S>) -> Quaternion<S> {
        build(|i| self.i(i).add(other.i(i)))
    }

    /// The the result of multipliplying the quaternion by `other`
    pub fn mul_q(&self, other: &Quaternion<S>) -> Quaternion<S> {
        Quaternion::new(self.s * other.s - self.v.x * other.v.x - self.v.y * other.v.y - self.v.z * other.v.z,
                        self.s * other.v.x + self.v.x * other.s + self.v.y * other.v.z - self.v.z * other.v.y,
                        self.s * other.v.y + self.v.y * other.s + self.v.z * other.v.x - self.v.x * other.v.z,
                        self.s * other.v.z + self.v.z * other.s + self.v.x * other.v.y - self.v.y * other.v.x)
    }

    #[inline]
    pub fn mul_self_s(&mut self, s: S) {
        self.each_mut(|_, x| *x = x.mul(&s))
    }

    #[inline]
    pub fn div_self_s(&mut self, s: S) {
        self.each_mut(|_, x| *x = x.div(&s))
    }

    #[inline]
    pub fn add_self_q(&mut self, other: &Quaternion<S>) {
        self.each_mut(|i, x| *x = x.add(other.i(i)));
    }

    #[inline]
    pub fn sub_self_q(&mut self, other: &Quaternion<S>) {
        self.each_mut(|i, x| *x = x.sub(other.i(i)));
    }

    #[inline]
    pub fn mul_self_q(&mut self, other: &Quaternion<S>) {
        *self = self.mul_q(other);
    }

    /// The dot product of the quaternion and `other`
    #[inline]
    pub fn dot(&self, other: &Quaternion<S>) -> S {
        self.s * other.s + self.v.dot(&other.v)
    }

    /// The conjugate of the quaternion
    #[inline]
    pub fn conjugate(&self) -> Quaternion<S> {
        Quaternion::from_sv(self.s.clone(), -self.v.clone())
    }

    /// The squared magnitude of the quaternion. This is useful for
    /// magnitude comparisons where the exact magnitude does not need to be
    /// calculated.
    #[inline]
    pub fn magnitude2(&self) -> S {
        self.s * self.s + self.v.length2()
    }

    /// The magnitude of the quaternion
    ///
    /// # Performance notes
    ///
    /// For instances where the exact magnitude of the quaternion does not need
    /// to be known, for example for quaternion-quaternion magnitude comparisons,
    /// it is advisable to use the `magnitude2` method instead.
    #[inline]
    pub fn magnitude(&self) -> S {
        self.magnitude2().sqrt()
    }

    /// The normalized quaternion
    #[inline]
    pub fn normalize(&self) -> Quaternion<S> {
        self.mul_s(one::<S>() / self.magnitude())
    }

    /// Normalised linear interpolation
    ///
    /// # Return value
    ///
    /// The intoperlated quaternion
    pub fn nlerp(&self, other: &Quaternion<S>, amount: S) -> Quaternion<S> {
        self.mul_s(one::<S>() - amount).add_q(&other.mul_s(amount)).normalize()
    }
}

impl<S: PartOrdFloat<S>>
Quaternion<S> {
    /// Spherical Linear Intoperlation
    ///
    /// Perform a spherical linear interpolation between the quaternion and
    /// `other`. Both quaternions should be normalized first.
    ///
    /// # Return value
    ///
    /// The intoperlated quaternion
    ///
    /// # Performance notes
    ///
    /// The `acos` operation used in `slerp` is an expensive operation, so unless
    /// your quarternions a far away from each other it's generally more advisable
    /// to use `nlerp` when you know your rotations are going to be small.
    ///
    /// - [Understanding Slerp, Then Not Using It]
    ///   (http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/)
    /// - [Arcsynthesis OpenGL tutorial]
    ///   (http://www.arcsynthesis.org/gltut/Positioning/Tut08%20Interpolation.html)
    pub fn slerp(&self, other: &Quaternion<S>, amount: S) -> Quaternion<S> {
        use std::num::cast;

        let dot = self.dot(other);
        let dot_threshold = cast(0.9995).unwrap();

        // if quaternions are close together use `nlerp`
        if dot > dot_threshold {
            self.nlerp(other, amount)
        } else {
            // stay within the domain of acos()
            // TODO REMOVE WHEN https://github.com/mozilla/rust/issues/12068 IS RESOLVED
            let robust_dot = if dot > one::<S>() {
                one::<S>()
            } else if dot < -one::<S>() {
                -one::<S>()
            } else {
                dot
            };

            let theta: Rad<S> = acos(robust_dot.clone());

            let scale1 = sin(theta.mul_s(one::<S>() - amount));
            let scale2 = sin(theta.mul_s(amount));

            self.mul_s(scale1)
                .add_q(&other.mul_s(scale2))
                .mul_s(sin(theta).recip())
        }
    }
}

impl<S: Float + ApproxEq<S>>
ToMatrix3<S> for Quaternion<S> {
    /// Convert the quaternion to a 3 x 3 rotation matrix
    fn to_matrix3(&self) -> Matrix3<S> {
        let x2 = self.v.x + self.v.x;
        let y2 = self.v.y + self.v.y;
        let z2 = self.v.z + self.v.z;

        let xx2 = x2 * self.v.x;
        let xy2 = x2 * self.v.y;
        let xz2 = x2 * self.v.z;

        let yy2 = y2 * self.v.y;
        let yz2 = y2 * self.v.z;
        let zz2 = z2 * self.v.z;

        let sy2 = y2 * self.s;
        let sz2 = z2 * self.s;
        let sx2 = x2 * self.s;

        Matrix3::new(one::<S>() - yy2 - zz2, xy2 + sz2, xz2 - sy2,
                     xy2 - sz2, one::<S>() - xx2 - zz2, yz2 + sx2,
                     xz2 + sy2, yz2 - sx2, one::<S>() - xx2 - yy2)
    }
}

impl<S: Float + ApproxEq<S>>
ToMatrix4<S> for Quaternion<S> {
    /// Convert the quaternion to a 4 x 4 rotation matrix
    fn to_matrix4(&self) -> Matrix4<S> {
        let x2 = self.v.x + self.v.x;
        let y2 = self.v.y + self.v.y;
        let z2 = self.v.z + self.v.z;

        let xx2 = x2 * self.v.x;
        let xy2 = x2 * self.v.y;
        let xz2 = x2 * self.v.z;

        let yy2 = y2 * self.v.y;
        let yz2 = y2 * self.v.z;
        let zz2 = z2 * self.v.z;

        let sy2 = y2 * self.s;
        let sz2 = z2 * self.s;
        let sx2 = x2 * self.s;

        Matrix4::new(one::<S>() - yy2 - zz2, xy2 + sz2, xz2 - sy2, zero::<S>(),
                     xy2 - sz2, one::<S>() - xx2 - zz2, yz2 + sx2, zero::<S>(),
                     xz2 + sy2, yz2 - sx2, one::<S>() - xx2 - yy2, zero::<S>(),
                     zero::<S>(), zero::<S>(), zero::<S>(), one::<S>())
    }
}

impl<S: PartOrdFloat<S>>
Neg<Quaternion<S>> for Quaternion<S> {
    #[inline]
    fn neg(&self) -> Quaternion<S> {
        Quaternion::from_sv(-self.s, -self.v)
    }
}

impl<S: fmt::Show> fmt::Show for Quaternion<S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} + {}i + {}j + {}k",
                self.s,
                self.v.x,
                self.v.y,
                self.v.z)
    }
}

// Quaternion Rotation impls

impl<S: PartOrdFloat<S>>
ToBasis3<S> for Quaternion<S> {
    #[inline]
    fn to_rot3(&self) -> Basis3<S> { Basis3::from_quaternion(self) }
}

impl<S: Float> ToQuaternion<S> for Quaternion<S> {
    #[inline]
    fn to_quaternion(&self) -> Quaternion<S> { self.clone() }
}

impl<S: PartOrdFloat<S>>
Rotation<S, [S, ..3], Vector3<S>, Point3<S>> for Quaternion<S> {
    #[inline]
    fn identity() -> Quaternion<S> { Quaternion::identity() }

    #[inline]
    fn look_at(dir: &Vector3<S>, up: &Vector3<S>) -> Quaternion<S> {
        Matrix3::look_at(dir, up).to_quaternion()
    }

    #[inline]
    fn between_vectors(a: &Vector3<S>, b: &Vector3<S>) -> Quaternion<S> {
        //http://stackoverflow.com/questions/1171849/
        //finding-quaternion-representing-the-rotation-from-one-vector-to-another
        Quaternion::from_sv(one::<S>() + a.dot(b), a.cross(b)).normalize()
    }

    #[inline]
    fn rotate_vector(&self, vec: &Vector3<S>) -> Vector3<S> { self.mul_v(vec) }

    #[inline]
    fn concat(&self, other: &Quaternion<S>) -> Quaternion<S> { self.mul_q(other) }

    #[inline]
    fn concat_self(&mut self, other: &Quaternion<S>) { self.mul_self_q(other); }

    #[inline]
    fn invert(&self) -> Quaternion<S> { self.conjugate().div_s(self.magnitude2()) }

    #[inline]
    fn invert_self(&mut self) { *self = self.invert() }
}

impl<S: PartOrdFloat<S>>
Rotation3<S> for Quaternion<S>
{
    #[inline]
    fn from_axis_angle(axis: &Vector3<S>, angle: Rad<S>) -> Quaternion<S> {
        let (s, c) = sin_cos(angle.mul_s(cast(0.5).unwrap()));
        Quaternion::from_sv(c, axis.mul_s(s))
    }

    fn from_euler(x: Rad<S>, y: Rad<S>, z: Rad<S>) -> Quaternion<S> {
        // http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles#Conversion
        let (sx2, cx2) = sin_cos(x.mul_s(cast(0.5).unwrap()));
        let (sy2, cy2) = sin_cos(y.mul_s(cast(0.5).unwrap()));
        let (sz2, cz2) = sin_cos(z.mul_s(cast(0.5).unwrap()));

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

use std::fmt;
use std::num::{zero, one, cast};

use angle::{Angle, Rad, acos, sin, sin_cos};
use approx::ApproxEq;
use array::{Array, build};
use matrix::{Matrix3, ToMatrix3, ToMatrix4, Matrix4};
use point::{Point3};
use rotation::{Rotation, Rotation3, Basis3, ToBasis3};
use vector::{Vector3, Vector, EuclideanVector};
use partial_ord::PartOrdFloat;

/// A [quaternion](https://en.wikipedia.org/wiki/Quaternion) in scalar/vector
/// form.
#[deriving(Clone, Eq)]
pub struct Quaternion<S> { pub s: S, pub v: Vector3<S> }

array!(impl<S> Quaternion<S> -> [S, ..4] _4)

/// Represents types which can be expressed as a quaternion.
pub trait ToQuaternion<S: Float> {
    /// Convert this value to a quaternion.
    fn to_quaternion(&self) -> Quaternion<S>;
}

impl<S: PartOrdFloat<S>>
Quaternion<S> {
    /// Construct a new quaternion from one scalar component and three
    /// imaginary components
    #[inline]
    pub fn new(w: S, xi: S, yj: S, zk: S) -> Quaternion<S> {
        Quaternion::from_sv(w, Vector3::new(xi, yj, zk))
    }

    /// Construct a new quaternion from a scalar and a vector
    #[inline]
    pub fn from_sv(s: S, v: Vector3<S>) -> Quaternion<S> {
        Quaternion { s: s, v: v }
    }

    /// The additive identity, ie: `q = 0 + 0i + 0j + 0i`
    #[inline]
    pub fn zero() -> Quaternion<S> {
        Quaternion::new(zero(), zero(), zero(), zero())
    }

    /// The multiplicative identity, ie: `q = 1 + 0i + 0j + 0i`
    #[inline]
    pub fn identity() -> Quaternion<S> {
        Quaternion::from_sv(one::<S>(), Vector3::zero())
    }

    /// The result of multiplying the quaternion a scalar
    #[inline]
    pub fn mul_s(&self, value: S) -> Quaternion<S> {
        Quaternion::from_sv(self.s * value, self.v.mul_s(value))
    }

    /// The result of dividing the quaternion a scalar
    #[inline]
    pub fn div_s(&self, value: S) -> Quaternion<S> {
        Quaternion::from_sv(self.s / value, self.v.div_s(value))
    }

    /// The result of multiplying the quaternion by a vector
    #[inline]
    pub fn mul_v(&self, vec: &Vector3<S>) -> Vector3<S>  {
        let tmp = self.v.cross(vec).add_v(&vec.mul_s(self.s.clone()));
        self.v.cross(&tmp).mul_s(cast(2).unwrap()).add_v(vec)
    }

    /// The sum of this quaternion and `other`
    #[inline]
    pub fn add_q(&self, other: &Quaternion<S>) -> Quaternion<S> {
        build(|i| self.i(i).add(other.i(i)))
    }

    /// The difference between this quaternion and `other`
    #[inline]
    pub fn sub_q(&self, other: &Quaternion<S>) -> Quaternion<S> {
        build(|i| self.i(i).add(other.i(i)))
    }

    /// The result of multipliplying the quaternion by `other`
    pub fn mul_q(&self, other: &Quaternion<S>) -> Quaternion<S> {
        Quaternion::new(self.s * other.s - self.v.x * other.v.x - self.v.y * other.v.y - self.v.z * other.v.z,
                        self.s * other.v.x + self.v.x * other.s + self.v.y * other.v.z - self.v.z * other.v.y,
                        self.s * other.v.y + self.v.y * other.s + self.v.z * other.v.x - self.v.x * other.v.z,
                        self.s * other.v.z + self.v.z * other.s + self.v.x * other.v.y - self.v.y * other.v.x)
    }

    /// Multiply this quaternion by a scalar, in-place.
    #[inline]
    pub fn mul_self_s(&mut self, s: S) {
        self.each_mut(|_, x| *x = x.mul(&s))
    }

    /// Divide this quaternion by a scalar, in-place.
    #[inline]
    pub fn div_self_s(&mut self, s: S) {
        self.each_mut(|_, x| *x = x.div(&s))
    }

    /// Add this quaternion by another, in-place.
    #[inline]
    pub fn add_self_q(&mut self, other: &Quaternion<S>) {
        self.each_mut(|i, x| *x = x.add(other.i(i)));
    }

    /// Subtract another quaternion from this one, in-place.
    #[inline]
    pub fn sub_self_q(&mut self, other: &Quaternion<S>) {
        self.each_mut(|i, x| *x = x.sub(other.i(i)));
    }

    /// Multiply this quaternion by another, in-place.
    #[inline]
    pub fn mul_self_q(&mut self, other: &Quaternion<S>) {
        *self = self.mul_q(other);
    }

    /// The dot product of the quaternion and `other`.
    #[inline]
    pub fn dot(&self, other: &Quaternion<S>) -> S {
        self.s * other.s + self.v.dot(&other.v)
    }

    /// The conjugate of the quaternion.
    #[inline]
    pub fn conjugate(&self) -> Quaternion<S> {
        Quaternion::from_sv(self.s.clone(), -self.v.clone())
    }

    /// The squared magnitude of the quaternion. This is useful for
    /// magnitude comparisons where the exact magnitude does not need to be
    /// calculated.
    #[inline]
    pub fn magnitude2(&self) -> S {
        self.s * self.s + self.v.length2()
    }

    /// The magnitude of the quaternion
    ///
    /// # Performance notes
    ///
    /// For instances where the exact magnitude of the quaternion does not need
    /// to be known, for example for quaternion-quaternion magnitude comparisons,
    /// it is advisable to use the `magnitude2` method instead.
    #[inline]
    pub fn magnitude(&self) -> S {
        self.magnitude2().sqrt()
    }

    /// Normalize this quaternion, returning the new quaternion.
    #[inline]
    pub fn normalize(&self) -> Quaternion<S> {
        self.mul_s(one::<S>() / self.magnitude())
    }

    /// Do a normalized linear interpolation with `other`, by `amount`.
    pub fn nlerp(&self, other: &Quaternion<S>, amount: S) -> Quaternion<S> {
        self.mul_s(one::<S>() - amount).add_q(&other.mul_s(amount)).normalize()
    }
}

impl<S: PartOrdFloat<S>>
Quaternion<S> {
    /// Spherical Linear Intoperlation
    ///
    /// Return the spherical linear interpolation between the quaternion and
    /// `other`. Both quaternions should be normalized first.
    ///
    /// # Performance notes
    ///
    /// The `acos` operation used in `slerp` is an expensive operation, so
    /// unless your quarternions are far away from each other it's generally
    /// more advisable to use `nlerp` when you know your rotations are going
    /// to be small.
    ///
    /// - [Understanding Slerp, Then Not Using It]
    ///   (http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/)
    /// - [Arcsynthesis OpenGL tutorial]
    ///   (http://www.arcsynthesis.org/gltut/Positioning/Tut08%20Interpolation.html)
    pub fn slerp(&self, other: &Quaternion<S>, amount: S) -> Quaternion<S> {
        use std::num::cast;

        let dot = self.dot(other);
        let dot_threshold = cast(0.9995).unwrap();

        // if quaternions are close together use `nlerp`
        if dot > dot_threshold {
            self.nlerp(other, amount)
        } else {
            // stay within the domain of acos()
            // TODO REMOVE WHEN https://github.com/mozilla/rust/issues/12068 IS RESOLVED
            let robust_dot = if dot > one::<S>() {
                one::<S>()
            } else if dot < -one::<S>() {
                -one::<S>()
            } else {
                dot
            };

            let theta: Rad<S> = acos(robust_dot.clone());

            let scale1 = sin(theta.mul_s(one::<S>() - amount));
            let scale2 = sin(theta.mul_s(amount));

            self.mul_s(scale1)
                .add_q(&other.mul_s(scale2))
                .mul_s(sin(theta).recip())
        }
    }
}

impl<S: Float + ApproxEq<S>>
ToMatrix3<S> for Quaternion<S> {
    /// Convert the quaternion to a 3 x 3 rotation matrix
    fn to_matrix3(&self) -> Matrix3<S> {
        let x2 = self.v.x + self.v.x;
        let y2 = self.v.y + self.v.y;
        let z2 = self.v.z + self.v.z;

        let xx2 = x2 * self.v.x;
        let xy2 = x2 * self.v.y;
        let xz2 = x2 * self.v.z;

        let yy2 = y2 * self.v.y;
        let yz2 = y2 * self.v.z;
        let zz2 = z2 * self.v.z;

        let sy2 = y2 * self.s;
        let sz2 = z2 * self.s;
        let sx2 = x2 * self.s;

        Matrix3::new(one::<S>() - yy2 - zz2, xy2 + sz2, xz2 - sy2,
                     xy2 - sz2, one::<S>() - xx2 - zz2, yz2 + sx2,
                     xz2 + sy2, yz2 - sx2, one::<S>() - xx2 - yy2)
    }
}

impl<S: Float + ApproxEq<S>>
ToMatrix4<S> for Quaternion<S> {
    /// Convert the quaternion to a 4 x 4 rotation matrix
    fn to_matrix4(&self) -> Matrix4<S> {
        let x2 = self.v.x + self.v.x;
        let y2 = self.v.y + self.v.y;
        let z2 = self.v.z + self.v.z;

        let xx2 = x2 * self.v.x;
        let xy2 = x2 * self.v.y;
        let xz2 = x2 * self.v.z;

        let yy2 = y2 * self.v.y;
        let yz2 = y2 * self.v.z;
        let zz2 = z2 * self.v.z;

        let sy2 = y2 * self.s;
        let sz2 = z2 * self.s;
        let sx2 = x2 * self.s;

        Matrix4::new(one::<S>() - yy2 - zz2, xy2 + sz2, xz2 - sy2, zero::<S>(),
                     xy2 - sz2, one::<S>() - xx2 - zz2, yz2 + sx2, zero::<S>(),
                     xz2 + sy2, yz2 - sx2, one::<S>() - xx2 - yy2, zero::<S>(),
                     zero::<S>(), zero::<S>(), zero::<S>(), one::<S>())
    }
}

impl<S: PartOrdFloat<S>>
Neg<Quaternion<S>> for Quaternion<S> {
    #[inline]
    fn neg(&self) -> Quaternion<S> {
        Quaternion::from_sv(-self.s, -self.v)
    }
}

impl<S: fmt::Show> fmt::Show for Quaternion<S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} + {}i + {}j + {}k",
                self.s,
                self.v.x,
                self.v.y,
                self.v.z)
    }
}

// Quaternion Rotation impls

impl<S: PartOrdFloat<S>>
ToBasis3<S> for Quaternion<S> {
    #[inline]
    fn to_rot3(&self) -> Basis3<S> { Basis3::from_quaternion(self) }
}

impl<S: Float> ToQuaternion<S> for Quaternion<S> {
    #[inline]
    fn to_quaternion(&self) -> Quaternion<S> { self.clone() }
}

impl<S: PartOrdFloat<S>>
Rotation<S, [S, ..3], Vector3<S>, Point3<S>> for Quaternion<S> {
    #[inline]
    fn identity() -> Quaternion<S> { Quaternion::identity() }

    #[inline]
    fn look_at(dir: &Vector3<S>, up: &Vector3<S>) -> Quaternion<S> {
        Matrix3::look_at(dir, up).to_quaternion()
    }

    #[inline]
    fn between_vectors(a: &Vector3<S>, b: &Vector3<S>) -> Quaternion<S> {
        //http://stackoverflow.com/questions/1171849/
        //finding-quaternion-representing-the-rotation-from-one-vector-to-another
        Quaternion::from_sv(one::<S>() + a.dot(b), a.cross(b)).normalize()
    }

    #[inline]
    fn rotate_vector(&self, vec: &Vector3<S>) -> Vector3<S> { self.mul_v(vec) }

    #[inline]
    fn concat(&self, other: &Quaternion<S>) -> Quaternion<S> { self.mul_q(other) }

    #[inline]
    fn concat_self(&mut self, other: &Quaternion<S>) { self.mul_self_q(other); }

    #[inline]
    fn invert(&self) -> Quaternion<S> { self.conjugate().div_s(self.magnitude2()) }

    #[inline]
    fn invert_self(&mut self) { *self = self.invert() }
}

impl<S: PartOrdFloat<S>>
Rotation3<S> for Quaternion<S>
{
    #[inline]
    fn from_axis_angle(axis: &Vector3<S>, angle: Rad<S>) -> Quaternion<S> {
        let (s, c) = sin_cos(angle.mul_s(cast(0.5).unwrap()));
        Quaternion::from_sv(c, axis.mul_s(s))
    }

    fn from_euler(x: Rad<S>, y: Rad<S>, z: Rad<S>) -> Quaternion<S> {
        // http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles#Conversion
        let (sx2, cx2) = sin_cos(x.mul_s(cast(0.5).unwrap()));
        let (sy2, cy2) = sin_cos(y.mul_s(cast(0.5).unwrap()));
        let (sz2, cz2) = sin_cos(z.mul_s(cast(0.5).unwrap()));

        Quaternion::new(cz2 * cx2 * cy2 + sz2 * sx2 * sy2,
                        sz2 * cx2 * cy2 - cz2 * sx2 * sy2,
                        cz2 * sx2 * cy2 + sz2 * cx2 * sy2,
                        cz2 * cx2 * sy2 - sz2 * sx2 * cy2)
    }
}
<|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use libimagrt::runtime::Runtime;

pub fn day(rt: &Runtime) -> i32 {
    unimplemented!()
}

<commit_msg>Impl "day" command<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use std::cmp::Ord;
use std::cmp::Ordering;
use std::str::FromStr;

use filters::ops::not::Not;
use filters::filter::Filter;
use itertools::Itertools;
use itertools::MinMaxResult;
use chrono::NaiveDateTime;

use libimagerror::trace::trace_error;
use libimagerror::trace::MapErrTrace;
use libimagerror::iter::TraceIterator;
use libimagstore::store::FileLockEntry;
use libimagentrytimetrack::timetrackingstore::TimeTrackStore;
use libimagentrytimetrack::timetracking::TimeTracking;
use libimagentrytimetrack::tag::TimeTrackingTag;
use libimagentrytimetrack::iter::filter::*;

use libimagrt::runtime::Runtime;

pub fn day(rt: &Runtime) -> i32 {
    let (_, cmd) = rt.cli().subcommand();
    let cmd = cmd.unwrap(); // checked in main()

    let filter = {
        let start = match cmd.value_of("start").map(::chrono::naive::NaiveDateTime::from_str) {
            None         => ::chrono::offset::Local::today().and_hms(0, 0, 0).naive_local(),
            Some(Ok(dt)) => dt,
            Some(Err(e)) => {
                trace_error(&e);
                return 1
            }
        };

        let end = match cmd.value_of("end").map(::chrono::naive::NaiveDateTime::from_str) {
            None         => ::chrono::offset::Local::today().and_hms(23, 59, 59).naive_local(),
            Some(Ok(dt)) => dt,
            Some(Err(e)) => {
                trace_error(&e);
                return 1
            }
        };

        let tags = cmd
            .values_of("tags")
            .map(|ts| ts.into_iter().map(String::from).map(TimeTrackingTag::from).collect());

        let start_time_filter = has_start_time_where(move |dt: &NaiveDateTime| {
            start <= *dt
        });

        let end_time_filter = has_end_time_where(move |dt: &NaiveDateTime| {
            end >= *dt
        });

        let tags_filter = move |fle: &FileLockEntry| {
            match tags {
                Some(ref tags) => has_one_of_tags(&tags).filter(fle),
                None => true,
            }
        };

        tags_filter.and(start_time_filter).and(end_time_filter)
    };

    rt.store()
        .get_timetrackings()
        .and_then(|iter| {
            iter.trace_unwrap()
                .filter(|e| filter.filter(e))
                .fold(Ok(()), |acc, e| {
                    acc.and_then(|_| {
                        debug!("Processing {:?}", e.get_location());

                        let tag   = try!(e.get_timetrack_tag());
                        debug!(" -> tag = {:?}", tag);

                        let start = try!(e.get_start_datetime());
                        debug!(" -> start = {:?}", start);

                        let end   = try!(e.get_end_datetime());
                        debug!(" -> end = {:?}", end);

                        match (start, end) {
                            (None, _)          => println!("{} has no start time.", tag),
                            (Some(s), None)    => println!("{} | {} - ...", tag, s),
                            (Some(s), Some(e)) => println!("{} | {} - {}", tag, s, e),
                        }

                        Ok(())
                    })
                })
        })
        .map(|_| 0)
        .map_err_trace()
        .unwrap_or(1)
}

<|endoftext|>


<commit_before>use crate::fmt;
use crate::io::{
    self, Error, ErrorKind, IntoInnerError, IoSlice, Seek, SeekFrom, Write, DEFAULT_BUF_SIZE,
};

/// Wraps a writer and buffers its output.
///
/// It can be excessively inefficient to work directly with something that
/// implements [`Write`]. For example, every call to
/// [`write`][`TcpStream::write`] on [`TcpStream`] results in a system call. A
/// `BufWriter<W>` keeps an in-memory buffer of data and writes it to an underlying
/// writer in large, infrequent batches.
///
/// `BufWriter<W>` can improve the speed of programs that make *small* and
/// *repeated* write calls to the same file or network socket. It does not
/// help when writing very large amounts at once, or writing just one or a few
/// times. It also provides no advantage when writing to a destination that is
/// in memory, like a [`Vec`]<u8>`.
///
/// It is critical to call [`flush`] before `BufWriter<W>` is dropped. Though
/// dropping will attempt to flush the contents of the buffer, any errors
/// that happen in the process of dropping will be ignored. Calling [`flush`]
/// ensures that the buffer is empty and thus dropping will not even attempt
/// file operations.
///
/// # Examples
///
/// Let's write the numbers one through ten to a [`TcpStream`]:
///
/// ```no_run
/// use std::io::prelude::*;
/// use std::net::TcpStream;
///
/// let mut stream = TcpStream::connect("127.0.0.1:34254").unwrap();
///
/// for i in 0..10 {
///     stream.write(&[i+1]).unwrap();
/// }
/// ```
///
/// Because we're not buffering, we write each one in turn, incurring the
/// overhead of a system call per byte written. We can fix this with a
/// `BufWriter<W>`:
///
/// ```no_run
/// use std::io::prelude::*;
/// use std::io::BufWriter;
/// use std::net::TcpStream;
///
/// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
///
/// for i in 0..10 {
///     stream.write(&[i+1]).unwrap();
/// }
/// stream.flush().unwrap();
/// ```
///
/// By wrapping the stream with a `BufWriter<W>`, these ten writes are all grouped
/// together by the buffer and will all be written out in one system call when
/// the `stream` is flushed.
///
/// [`TcpStream::write`]: Write::write
/// [`TcpStream`]: crate::net::TcpStream
/// [`flush`]: Write::flush
#[stable(feature = "rust1", since = "1.0.0")]
pub struct BufWriter<W: Write> {
    inner: Option<W>,
    buf: Vec<u8>,
    // #30888: If the inner writer panics in a call to write, we don't want to
    // write the buffered data a second time in BufWriter's destructor. This
    // flag tells the Drop impl if it should skip the flush.
    panicked: bool,
}

impl<W: Write> BufWriter<W> {
    /// Creates a new `BufWriter<W>` with a default buffer capacity. The default is currently 8 KB,
    /// but may change in the future.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::io::BufWriter;
    /// use std::net::TcpStream;
    ///
    /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn new(inner: W) -> BufWriter<W> {
        BufWriter::with_capacity(DEFAULT_BUF_SIZE, inner)
    }

    /// Creates a new `BufWriter<W>` with the specified buffer capacity.
    ///
    /// # Examples
    ///
    /// Creating a buffer with a buffer of a hundred bytes.
    ///
    /// ```no_run
    /// use std::io::BufWriter;
    /// use std::net::TcpStream;
    ///
    /// let stream = TcpStream::connect("127.0.0.1:34254").unwrap();
    /// let mut buffer = BufWriter::with_capacity(100, stream);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn with_capacity(capacity: usize, inner: W) -> BufWriter<W> {
        BufWriter { inner: Some(inner), buf: Vec::with_capacity(capacity), panicked: false }
    }

    /// Send data in our local buffer into the inner writer, looping as
    /// necessary until either it's all been sent or an error occurs.
    ///
    /// Because all the data in the buffer has been reported to our owner as
    /// "successfully written" (by returning nonzero success values from
    /// `write`), any 0-length writes from `inner` must be reported as i/o
    /// errors from this method.
    pub(super) fn flush_buf(&mut self) -> io::Result<()> {
        /// Helper struct to ensure the buffer is updated after all the writes
        /// are complete. It tracks the number of written bytes and drains them
        /// all from the front of the buffer when dropped.
        struct BufGuard<'a> {
            buffer: &'a mut Vec<u8>,
            written: usize,
        }

        impl<'a> BufGuard<'a> {
            fn new(buffer: &'a mut Vec<u8>) -> Self {
                Self { buffer, written: 0 }
            }

            /// The unwritten part of the buffer
            fn remaining(&self) -> &[u8] {
                &self.buffer[self.written..]
            }

            /// Flag some bytes as removed from the front of the buffer
            fn consume(&mut self, amt: usize) {
                self.written += amt;
            }

            /// true if all of the bytes have been written
            fn done(&self) -> bool {
                self.written >= self.buffer.len()
            }
        }

        impl Drop for BufGuard<'_> {
            fn drop(&mut self) {
                if self.written > 0 {
                    self.buffer.drain(..self.written);
                }
            }
        }

        let mut guard = BufGuard::new(&mut self.buf);
        let inner = self.inner.as_mut().unwrap();
        while !guard.done() {
            self.panicked = true;
            let r = inner.write(guard.remaining());
            self.panicked = false;

            match r {
                Ok(0) => {
                    return Err(Error::new(
                        ErrorKind::WriteZero,
                        "failed to write the buffered data",
                    ));
                }
                Ok(n) => guard.consume(n),
                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
                Err(e) => return Err(e),
            }
        }
        Ok(())
    }

    /// Buffer some data without flushing it, regardless of the size of the
    /// data. Writes as much as possible without exceeding capacity. Returns
    /// the number of bytes written.
    pub(super) fn write_to_buf(&mut self, buf: &[u8]) -> usize {
        let available = self.buf.capacity() - self.buf.len();
        let amt_to_buffer = available.min(buf.len());
        self.buf.extend_from_slice(&buf[..amt_to_buffer]);
        amt_to_buffer
    }

    /// Gets a reference to the underlying writer.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::io::BufWriter;
    /// use std::net::TcpStream;
    ///
    /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
    ///
    /// // we can use reference just like buffer
    /// let reference = buffer.get_ref();
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn get_ref(&self) -> &W {
        self.inner.as_ref().unwrap()
    }

    /// Gets a mutable reference to the underlying writer.
    ///
    /// It is inadvisable to directly write to the underlying writer.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::io::BufWriter;
    /// use std::net::TcpStream;
    ///
    /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
    ///
    /// // we can use reference just like buffer
    /// let reference = buffer.get_mut();
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn get_mut(&mut self) -> &mut W {
        self.inner.as_mut().unwrap()
    }

    /// Returns a reference to the internally buffered data.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::io::BufWriter;
    /// use std::net::TcpStream;
    ///
    /// let buf_writer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
    ///
    /// // See how many bytes are currently buffered
    /// let bytes_buffered = buf_writer.buffer().len();
    /// ```
    #[stable(feature = "bufreader_buffer", since = "1.37.0")]
    pub fn buffer(&self) -> &[u8] {
        &self.buf
    }

    /// Returns the number of bytes the internal buffer can hold without flushing.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::io::BufWriter;
    /// use std::net::TcpStream;
    ///
    /// let buf_writer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
    ///
    /// // Check the capacity of the inner buffer
    /// let capacity = buf_writer.capacity();
    /// // Calculate how many bytes can be written without flushing
    /// let without_flush = capacity - buf_writer.buffer().len();
    /// ```
    #[stable(feature = "buffered_io_capacity", since = "1.46.0")]
    pub fn capacity(&self) -> usize {
        self.buf.capacity()
    }

    /// Unwraps this `BufWriter<W>`, returning the underlying writer.
    ///
    /// The buffer is written out before returning the writer.
    ///
    /// # Errors
    ///
    /// An [`Err`] will be returned if an error occurs while flushing the buffer.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::io::BufWriter;
    /// use std::net::TcpStream;
    ///
    /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
    ///
    /// // unwrap the TcpStream and flush the buffer
    /// let stream = buffer.into_inner().unwrap();
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn into_inner(mut self) -> Result<W, IntoInnerError<BufWriter<W>>> {
        match self.flush_buf() {
            Err(e) => Err(IntoInnerError::new(self, e)),
            Ok(()) => Ok(self.inner.take().unwrap()),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<W: Write> Write for BufWriter<W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        if self.buf.len() + buf.len() > self.buf.capacity() {
            self.flush_buf()?;
        }
        // FIXME: Why no len > capacity? Why not buffer len == capacity? #72919
        if buf.len() >= self.buf.capacity() {
            self.panicked = true;
            let r = self.get_mut().write(buf);
            self.panicked = false;
            r
        } else {
            self.buf.extend_from_slice(buf);
            Ok(buf.len())
        }
    }

    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
        // Normally, `write_all` just calls `write` in a loop. We can do better
        // by calling `self.get_mut().write_all()` directly, which avoids
        // round trips through the buffer in the event of a series of partial
        // writes in some circumstances.
        if self.buf.len() + buf.len() > self.buf.capacity() {
            self.flush_buf()?;
        }
        // FIXME: Why no len > capacity? Why not buffer len == capacity? #72919
        if buf.len() >= self.buf.capacity() {
            self.panicked = true;
            let r = self.get_mut().write_all(buf);
            self.panicked = false;
            r
        } else {
            self.buf.extend_from_slice(buf);
            Ok(())
        }
    }

    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
        let total_len = bufs.iter().map(|b| b.len()).sum::<usize>();
        if self.buf.len() + total_len > self.buf.capacity() {
            self.flush_buf()?;
        }
        // FIXME: Why no len > capacity? Why not buffer len == capacity? #72919
        if total_len >= self.buf.capacity() {
            self.panicked = true;
            let r = self.get_mut().write_vectored(bufs);
            self.panicked = false;
            r
        } else {
            bufs.iter().for_each(|b| self.buf.extend_from_slice(b));
            Ok(total_len)
        }
    }

    fn is_write_vectored(&self) -> bool {
        self.get_ref().is_write_vectored()
    }

    fn flush(&mut self) -> io::Result<()> {
        self.flush_buf().and_then(|()| self.get_mut().flush())
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<W: Write> fmt::Debug for BufWriter<W>
where
    W: fmt::Debug,
{
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt.debug_struct("BufWriter")
            .field("writer", &self.inner.as_ref().unwrap())
            .field("buffer", &format_args!("{}/{}", self.buf.len(), self.buf.capacity()))
            .finish()
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<W: Write + Seek> Seek for BufWriter<W> {
    /// Seek to the offset, in bytes, in the underlying writer.
    ///
    /// Seeking always writes out the internal buffer before seeking.
    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
        self.flush_buf()?;
        self.get_mut().seek(pos)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<W: Write> Drop for BufWriter<W> {
    fn drop(&mut self) {
        if self.inner.is_some() && !self.panicked {
            // dtors should not panic, so we ignore a failed flush
            let _r = self.flush_buf();
        }
    }
}
<commit_msg>Rollup merge of #78394 - rubik:master, r=m-ou-se<commit_after>use crate::fmt;
use crate::io::{
    self, Error, ErrorKind, IntoInnerError, IoSlice, Seek, SeekFrom, Write, DEFAULT_BUF_SIZE,
};

/// Wraps a writer and buffers its output.
///
/// It can be excessively inefficient to work directly with something that
/// implements [`Write`]. For example, every call to
/// [`write`][`TcpStream::write`] on [`TcpStream`] results in a system call. A
/// `BufWriter<W>` keeps an in-memory buffer of data and writes it to an underlying
/// writer in large, infrequent batches.
///
/// `BufWriter<W>` can improve the speed of programs that make *small* and
/// *repeated* write calls to the same file or network socket. It does not
/// help when writing very large amounts at once, or writing just one or a few
/// times. It also provides no advantage when writing to a destination that is
/// in memory, like a [`Vec`]`<u8>`.
///
/// It is critical to call [`flush`] before `BufWriter<W>` is dropped. Though
/// dropping will attempt to flush the contents of the buffer, any errors
/// that happen in the process of dropping will be ignored. Calling [`flush`]
/// ensures that the buffer is empty and thus dropping will not even attempt
/// file operations.
///
/// # Examples
///
/// Let's write the numbers one through ten to a [`TcpStream`]:
///
/// ```no_run
/// use std::io::prelude::*;
/// use std::net::TcpStream;
///
/// let mut stream = TcpStream::connect("127.0.0.1:34254").unwrap();
///
/// for i in 0..10 {
///     stream.write(&[i+1]).unwrap();
/// }
/// ```
///
/// Because we're not buffering, we write each one in turn, incurring the
/// overhead of a system call per byte written. We can fix this with a
/// `BufWriter<W>`:
///
/// ```no_run
/// use std::io::prelude::*;
/// use std::io::BufWriter;
/// use std::net::TcpStream;
///
/// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
///
/// for i in 0..10 {
///     stream.write(&[i+1]).unwrap();
/// }
/// stream.flush().unwrap();
/// ```
///
/// By wrapping the stream with a `BufWriter<W>`, these ten writes are all grouped
/// together by the buffer and will all be written out in one system call when
/// the `stream` is flushed.
///
/// [`TcpStream::write`]: Write::write
/// [`TcpStream`]: crate::net::TcpStream
/// [`flush`]: Write::flush
#[stable(feature = "rust1", since = "1.0.0")]
pub struct BufWriter<W: Write> {
    inner: Option<W>,
    buf: Vec<u8>,
    // #30888: If the inner writer panics in a call to write, we don't want to
    // write the buffered data a second time in BufWriter's destructor. This
    // flag tells the Drop impl if it should skip the flush.
    panicked: bool,
}

impl<W: Write> BufWriter<W> {
    /// Creates a new `BufWriter<W>` with a default buffer capacity. The default is currently 8 KB,
    /// but may change in the future.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::io::BufWriter;
    /// use std::net::TcpStream;
    ///
    /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn new(inner: W) -> BufWriter<W> {
        BufWriter::with_capacity(DEFAULT_BUF_SIZE, inner)
    }

    /// Creates a new `BufWriter<W>` with the specified buffer capacity.
    ///
    /// # Examples
    ///
    /// Creating a buffer with a buffer of a hundred bytes.
    ///
    /// ```no_run
    /// use std::io::BufWriter;
    /// use std::net::TcpStream;
    ///
    /// let stream = TcpStream::connect("127.0.0.1:34254").unwrap();
    /// let mut buffer = BufWriter::with_capacity(100, stream);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn with_capacity(capacity: usize, inner: W) -> BufWriter<W> {
        BufWriter { inner: Some(inner), buf: Vec::with_capacity(capacity), panicked: false }
    }

    /// Send data in our local buffer into the inner writer, looping as
    /// necessary until either it's all been sent or an error occurs.
    ///
    /// Because all the data in the buffer has been reported to our owner as
    /// "successfully written" (by returning nonzero success values from
    /// `write`), any 0-length writes from `inner` must be reported as i/o
    /// errors from this method.
    pub(super) fn flush_buf(&mut self) -> io::Result<()> {
        /// Helper struct to ensure the buffer is updated after all the writes
        /// are complete. It tracks the number of written bytes and drains them
        /// all from the front of the buffer when dropped.
        struct BufGuard<'a> {
            buffer: &'a mut Vec<u8>,
            written: usize,
        }

        impl<'a> BufGuard<'a> {
            fn new(buffer: &'a mut Vec<u8>) -> Self {
                Self { buffer, written: 0 }
            }

            /// The unwritten part of the buffer
            fn remaining(&self) -> &[u8] {
                &self.buffer[self.written..]
            }

            /// Flag some bytes as removed from the front of the buffer
            fn consume(&mut self, amt: usize) {
                self.written += amt;
            }

            /// true if all of the bytes have been written
            fn done(&self) -> bool {
                self.written >= self.buffer.len()
            }
        }

        impl Drop for BufGuard<'_> {
            fn drop(&mut self) {
                if self.written > 0 {
                    self.buffer.drain(..self.written);
                }
            }
        }

        let mut guard = BufGuard::new(&mut self.buf);
        let inner = self.inner.as_mut().unwrap();
        while !guard.done() {
            self.panicked = true;
            let r = inner.write(guard.remaining());
            self.panicked = false;

            match r {
                Ok(0) => {
                    return Err(Error::new(
                        ErrorKind::WriteZero,
                        "failed to write the buffered data",
                    ));
                }
                Ok(n) => guard.consume(n),
                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
                Err(e) => return Err(e),
            }
        }
        Ok(())
    }

    /// Buffer some data without flushing it, regardless of the size of the
    /// data. Writes as much as possible without exceeding capacity. Returns
    /// the number of bytes written.
    pub(super) fn write_to_buf(&mut self, buf: &[u8]) -> usize {
        let available = self.buf.capacity() - self.buf.len();
        let amt_to_buffer = available.min(buf.len());
        self.buf.extend_from_slice(&buf[..amt_to_buffer]);
        amt_to_buffer
    }

    /// Gets a reference to the underlying writer.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::io::BufWriter;
    /// use std::net::TcpStream;
    ///
    /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
    ///
    /// // we can use reference just like buffer
    /// let reference = buffer.get_ref();
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn get_ref(&self) -> &W {
        self.inner.as_ref().unwrap()
    }

    /// Gets a mutable reference to the underlying writer.
    ///
    /// It is inadvisable to directly write to the underlying writer.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::io::BufWriter;
    /// use std::net::TcpStream;
    ///
    /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
    ///
    /// // we can use reference just like buffer
    /// let reference = buffer.get_mut();
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn get_mut(&mut self) -> &mut W {
        self.inner.as_mut().unwrap()
    }

    /// Returns a reference to the internally buffered data.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::io::BufWriter;
    /// use std::net::TcpStream;
    ///
    /// let buf_writer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
    ///
    /// // See how many bytes are currently buffered
    /// let bytes_buffered = buf_writer.buffer().len();
    /// ```
    #[stable(feature = "bufreader_buffer", since = "1.37.0")]
    pub fn buffer(&self) -> &[u8] {
        &self.buf
    }

    /// Returns the number of bytes the internal buffer can hold without flushing.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::io::BufWriter;
    /// use std::net::TcpStream;
    ///
    /// let buf_writer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
    ///
    /// // Check the capacity of the inner buffer
    /// let capacity = buf_writer.capacity();
    /// // Calculate how many bytes can be written without flushing
    /// let without_flush = capacity - buf_writer.buffer().len();
    /// ```
    #[stable(feature = "buffered_io_capacity", since = "1.46.0")]
    pub fn capacity(&self) -> usize {
        self.buf.capacity()
    }

    /// Unwraps this `BufWriter<W>`, returning the underlying writer.
    ///
    /// The buffer is written out before returning the writer.
    ///
    /// # Errors
    ///
    /// An [`Err`] will be returned if an error occurs while flushing the buffer.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::io::BufWriter;
    /// use std::net::TcpStream;
    ///
    /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
    ///
    /// // unwrap the TcpStream and flush the buffer
    /// let stream = buffer.into_inner().unwrap();
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn into_inner(mut self) -> Result<W, IntoInnerError<BufWriter<W>>> {
        match self.flush_buf() {
            Err(e) => Err(IntoInnerError::new(self, e)),
            Ok(()) => Ok(self.inner.take().unwrap()),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<W: Write> Write for BufWriter<W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        if self.buf.len() + buf.len() > self.buf.capacity() {
            self.flush_buf()?;
        }
        // FIXME: Why no len > capacity? Why not buffer len == capacity? #72919
        if buf.len() >= self.buf.capacity() {
            self.panicked = true;
            let r = self.get_mut().write(buf);
            self.panicked = false;
            r
        } else {
            self.buf.extend_from_slice(buf);
            Ok(buf.len())
        }
    }

    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
        // Normally, `write_all` just calls `write` in a loop. We can do better
        // by calling `self.get_mut().write_all()` directly, which avoids
        // round trips through the buffer in the event of a series of partial
        // writes in some circumstances.
        if self.buf.len() + buf.len() > self.buf.capacity() {
            self.flush_buf()?;
        }
        // FIXME: Why no len > capacity? Why not buffer len == capacity? #72919
        if buf.len() >= self.buf.capacity() {
            self.panicked = true;
            let r = self.get_mut().write_all(buf);
            self.panicked = false;
            r
        } else {
            self.buf.extend_from_slice(buf);
            Ok(())
        }
    }

    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
        let total_len = bufs.iter().map(|b| b.len()).sum::<usize>();
        if self.buf.len() + total_len > self.buf.capacity() {
            self.flush_buf()?;
        }
        // FIXME: Why no len > capacity? Why not buffer len == capacity? #72919
        if total_len >= self.buf.capacity() {
            self.panicked = true;
            let r = self.get_mut().write_vectored(bufs);
            self.panicked = false;
            r
        } else {
            bufs.iter().for_each(|b| self.buf.extend_from_slice(b));
            Ok(total_len)
        }
    }

    fn is_write_vectored(&self) -> bool {
        self.get_ref().is_write_vectored()
    }

    fn flush(&mut self) -> io::Result<()> {
        self.flush_buf().and_then(|()| self.get_mut().flush())
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<W: Write> fmt::Debug for BufWriter<W>
where
    W: fmt::Debug,
{
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt.debug_struct("BufWriter")
            .field("writer", &self.inner.as_ref().unwrap())
            .field("buffer", &format_args!("{}/{}", self.buf.len(), self.buf.capacity()))
            .finish()
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<W: Write + Seek> Seek for BufWriter<W> {
    /// Seek to the offset, in bytes, in the underlying writer.
    ///
    /// Seeking always writes out the internal buffer before seeking.
    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
        self.flush_buf()?;
        self.get_mut().seek(pos)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<W: Write> Drop for BufWriter<W> {
    fn drop(&mut self) {
        if self.inner.is_some() && !self.panicked {
            // dtors should not panic, so we ignore a failed flush
            let _r = self.flush_buf();
        }
    }
}
<|endoftext|>


<commit_before>// run-pass

#![feature(untagged_unions)]

#![allow(dead_code)]

use std::mem::needs_drop;
use std::mem::ManuallyDrop;

struct NeedDrop;

impl Drop for NeedDrop {
    fn drop(&mut self) {}
}

// Constant expressions allow `NoDrop` to go out of scope,
// unlike a value of the interior type implementing `Drop`.
static X: () = (NoDrop { inner: ManuallyDrop::new(NeedDrop) }, ()).1;

// A union that scrubs the drop glue from its inner type
union NoDrop<T> { inner: ManuallyDrop<T> }

// Copy currently can't be implemented on drop-containing unions,
// this may change later
// https://github.com/rust-lang/rust/pull/38934#issuecomment-271219289

// // We should be able to implement Copy for NoDrop
// impl<T> Copy for NoDrop<T> {}
// impl<T> Clone for NoDrop<T> {fn clone(&self) -> Self { *self }}

// // We should be able to implement Copy for things using NoDrop
// #[derive(Copy, Clone)]
struct Foo {
    x: NoDrop<Box<u8>>
}

struct Baz {
    x: NoDrop<Box<u8>>,
    y: Box<u8>,
}

union ActuallyDrop<T> { inner: ManuallyDrop<T> }

impl<T> Drop for ActuallyDrop<T> {
    fn drop(&mut self) {}
}

fn main() {
    // NoDrop should not make needs_drop true
    assert!(!needs_drop::<Foo>());
    assert!(!needs_drop::<NoDrop<u8>>());
    assert!(!needs_drop::<NoDrop<Box<u8>>>());
    // presence of other drop types should still work
    assert!(needs_drop::<Baz>());
    // drop impl on union itself should work
    assert!(needs_drop::<ActuallyDrop<u8>>());
    assert!(needs_drop::<ActuallyDrop<Box<u8>>>());
}
<commit_msg>Extend union-nodrop.rs test<commit_after>// run-pass

#![feature(untagged_unions)]

#![allow(dead_code)]

use std::mem::needs_drop;
use std::mem::ManuallyDrop;

struct NeedDrop;

impl Drop for NeedDrop {
    fn drop(&mut self) {}
}

// Constant expressios allow `NoDrop` to go out of scope,
// unlike a value of the interior type implementing `Drop`.
static X: () = (NoDrop { inner: ManuallyDrop::new(NeedDrop) }, ()).1;

const Y: () = (NoDrop { inner: ManuallyDrop::new(NeedDrop) }, ()).1;

const fn _f() { (NoDrop { inner: ManuallyDrop::new(NeedDrop) }, ()).1 }

// A union that scrubs the drop glue from its inner type
union NoDrop<T> { inner: ManuallyDrop<T> }

// Copy currently can't be implemented on drop-containing unions,
// this may change later
// https://github.com/rust-lang/rust/pull/38934#issuecomment-271219289

// // We should be able to implement Copy for NoDrop
// impl<T> Copy for NoDrop<T> {}
// impl<T> Clone for NoDrop<T> {fn clone(&self) -> Self { *self }}

// // We should be able to implement Copy for things using NoDrop
// #[derive(Copy, Clone)]
struct Foo {
    x: NoDrop<Box<u8>>
}

struct Baz {
    x: NoDrop<Box<u8>>,
    y: Box<u8>,
}

union ActuallyDrop<T> { inner: ManuallyDrop<T> }

impl<T> Drop for ActuallyDrop<T> {
    fn drop(&mut self) {}
}

fn main() {
    // NoDrop should not make needs_drop true
    assert!(!needs_drop::<Foo>());
    assert!(!needs_drop::<NoDrop<u8>>());
    assert!(!needs_drop::<NoDrop<Box<u8>>>());
    // presence of other drop types should still work
    assert!(needs_drop::<Baz>());
    // drop impl on union itself should work
    assert!(needs_drop::<ActuallyDrop<u8>>());
    assert!(needs_drop::<ActuallyDrop<Box<u8>>>());
}
<|endoftext|>


<commit_before>// compile-flags:-g

// min-gdb-version: 8.1

// === GDB TESTS ==================================================================================

// gdb-command:run

// gdb-command:print r
// gdb-check:[...]$1 = Rc(strong=2, weak=1) = {value = 42, strong = 2, weak = 1}
// gdb-command:print a
// gdb-check:[...]$2 = Arc(strong=2, weak=1) = {value = 42, strong = 2, weak = 1}

// === LLDB TESTS ==================================================================================

// lldb-command:run

// lldb-command:print r
// lldb-check:[...]$0 = strong=2, weak=1 { value = 42 }
// lldb-command:print a
// lldb-check:[...]$1 = strong=2, weak=1 { data = 42 }

use std::rc::Rc;
use std::sync::Arc;

fn main() {
    let r = Rc::new(42);
    let r1 = Rc::clone(&r);
    let w1 = Rc::downgrade(&r);

    let a = Arc::new(42);
    let a1 = Arc::clone(&a);
    let w2 = Arc::downgrade(&a);

    print!(""); // #break
}
<commit_msg>Auto merge of #75068 - petrochenkov:ignore-debinfo, r=Mark-Simulacrum<commit_after>// ignore-windows pretty-printers are not loaded
// compile-flags:-g

// min-gdb-version: 8.1

// === GDB TESTS ==================================================================================

// gdb-command:run

// gdb-command:print r
// gdb-check:[...]$1 = Rc(strong=2, weak=1) = {value = 42, strong = 2, weak = 1}
// gdb-command:print a
// gdb-check:[...]$2 = Arc(strong=2, weak=1) = {value = 42, strong = 2, weak = 1}

// === LLDB TESTS ==================================================================================

// lldb-command:run

// lldb-command:print r
// lldb-check:[...]$0 = strong=2, weak=1 { value = 42 }
// lldb-command:print a
// lldb-check:[...]$1 = strong=2, weak=1 { data = 42 }

use std::rc::Rc;
use std::sync::Arc;

fn main() {
    let r = Rc::new(42);
    let r1 = Rc::clone(&r);
    let w1 = Rc::downgrade(&r);

    let a = Arc::new(42);
    let a1 = Arc::clone(&a);
    let w2 = Arc::downgrade(&a);

    print!(""); // #break
}
<|endoftext|>


<commit_before>use std::path::Path;

use serde::{
    Deserialize,
    Serialize,
};

use itertools::Itertools;

use anyhow::Result;

use sorted_iter::{
    assume::*,
    SortedPairIterator,
};

use rnc_core::psql::JsonlIterator;

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Accession {
    urs_taxid: String,
    accession: String,
    is_active: bool,
    description: String,
    gene: Option<String>,
    optional_id: Option<String>,
    database: String,
    species: Option<String>,
    common_name: Option<String>,
    feature_name: Option<String>,
    ncrna_class: Option<String>,
    locus_tag: Option<String>,
    organelle: Option<String>,
    lineage: Option<String>,
    all_species: Vec<String>,
    all_common_names: Vec<String>,
    so_rna_type: Option<String>,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct RfamHit {
    #[serde(rename = "id")]
    urs_taxid: String,
    rfam_hit_id: usize,
    model: String,
    model_rna_type: Option<String>,
    model_domain: Option<String>,
    model_name: String,
    model_long_name: String,
    model_completeness: f64,
    model_start: usize,
    model_stop: usize,
    sequence_completeness: f64,
    sequence_start: usize,
    sequence_stop: usize,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct R2dtHit {
    #[serde(rename = "id")]
    urs_taxid: String,
    model_id: usize,
    model_name: String,
    model_source: String,
    model_so_term: Option<String>,
    sequence_coverage: Option<f64>,
    model_coverage: Option<f64>,
    sequence_basepairs: Option<usize>,
    model_basepairs: Option<usize>,
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
pub struct Previous {
    #[serde(rename = "id")]
    urs_taxid: String,
    upi: String,
    taxid: usize,
    databases: Option<String>,
    description: Option<String>,
    has_coordinates: Option<bool>,
    is_active: Option<bool>,
    is_fragment: Option<bool>,
    is_locus_representative: Option<bool>,
    last_release: Option<usize>,
    rfam_problems: Option<String>,
    rna_type: Option<String>,
    short_description: Option<String>,
    so_rna_type: Option<String>,
    update_date: Option<String>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct RawAccessionEntry {
    #[serde(rename = "id")]
    urs_taxid: String,
    accession: String,
    is_active: bool,
    description: String,
    gene: Option<String>,
    optional_id: Option<String>,
    database: String,
    species: Option<String>,
    common_name: Option<String>,
    feature_name: Option<String>,
    ncrna_class: Option<String>,
    locus_tag: Option<String>,
    organelle: Option<String>,
    lineage: Option<String>,
    all_species: Vec<Option<String>>,
    all_common_names: Vec<Option<String>>,
    so_rna_type: Option<String>,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Coordinate {
    #[serde(rename = "id")]
    urs_taxid: String,
    assembly_id: String,
    chromosome: String,
    strand: i8,
    start: usize,
    stop: usize,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Xref {
    #[serde(rename = "id")]
    urs_taxid: String,
    length: usize,
    deleted: String,
    last_release: usize,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Metadata {
    urs_taxid: String,
    upi: String,
    taxid: usize,
    length: usize,
    last_release: usize,
    coordinates: Vec<Coordinate>,
    deleted: bool,
    previous: Option<Previous>,
    rfam_hits: Vec<RfamHit>,
    r2dt_hits: Vec<R2dtHit>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Normalized {
    upi: String,
    taxid: usize,
    length: usize,
    last_release: usize,
    coordinates: Vec<Coordinate>,
    accessions: Vec<Accession>,
    deleted: bool,
    previous: Option<Previous>,
    rfam_hits: Vec<RfamHit>,
    r2dt_hits: Vec<R2dtHit>,
}

impl From<RawAccessionEntry> for Accession {
    fn from(raw: RawAccessionEntry) -> Self {
        return Self {
            urs_taxid: raw.urs_taxid,
            accession: raw.accession,
            is_active: raw.is_active,
            description: raw.description,
            gene: raw.gene,
            optional_id: raw.optional_id,
            database: raw.database,
            species: raw.species,
            common_name: raw.common_name,
            feature_name: raw.feature_name,
            ncrna_class: raw.ncrna_class,
            locus_tag: raw.locus_tag,
            organelle: raw.organelle,
            lineage: raw.lineage,
            all_species: raw.all_species.into_iter().filter_map(|s| s).collect(),
            all_common_names: raw.all_common_names.into_iter().filter_map(|s| s).collect(),
            so_rna_type: raw.so_rna_type,
        };
    }
}

impl Normalized {
    fn new(
        raw_accessions: impl Iterator<Item = RawAccessionEntry>,
        metadata: Metadata,
    ) -> Result<Self> {
        let accessions = raw_accessions.map(Accession::from).collect();
        return Ok(Self {
            upi: metadata.upi,
            taxid: metadata.taxid,
            length: metadata.length,
            last_release: metadata.last_release,
            coordinates: metadata.coordinates,
            accessions,
            deleted: metadata.deleted,
            previous: metadata.previous,
            rfam_hits: metadata.rfam_hits,
            r2dt_hits: metadata.r2dt_hits,
        });
    }
}

impl Metadata {
    fn new(
        urs_taxid: String,
        raw_xrefs: impl Iterator<Item = Xref>,
        raw_coordinates: Option<impl Iterator<Item = Coordinate>>,
        raw_rfam_hits: Option<impl Iterator<Item = RfamHit>>,
        raw_r2dt_hits: Option<impl Iterator<Item = R2dtHit>>,
        raw_previous: Option<impl Iterator<Item = Previous>>,
    ) -> Result<Self> {
        let parts: Vec<&str> = urs_taxid.split("_").collect();
        let upi = parts[0].to_owned();
        let taxid = parts[1].parse::<usize>().unwrap();

        let xrefs: Vec<Xref> = raw_xrefs.collect();

        let coordinates = raw_coordinates.into_iter().flatten().collect();
        let rfam_hits = raw_rfam_hits.into_iter().flatten().collect();
        let r2dt_hits = raw_r2dt_hits.into_iter().flatten().collect();
        let previous: Vec<Previous> = raw_previous.into_iter().flatten().collect();
        let previous = match previous.len() {
            0 => None,
            _ => Some(previous[0].clone()),
        };

        let length = xrefs[0].length;
        let last_release = xrefs.iter().map(|x| x.last_release).max().unwrap();

        let deleted = xrefs.iter().all(|x| x.deleted == "Y");

        return Ok(Self {
            urs_taxid,
            upi,
            taxid,
            length,
            last_release,
            coordinates,
            deleted,
            previous,
            rfam_hits,
            r2dt_hits,
        });
    }
}

pub fn write_metadata(
    coordinate_file: &Path,
    rfam_hits_file: &Path,
    r2dt_hits_file: &Path,
    previous_file: &Path,
    xref_file: &Path,
    output: &Path,
) -> Result<()> {
    let xrefs = JsonlIterator::from_path(xref_file)?;
    let xrefs = xrefs.group_by(|x: &Xref| x.urs_taxid.to_owned());
    let xrefs = xrefs.into_iter().assume_sorted_by_key();

    let coordinates = JsonlIterator::from_path(coordinate_file)?;
    let coordinates = coordinates.group_by(|c: &Coordinate| c.urs_taxid.to_owned());
    let coordinates = coordinates.into_iter().assume_sorted_by_key();

    let rfam_hits = JsonlIterator::from_path(rfam_hits_file)?;
    let rfam_hits = rfam_hits.group_by(|h: &RfamHit| h.urs_taxid.to_owned());
    let rfam_hits = rfam_hits.into_iter().assume_sorted_by_key();

    let r2dt_hits = JsonlIterator::from_path(r2dt_hits_file)?;
    let r2dt_hits = r2dt_hits.group_by(|h: &R2dtHit| h.urs_taxid.to_owned());
    let r2dt_hits = r2dt_hits.into_iter().assume_sorted_by_key();

    let previous = JsonlIterator::from_path(previous_file)?;
    let previous = previous.group_by(|p: &Previous| p.urs_taxid.to_owned());
    let previous = previous.into_iter().assume_sorted_by_key();

    let partial =
        xrefs.left_join(coordinates).left_join(rfam_hits).left_join(r2dt_hits).left_join(previous);

    let mut output = rnc_utils::buf_writer(output)?;
    for (id, data) in partial {
        let ((((xrefs, coordinates), rfam_hits), r2dt_hits), previous) = data;
        let norm = Metadata::new(id, xrefs, coordinates, rfam_hits, r2dt_hits, previous)?;
        serde_json::to_writer(&mut output, &norm)?;
        writeln!(&mut output)?;
    }

    Ok(())
}

pub fn write(accession_file: &Path, metadata_file: &Path, output: &Path) -> Result<()> {
    let accessions = JsonlIterator::from_path(accession_file)?;
    let accessions = accessions.group_by(|a: &RawAccessionEntry| a.urs_taxid.to_owned());
    let accessions = accessions.into_iter().assume_sorted_by_key();

    let metadata = JsonlIterator::from_path(metadata_file)?;
    let metadata = metadata.map(|m: Metadata| (m.urs_taxid.to_owned(), m));
    let metadata = metadata.into_iter().assume_sorted_by_key();

    let partial = accessions.join(metadata);

    let mut output = rnc_utils::buf_writer(output)?;
    for (_id, data) in partial {
        let (accessions, metadata) = data;
        let norm = Normalized::new(accessions, metadata)?;
        serde_json::to_writer(&mut output, &norm)?;
        writeln!(&mut output)?;
    }

    Ok(())
}
<commit_msg>Fix where we get accession active from<commit_after>use std::path::Path;
use std::collections::HashMap;

use serde::{
    Deserialize,
    Serialize,
};

use itertools::Itertools;

use anyhow::Result;

use sorted_iter::{
    assume::*,
    SortedPairIterator,
};

use rnc_core::psql::JsonlIterator;

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Accession {
    urs_taxid: String,
    accession: String,
    is_active: bool,
    description: String,
    gene: Option<String>,
    optional_id: Option<String>,
    database: String,
    species: Option<String>,
    common_name: Option<String>,
    feature_name: Option<String>,
    ncrna_class: Option<String>,
    locus_tag: Option<String>,
    organelle: Option<String>,
    lineage: Option<String>,
    all_species: Vec<String>,
    all_common_names: Vec<String>,
    so_rna_type: Option<String>,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct RfamHit {
    #[serde(rename = "id")]
    urs_taxid: String,
    rfam_hit_id: usize,
    model: String,
    model_rna_type: Option<String>,
    model_domain: Option<String>,
    model_name: String,
    model_long_name: String,
    model_completeness: f64,
    model_start: usize,
    model_stop: usize,
    sequence_completeness: f64,
    sequence_start: usize,
    sequence_stop: usize,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct R2dtHit {
    #[serde(rename = "id")]
    urs_taxid: String,
    model_id: usize,
    model_name: String,
    model_source: String,
    model_so_term: Option<String>,
    sequence_coverage: Option<f64>,
    model_coverage: Option<f64>,
    sequence_basepairs: Option<usize>,
    model_basepairs: Option<usize>,
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
pub struct Previous {
    #[serde(rename = "id")]
    urs_taxid: String,
    upi: String,
    taxid: usize,
    databases: Option<String>,
    description: Option<String>,
    has_coordinates: Option<bool>,
    is_active: Option<bool>,
    is_fragment: Option<bool>,
    is_locus_representative: Option<bool>,
    last_release: Option<usize>,
    rfam_problems: Option<String>,
    rna_type: Option<String>,
    short_description: Option<String>,
    so_rna_type: Option<String>,
    update_date: Option<String>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct RawAccessionEntry {
    #[serde(rename = "id")]
    urs_taxid: String,
    accession: String,
    description: String,
    gene: Option<String>,
    optional_id: Option<String>,
    database: String,
    species: Option<String>,
    common_name: Option<String>,
    feature_name: Option<String>,
    ncrna_class: Option<String>,
    locus_tag: Option<String>,
    organelle: Option<String>,
    lineage: Option<String>,
    all_species: Vec<Option<String>>,
    all_common_names: Vec<Option<String>>,
    so_rna_type: Option<String>,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Coordinate {
    #[serde(rename = "id")]
    urs_taxid: String,
    assembly_id: String,
    chromosome: String,
    strand: i8,
    start: usize,
    stop: usize,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Xref {
    #[serde(rename = "id")]
    urs_taxid: String,
    length: usize,
    deleted: String,
    last_release: usize,
    accession: String,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Metadata {
    urs_taxid: String,
    upi: String,
    taxid: usize,
    length: usize,
    last_release: usize,
    coordinates: Vec<Coordinate>,
    deleted: bool,
    previous: Option<Previous>,
    rfam_hits: Vec<RfamHit>,
    r2dt_hits: Vec<R2dtHit>,
    active_mapping: HashMap<String, bool>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Normalized {
    upi: String,
    taxid: usize,
    length: usize,
    last_release: usize,
    coordinates: Vec<Coordinate>,
    accessions: Vec<Accession>,
    deleted: bool,
    previous: Option<Previous>,
    rfam_hits: Vec<RfamHit>,
    r2dt_hits: Vec<R2dtHit>,
}

impl From<(RawAccessionEntry, bool)> for Accession {
    fn from(given: (RawAccessionEntry, bool)) -> Self {
        let (raw, is_active) = given;
        return Self {
            urs_taxid: raw.urs_taxid,
            accession: raw.accession,
            is_active,
            description: raw.description,
            gene: raw.gene,
            optional_id: raw.optional_id,
            database: raw.database,
            species: raw.species,
            common_name: raw.common_name,
            feature_name: raw.feature_name,
            ncrna_class: raw.ncrna_class,
            locus_tag: raw.locus_tag,
            organelle: raw.organelle,
            lineage: raw.lineage,
            all_species: raw.all_species.into_iter().filter_map(|s| s).collect(),
            all_common_names: raw.all_common_names.into_iter().filter_map(|s| s).collect(),
            so_rna_type: raw.so_rna_type,
        };
    }
}

impl Xref {
    fn is_active(&self) -> bool {
        self.deleted == "N"
    }
}

impl Normalized {
    fn new(
        raw_accessions: impl Iterator<Item = RawAccessionEntry>,
        metadata: Metadata,
    ) -> Result<Self> {
        let accessions = raw_accessions.map(|a: RawAccessionEntry| {
            let is_active = metadata.active_mapping.get(&a.urs_taxid).unwrap();
            Accession::from((a, is_active.clone()))
        }).collect();
        return Ok(Self {
            upi: metadata.upi,
            taxid: metadata.taxid,
            length: metadata.length,
            last_release: metadata.last_release,
            coordinates: metadata.coordinates,
            accessions,
            deleted: metadata.deleted,
            previous: metadata.previous,
            rfam_hits: metadata.rfam_hits,
            r2dt_hits: metadata.r2dt_hits,
        });
    }
}

impl Metadata {
    fn new(
        urs_taxid: String,
        raw_xrefs: impl Iterator<Item = Xref>,
        raw_coordinates: Option<impl Iterator<Item = Coordinate>>,
        raw_rfam_hits: Option<impl Iterator<Item = RfamHit>>,
        raw_r2dt_hits: Option<impl Iterator<Item = R2dtHit>>,
        raw_previous: Option<impl Iterator<Item = Previous>>,
    ) -> Result<Self> {
        let parts: Vec<&str> = urs_taxid.split("_").collect();
        let upi = parts[0].to_owned();
        let taxid = parts[1].parse::<usize>().unwrap();

        let xrefs: Vec<Xref> = raw_xrefs.collect();
        let mut active_mapping: HashMap<String, bool> = HashMap::new();
        for xref in &xrefs {
            active_mapping.insert(xref.accession.to_owned(), xref.is_active());
        }

        let coordinates = raw_coordinates.into_iter().flatten().collect();
        let rfam_hits = raw_rfam_hits.into_iter().flatten().collect();
        let r2dt_hits = raw_r2dt_hits.into_iter().flatten().collect();
        let previous: Vec<Previous> = raw_previous.into_iter().flatten().collect();
        let previous = match previous.len() {
            0 => None,
            _ => Some(previous[0].clone()),
        };

        let length = xrefs[0].length;
        let last_release = xrefs.iter().map(|x| x.last_release).max().unwrap();

        let deleted = xrefs.iter().all(|x| x.deleted == "Y");

        return Ok(Self {
            urs_taxid,
            upi,
            taxid,
            length,
            last_release,
            coordinates,
            deleted,
            previous,
            rfam_hits,
            r2dt_hits,
            active_mapping,
        });
    }
}

pub fn write_metadata(
    coordinate_file: &Path,
    rfam_hits_file: &Path,
    r2dt_hits_file: &Path,
    previous_file: &Path,
    xref_file: &Path,
    output: &Path,
) -> Result<()> {
    let xrefs = JsonlIterator::from_path(xref_file)?;
    let xrefs = xrefs.group_by(|x: &Xref| x.urs_taxid.to_owned());
    let xrefs = xrefs.into_iter().assume_sorted_by_key();

    let coordinates = JsonlIterator::from_path(coordinate_file)?;
    let coordinates = coordinates.group_by(|c: &Coordinate| c.urs_taxid.to_owned());
    let coordinates = coordinates.into_iter().assume_sorted_by_key();

    let rfam_hits = JsonlIterator::from_path(rfam_hits_file)?;
    let rfam_hits = rfam_hits.group_by(|h: &RfamHit| h.urs_taxid.to_owned());
    let rfam_hits = rfam_hits.into_iter().assume_sorted_by_key();

    let r2dt_hits = JsonlIterator::from_path(r2dt_hits_file)?;
    let r2dt_hits = r2dt_hits.group_by(|h: &R2dtHit| h.urs_taxid.to_owned());
    let r2dt_hits = r2dt_hits.into_iter().assume_sorted_by_key();

    let previous = JsonlIterator::from_path(previous_file)?;
    let previous = previous.group_by(|p: &Previous| p.urs_taxid.to_owned());
    let previous = previous.into_iter().assume_sorted_by_key();

    let partial =
        xrefs.left_join(coordinates).left_join(rfam_hits).left_join(r2dt_hits).left_join(previous);

    let mut output = rnc_utils::buf_writer(output)?;
    for (id, data) in partial {
        let ((((xrefs, coordinates), rfam_hits), r2dt_hits), previous) = data;
        let norm = Metadata::new(id, xrefs, coordinates, rfam_hits, r2dt_hits, previous)?;
        serde_json::to_writer(&mut output, &norm)?;
        writeln!(&mut output)?;
    }

    Ok(())
}

pub fn write(accession_file: &Path, metadata_file: &Path, output: &Path) -> Result<()> {
    let accessions = JsonlIterator::from_path(accession_file)?;
    let accessions = accessions.group_by(|a: &RawAccessionEntry| a.urs_taxid.to_owned());
    let accessions = accessions.into_iter().assume_sorted_by_key();

    let metadata = JsonlIterator::from_path(metadata_file)?;
    let metadata = metadata.map(|m: Metadata| (m.urs_taxid.to_owned(), m));
    let metadata = metadata.into_iter().assume_sorted_by_key();

    let partial = accessions.join(metadata);

    let mut output = rnc_utils::buf_writer(output)?;
    for (_id, data) in partial {
        let (accessions, metadata) = data;
        let norm = Normalized::new(accessions, metadata)?;
        serde_json::to_writer(&mut output, &norm)?;
        writeln!(&mut output)?;
    }

    Ok(())
}
<|endoftext|>


<commit_before>s! {
    pub struct shmid_ds {
        pub shm_perm: ::ipc_perm,
        pub shm_segsz: ::size_t,
        pub shm_amp: *mut ::c_void,
        pub shm_lkcnt: ::c_ushort,
        pub shm_lpid: ::pid_t,
        pub shm_cpid: ::pid_t,
        pub shm_nattch: ::shmatt_t,
        pub shm_cnattch: ::c_ulong,
        pub shm_atime: ::time_t,
        pub shm_dtime: ::time_t,
        pub shm_ctime: ::time_t,
        pub shm_pad4: [i64; 4],
    }
}

pub const AF_LOCAL: ::c_int = 1; // AF_UNIX
pub const AF_FILE: ::c_int = 1; // AF_UNIX

pub const EFD_SEMAPHORE: ::c_int = 0x1;
pub const EFD_NONBLOCK: ::c_int = 0x800;
pub const EFD_CLOEXEC: ::c_int = 0x80000;

pub const TCP_KEEPIDLE: ::c_int = 34;
pub const TCP_KEEPCNT: ::c_int = 35;
pub const TCP_KEEPINTVL: ::c_int = 36;
pub const TCP_CONGESTION: ::c_int = 37;

pub const F_OFD_GETLK: ::c_int = 50;
pub const F_OFD_SETLKL: ::c_int = 51;
pub const F_OFD_SETLKW: ::c_int = 52;
pub const F_FLOCK: ::c_int = 55;
pub const F_FLOCKW: ::c_int = 56;

pub const MR_HDR_AOUT: ::c_uint = 0x3;

extern "C" {
    pub fn eventfd(init: ::c_uint, flags: ::c_int) -> ::c_int;

    pub fn mincore(addr: ::caddr_t, len: ::size_t, vec: *mut ::c_char) -> ::c_int;

    pub fn pset_bind_lwp(
        pset: ::psetid_t,
        id: ::id_t,
        pid: ::pid_t,
        opset: *mut ::psetid_t,
    ) -> ::c_int;
    pub fn pset_getloadavg(pset: ::psetid_t, load: *mut ::c_double, num: ::c_int) -> ::c_int;

    pub fn preadv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) -> ::ssize_t;
    pub fn pwritev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t)
        -> ::ssize_t;
    pub fn getpagesizes2(pagesize: *mut ::size_t, nelem: ::c_int) -> ::c_int;
}
<commit_msg>Auto merge of #2609 - devnexen:solarish_sol_filter, r=Amanieu<commit_after>s! {
    pub struct shmid_ds {
        pub shm_perm: ::ipc_perm,
        pub shm_segsz: ::size_t,
        pub shm_amp: *mut ::c_void,
        pub shm_lkcnt: ::c_ushort,
        pub shm_lpid: ::pid_t,
        pub shm_cpid: ::pid_t,
        pub shm_nattch: ::shmatt_t,
        pub shm_cnattch: ::c_ulong,
        pub shm_atime: ::time_t,
        pub shm_dtime: ::time_t,
        pub shm_ctime: ::time_t,
        pub shm_pad4: [i64; 4],
    }

    pub struct fil_info {
        pub fi_flags: ::c_int,
        pub fi_pos: ::c_int,
        pub fi_name: [::c_char; ::FILNAME_MAX as usize],
    }
}

pub const AF_LOCAL: ::c_int = 1; // AF_UNIX
pub const AF_FILE: ::c_int = 1; // AF_UNIX

pub const EFD_SEMAPHORE: ::c_int = 0x1;
pub const EFD_NONBLOCK: ::c_int = 0x800;
pub const EFD_CLOEXEC: ::c_int = 0x80000;

pub const TCP_KEEPIDLE: ::c_int = 34;
pub const TCP_KEEPCNT: ::c_int = 35;
pub const TCP_KEEPINTVL: ::c_int = 36;
pub const TCP_CONGESTION: ::c_int = 37;

pub const F_OFD_GETLK: ::c_int = 50;
pub const F_OFD_SETLKL: ::c_int = 51;
pub const F_OFD_SETLKW: ::c_int = 52;
pub const F_FLOCK: ::c_int = 55;
pub const F_FLOCKW: ::c_int = 56;

pub const FIL_ATTACH: ::c_int = 0x1;
pub const FIL_DETACH: ::c_int = 0x2;
pub const FIL_LIST: ::c_int = 0x3;
pub const FILNAME_MAX: ::c_int = 32;
pub const FILF_PROG: ::c_int = 0x1;
pub const FILF_AUTO: ::c_int = 0x2;
pub const FILF_BYPASS: ::c_int = 0x4;
pub const SOL_FILTER: ::c_int = 0xfffc;

pub const MR_HDR_AOUT: ::c_uint = 0x3;

extern "C" {
    pub fn eventfd(init: ::c_uint, flags: ::c_int) -> ::c_int;

    pub fn mincore(addr: ::caddr_t, len: ::size_t, vec: *mut ::c_char) -> ::c_int;

    pub fn pset_bind_lwp(
        pset: ::psetid_t,
        id: ::id_t,
        pid: ::pid_t,
        opset: *mut ::psetid_t,
    ) -> ::c_int;
    pub fn pset_getloadavg(pset: ::psetid_t, load: *mut ::c_double, num: ::c_int) -> ::c_int;

    pub fn preadv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) -> ::ssize_t;
    pub fn pwritev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t)
        -> ::ssize_t;
    pub fn getpagesizes2(pagesize: *mut ::size_t, nelem: ::c_int) -> ::c_int;
}
<|endoftext|>


<commit_before>use typedef::*;

/// A preamble to identify bakervm images
pub const PREAMBLE: &str = "BAKER1";

/// Stops the program and shuts down the vm
///
/// # Example
///
/// ```
/// halt
/// ```
pub const HALT: Byte = 0x01;

/// Adds the two top most values and pushes the result back to the data stack.
/// This also removes the processed values from the data stack.
///
/// # Example
///
/// ```
/// add
/// ```
pub const ADD: Byte = 0x02;

/// Subtracts the first value on the data stack from the second and pushes the
/// result back to the data stack. This also removes the processed values from
/// the data stack.
///
/// # Example
///
/// ```
/// sub
/// ```
pub const SUB: Byte = 0x03;

/// Adds the two top most values and pushes the result back to the data stack.
/// This also removes the processed values from the data stack.
///
/// # Example
///
/// ```
/// mul
/// ```
pub const MUL: Byte = 0x04;

/// Divides the second value on the data stack throuh the first one and pushes
/// the result back to the top of the data stack. This also removes the
/// processed values from the data stack.
///
/// # Example
///
/// ```
/// div
/// ```
pub const DIV: Byte = 0x05;

/// Prints out the top most value on the data stack
#[deprecated(since="0.1.0", note="will be replaced soon")]
pub const PRINT: Byte = 0x06;

/// Pushes a value (Word) to the data stack
///
/// # Example
///
/// ```
/// push WORD
/// ```
pub const PUSH: Byte = 0x07;

/// An unconditional jump to the specified address
///
/// # Example
///
/// ```
/// jmp ADDRESS
/// ```
pub const JMP: Byte = 0x08;

/// Jumps to the specified address if the top most value on the data stack
/// equals 0
///
/// # Example
///
/// ```
/// jz ADDRESS
/// ```
pub const JZ: Byte = 0x09;

/// Jumps to the specified address if the top most value on the data stack is
/// not equal to 0
///
/// # Example
///
/// ```
/// jnz ADDRESS
/// ```
pub const JNZ: Byte = 0x0A;

/// Moves the specified value (Word) to the specified register (Address)
///
/// # Example
///
/// ```
/// movw WORD, ADDRESS
/// ```
pub const MOVW: Byte = 0x0B;

/// Moves the specified value (SmallWord) to the specified register (Address)
///
/// # Example
///
/// ```
/// movs SMALLWORD, ADDRESS
/// ```
pub const MOVS: Byte = 0x0C;

/// Moves the specified value (TinyWord) to the specified register (Address)
///
/// # Example
///
/// ```
/// movt TINYWORD, ADDRESS
/// ```
pub const MOVT: Byte = 0x0D;

/// Moves the specified value (Byte) to the specified register (Address)
///
/// # Example
///
/// ```
/// movb BYTE, ADDRESS
/// ```
pub const MOVB: Byte = 0x0E;

/// Moves the value in the specified buffer register (Address) to the otherwise
/// specified buffer register (Address)
///
/// # Example
///
/// ```
/// mov ADDRESS, ADDRESS
/// ```
pub const MOV: Byte = 0x0F;

/// Moves the top most value of the data stack to the specified register
/// (Address)
///
/// # Example
///
/// ```
/// smov ADDRESS
/// ```
pub const SMOV: Byte = 0x10;

/// Registers an interrupt callback by mapping the specified signal_id to the
/// given function call address
///
/// # Example
///
/// ```
/// regi WORD, ADDRESS
/// ```
pub const REGI: Byte = 0x11;

/// Calls a function while pushing the return address to the return stack
///
/// # Example
///
/// ```
/// call ADDRESS
/// ```
pub const CALL: Byte = 0x12;

/// Returns from a function. The return value is pushed to the data stack
///
/// # Example
///
/// ```
/// ret
/// ```
pub const RET: Byte = 0x13;
<commit_msg>Added yield bytecode<commit_after>use typedef::*;

/// A preamble to identify bakervm images
pub const PREAMBLE: &str = "BAKER1";

/// Stops the program and shuts down the vm
///
/// # Example
///
/// ```
/// halt
/// ```
pub const HALT: Byte = 0x01;

/// Adds the two top most values and pushes the result back to the data stack.
/// This also removes the processed values from the data stack.
///
/// # Example
///
/// ```
/// add
/// ```
pub const ADD: Byte = 0x02;

/// Subtracts the first value on the data stack from the second and pushes the
/// result back to the data stack. This also removes the processed values from
/// the data stack.
///
/// # Example
///
/// ```
/// sub
/// ```
pub const SUB: Byte = 0x03;

/// Adds the two top most values and pushes the result back to the data stack.
/// This also removes the processed values from the data stack.
///
/// # Example
///
/// ```
/// mul
/// ```
pub const MUL: Byte = 0x04;

/// Divides the second value on the data stack throuh the first one and pushes
/// the result back to the top of the data stack. This also removes the
/// processed values from the data stack.
///
/// # Example
///
/// ```
/// div
/// ```
pub const DIV: Byte = 0x05;

/// Prints out the top most value on the data stack
#[deprecated(since="0.1.0", note="will be replaced soon")]
pub const PRINT: Byte = 0x06;

/// Pushes a value (Word) to the data stack
///
/// # Example
///
/// ```
/// push WORD
/// ```
pub const PUSH: Byte = 0x07;

/// An unconditional jump to the specified address
///
/// # Example
///
/// ```
/// jmp ADDRESS
/// ```
pub const JMP: Byte = 0x08;

/// Jumps to the specified address if the top most value on the data stack
/// equals 0
///
/// # Example
///
/// ```
/// jz ADDRESS
/// ```
pub const JZ: Byte = 0x09;

/// Jumps to the specified address if the top most value on the data stack is
/// not equal to 0
///
/// # Example
///
/// ```
/// jnz ADDRESS
/// ```
pub const JNZ: Byte = 0x0A;

/// Moves the specified value (Word) to the specified register (Address)
///
/// # Example
///
/// ```
/// movw WORD, ADDRESS
/// ```
pub const MOVW: Byte = 0x0B;

/// Moves the specified value (SmallWord) to the specified register (Address)
///
/// # Example
///
/// ```
/// movs SMALLWORD, ADDRESS
/// ```
pub const MOVS: Byte = 0x0C;

/// Moves the specified value (TinyWord) to the specified register (Address)
///
/// # Example
///
/// ```
/// movt TINYWORD, ADDRESS
/// ```
pub const MOVT: Byte = 0x0D;

/// Moves the specified value (Byte) to the specified register (Address)
///
/// # Example
///
/// ```
/// movb BYTE, ADDRESS
/// ```
pub const MOVB: Byte = 0x0E;

/// Moves the value in the specified buffer register (Address) to the otherwise
/// specified buffer register (Address)
///
/// # Example
///
/// ```
/// mov ADDRESS, ADDRESS
/// ```
pub const MOV: Byte = 0x0F;

/// Moves the top most value of the data stack to the specified register
/// (Address)
///
/// # Example
///
/// ```
/// smov ADDRESS
/// ```
pub const SMOV: Byte = 0x10;

/// Registers an interrupt callback by mapping the specified signal_id to the
/// given function call address
///
/// # Example
///
/// ```
/// regi WORD, ADDRESS
/// ```
pub const REGI: Byte = 0x11;

/// Calls a function while pushing the return address to the return stack
///
/// # Example
///
/// ```
/// call ADDRESS
/// ```
pub const CALL: Byte = 0x12;

/// Returns from a function. The return value is pushed to the data stack
///
/// # Example
///
/// ```
/// ret
/// ```
pub const RET: Byte = 0x13;

/// Pushes a value from the data stack as a return value to the return value
/// stack. This also tracks the number of return values yielded when `ret` is
/// called
///
/// # Examples
///
/// ```
/// yld
/// ```
pub const YLD: Byte = 0x14;
<|endoftext|>


<commit_before>#[macro_use]
extern crate nom;
extern crate proc_macro;
extern crate quote;
extern crate syn;

use proc_macro::TokenStream;

mod generator;
mod parser;
mod path;

#[proc_macro_derive(Template, attributes(template))]
pub fn derive_template(input: TokenStream) -> TokenStream {
    let ast = syn::parse_derive_input(&input.to_string()).unwrap();
    match ast.body {
        syn::Body::Struct(ref data) => data,
        _ => panic!("#[derive(Template)] can only be used with structs"),
    };
    build_template(&ast).parse().unwrap()
}

/// Takes a `syn::DeriveInput` and generates source code for it
///
/// Reads the metadata from the `template()` attribute to get the template
/// metadata, then fetches the source from the filesystem. The source is
/// parsed, and the parse tree is fed to the code generator. Will print
/// the parse tree and/or generated source according to the `print` key's
/// value as passed to the `template()` attribute.
fn build_template(ast: &syn::DeriveInput) -> String {
    let meta = get_template_meta(ast);
    let path = path::find_template_from_path(&meta.path, None);
    let src = path::get_template_source(&path);
    let nodes = parser::parse(&src);
    if meta.print == Print::Ast || meta.print == Print::All {
        println!("{:?}", nodes);
    }
    let code = generator::generate(ast, &meta.path, nodes);
    if meta.print == Print::Code || meta.print == Print::All {
        println!("{}", code);
    }
    code
}

// Returns a `TemplateMeta` based on the `template()` attribute data found
// in the parsed struct or enum. Will panic if it does not find the required
// template path, or if the `print` key has an unexpected value.
fn get_template_meta(ast: &syn::DeriveInput) -> TemplateMeta {
    let attr = ast.attrs.iter().find(|a| a.name() == "template");
    if attr.is_none() {
        let msg = format!("'template' attribute not found on struct '{}'",
                          ast.ident.as_ref());
        panic!(msg);
    }

    let attr = attr.unwrap();
    let mut path = None;
    let mut print = Print::None;
    if let syn::MetaItem::List(_, ref inner) = attr.value {
        for nm_item in inner {
            if let syn::NestedMetaItem::MetaItem(ref item) = *nm_item {
                if let syn::MetaItem::NameValue(ref key, ref val) = *item {
                    match key.as_ref() {
                        "path" => if let syn::Lit::Str(ref s, _) = *val {
                            path = Some(s.clone());
                        } else {
                            panic!("template path must be string literal");
                        },
                        "print" => if let syn::Lit::Str(ref s, _) = *val {
                            print = s.into();
                        } else {
                            panic!("print value must be string literal");
                        },
                        _ => { panic!("unsupported annotation key found") }
                    }
                }
            }
        }
    }
    if path.is_none() {
        panic!("template path not found in struct attributes");
    }
    TemplateMeta { path: path.unwrap(), print: print }
}

// Holds metadata for the template, based on the `template()` attribute.
struct TemplateMeta {
    path: String,
    print: Print,
}

#[derive(PartialEq)]
enum Print {
    All,
    Ast,
    Code,
    None,
}

impl<'a> From<&'a String> for Print {
    fn from(s: &'a String) -> Print {
        use Print::*;
        match s.as_ref() {
            "all" => All,
            "ast" => Ast,
            "code" => Code,
            "none" => None,
            v => panic!("invalid value for print option: {}", v),
        }
    }
}
<commit_msg>Use reference into AST for template path instead of cloning<commit_after>#[macro_use]
extern crate nom;
extern crate proc_macro;
extern crate quote;
extern crate syn;

use proc_macro::TokenStream;

mod generator;
mod parser;
mod path;

#[proc_macro_derive(Template, attributes(template))]
pub fn derive_template(input: TokenStream) -> TokenStream {
    let ast = syn::parse_derive_input(&input.to_string()).unwrap();
    match ast.body {
        syn::Body::Struct(ref data) => data,
        _ => panic!("#[derive(Template)] can only be used with structs"),
    };
    build_template(&ast).parse().unwrap()
}

/// Takes a `syn::DeriveInput` and generates source code for it
///
/// Reads the metadata from the `template()` attribute to get the template
/// metadata, then fetches the source from the filesystem. The source is
/// parsed, and the parse tree is fed to the code generator. Will print
/// the parse tree and/or generated source according to the `print` key's
/// value as passed to the `template()` attribute.
fn build_template(ast: &syn::DeriveInput) -> String {
    let meta = get_template_meta(ast);
    let path = path::find_template_from_path(&meta.path, None);
    let src = path::get_template_source(&path);
    let nodes = parser::parse(&src);
    if meta.print == Print::Ast || meta.print == Print::All {
        println!("{:?}", nodes);
    }
    let code = generator::generate(ast, &meta.path, nodes);
    if meta.print == Print::Code || meta.print == Print::All {
        println!("{}", code);
    }
    code
}

// Returns a `TemplateMeta` based on the `template()` attribute data found
// in the parsed struct or enum. Will panic if it does not find the required
// template path, or if the `print` key has an unexpected value.
fn get_template_meta<'a>(ast: &'a syn::DeriveInput) -> TemplateMeta<'a> {
    let attr = ast.attrs.iter().find(|a| a.name() == "template");
    if attr.is_none() {
        let msg = format!("'template' attribute not found on struct '{}'",
                          ast.ident.as_ref());
        panic!(msg);
    }

    let attr = attr.unwrap();
    let mut path = None;
    let mut print = Print::None;
    if let syn::MetaItem::List(_, ref inner) = attr.value {
        for nm_item in inner {
            if let syn::NestedMetaItem::MetaItem(ref item) = *nm_item {
                if let syn::MetaItem::NameValue(ref key, ref val) = *item {
                    match key.as_ref() {
                        "path" => if let syn::Lit::Str(ref s, _) = *val {
                            path = Some(s.as_ref());
                        } else {
                            panic!("template path must be string literal");
                        },
                        "print" => if let syn::Lit::Str(ref s, _) = *val {
                            print = s.into();
                        } else {
                            panic!("print value must be string literal");
                        },
                        _ => { panic!("unsupported annotation key found") }
                    }
                }
            }
        }
    }
    if path.is_none() {
        panic!("template path not found in struct attributes");
    }
    TemplateMeta { path: path.unwrap(), print: print }
}

// Holds metadata for the template, based on the `template()` attribute.
struct TemplateMeta<'a> {
    path: &'a str,
    print: Print,
}

#[derive(PartialEq)]
enum Print {
    All,
    Ast,
    Code,
    None,
}

impl<'a> From<&'a String> for Print {
    fn from(s: &'a String) -> Print {
        use Print::*;
        match s.as_ref() {
            "all" => All,
            "ast" => Ast,
            "code" => Code,
            "none" => None,
            v => panic!("invalid value for print option: {}", v),
        }
    }
}
<|endoftext|>