<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Computed types for CSS values that are related to transformations.

use app_units::Au;
use euclid::{Rect, Transform3D, Vector3D};
use properties::longhands::transform::computed_value::{ComputedOperation, ComputedMatrix};
use properties::longhands::transform::computed_value::T as TransformList;
use std::f32;
use super::CSSFloat;
use values::computed::{Angle, Integer, Length, LengthOrPercentage, Number, Percentage};
use values::computed::{LengthOrNumber, LengthOrPercentageOrNumber};
use values::generics::transform::TimingFunction as GenericTimingFunction;
use values::generics::transform::{Transform as GenericTransform, TransformOperation as GenericTransformOperation};
use values::generics::transform::TransformOrigin as GenericTransformOrigin;

/// A single operation in a computed CSS `transform`
pub type TransformOperation = GenericTransformOperation<Angle, Number, Length, Integer,
                                                        LengthOrNumber, LengthOrPercentage, LengthOrPercentageOrNumber>;
/// A computed CSS `transform`
pub type Transform = GenericTransform<TransformOperation>;

/// The computed value of a CSS `<transform-origin>`
pub type TransformOrigin = GenericTransformOrigin<LengthOrPercentage, LengthOrPercentage, Length>;

/// A computed timing function.
pub type TimingFunction = GenericTimingFunction<u32, Number>;

/// A vector to represent the direction vector (rotate axis) for Rotate3D.
pub type DirectionVector = Vector3D<CSSFloat>;

impl TransformOrigin {
    /// Returns the initial computed value for `transform-origin`.
    #[inline]
    pub fn initial_value() -> Self {
        Self::new(
            LengthOrPercentage::Percentage(Percentage(0.5)),
            LengthOrPercentage::Percentage(Percentage(0.5)),
            Length::new(0.),
        )
    }
}

impl From<ComputedMatrix> for Transform3D<CSSFloat> {
    #[inline]
    fn from(m: ComputedMatrix) -> Self {
        Transform3D::row_major(
            m.m11, m.m12, m.m13, m.m14,
            m.m21, m.m22, m.m23, m.m24,
            m.m31, m.m32, m.m33, m.m34,
            m.m41, m.m42, m.m43, m.m44)
    }
}

impl From<Transform3D<CSSFloat>> for ComputedMatrix {
    #[inline]
    fn from(m: Transform3D<CSSFloat>) -> Self {
        ComputedMatrix {
            m11: m.m11, m12: m.m12, m13: m.m13, m14: m.m14,
            m21: m.m21, m22: m.m22, m23: m.m23, m24: m.m24,
            m31: m.m31, m32: m.m32, m33: m.m33, m34: m.m34,
            m41: m.m41, m42: m.m42, m43: m.m43, m44: m.m44
        }
    }
}

impl TransformList {
    /// Return the equivalent 3d matrix of this transform list.
    /// If |reference_box| is None, we will drop the percent part from translate because
    /// we can resolve it without the layout info.
    pub fn to_transform_3d_matrix(&self, reference_box: Option<&Rect<Au>>)
                                  -> Option<Transform3D<CSSFloat>> {
        let mut transform = Transform3D::identity();
        let list = match self.0.as_ref() {
            Some(list) => list,
            None => return None,
        };

        let extract_pixel_length = |lop: &LengthOrPercentage| {
            match *lop {
                LengthOrPercentage::Length(px) => px.px(),
                LengthOrPercentage::Percentage(_) => 0.,
                LengthOrPercentage::Calc(calc) => calc.length().px(),
            }
        };

        for operation in list {
            let matrix = match *operation {
                ComputedOperation::Rotate(ax, ay, az, theta) => {
                    let theta = Angle::from_radians(2.0f32 * f32::consts::PI - theta.radians());
                    let (ax, ay, az, theta) =
                        Self::get_normalized_vector_and_angle(ax, ay, az, theta);
                    Transform3D::create_rotation(ax, ay, az, theta.into())
                }
                ComputedOperation::Perspective(d) => {
                    Self::create_perspective_matrix(d.px())
                }
                ComputedOperation::Scale(sx, sy, sz) => {
                    Transform3D::create_scale(sx, sy, sz)
                }
                ComputedOperation::Translate(tx, ty, tz) => {
                    let (tx, ty) = match reference_box {
                        Some(relative_border_box) => {
                            (tx.to_pixel_length(relative_border_box.size.width).px(),
                             ty.to_pixel_length(relative_border_box.size.height).px())
                        },
                        None => {
                            // If we don't have reference box, we cannot resolve the used value,
                            // so only retrieve the length part. This will be used for computing
                            // distance without any layout info.
                            (extract_pixel_length(&tx), extract_pixel_length(&ty))
                        }
                    };
                    let tz = tz.px();
                    Transform3D::create_translation(tx, ty, tz)
                }
                ComputedOperation::Matrix(m) => {
                    m.into()
                }
                ComputedOperation::MatrixWithPercents(_) => {
                    // `-moz-transform` is not implemented in Servo yet.
                    unreachable!()
                }
                ComputedOperation::Skew(theta_x, theta_y) => {
                    Transform3D::create_skew(theta_x.into(), theta_y.into())
                }
                ComputedOperation::InterpolateMatrix { .. } |
                ComputedOperation::AccumulateMatrix { .. } => {
                    // TODO: Convert InterpolateMatrix/AccmulateMatrix into a valid Transform3D by
                    // the reference box and do interpolation on these two Transform3D matrices.
                    // Both Gecko and Servo don't support this for computing distance, and Servo
                    // doesn't support animations on InterpolateMatrix/AccumulateMatrix, so
                    // return None.
                    return None;
                }
            };

            transform = transform.pre_mul(&matrix);
        }

        Some(transform)
    }

    /// Return the transform matrix from a perspective length.
    #[inline]
    pub fn create_perspective_matrix(d: CSSFloat) -> Transform3D<f32> {
        // TODO(gw): The transforms spec says that perspective length must
        // be positive. However, there is some confusion between the spec
        // and browser implementations as to handling the case of 0 for the
        // perspective value. Until the spec bug is resolved, at least ensure
        // that a provided perspective value of <= 0.0 doesn't cause panics
        // and behaves as it does in other browsers.
        // See https://lists.w3.org/Archives/Public/www-style/2016Jan/0020.html for more details.
        if d <= 0.0 {
            Transform3D::identity()
        } else {
            Transform3D::create_perspective(d)
        }
    }

    /// Return the normalized direction vector and its angle for Rotate3D.
    pub fn get_normalized_vector_and_angle(x: f32, y: f32, z: f32, angle: Angle)
                                           -> (f32, f32, f32, Angle) {
        use euclid::approxeq::ApproxEq;
        use euclid::num::Zero;
        let vector = DirectionVector::new(x, y, z);
        if vector.square_length().approx_eq(&f32::zero()) {
            // https://www.w3.org/TR/css-transforms-1/#funcdef-rotate3d
            // A direction vector that cannot be normalized, such as [0, 0, 0], will cause the
            // rotation to not be applied, so we use identity matrix (i.e. rotate3d(0, 0, 1, 0)).
            (0., 0., 1., Angle::zero())
        } else {
            let vector = vector.normalize();
            (vector.x, vector.y, vector.z, angle)
        }
    }
}
<commit_msg>Add ToAnimatedZero implementation<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Computed types for CSS values that are related to transformations.

use app_units::Au;
use euclid::{Rect, Transform3D, Vector3D};
use properties::longhands::transform::computed_value::{ComputedOperation, ComputedMatrix};
use properties::longhands::transform::computed_value::T as TransformList;
use std::f32;
use super::{CSSFloat, Either};
use values::animated::ToAnimatedZero;
use values::computed::{Angle, Integer, Length, LengthOrPercentage, Number, Percentage};
use values::computed::{LengthOrNumber, LengthOrPercentageOrNumber};
use values::generics::transform::{Matrix as GenericMatrix, Matrix3D as GenericMatrix3D};
use values::generics::transform::TimingFunction as GenericTimingFunction;
use values::generics::transform::{Transform as GenericTransform, TransformOperation as GenericTransformOperation};
use values::generics::transform::TransformOrigin as GenericTransformOrigin;

/// A single operation in a computed CSS `transform`
pub type TransformOperation = GenericTransformOperation<Angle, Number, Length, Integer,
                                                        LengthOrNumber, LengthOrPercentage, LengthOrPercentageOrNumber>;
/// A computed CSS `transform`
pub type Transform = GenericTransform<TransformOperation>;

/// The computed value of a CSS `<transform-origin>`
pub type TransformOrigin = GenericTransformOrigin<LengthOrPercentage, LengthOrPercentage, Length>;

/// A computed timing function.
pub type TimingFunction = GenericTimingFunction<u32, Number>;

/// A vector to represent the direction vector (rotate axis) for Rotate3D.
pub type DirectionVector = Vector3D<CSSFloat>;

impl TransformOrigin {
    /// Returns the initial computed value for `transform-origin`.
    #[inline]
    pub fn initial_value() -> Self {
        Self::new(
            LengthOrPercentage::Percentage(Percentage(0.5)),
            LengthOrPercentage::Percentage(Percentage(0.5)),
            Length::new(0.),
        )
    }
}

impl From<ComputedMatrix> for Transform3D<CSSFloat> {
    #[inline]
    fn from(m: ComputedMatrix) -> Self {
        Transform3D::row_major(
            m.m11, m.m12, m.m13, m.m14,
            m.m21, m.m22, m.m23, m.m24,
            m.m31, m.m32, m.m33, m.m34,
            m.m41, m.m42, m.m43, m.m44)
    }
}

impl From<Transform3D<CSSFloat>> for ComputedMatrix {
    #[inline]
    fn from(m: Transform3D<CSSFloat>) -> Self {
        ComputedMatrix {
            m11: m.m11, m12: m.m12, m13: m.m13, m14: m.m14,
            m21: m.m21, m22: m.m22, m23: m.m23, m24: m.m24,
            m31: m.m31, m32: m.m32, m33: m.m33, m34: m.m34,
            m41: m.m41, m42: m.m42, m43: m.m43, m44: m.m44
        }
    }
}

/// computed value of matrix3d()
pub type Matrix3D = GenericMatrix3D<Number>;
/// computed value of matrix3d() in -moz-transform
pub type PrefixedMatrix3D = GenericMatrix3D<Number, LengthOrPercentageOrNumber, LengthOrNumber>;
/// computed value of matrix()
pub type Matrix = GenericMatrix<Number>;
/// computed value of matrix() in -moz-transform
pub type PrefixedMatrix = GenericMatrix<Number, LengthOrPercentageOrNumber>;

impl Matrix3D {
    #[inline]
    /// Get an identity matrix
    pub fn identity() -> Self {
        Self {
            m11: 1.0, m12: 0.0, m13: 0.0, m14: 0.0,
            m21: 0.0, m22: 1.0, m23: 0.0, m24: 0.0,
            m31: 0.0, m32: 0.0, m33: 1.0, m34: 0.0,
            m41: 0., m42: 0., m43: 0., m44: 1.0
        }
    }
}

impl PrefixedMatrix3D {
    #[inline]
    /// Get an identity matrix
    pub fn identity() -> Self {
        Self {
            m11: 1.0, m12: 0.0, m13: 0.0, m14: 0.0,
            m21: 0.0, m22: 1.0, m23: 0.0, m24: 0.0,
            m31: 0.0, m32: 0.0, m33: 1.0, m34: 0.0,
            m41: Either::First(0.), m42: Either::First(0.),
            m43: Either::First(Length::new(0.)), m44: 1.0
        }
    }
}

impl Matrix {
    #[inline]
    /// Get an identity matrix
    pub fn identity() -> Self {
        Self {
            a: 1., c: 0., /* 0 */e: 0.,
            b: 0., d: 1., /* 0 */f: 0.,
            /* 0      0      1      0 */
            /* 0      0      0      1 */
        }
    }
}

impl PrefixedMatrix {
    #[inline]
    /// Get an identity matrix
    pub fn identity() -> Self {
        Self {
            a: 1., c: 0., /* 0 */e: Either::First(0.),
            b: 0., d: 1., /* 0 */f: Either::First(0.),
            /* 0      0      1      0 */
            /* 0      0      0      1 */
        }
    }
}

impl TransformList {
    /// Return the equivalent 3d matrix of this transform list.
    /// If |reference_box| is None, we will drop the percent part from translate because
    /// we can resolve it without the layout info.
    pub fn to_transform_3d_matrix(&self, reference_box: Option<&Rect<Au>>)
                                  -> Option<Transform3D<CSSFloat>> {
        let mut transform = Transform3D::identity();
        let list = match self.0.as_ref() {
            Some(list) => list,
            None => return None,
        };

        let extract_pixel_length = |lop: &LengthOrPercentage| {
            match *lop {
                LengthOrPercentage::Length(px) => px.px(),
                LengthOrPercentage::Percentage(_) => 0.,
                LengthOrPercentage::Calc(calc) => calc.length().px(),
            }
        };

        for operation in list {
            let matrix = match *operation {
                ComputedOperation::Rotate(ax, ay, az, theta) => {
                    let theta = Angle::from_radians(2.0f32 * f32::consts::PI - theta.radians());
                    let (ax, ay, az, theta) =
                        Self::get_normalized_vector_and_angle(ax, ay, az, theta);
                    Transform3D::create_rotation(ax, ay, az, theta.into())
                }
                ComputedOperation::Perspective(d) => {
                    Self::create_perspective_matrix(d.px())
                }
                ComputedOperation::Scale(sx, sy, sz) => {
                    Transform3D::create_scale(sx, sy, sz)
                }
                ComputedOperation::Translate(tx, ty, tz) => {
                    let (tx, ty) = match reference_box {
                        Some(relative_border_box) => {
                            (tx.to_pixel_length(relative_border_box.size.width).px(),
                             ty.to_pixel_length(relative_border_box.size.height).px())
                        },
                        None => {
                            // If we don't have reference box, we cannot resolve the used value,
                            // so only retrieve the length part. This will be used for computing
                            // distance without any layout info.
                            (extract_pixel_length(&tx), extract_pixel_length(&ty))
                        }
                    };
                    let tz = tz.px();
                    Transform3D::create_translation(tx, ty, tz)
                }
                ComputedOperation::Matrix(m) => {
                    m.into()
                }
                ComputedOperation::MatrixWithPercents(_) => {
                    // `-moz-transform` is not implemented in Servo yet.
                    unreachable!()
                }
                ComputedOperation::Skew(theta_x, theta_y) => {
                    Transform3D::create_skew(theta_x.into(), theta_y.into())
                }
                ComputedOperation::InterpolateMatrix { .. } |
                ComputedOperation::AccumulateMatrix { .. } => {
                    // TODO: Convert InterpolateMatrix/AccmulateMatrix into a valid Transform3D by
                    // the reference box and do interpolation on these two Transform3D matrices.
                    // Both Gecko and Servo don't support this for computing distance, and Servo
                    // doesn't support animations on InterpolateMatrix/AccumulateMatrix, so
                    // return None.
                    return None;
                }
            };

            transform = transform.pre_mul(&matrix);
        }

        Some(transform)
    }

    /// Return the transform matrix from a perspective length.
    #[inline]
    pub fn create_perspective_matrix(d: CSSFloat) -> Transform3D<f32> {
        // TODO(gw): The transforms spec says that perspective length must
        // be positive. However, there is some confusion between the spec
        // and browser implementations as to handling the case of 0 for the
        // perspective value. Until the spec bug is resolved, at least ensure
        // that a provided perspective value of <= 0.0 doesn't cause panics
        // and behaves as it does in other browsers.
        // See https://lists.w3.org/Archives/Public/www-style/2016Jan/0020.html for more details.
        if d <= 0.0 {
            Transform3D::identity()
        } else {
            Transform3D::create_perspective(d)
        }
    }

    /// Return the normalized direction vector and its angle for Rotate3D.
    pub fn get_normalized_vector_and_angle(x: f32, y: f32, z: f32, angle: Angle)
                                           -> (f32, f32, f32, Angle) {
        use euclid::approxeq::ApproxEq;
        use euclid::num::Zero;
        let vector = DirectionVector::new(x, y, z);
        if vector.square_length().approx_eq(&f32::zero()) {
            // https://www.w3.org/TR/css-transforms-1/#funcdef-rotate3d
            // A direction vector that cannot be normalized, such as [0, 0, 0], will cause the
            // rotation to not be applied, so we use identity matrix (i.e. rotate3d(0, 0, 1, 0)).
            (0., 0., 1., Angle::zero())
        } else {
            let vector = vector.normalize();
            (vector.x, vector.y, vector.z, angle)
        }
    }
}

/// Build an equivalent 'identity transform function list' based
/// on an existing transform list.
/// http://dev.w3.org/csswg/css-transforms/#none-transform-animation
impl ToAnimatedZero for TransformOperation {
    fn to_animated_zero(&self) -> Result<Self, ()> {
        match *self {
            GenericTransformOperation::Matrix3D(..) => {
                Ok(GenericTransformOperation::Matrix3D(Matrix3D::identity()))
            },
            GenericTransformOperation::PrefixedMatrix3D(..) => {
                Ok(GenericTransformOperation::PrefixedMatrix3D(PrefixedMatrix3D::identity()))
            },
            GenericTransformOperation::Matrix(..) => {
                Ok(GenericTransformOperation::Matrix(Matrix::identity()))
            },
            GenericTransformOperation::PrefixedMatrix(..) => {
                Ok(GenericTransformOperation::PrefixedMatrix(PrefixedMatrix::identity()))
            },
            GenericTransformOperation::Skew(sx, sy) => {
                Ok(GenericTransformOperation::Skew(
                    sx.to_animated_zero()?,
                    sy.to_animated_zero()?,
                ))
            },
            GenericTransformOperation::SkewX(s) => {
                Ok(GenericTransformOperation::SkewX(
                    s.to_animated_zero()?,
                ))
            },
            GenericTransformOperation::SkewY(s) => {
                Ok(GenericTransformOperation::SkewY(
                    s.to_animated_zero()?,
                ))
            },
            GenericTransformOperation::Translate3D(ref tx, ref ty, ref tz) => {
                Ok(GenericTransformOperation::Translate3D(
                    tx.to_animated_zero()?,
                    ty.to_animated_zero()?,
                    tz.to_animated_zero()?,
                ))
            },
            GenericTransformOperation::Translate(ref tx, ref ty) => {
                Ok(GenericTransformOperation::Translate(
                    tx.to_animated_zero()?,
                    ty.to_animated_zero()?,
                ))
            },
            GenericTransformOperation::TranslateX(ref t) => {
                Ok(GenericTransformOperation::TranslateX(
                    t.to_animated_zero()?,
                ))
            },
            GenericTransformOperation::TranslateY(ref t) => {
                Ok(GenericTransformOperation::TranslateY(
                    t.to_animated_zero()?,
                ))
            },
            GenericTransformOperation::TranslateZ(ref t) => {
                Ok(GenericTransformOperation::TranslateZ(
                    t.to_animated_zero()?,
                ))
            },
            GenericTransformOperation::Scale3D(..) => {
                Ok(GenericTransformOperation::Scale3D(1.0, 1.0, 1.0))
            },
            GenericTransformOperation::Scale(_, None) => {
                Ok(GenericTransformOperation::Scale(1.0, None))
            },
            GenericTransformOperation::Scale(_, Some(_)) => {
                Ok(GenericTransformOperation::Scale(1.0, Some(1.0)))
            },
            GenericTransformOperation::ScaleX(..) => {
                Ok(GenericTransformOperation::ScaleX(1.0))
            },
            GenericTransformOperation::ScaleY(..) => {
                Ok(GenericTransformOperation::ScaleY(1.0))
            },
            GenericTransformOperation::ScaleZ(..) => {
                Ok(GenericTransformOperation::ScaleZ(1.0))
            },
            GenericTransformOperation::Rotate3D(x, y, z, a) => {
                let (x, y, z, _) = TransformList::get_normalized_vector_and_angle(x, y, z, a);
                Ok(GenericTransformOperation::Rotate3D(x, y, z, Angle::zero()))
            },
            GenericTransformOperation::RotateX(_) => {
                Ok(GenericTransformOperation::RotateX(Angle::zero()))
            },
            GenericTransformOperation::RotateY(_) => {
                Ok(GenericTransformOperation::RotateY(Angle::zero()))
            },
            GenericTransformOperation::RotateZ(_) => {
                Ok(GenericTransformOperation::RotateZ(Angle::zero()))
            },
            GenericTransformOperation::Rotate(_) => {
                Ok(GenericTransformOperation::Rotate(Angle::zero()))
            },
            GenericTransformOperation::Perspective(..) |
            GenericTransformOperation::AccumulateMatrix { .. } |
            GenericTransformOperation::InterpolateMatrix { .. } => {
                // Perspective: We convert a perspective function into an equivalent
                //     ComputedMatrix, and then decompose/interpolate/recompose these matrices.
                // AccumulateMatrix/InterpolateMatrix: We do interpolation on
                //     AccumulateMatrix/InterpolateMatrix by reading it as a ComputedMatrix
                //     (with layout information), and then do matrix interpolation.
                //
                // Therefore, we use an identity matrix to represent the identity transform list.
                // http://dev.w3.org/csswg/css-transforms/#identity-transform-function
                Ok(GenericTransformOperation::Matrix3D(Matrix3D::identity()))
            },
        }
    }
}
<|endoftext|>


<commit_before>//! Complete fields in record literals and patterns.
use crate::completion::{CompletionContext, Completions};
use ra_syntax::{ast, ast::NameOwner, SmolStr};

pub(super) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
    let (ty, variant, already_present_fields) =
        match (ctx.record_lit_pat.as_ref(), ctx.record_lit_syntax.as_ref()) {
            (None, None) => return None,
            (Some(_), Some(_)) => panic!("A record cannot be both a literal and a pattern"),
            (Some(record_pat), _) => (
                ctx.sema.type_of_pat(&record_pat.clone().into())?,
                ctx.sema.resolve_record_pattern(record_pat)?,
                pattern_ascribed_fields(record_pat),
            ),
            (_, Some(record_lit)) => (
                ctx.sema.type_of_expr(&record_lit.clone().into())?,
                ctx.sema.resolve_record_literal(record_lit)?,
                literal_ascribed_fields(record_lit),
            ),
        };

    for (field, field_ty) in ty.variant_fields(ctx.db, variant).into_iter().filter(|(field, _)| {
        // FIXME: already_present_names better be `Vec<hir::Name>`
        !already_present_fields.contains(&SmolStr::from(field.name(ctx.db).to_string()))
    }) {
        acc.add_field(ctx, field, &field_ty);
    }
    Some(())
}

fn literal_ascribed_fields(record_lit: &ast::RecordLit) -> Vec<SmolStr> {
    record_lit
        .record_field_list()
        .map(|field_list| field_list.fields())
        .map(|fields| {
            fields
                .into_iter()
                .filter_map(|field| field.name_ref())
                .map(|name_ref| name_ref.text().clone())
                .collect()
        })
        .unwrap_or_default()
}

fn pattern_ascribed_fields(record_pat: &ast::RecordPat) -> Vec<SmolStr> {
    record_pat
        .record_field_pat_list()
        .map(|pat_list| {
            pat_list
                .record_field_pats()
                .filter_map(|fild_pat| fild_pat.name())
                .chain(pat_list.bind_pats().filter_map(|bind_pat| bind_pat.name()))
                .map(|name| name.text().clone())
                .collect()
        })
        .unwrap_or_default()
}

#[cfg(test)]
mod tests {
    mod record_lit_tests {
        use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind};
        use insta::assert_debug_snapshot;

        fn complete(code: &str) -> Vec<CompletionItem> {
            do_completion(code, CompletionKind::Reference)
        }

        #[test]
        fn test_record_pattern_field() {
            let completions = complete(
                r"
            struct S { foo: u32 }

            fn process(f: S) {
                match f {
                    S { f<|>: 92 } => (),
                }
            }
            ",
            );
            assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "foo",
                source_range: [117; 118),
                delete: [117; 118),
                insert: "foo",
                kind: Field,
                detail: "u32",
            },
        ]
        "###);
        }

        #[test]
        fn test_record_pattern_enum_variant() {
            let completions = complete(
                r"
            enum E {
                S { foo: u32, bar: () }
            }

            fn process(e: E) {
                match e {
                    E::S { <|> } => (),
                }
            }
            ",
            );
            assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "bar",
                source_range: [161; 161),
                delete: [161; 161),
                insert: "bar",
                kind: Field,
                detail: "()",
            },
            CompletionItem {
                label: "foo",
                source_range: [161; 161),
                delete: [161; 161),
                insert: "foo",
                kind: Field,
                detail: "u32",
            },
        ]
        "###);
        }

        #[test]
        fn test_record_pattern_field_in_simple_macro() {
            let completions = complete(
                r"
            macro_rules! m { ($e:expr) => { $e } }
            struct S { foo: u32 }

            fn process(f: S) {
                m!(match f {
                    S { f<|>: 92 } => (),
                })
            }
            ",
            );
            assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "foo",
                source_range: [171; 172),
                delete: [171; 172),
                insert: "foo",
                kind: Field,
                detail: "u32",
            },
        ]
        "###);
        }

        #[test]
        fn only_missing_fields_are_completed_in_destruct_pats() {
            let completions = complete(
                r"
            struct S {
                foo1: u32,
                foo2: u32,
                bar: u32,
                baz: u32,
            }

            fn main() {
                let s = S {
                    foo1: 1,
                    foo2: 2,
                    bar: 3,
                    baz: 4,
                };
                if let S { foo1, foo2: a, <|> } = s {}
            }
            ",
            );
            assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "bar",
                source_range: [372; 372),
                delete: [372; 372),
                insert: "bar",
                kind: Field,
                detail: "u32",
            },
            CompletionItem {
                label: "baz",
                source_range: [372; 372),
                delete: [372; 372),
                insert: "baz",
                kind: Field,
                detail: "u32",
            },
        ]
        "###);
        }
    }

    mod record_pat_tests {
        use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind};
        use insta::assert_debug_snapshot;

        fn complete(code: &str) -> Vec<CompletionItem> {
            do_completion(code, CompletionKind::Reference)
        }

        #[test]
        fn test_record_literal_deprecated_field() {
            let completions = complete(
                r"
            struct A {
                #[deprecated]
                the_field: u32,
            }
            fn foo() {
               A { the<|> }
            }
            ",
            );
            assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "the_field",
                source_range: [142; 145),
                delete: [142; 145),
                insert: "the_field",
                kind: Field,
                detail: "u32",
                deprecated: true,
            },
        ]
        "###);
        }

        #[test]
        fn test_record_literal_field() {
            let completions = complete(
                r"
            struct A { the_field: u32 }
            fn foo() {
               A { the<|> }
            }
            ",
            );
            assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "the_field",
                source_range: [83; 86),
                delete: [83; 86),
                insert: "the_field",
                kind: Field,
                detail: "u32",
            },
        ]
        "###);
        }

        #[test]
        fn test_record_literal_enum_variant() {
            let completions = complete(
                r"
            enum E {
                A { a: u32 }
            }
            fn foo() {
                let _ = E::A { <|> }
            }
            ",
            );
            assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "a",
                source_range: [119; 119),
                delete: [119; 119),
                insert: "a",
                kind: Field,
                detail: "u32",
            },
        ]
        "###);
        }

        #[test]
        fn test_record_literal_two_structs() {
            let completions = complete(
                r"
            struct A { a: u32 }
            struct B { b: u32 }

            fn foo() {
               let _: A = B { <|> }
            }
            ",
            );
            assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "b",
                source_range: [119; 119),
                delete: [119; 119),
                insert: "b",
                kind: Field,
                detail: "u32",
            },
        ]
        "###);
        }

        #[test]
        fn test_record_literal_generic_struct() {
            let completions = complete(
                r"
            struct A<T> { a: T }

            fn foo() {
               let _: A<u32> = A { <|> }
            }
            ",
            );
            assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "a",
                source_range: [93; 93),
                delete: [93; 93),
                insert: "a",
                kind: Field,
                detail: "u32",
            },
        ]
        "###);
        }

        #[test]
        fn test_record_literal_field_in_simple_macro() {
            let completions = complete(
                r"
            macro_rules! m { ($e:expr) => { $e } }
            struct A { the_field: u32 }
            fn foo() {
               m!(A { the<|> })
            }
            ",
            );
            assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "the_field",
                source_range: [137; 140),
                delete: [137; 140),
                insert: "the_field",
                kind: Field,
                detail: "u32",
            },
        ]
        "###);
        }

        #[test]
        fn only_missing_fields_are_completed() {
            let completions = complete(
                r"
            struct S {
                foo1: u32,
                foo2: u32,
                bar: u32,
                baz: u32,
            }

            fn main() {
                let foo1 = 1;
                let s = S {
                    foo1,
                    foo2: 5,
                    <|>
                }
            }
            ",
            );
            assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "bar",
                source_range: [302; 302),
                delete: [302; 302),
                insert: "bar",
                kind: Field,
                detail: "u32",
            },
            CompletionItem {
                label: "baz",
                source_range: [302; 302),
                delete: [302; 302),
                insert: "baz",
                kind: Field,
                detail: "u32",
            },
        ]
        "###);
        }
    }
}
<commit_msg>Reorder imports<commit_after>//! Complete fields in record literals and patterns.
use ra_syntax::{ast, ast::NameOwner, SmolStr};

use crate::completion::{CompletionContext, Completions};

pub(super) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
    let (ty, variant, already_present_fields) =
        match (ctx.record_lit_pat.as_ref(), ctx.record_lit_syntax.as_ref()) {
            (None, None) => return None,
            (Some(_), Some(_)) => panic!("A record cannot be both a literal and a pattern"),
            (Some(record_pat), _) => (
                ctx.sema.type_of_pat(&record_pat.clone().into())?,
                ctx.sema.resolve_record_pattern(record_pat)?,
                pattern_ascribed_fields(record_pat),
            ),
            (_, Some(record_lit)) => (
                ctx.sema.type_of_expr(&record_lit.clone().into())?,
                ctx.sema.resolve_record_literal(record_lit)?,
                literal_ascribed_fields(record_lit),
            ),
        };

    for (field, field_ty) in ty.variant_fields(ctx.db, variant).into_iter().filter(|(field, _)| {
        // FIXME: already_present_names better be `Vec<hir::Name>`
        !already_present_fields.contains(&SmolStr::from(field.name(ctx.db).to_string()))
    }) {
        acc.add_field(ctx, field, &field_ty);
    }
    Some(())
}

fn literal_ascribed_fields(record_lit: &ast::RecordLit) -> Vec<SmolStr> {
    record_lit
        .record_field_list()
        .map(|field_list| field_list.fields())
        .map(|fields| {
            fields
                .into_iter()
                .filter_map(|field| field.name_ref())
                .map(|name_ref| name_ref.text().clone())
                .collect()
        })
        .unwrap_or_default()
}

fn pattern_ascribed_fields(record_pat: &ast::RecordPat) -> Vec<SmolStr> {
    record_pat
        .record_field_pat_list()
        .map(|pat_list| {
            pat_list
                .record_field_pats()
                .filter_map(|fild_pat| fild_pat.name())
                .chain(pat_list.bind_pats().filter_map(|bind_pat| bind_pat.name()))
                .map(|name| name.text().clone())
                .collect()
        })
        .unwrap_or_default()
}

#[cfg(test)]
mod tests {
    mod record_lit_tests {
        use insta::assert_debug_snapshot;

        use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind};

        fn complete(code: &str) -> Vec<CompletionItem> {
            do_completion(code, CompletionKind::Reference)
        }

        #[test]
        fn test_record_pattern_field() {
            let completions = complete(
                r"
            struct S { foo: u32 }

            fn process(f: S) {
                match f {
                    S { f<|>: 92 } => (),
                }
            }
            ",
            );
            assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "foo",
                source_range: [117; 118),
                delete: [117; 118),
                insert: "foo",
                kind: Field,
                detail: "u32",
            },
        ]
        "###);
        }

        #[test]
        fn test_record_pattern_enum_variant() {
            let completions = complete(
                r"
            enum E {
                S { foo: u32, bar: () }
            }

            fn process(e: E) {
                match e {
                    E::S { <|> } => (),
                }
            }
            ",
            );
            assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "bar",
                source_range: [161; 161),
                delete: [161; 161),
                insert: "bar",
                kind: Field,
                detail: "()",
            },
            CompletionItem {
                label: "foo",
                source_range: [161; 161),
                delete: [161; 161),
                insert: "foo",
                kind: Field,
                detail: "u32",
            },
        ]
        "###);
        }

        #[test]
        fn test_record_pattern_field_in_simple_macro() {
            let completions = complete(
                r"
            macro_rules! m { ($e:expr) => { $e } }
            struct S { foo: u32 }

            fn process(f: S) {
                m!(match f {
                    S { f<|>: 92 } => (),
                })
            }
            ",
            );
            assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "foo",
                source_range: [171; 172),
                delete: [171; 172),
                insert: "foo",
                kind: Field,
                detail: "u32",
            },
        ]
        "###);
        }

        #[test]
        fn only_missing_fields_are_completed_in_destruct_pats() {
            let completions = complete(
                r"
            struct S {
                foo1: u32,
                foo2: u32,
                bar: u32,
                baz: u32,
            }

            fn main() {
                let s = S {
                    foo1: 1,
                    foo2: 2,
                    bar: 3,
                    baz: 4,
                };
                if let S { foo1, foo2: a, <|> } = s {}
            }
            ",
            );
            assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "bar",
                source_range: [372; 372),
                delete: [372; 372),
                insert: "bar",
                kind: Field,
                detail: "u32",
            },
            CompletionItem {
                label: "baz",
                source_range: [372; 372),
                delete: [372; 372),
                insert: "baz",
                kind: Field,
                detail: "u32",
            },
        ]
        "###);
        }
    }

    mod record_pat_tests {
        use insta::assert_debug_snapshot;

        use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind};

        fn complete(code: &str) -> Vec<CompletionItem> {
            do_completion(code, CompletionKind::Reference)
        }

        #[test]
        fn test_record_literal_deprecated_field() {
            let completions = complete(
                r"
            struct A {
                #[deprecated]
                the_field: u32,
            }
            fn foo() {
               A { the<|> }
            }
            ",
            );
            assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "the_field",
                source_range: [142; 145),
                delete: [142; 145),
                insert: "the_field",
                kind: Field,
                detail: "u32",
                deprecated: true,
            },
        ]
        "###);
        }

        #[test]
        fn test_record_literal_field() {
            let completions = complete(
                r"
            struct A { the_field: u32 }
            fn foo() {
               A { the<|> }
            }
            ",
            );
            assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "the_field",
                source_range: [83; 86),
                delete: [83; 86),
                insert: "the_field",
                kind: Field,
                detail: "u32",
            },
        ]
        "###);
        }

        #[test]
        fn test_record_literal_enum_variant() {
            let completions = complete(
                r"
            enum E {
                A { a: u32 }
            }
            fn foo() {
                let _ = E::A { <|> }
            }
            ",
            );
            assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "a",
                source_range: [119; 119),
                delete: [119; 119),
                insert: "a",
                kind: Field,
                detail: "u32",
            },
        ]
        "###);
        }

        #[test]
        fn test_record_literal_two_structs() {
            let completions = complete(
                r"
            struct A { a: u32 }
            struct B { b: u32 }

            fn foo() {
               let _: A = B { <|> }
            }
            ",
            );
            assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "b",
                source_range: [119; 119),
                delete: [119; 119),
                insert: "b",
                kind: Field,
                detail: "u32",
            },
        ]
        "###);
        }

        #[test]
        fn test_record_literal_generic_struct() {
            let completions = complete(
                r"
            struct A<T> { a: T }

            fn foo() {
               let _: A<u32> = A { <|> }
            }
            ",
            );
            assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "a",
                source_range: [93; 93),
                delete: [93; 93),
                insert: "a",
                kind: Field,
                detail: "u32",
            },
        ]
        "###);
        }

        #[test]
        fn test_record_literal_field_in_simple_macro() {
            let completions = complete(
                r"
            macro_rules! m { ($e:expr) => { $e } }
            struct A { the_field: u32 }
            fn foo() {
               m!(A { the<|> })
            }
            ",
            );
            assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "the_field",
                source_range: [137; 140),
                delete: [137; 140),
                insert: "the_field",
                kind: Field,
                detail: "u32",
            },
        ]
        "###);
        }

        #[test]
        fn only_missing_fields_are_completed() {
            let completions = complete(
                r"
            struct S {
                foo1: u32,
                foo2: u32,
                bar: u32,
                baz: u32,
            }

            fn main() {
                let foo1 = 1;
                let s = S {
                    foo1,
                    foo2: 5,
                    <|>
                }
            }
            ",
            );
            assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "bar",
                source_range: [302; 302),
                delete: [302; 302),
                insert: "bar",
                kind: Field,
                detail: "u32",
            },
            CompletionItem {
                label: "baz",
                source_range: [302; 302),
                delete: [302; 302),
                insert: "baz",
                kind: Field,
                detail: "u32",
            },
        ]
        "###);
        }
    }
}
<|endoftext|>


<commit_before>//! Xml Attributes module
//!
//! Provides an iterator over attributes key/value pairs
use std::borrow::Cow;
use error::{Error, ResultPos};
use escape::unescape;

/// Iterator over attributes key/value pairs
pub struct Attributes<'a> {
    bytes: &'a [u8],
    position: usize,
    was_error: bool,
}

impl<'a> Attributes<'a> {
    /// creates a new attribute from a buffer
    ///
    /// pos represents current position of the iterator
    /// (starts after start element name)
    pub fn new(buf: &'a [u8], pos: usize) -> Attributes<'a> {
        Attributes {
            bytes: buf,
            position: pos,
            was_error: false,
        }
    }

    /// gets unescaped variant
    ///
    /// all escaped characters ('&...;') in attribute values are replaced
    /// with their corresponding character
    pub fn unescaped(self) -> UnescapedAttributes<'a> {
        UnescapedAttributes {
            inner: self
        }
    }
}

impl<'a> Iterator for Attributes<'a> {
    type Item = ResultPos<(&'a [u8], &'a [u8])>;
    fn next(&mut self) -> Option<Self::Item> {

        if self.was_error { return None; }

        let len = self.bytes.len();
        let p = self.position;
        if len <= p { return None; }

        let mut iter = self.bytes[p..].iter().cloned().enumerate();

        let start_key = {
            let mut found_space = false;
            let start: usize;
            loop {
                match iter.next() {
                    Some((_, b' '))
                        | Some((_, b'\r'))
                        | Some((_, b'\n'))
                        | Some((_, b'\t')) => if !found_space { found_space = true; },
                    Some((i, _)) => if found_space {
                        start = i;
                        break;
                    },
                    None => {
                        self.position = len;
                        return None;
                    }
                }
            }
            start
        };

        let mut has_equal = false;
        let mut end_key = None;
        let mut start_val = None;
        let mut end_val = None;
        let mut quote = 0;
        loop {
            match iter.next() {
                Some((i, b' '))
                    | Some((i, b'\r'))
                    | Some((i, b'\n'))
                    | Some((i, b'\t')) => {
                    if end_key.is_none() { end_key = Some(i); }
                },
                Some((i, b'=')) => {
                    if has_equal {
                        self.was_error = true;
                        return Some(Err((Error::Malformed("Got 2 '=' tokens".to_owned()), p + i)));
                    }
                    has_equal = true;
                    if end_key.is_none() {
                        end_key = Some(i);
                    }
                },
                Some((i, q @ b'"')) | Some((i, q @ b'\'')) => {
                    if !has_equal {
                        self.was_error = true;
                        return Some(Err((Error::Malformed("Unexpected quote before '='".to_owned()), p + i)));
                    }
                    if start_val.is_none() {
                        start_val = Some(i + 1);
                        quote = q;
                    } else if quote == q && end_val.is_none() {
                        end_val = Some(i);
                        break;
                    }
                },
                None => {
                    self.position = len;
                    return None;
                }
                Some((_, _)) => (),
            }
        }
        self.position += end_val.unwrap() + 1;

        Some(Ok((&self.bytes[(p + start_key)..(p + end_key.unwrap())],
           &self.bytes[(p + start_val.unwrap())..(p + end_val.unwrap())])))
    }
}

/// Escaped attributes
///
/// Iterate over all attributes and unescapes attribute values
pub struct UnescapedAttributes<'a> {
    inner: Attributes<'a>
}

impl<'a> Iterator for UnescapedAttributes<'a> {
    type Item = ResultPos<(&'a [u8], Cow<'a, [u8]>)>;
    fn next(&mut self) -> Option<Self::Item> {
        self.inner.next()
            .map(|a| a.and_then(|(k, v)| unescape(v).map(|v| (k, v))))
    }
}
<commit_msg>check atts to be distincts<commit_after>//! Xml Attributes module
//!
//! Provides an iterator over attributes key/value pairs
use std::borrow::Cow;
use std::ops::Range;
use error::{Error, ResultPos};
use escape::unescape;

/// Iterator over attributes key/value pairs
pub struct Attributes<'a> {
    bytes: &'a [u8],
    position: usize,
    was_error: bool,
    with_checks: bool,
    consumed: Vec<Range<usize>>,
}

impl<'a> Attributes<'a> {
    /// creates a new attribute from a buffer
    ///
    /// pos represents current position of the iterator
    /// (starts after start element name)
    pub fn new(buf: &'a [u8], pos: usize) -> Attributes<'a> {
        Attributes {
            bytes: buf,
            position: pos,
            was_error: false,
            with_checks: true,
            consumed: Vec::new(),
        }
    }

    /// gets unescaped variant
    ///
    /// all escaped characters ('&...;') in attribute values are replaced
    /// with their corresponding character
    pub fn unescaped(self) -> UnescapedAttributes<'a> {
        UnescapedAttributes {
            inner: self
        }
    }
}

impl<'a> Iterator for Attributes<'a> {
    type Item = ResultPos<(&'a [u8], &'a [u8])>;
    fn next(&mut self) -> Option<Self::Item> {

        if self.was_error { return None; }

        let len = self.bytes.len();
        let p = self.position;
        if len <= p { return None; }

        let mut iter = self.bytes[p..].iter().cloned().enumerate();

        let start_key = {
            let mut found_space = false;
            let start: usize;
            loop {
                match iter.next() {
                    Some((_, b' '))
                        | Some((_, b'\r'))
                        | Some((_, b'\n'))
                        | Some((_, b'\t')) => if !found_space { found_space = true; },
                    Some((i, _)) => if found_space {
                        start = i;
                        break;
                    },
                    None => {
                        self.position = len;
                        return None;
                    }
                }
            }
            start
        };

        let mut has_equal = false;
        let mut end_key = None;
        let mut start_val = None;
        let mut end_val = None;
        let mut quote = 0;
        loop {
            match iter.next() {
                Some((i, b' '))
                    | Some((i, b'\r'))
                    | Some((i, b'\n'))
                    | Some((i, b'\t')) => {
                    if end_key.is_none() { end_key = Some(i); }
                },
                Some((i, b'=')) => {
                    if has_equal {
                        self.was_error = true;
                        return Some(Err((Error::Malformed("Got 2 '=' tokens".to_owned()), p + i)));
                    }
                    has_equal = true;
                    if end_key.is_none() {
                        end_key = Some(i);
                    }
                },
                Some((i, q @ b'"')) | Some((i, q @ b'\'')) => {
                    if !has_equal {
                        self.was_error = true;
                        return Some(Err((Error::Malformed("Unexpected quote before '='".to_owned()), p + i)));
                    }
                    if start_val.is_none() {
                        start_val = Some(i + 1);
                        quote = q;
                    } else if quote == q && end_val.is_none() {
                        end_val = Some(i);
                        break;
                    }
                },
                None => {
                    self.position = len;
                    return None;
                }
                Some((_, _)) => (),
            }
        }
        self.position += end_val.unwrap() + 1;

        let r = (p + start_key)..(p + end_key.unwrap());
        if self.with_checks {
            let name = &self.bytes[r.clone()];
            if let Some(ref r2) = self.consumed.iter().cloned().find(|r2| &self.bytes[r2.clone()] == name) {
                self.was_error = true;
                return Some(Err((Error::Malformed(format!(
                                    "Duplicate attribute at position {} and {}",
                                    r2.start, r.start)), r.start)));
            }
            self.consumed.push(r.clone());
        }

        Some(Ok((&self.bytes[r], &self.bytes[(p + start_val.unwrap())..(p + end_val.unwrap())])))
    }
}

/// Escaped attributes
///
/// Iterate over all attributes and unescapes attribute values
pub struct UnescapedAttributes<'a> {
    inner: Attributes<'a>
}

impl<'a> Iterator for UnescapedAttributes<'a> {
    type Item = ResultPos<(&'a [u8], Cow<'a, [u8]>)>;
    fn next(&mut self) -> Option<Self::Item> {
        self.inner.next()
            .map(|a| a.and_then(|(k, v)| unescape(v).map(|v| (k, v))))
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

use std::ptr;
use std::slice;
use std::ffi;
use std::i32;
use std::f32;

use htslib;

pub const MISSING_INTEGER: i32 = i32::MIN;
pub const MISSING_FLOAT: f32 = f32::NAN;
pub const VECTOR_END_INTEGER: i32 = i32::MIN + 1;
pub const VECTOR_END_FLOAT: f32 = 2.139095e+09;

pub struct Record {
    pub inner: *mut htslib::vcf::bcf1_t,
    pub header: *mut htslib::vcf::bcf_hdr_t,
    buffer: *mut ::libc::c_void,
}

impl Record {
    pub fn new() -> Self {
        let inner = unsafe { htslib::vcf::bcf_init() };
        Record { inner: inner, header: ptr::null_mut(), buffer: ptr::null_mut() }
    }

    pub fn rid(&self) -> Option<u32> {
        match unsafe { *self.inner }.rid {
            -1  => None,
            rid => Some(rid as u32)
        }
    }

    // 0-based position.
    pub fn pos(&self) -> u32 {
        unsafe { *self.inner }.pos as u32
    }

    pub fn set_pos(&mut self, pos: i32) {
        unsafe { (*self.inner).pos = pos; }
    }

    pub fn alleles(&self) -> Vec<&[u8]> {
        unsafe { htslib::vcf::bcf_unpack(self.inner, htslib::vcf::BCF_UN_STR) };
        let n = unsafe { *self.inner }.n_allele as usize;
        let dec = unsafe { *self.inner }.d;
        let alleles = unsafe { slice::from_raw_parts(dec.allele, n) };
        (0..n).map(|i| unsafe { ffi::CStr::from_ptr(alleles[i]).to_bytes() }).collect()
    }

    pub fn qual(&self) -> f32 {
        unsafe { *self.inner }.qual
    }

    pub fn set_qual(&mut self, qual: f32) {
        unsafe { (*self.inner).qual = qual; }
    }

    /// Get the value of the given info tag.
    pub fn info<'a>(&'a mut self, tag: &'a [u8]) -> Info {
        Info { record: self, tag: tag }
    }

    pub fn sample_count(&self) -> u32 {
        unsafe { *self.inner }.n_fmt_n_sample >> 8
    }

    pub fn allele_count(&self) -> u16 {
        unsafe { *self.inner }.n_allele
    }

    /// Get the value of the given format tag for each sample.
    pub fn format<'a>(&'a mut self, tag: &'a [u8]) -> Format {
        Format::new(self, tag)
    }

    /// Add an integer format tag. Data is a flattened two-dimensional array.
    /// The first dimension contains one array for each sample.
    /// Returns error if tag is not present in header.
    pub fn push_format_integer(&mut self, tag: &[u8], data: &[i32]) -> Result<(), ()> {
        self.push_format(tag, data, htslib::vcf::BCF_HT_INT)
    }

    /// Add a float format tag. Data is a flattened two-dimensional array.
    /// The first dimension contains one array for each sample.
    /// Returns error if tag is not present in header.
    pub fn push_format_float(&mut self, tag: &[u8], data: &[f32]) -> Result<(), ()> {
        self.push_format(tag, data, htslib::vcf::BCF_HT_REAL)
    }

    /// Add a format tag. Data is a flattened two-dimensional array.
    /// The first dimension contains one array for each sample.
    fn push_format<T>(&mut self, tag: &[u8], data: &[T], ht: i32) -> Result<(), ()> {
        assert!(data.len() > 0);
        unsafe {
            if htslib::vcf::bcf_update_format(
                self.header,
                self.inner,
                ffi::CString::new(tag).unwrap().as_ptr() as *mut i8,
                data.as_ptr() as *const ::libc::c_void,
                data.len() as i32,
                ht
            ) == 0 {
                Ok(())
            }
            else {
                Err(())
            }
        }
    }

    /// Add a info tag.
    pub fn push_info<T>(&mut self, tag: &[u8], data: &[T], ht: i32) -> Result<(), ()> {
        assert!(data.len() > 0);
        unsafe {
            if htslib::vcf::bcf_update_info(
                self.header,
                self.inner,
                ffi::CString::new(tag).unwrap().as_ptr() as *mut i8,
                data.as_ptr() as *const ::libc::c_void,
                data.len() as i32,
                ht
            ) == 0 {
                Ok(())
            }
            else {
                Err(())
            }
        }
    }

    /// Remove unused alleles.
    pub fn trim_alleles(&mut self) -> Result<(), ()> {
        match unsafe { htslib::vcfutils::bcf_trim_alleles(self.header, self.inner) } {
            -1 => Err(()),
            _  => Ok(())
        }
    }
}

impl Drop for Record {
    fn drop(&mut self) {
        if !self.buffer.is_null() {
            unsafe { ::libc::free(self.buffer) };
        }
        unsafe { htslib::vcf::bcf_destroy(self.inner) };
    }
}

unsafe impl Send for Record {}

pub struct Info<'a> {
    record: &'a mut Record,
    tag: &'a [u8],
}

impl<'a> Info<'a> {
    fn data(&mut self, data_type: i32) -> Result<(usize, i32), TagError> {
        let mut n: i32 = 0;
        match unsafe {
            htslib::vcf::bcf_get_info_values(
                self.record.header,
                self.record.inner,
                ffi::CString::new(self.tag).unwrap().as_ptr() as *mut i8,
                &mut self.record.buffer,
                &mut n,
                data_type
            )
        } {
            -1 => Err(TagError::UndefinedTag),
            -2 => Err(TagError::UnexpectedType),
            -3 => Err(TagError::MissingTag),
            ret  => Ok((n as usize, ret)),
        }
    }

    pub fn integer(&mut self) -> Result<&[i32], TagError> {
        self.data(htslib::vcf::BCF_HT_INT).map(|(n, _)| {
            trim_slice(
                unsafe { slice::from_raw_parts(self.record.buffer as *const i32, n) },
                VECTOR_END_INTEGER
            )
        })
    }

    pub fn integer_mut(&mut self) -> Result<&mut [i32], TagError> {
        self.data(htslib::vcf::BCF_HT_INT).map(|(n, _)| {
            unsafe { slice::from_raw_parts_mut(self.record.buffer as *mut i32, n) }
        })
    }

    pub fn float(&mut self) -> Result<&[f32], TagError> {
        self.data(htslib::vcf::BCF_HT_REAL).map(|(n, _)| {
            trim_slice(
                unsafe { slice::from_raw_parts(self.record.buffer as *const f32, n) },
                VECTOR_END_FLOAT
            )
        })
    }

    pub fn float_mut(&mut self) -> Result<&mut [f32], TagError> {
        self.data(htslib::vcf::BCF_HT_REAL).map(|(n, _)| {
            unsafe { slice::from_raw_parts_mut(self.record.buffer as *mut f32, n) }
        })
    }

    pub fn flag(&mut self) -> Result<bool, TagError> {
        self.data(htslib::vcf::BCF_HT_FLAG).map(|(_, ret)| {
            ret == 1
        })
    }

    pub fn string(&mut self) -> Result<Vec<&[u8]>, TagError> {
        self.data(htslib::vcf::BCF_HT_STR).map(|(n, ret)| {
            unsafe {
                slice::from_raw_parts(self.record.buffer as *const u8, ret as usize)
            }.chunks(n).map(|s| {
                // stop at zero character
                s.split(|c| *c == 0u8).next().expect("Bug: returned string should not be empty.")
            }).collect()
        })
    }

    pub fn string_mut(&mut self) -> Result<Vec<&mut [u8]>, TagError> {
        self.data(htslib::vcf::BCF_HT_STR).map(|(n, ret)| {
            unsafe {
                slice::from_raw_parts_mut(self.record.buffer as *mut u8, ret as usize)
            }.chunks_mut(n).collect()
        })
    }
}

fn trim_slice<T: PartialEq>(s: &[T], end_value: T) -> &[T] {
    s.split(|v| *v == end_value).next().expect("Bug: returned slice should not be empty.")
}

// TODO implement format.
pub struct Format<'a> {
    record: &'a mut Record,
    tag: &'a [u8],
    inner: *mut htslib::vcf::bcf_fmt_t,
}

impl<'a> Format<'a> {
    fn new(record: &'a mut Record, tag: &'a [u8]) -> Format<'a> {
        let inner = unsafe { htslib::vcf::bcf_get_fmt(
            record.header,
            record.inner,
            ffi::CString::new(tag).unwrap().as_ptr() as *mut i8
        ) };
        Format { record: record, tag: tag, inner: inner }
    }

    fn values_per_sample(&self) -> usize {
        unsafe { (*self.inner).n as usize }
    }

    fn data(&mut self, data_type: i32) -> Result<(usize, i32), TagError> {
        let mut n: i32 = 0;
        match unsafe {
            htslib::vcf::bcf_get_format_values(
                self.record.header,
                self.record.inner,
                ffi::CString::new(self.tag).unwrap().as_ptr() as *mut i8,
                &mut self.record.buffer,
                &mut n,
                data_type
            )
        } {
            -1 => Err(TagError::UndefinedTag),
            -2 => Err(TagError::UnexpectedType),
            -3 => Err(TagError::MissingTag),
            ret  => Ok((n as usize, ret)),
        }
    }

    pub fn integer(&mut self) -> Result<Vec<&[i32]>, TagError> {
        self.data(htslib::vcf::BCF_HT_INT).map(|(n, _)| {
            unsafe {
                slice::from_raw_parts(self.record.buffer as *const i32, n)
            }.chunks(self.values_per_sample()).map(|s| trim_slice(s, VECTOR_END_INTEGER)).collect()
        })
    }

    pub fn integer_mut(&mut self) -> Result<Vec<&mut [i32]>, TagError> {
        self.data(htslib::vcf::BCF_HT_INT).map(|(n, _)| {
            unsafe {
                slice::from_raw_parts_mut(self.record.buffer as *mut i32, n)
            }.chunks_mut(self.values_per_sample()).collect()
        })
    }

    pub fn float(&mut self) -> Result<Vec<&[f32]>, TagError> {
        self.data(htslib::vcf::BCF_HT_REAL).map(|(n, _)| {
            unsafe {
                slice::from_raw_parts(self.record.buffer as *const f32, n)
            }.chunks(self.values_per_sample()).map(|s| trim_slice(s, VECTOR_END_FLOAT)).collect()
        })
    }

    pub fn float_mut(&mut self) -> Result<Vec<&mut [f32]>, TagError> {
        self.data(htslib::vcf::BCF_HT_REAL).map(|(n, _)| {
            unsafe {
                slice::from_raw_parts_mut(self.record.buffer as *mut f32, n)
            }.chunks_mut(self.values_per_sample()).collect()
        })
    }

    pub fn string(&mut self) -> Result<Vec<&[u8]>, TagError> {
        self.data(htslib::vcf::BCF_HT_STR).map(|(n, _)| {
            unsafe {
                slice::from_raw_parts(self.record.buffer as *const u8, n)
            }.chunks(self.values_per_sample()).map(|s| {
                // stop at zero character
                s.split(|c| *c == 0u8).next().expect("Bug: returned string should not be empty.")
            }).collect()
        })
    }

    pub fn string_mut(&mut self) -> Result<Vec<&mut [u8]>, TagError> {
        self.data(htslib::vcf::BCF_HT_STR).map(|(n, _)| {
            unsafe {
                slice::from_raw_parts_mut(self.record.buffer as *mut u8, n)
            }.chunks_mut(self.values_per_sample()).collect()
        })
    }
}

#[derive(Debug)]
pub enum TagError {
    UndefinedTag,
    UnexpectedType,
    MissingTag,
}
<commit_msg>Wrap pointer dereference for BCF records.<commit_after>// Copyright 2014 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

use std::ptr;
use std::slice;
use std::ffi;
use std::i32;
use std::f32;

use htslib;

pub const MISSING_INTEGER: i32 = i32::MIN;
pub const MISSING_FLOAT: f32 = f32::NAN;
pub const VECTOR_END_INTEGER: i32 = i32::MIN + 1;
pub const VECTOR_END_FLOAT: f32 = 2.139095e+09;

pub struct Record {
    pub inner: *mut htslib::vcf::bcf1_t,
    pub header: *mut htslib::vcf::bcf_hdr_t,
    buffer: *mut ::libc::c_void,
}

impl Record {
    pub fn new() -> Self {
        let inner = unsafe { htslib::vcf::bcf_init() };
        Record { inner: inner, header: ptr::null_mut(), buffer: ptr::null_mut() }
    }

    pub fn inner(&self) -> &htslib::vcf::bcf1_t {
        unsafe { &*self.inner }
    }

    pub fn inner_mut(&mut self) -> &mut htslib::vcf::bcf1_t {
        unsafe { &mut *self.inner }
    }

    pub fn rid(&self) -> Option<u32> {
        match self.inner().rid {
            -1  => None,
            rid => Some(rid as u32)
        }
    }

    // 0-based position.
    pub fn pos(&self) -> u32 {
        self.inner().pos as u32
    }

    pub fn set_pos(&mut self, pos: i32) {
        self.inner_mut().pos = pos;
    }

    pub fn alleles(&self) -> Vec<&[u8]> {
        unsafe { htslib::vcf::bcf_unpack(self.inner, htslib::vcf::BCF_UN_STR) };
        let n = self.inner().n_allele as usize;
        let dec = self.inner().d;
        let alleles = unsafe { slice::from_raw_parts(dec.allele, n) };
        (0..n).map(|i| unsafe { ffi::CStr::from_ptr(alleles[i]).to_bytes() }).collect()
    }

    pub fn qual(&self) -> f32 {
        self.inner().qual
    }

    pub fn set_qual(&mut self, qual: f32) {
        self.inner_mut().qual = qual;
    }

    /// Get the value of the given info tag.
    pub fn info<'a>(&'a mut self, tag: &'a [u8]) -> Info {
        Info { record: self, tag: tag }
    }

    pub fn sample_count(&self) -> u32 {
        self.inner().n_fmt_n_sample >> 8
    }

    pub fn allele_count(&self) -> u16 {
        self.inner().n_allele
    }

    /// Get the value of the given format tag for each sample.
    pub fn format<'a>(&'a mut self, tag: &'a [u8]) -> Format {
        Format::new(self, tag)
    }

    /// Add an integer format tag. Data is a flattened two-dimensional array.
    /// The first dimension contains one array for each sample.
    /// Returns error if tag is not present in header.
    pub fn push_format_integer(&mut self, tag: &[u8], data: &[i32]) -> Result<(), ()> {
        self.push_format(tag, data, htslib::vcf::BCF_HT_INT)
    }

    /// Add a float format tag. Data is a flattened two-dimensional array.
    /// The first dimension contains one array for each sample.
    /// Returns error if tag is not present in header.
    pub fn push_format_float(&mut self, tag: &[u8], data: &[f32]) -> Result<(), ()> {
        self.push_format(tag, data, htslib::vcf::BCF_HT_REAL)
    }

    /// Add a format tag. Data is a flattened two-dimensional array.
    /// The first dimension contains one array for each sample.
    fn push_format<T>(&mut self, tag: &[u8], data: &[T], ht: i32) -> Result<(), ()> {
        assert!(data.len() > 0);
        unsafe {
            if htslib::vcf::bcf_update_format(
                self.header,
                self.inner,
                ffi::CString::new(tag).unwrap().as_ptr() as *mut i8,
                data.as_ptr() as *const ::libc::c_void,
                data.len() as i32,
                ht
            ) == 0 {
                Ok(())
            }
            else {
                Err(())
            }
        }
    }

    /// Add a info tag.
    pub fn push_info<T>(&mut self, tag: &[u8], data: &[T], ht: i32) -> Result<(), ()> {
        assert!(data.len() > 0);
        unsafe {
            if htslib::vcf::bcf_update_info(
                self.header,
                self.inner,
                ffi::CString::new(tag).unwrap().as_ptr() as *mut i8,
                data.as_ptr() as *const ::libc::c_void,
                data.len() as i32,
                ht
            ) == 0 {
                Ok(())
            }
            else {
                Err(())
            }
        }
    }

    /// Remove unused alleles.
    pub fn trim_alleles(&mut self) -> Result<(), ()> {
        match unsafe { htslib::vcfutils::bcf_trim_alleles(self.header, self.inner) } {
            -1 => Err(()),
            _  => Ok(())
        }
    }
}

impl Drop for Record {
    fn drop(&mut self) {
        if !self.buffer.is_null() {
            unsafe { ::libc::free(self.buffer) };
        }
        unsafe { htslib::vcf::bcf_destroy(self.inner) };
    }
}

unsafe impl Send for Record {}

pub struct Info<'a> {
    record: &'a mut Record,
    tag: &'a [u8],
}

impl<'a> Info<'a> {
    fn data(&mut self, data_type: i32) -> Result<(usize, i32), TagError> {
        let mut n: i32 = 0;
        match unsafe {
            htslib::vcf::bcf_get_info_values(
                self.record.header,
                self.record.inner,
                ffi::CString::new(self.tag).unwrap().as_ptr() as *mut i8,
                &mut self.record.buffer,
                &mut n,
                data_type
            )
        } {
            -1 => Err(TagError::UndefinedTag),
            -2 => Err(TagError::UnexpectedType),
            -3 => Err(TagError::MissingTag),
            ret  => Ok((n as usize, ret)),
        }
    }

    pub fn integer(&mut self) -> Result<&[i32], TagError> {
        self.data(htslib::vcf::BCF_HT_INT).map(|(n, _)| {
            trim_slice(
                unsafe { slice::from_raw_parts(self.record.buffer as *const i32, n) },
                VECTOR_END_INTEGER
            )
        })
    }

    pub fn integer_mut(&mut self) -> Result<&mut [i32], TagError> {
        self.data(htslib::vcf::BCF_HT_INT).map(|(n, _)| {
            unsafe { slice::from_raw_parts_mut(self.record.buffer as *mut i32, n) }
        })
    }

    pub fn float(&mut self) -> Result<&[f32], TagError> {
        self.data(htslib::vcf::BCF_HT_REAL).map(|(n, _)| {
            trim_slice(
                unsafe { slice::from_raw_parts(self.record.buffer as *const f32, n) },
                VECTOR_END_FLOAT
            )
        })
    }

    pub fn float_mut(&mut self) -> Result<&mut [f32], TagError> {
        self.data(htslib::vcf::BCF_HT_REAL).map(|(n, _)| {
            unsafe { slice::from_raw_parts_mut(self.record.buffer as *mut f32, n) }
        })
    }

    pub fn flag(&mut self) -> Result<bool, TagError> {
        self.data(htslib::vcf::BCF_HT_FLAG).map(|(_, ret)| {
            ret == 1
        })
    }

    pub fn string(&mut self) -> Result<Vec<&[u8]>, TagError> {
        self.data(htslib::vcf::BCF_HT_STR).map(|(n, ret)| {
            unsafe {
                slice::from_raw_parts(self.record.buffer as *const u8, ret as usize)
            }.chunks(n).map(|s| {
                // stop at zero character
                s.split(|c| *c == 0u8).next().expect("Bug: returned string should not be empty.")
            }).collect()
        })
    }

    pub fn string_mut(&mut self) -> Result<Vec<&mut [u8]>, TagError> {
        self.data(htslib::vcf::BCF_HT_STR).map(|(n, ret)| {
            unsafe {
                slice::from_raw_parts_mut(self.record.buffer as *mut u8, ret as usize)
            }.chunks_mut(n).collect()
        })
    }
}

fn trim_slice<T: PartialEq>(s: &[T], end_value: T) -> &[T] {
    s.split(|v| *v == end_value).next().expect("Bug: returned slice should not be empty.")
}

// TODO implement format.
pub struct Format<'a> {
    record: &'a mut Record,
    tag: &'a [u8],
    inner: *mut htslib::vcf::bcf_fmt_t,
}

impl<'a> Format<'a> {
    fn new(record: &'a mut Record, tag: &'a [u8]) -> Format<'a> {
        let inner = unsafe { htslib::vcf::bcf_get_fmt(
            record.header,
            record.inner,
            ffi::CString::new(tag).unwrap().as_ptr() as *mut i8
        ) };
        Format { record: record, tag: tag, inner: inner }
    }

    pub fn inner(&self) -> &htslib::vcf::bcf_fmt_t {
        unsafe { &*self.inner }
    }

    pub fn inner_mut(&mut self) -> &mut htslib::vcf::bcf_fmt_t {
        unsafe { &mut *self.inner }
    }

    fn values_per_sample(&self) -> usize {
        self.inner().n as usize
    }

    fn data(&mut self, data_type: i32) -> Result<(usize, i32), TagError> {
        let mut n: i32 = 0;
        match unsafe {
            htslib::vcf::bcf_get_format_values(
                self.record.header,
                self.record.inner,
                ffi::CString::new(self.tag).unwrap().as_ptr() as *mut i8,
                &mut self.record.buffer,
                &mut n,
                data_type
            )
        } {
            -1 => Err(TagError::UndefinedTag),
            -2 => Err(TagError::UnexpectedType),
            -3 => Err(TagError::MissingTag),
            ret  => Ok((n as usize, ret)),
        }
    }

    pub fn integer(&mut self) -> Result<Vec<&[i32]>, TagError> {
        self.data(htslib::vcf::BCF_HT_INT).map(|(n, _)| {
            unsafe {
                slice::from_raw_parts(self.record.buffer as *const i32, n)
            }.chunks(self.values_per_sample()).map(|s| trim_slice(s, VECTOR_END_INTEGER)).collect()
        })
    }

    pub fn integer_mut(&mut self) -> Result<Vec<&mut [i32]>, TagError> {
        self.data(htslib::vcf::BCF_HT_INT).map(|(n, _)| {
            unsafe {
                slice::from_raw_parts_mut(self.record.buffer as *mut i32, n)
            }.chunks_mut(self.values_per_sample()).collect()
        })
    }

    pub fn float(&mut self) -> Result<Vec<&[f32]>, TagError> {
        self.data(htslib::vcf::BCF_HT_REAL).map(|(n, _)| {
            unsafe {
                slice::from_raw_parts(self.record.buffer as *const f32, n)
            }.chunks(self.values_per_sample()).map(|s| trim_slice(s, VECTOR_END_FLOAT)).collect()
        })
    }

    pub fn float_mut(&mut self) -> Result<Vec<&mut [f32]>, TagError> {
        self.data(htslib::vcf::BCF_HT_REAL).map(|(n, _)| {
            unsafe {
                slice::from_raw_parts_mut(self.record.buffer as *mut f32, n)
            }.chunks_mut(self.values_per_sample()).collect()
        })
    }

    pub fn string(&mut self) -> Result<Vec<&[u8]>, TagError> {
        self.data(htslib::vcf::BCF_HT_STR).map(|(n, _)| {
            unsafe {
                slice::from_raw_parts(self.record.buffer as *const u8, n)
            }.chunks(self.values_per_sample()).map(|s| {
                // stop at zero character
                s.split(|c| *c == 0u8).next().expect("Bug: returned string should not be empty.")
            }).collect()
        })
    }

    pub fn string_mut(&mut self) -> Result<Vec<&mut [u8]>, TagError> {
        self.data(htslib::vcf::BCF_HT_STR).map(|(n, _)| {
            unsafe {
                slice::from_raw_parts_mut(self.record.buffer as *mut u8, n)
            }.chunks_mut(self.values_per_sample()).collect()
        })
    }
}

#[derive(Debug)]
pub enum TagError {
    UndefinedTag,
    UnexpectedType,
    MissingTag,
}
<|endoftext|>


<commit_before>extern crate rustpn;

use rustpn::parse;
use rustpn::vm::Vm;
use std::io::{stdin, BufRead};

fn main() {
    let mut vm = Vm::<i64>::new_with_builtins();
    let stdin = stdin();
    for program in stdin.lock().lines() {
        let program = program.unwrap();
        match parse::parse(&*program) {
            Ok(ref p) => match vm.run_block(p) {
                Ok(()) => println!("{}", vm),
                Err(e) => println!("runtime error: {}", e),
            },
            Err(e) => match e {
                parse::Error::LexError(e) =>
                    println!("lexer error: {}", e),
                _ => println!("parser error: {}", e),
            }
        }
    }
}
<commit_msg>Switch to BigInt in example binary<commit_after>extern crate rustpn;
extern crate num;

use rustpn::parse;
use rustpn::vm::Vm;
use std::io::{stdin, BufRead};
use num::bigint::BigInt;

fn main() {
    let mut vm = Vm::<BigInt>::new_with_builtins();
    let stdin = stdin();
    for program in stdin.lock().lines() {
        let program = program.unwrap();
        match parse::parse(&*program) {
            Ok(ref p) => match vm.run_block(p) {
                Ok(()) => println!("{}", vm),
                Err(e) => println!("runtime error: {}", e),
            },
            Err(e) => match e {
                parse::Error::LexError(e) =>
                    println!("lexer error: {}", e),
                _ => println!("parser error: {}", e),
            }
        }
    }
}
<|endoftext|>


<commit_before>#![cfg_attr(test, allow(dead_code, unused_imports))]

extern crate arguments;
extern crate mcpat;

#[macro_use]
extern crate squire;

mod dynamic;
mod statik;
mod support;

use arguments::Arguments;
use std::{env, process};
use std::fmt::Display;
use std::io::{self, Write};

const USAGE: &'static str = "
Usage: squire <command> [options]

Commands:
    dynamic        Record the power consumed of a system on a chip.
    static         Record the area occupied by a system on a chip.

Options:
    --help         Display the usage information of a particular command.
";

fn main() {
    let Arguments { options, orphans, .. } = match arguments::parse(env::args()) {
        Ok(arguments) => arguments,
        _ => usage(USAGE),
    };
    if orphans.len() != 1 {
        usage(USAGE);
    }
    let result = match &orphans[0][..] {
        "dynamic" => dynamic::execute(&options),
        "static" => statik::execute(&options),
        _ => fail("the command is unknown"),
    };
    match result {
        Err(error) => fail(error),
        _ => {},
    }
}

#[allow(unused_must_use)]
fn fail<T: Display>(error: T) -> ! {
    io::stderr().write_fmt(format_args!("Error: {}.\n", error));
    process::exit(1);
}

#[allow(unused_must_use)]
fn usage(message: &str) -> ! {
    io::stderr().write_fmt(format_args!("{}\n", message.trim()));
    process::exit(0);
}
<commit_msg>Fix a typo<commit_after>#![cfg_attr(test, allow(dead_code, unused_imports))]

extern crate arguments;
extern crate mcpat;

#[macro_use]
extern crate squire;

mod dynamic;
mod statik;
mod support;

use arguments::Arguments;
use std::{env, process};
use std::fmt::Display;
use std::io::{self, Write};

const USAGE: &'static str = "
Usage: squire <command> [options]

Commands:
    dynamic        Record the power consumed by a system on a chip.
    static         Record the area occupied by a system on a chip.

Options:
    --help         Display the usage information of a particular command.
";

fn main() {
    let Arguments { options, orphans, .. } = match arguments::parse(env::args()) {
        Ok(arguments) => arguments,
        _ => usage(USAGE),
    };
    if orphans.len() != 1 {
        usage(USAGE);
    }
    let result = match &orphans[0][..] {
        "dynamic" => dynamic::execute(&options),
        "static" => statik::execute(&options),
        _ => fail("the command is unknown"),
    };
    match result {
        Err(error) => fail(error),
        _ => {},
    }
}

#[allow(unused_must_use)]
fn fail<T: Display>(error: T) -> ! {
    io::stderr().write_fmt(format_args!("Error: {}.\n", error));
    process::exit(1);
}

#[allow(unused_must_use)]
fn usage(message: &str) -> ! {
    io::stderr().write_fmt(format_args!("{}\n", message.trim()));
    process::exit(0);
}
<|endoftext|>


<commit_before>use erased_serde::{Deserializer, Serialize, Serializer};
use std::collections::BTreeMap as Map;
use std::io;

#[test]
fn serialization() {
    // Construct some serializers.
    let json = &mut serde_json::ser::Serializer::new(io::stdout());
    let cbor = &mut serde_cbor::ser::Serializer::new(serde_cbor::ser::IoWrite::new(io::stdout()));

    // The values in this map are boxed trait objects. Ordinarily this would not
    // be possible with serde::Serializer because of object safety, but type
    // erasure makes it possible with erased_serde::Serializer.
    let mut formats: Map<&str, Box<dyn Serializer>> = Map::new();
    formats.insert("json", Box::new(Serializer::erase(json)));
    formats.insert("cbor", Box::new(Serializer::erase(cbor)));

    // These are boxed trait objects as well. Same thing here - type erasure
    // makes this possible.
    let mut values: Map<&str, Box<dyn Serialize>> = Map::new();
    values.insert("vec", Box::new(vec!["a", "b"]));
    values.insert("int", Box::new(65536));

    // Pick a Serializer out of the formats map.
    let format = formats.get_mut("json").unwrap();

    // Pick a Serialize out of the values map.
    let value = values.get("vec").unwrap();

    // This line prints `["a","b"]` to stdout.
    value.erased_serialize(format).unwrap();
}

#[test]
fn deserialization() {
    static JSON: &'static [u8] = br#"{"A": 65, "B": 66}"#;
    static CBOR: &'static [u8] = &[162, 97, 65, 24, 65, 97, 66, 24, 66];

    // Construct some deserializers.
    let json = &mut serde_json::de::Deserializer::from_slice(JSON);
    let cbor = &mut serde_cbor::de::Deserializer::from_slice(CBOR);

    // The values in this map are boxed trait objects, which is not possible
    // with the normal serde::Deserializer because of object safety.
    let mut formats: Map<&str, Box<dyn Deserializer>> = Map::new();
    formats.insert("json", Box::new(Deserializer::erase(json)));
    formats.insert("cbor", Box::new(Deserializer::erase(cbor)));

    // Pick a Deserializer out of the formats map.
    let format = formats.get_mut("json").unwrap();

    let data: Map<String, usize> = erased_serde::deserialize(format).unwrap();

    println!("{}", data["A"] + data["B"]);
}
<commit_msg>Add reminder to tests/readme.md<commit_after>// Please also update README.md when making changes to this code.

use erased_serde::{Deserializer, Serialize, Serializer};
use std::collections::BTreeMap as Map;
use std::io;

#[test]
fn serialization() {
    // Construct some serializers.
    let json = &mut serde_json::ser::Serializer::new(io::stdout());
    let cbor = &mut serde_cbor::ser::Serializer::new(serde_cbor::ser::IoWrite::new(io::stdout()));

    // The values in this map are boxed trait objects. Ordinarily this would not
    // be possible with serde::Serializer because of object safety, but type
    // erasure makes it possible with erased_serde::Serializer.
    let mut formats: Map<&str, Box<dyn Serializer>> = Map::new();
    formats.insert("json", Box::new(Serializer::erase(json)));
    formats.insert("cbor", Box::new(Serializer::erase(cbor)));

    // These are boxed trait objects as well. Same thing here - type erasure
    // makes this possible.
    let mut values: Map<&str, Box<dyn Serialize>> = Map::new();
    values.insert("vec", Box::new(vec!["a", "b"]));
    values.insert("int", Box::new(65536));

    // Pick a Serializer out of the formats map.
    let format = formats.get_mut("json").unwrap();

    // Pick a Serialize out of the values map.
    let value = values.get("vec").unwrap();

    // This line prints `["a","b"]` to stdout.
    value.erased_serialize(format).unwrap();
}

#[test]
fn deserialization() {
    static JSON: &'static [u8] = br#"{"A": 65, "B": 66}"#;
    static CBOR: &'static [u8] = &[162, 97, 65, 24, 65, 97, 66, 24, 66];

    // Construct some deserializers.
    let json = &mut serde_json::de::Deserializer::from_slice(JSON);
    let cbor = &mut serde_cbor::de::Deserializer::from_slice(CBOR);

    // The values in this map are boxed trait objects, which is not possible
    // with the normal serde::Deserializer because of object safety.
    let mut formats: Map<&str, Box<dyn Deserializer>> = Map::new();
    formats.insert("json", Box::new(Deserializer::erase(json)));
    formats.insert("cbor", Box::new(Deserializer::erase(cbor)));

    // Pick a Deserializer out of the formats map.
    let format = formats.get_mut("json").unwrap();

    let data: Map<String, usize> = erased_serde::deserialize(format).unwrap();

    println!("{}", data["A"] + data["B"]);
}
<|endoftext|>


<commit_before>extern crate klee;

#[test]
fn basic_test() {
  let a : i32 = 0;
  klee::symbol(&a, "a");
  assert_eq!(a, 56);
}

#[test]
fn other_test() {
  let a : i32 = 0;
  let b : i32 = 0;

  klee::symbol(&a, "a");
  klee::symbol(&b, "b");

  if a == 50 {
    if b == 49 {
      klee::warning("this path is reachable");
    }
  }
}

#[test]
fn another_test() {
  let a = klee::i32("a");
  if a > 60 && a < 90 {
    let b = a + 40;
    klee::assert_warn(b == 0, "this assertion should not trigger");

    if b == 12 {
      klee::warning("This path should be unreachable");
    }

    klee::assert_warn(b == 101, "this assertion should trigger");
    klee::assert_warn(b == 150000, "this assersion should not trigger");
  }
}
<commit_msg>Update simple.rs<commit_after>extern crate klee;

#[test]
fn basic_test() {
  let a : i32 = 0;
  klee::symbol(&a, "a");
  assert_eq!(a, 56);
}

#[test]
fn other_test() {
  let a : i32 = 0;
  let b : i32 = 0;

  klee::symbol(&a, "a");
  klee::symbol(&b, "b");

  if a == 50 {
    if b == 49 {
      klee::warning_once("this path is reachable");
    }
  }
}

#[test]
fn another_test() {
  let a = klee::i32("a");
  if a > 60 && a < 90 {
    let b = a + 40;
    klee::assert_warn(b == 0, "this assertion should not trigger");

    if b == 12 {
      klee::warning_once("This path should be unreachable");
    }

    klee::assert_warn(b == 101, "this assertion should trigger");
    klee::assert_warn(b == 150000, "this assersion should not trigger");
  }
}
<|endoftext|>