<commit_before>//! Visitor for a run-time value with a given layout: Traverse enums, structs and other compound
//! types until we arrive at the leaves, with custom handling for primitive types.

use rustc::ty::layout::{self, TyLayout, VariantIdx};
use rustc::ty;
use rustc::mir::interpret::{
    EvalResult,
};

use super::{
    Machine, EvalContext, MPlaceTy, OpTy,
};

// A thing that we can project into, and that has a layout.
// This wouldn't have to depend on `Machine` but with the current type inference,
// that's just more convenient to work with (avoids repeating all the `Machine` bounds).
pub trait Value<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>: Copy
{
    /// Get this value's layout.
    fn layout(&self) -> TyLayout<'tcx>;

    /// Make this into an `OpTy`.
    fn to_op(
        self,
        ecx: &EvalContext<'a, 'mir, 'tcx, M>,
    ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>>;

    /// Create this from an `MPlaceTy`.
    fn from_mem_place(mplace: MPlaceTy<'tcx, M::PointerTag>) -> Self;

    /// Project to the given enum variant.
    fn project_downcast(
        self,
        ecx: &EvalContext<'a, 'mir, 'tcx, M>,
        variant: VariantIdx,
    ) -> EvalResult<'tcx, Self>;

    /// Project to the n-th field.
    fn project_field(
        self,
        ecx: &EvalContext<'a, 'mir, 'tcx, M>,
        field: u64,
    ) -> EvalResult<'tcx, Self>;
}

// Operands and memory-places are both values.
// Places in general are not due to `place_field` having to do `force_allocation`.
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M>
    for OpTy<'tcx, M::PointerTag>
{
    #[inline(always)]
    fn layout(&self) -> TyLayout<'tcx> {
        self.layout
    }

    #[inline(always)]
    fn to_op(
        self,
        _ecx: &EvalContext<'a, 'mir, 'tcx, M>,
    ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
        Ok(self)
    }

    #[inline(always)]
    fn from_mem_place(mplace: MPlaceTy<'tcx, M::PointerTag>) -> Self {
        mplace.into()
    }

    #[inline(always)]
    fn project_downcast(
        self,
        ecx: &EvalContext<'a, 'mir, 'tcx, M>,
        variant: VariantIdx,
    ) -> EvalResult<'tcx, Self> {
        ecx.operand_downcast(self, variant)
    }

    #[inline(always)]
    fn project_field(
        self,
        ecx: &EvalContext<'a, 'mir, 'tcx, M>,
        field: u64,
    ) -> EvalResult<'tcx, Self> {
        ecx.operand_field(self, field)
    }
}
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M>
    for MPlaceTy<'tcx, M::PointerTag>
{
    #[inline(always)]
    fn layout(&self) -> TyLayout<'tcx> {
        self.layout
    }

    #[inline(always)]
    fn to_op(
        self,
        _ecx: &EvalContext<'a, 'mir, 'tcx, M>,
    ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
        Ok(self.into())
    }

    #[inline(always)]
    fn from_mem_place(mplace: MPlaceTy<'tcx, M::PointerTag>) -> Self {
        mplace
    }

    #[inline(always)]
    fn project_downcast(
        self,
        ecx: &EvalContext<'a, 'mir, 'tcx, M>,
        variant: VariantIdx,
    ) -> EvalResult<'tcx, Self> {
        ecx.mplace_downcast(self, variant)
    }

    #[inline(always)]
    fn project_field(
        self,
        ecx: &EvalContext<'a, 'mir, 'tcx, M>,
        field: u64,
    ) -> EvalResult<'tcx, Self> {
        ecx.mplace_field(self, field)
    }
}

macro_rules! make_value_visitor {
    ($visitor_trait_name:ident, $($mutability:ident)*) => {
        // How to traverse a value and what to do when we are at the leaves.
        pub trait $visitor_trait_name<'a, 'mir, 'tcx: 'mir+'a, M: Machine<'a, 'mir, 'tcx>>: Sized {
            type V: Value<'a, 'mir, 'tcx, M>;

            /// The visitor must have an `EvalContext` in it.
            fn ecx(&$($mutability)* self)
                -> &$($mutability)* EvalContext<'a, 'mir, 'tcx, M>;

            // Recursive actions, ready to be overloaded.
            /// Visit the given value, dispatching as appropriate to more specialized visitors.
            #[inline(always)]
            fn visit_value(&mut self, v: Self::V) -> EvalResult<'tcx>
            {
                self.walk_value(v)
            }
            /// Visit the given value as a union.  No automatic recursion can happen here.
            #[inline(always)]
            fn visit_union(&mut self, _v: Self::V) -> EvalResult<'tcx>
            {
                Ok(())
            }
            /// Visit this vale as an aggregate, you are even getting an iterator yielding
            /// all the fields (still in an `EvalResult`, you have to do error handling yourself).
            /// Recurses into the fields.
            #[inline(always)]
            fn visit_aggregate(
                &mut self,
                v: Self::V,
                fields: impl Iterator<Item=EvalResult<'tcx, Self::V>>,
            ) -> EvalResult<'tcx> {
                self.walk_aggregate(v, fields)
            }

            /// Called each time we recurse down to a field of a "product-like" aggregate
            /// (structs, tuples, arrays and the like, but not enums), passing in old and new value.
            /// This gives the visitor the chance to track the stack of nested fields that
            /// we are descending through.
            #[inline(always)]
            fn visit_field(
                &mut self,
                _old_val: Self::V,
                _field: usize,
                new_val: Self::V,
            ) -> EvalResult<'tcx> {
                self.visit_value(new_val)
            }

            /// Called for recursing into the field of a generator.  These are not known to be
            /// initialized, so we treat them like unions.
            #[inline(always)]
            fn visit_generator_field(
                &mut self,
                _old_val: Self::V,
                _field: usize,
                new_val: Self::V,
            ) -> EvalResult<'tcx> {
                self.visit_union(new_val)
            }

            /// Called when recursing into an enum variant.
            #[inline(always)]
            fn visit_variant(
                &mut self,
                _old_val: Self::V,
                _variant: VariantIdx,
                new_val: Self::V,
            ) -> EvalResult<'tcx> {
                self.visit_value(new_val)
            }

            /// Called whenever we reach a value with uninhabited layout.
            /// Recursing to fields will *always* continue after this!  This is not meant to control
            /// whether and how we descend recursively/ into the scalar's fields if there are any,
            /// it is meant to provide the chance for additional checks when a value of uninhabited
            /// layout is detected.
            #[inline(always)]
            fn visit_uninhabited(&mut self) -> EvalResult<'tcx>
            { Ok(()) }
            /// Called whenever we reach a value with scalar layout.
            /// We do NOT provide a `ScalarMaybeUndef` here to avoid accessing memory if the
            /// visitor is not even interested in scalars.
            /// Recursing to fields will *always* continue after this!  This is not meant to control
            /// whether and how we descend recursively/ into the scalar's fields if there are any,
            /// it is meant to provide the chance for additional checks when a value of scalar
            /// layout is detected.
            #[inline(always)]
            fn visit_scalar(&mut self, _v: Self::V, _layout: &layout::Scalar) -> EvalResult<'tcx>
            { Ok(()) }

            /// Called whenever we reach a value of primitive type.  There can be no recursion
            /// below such a value.  This is the leaf function.
            /// We do *not* provide an `ImmTy` here because some implementations might want
            /// to write to the place this primitive lives in.
            #[inline(always)]
            fn visit_primitive(&mut self, _v: Self::V) -> EvalResult<'tcx>
            { Ok(()) }

            // Default recursors. Not meant to be overloaded.
            fn walk_aggregate(
                &mut self,
                v: Self::V,
                fields: impl Iterator<Item=EvalResult<'tcx, Self::V>>,
            ) -> EvalResult<'tcx> {
                // Now iterate over it.
                for (idx, field_val) in fields.enumerate() {
                    self.visit_field(v, idx, field_val?)?;
                }
                Ok(())
            }
            fn walk_value(&mut self, v: Self::V) -> EvalResult<'tcx>
            {
                trace!("walk_value: type: {}", v.layout().ty);
                // If this is a multi-variant layout, we have find the right one and proceed with
                // that.
                match v.layout().variants {
                    layout::Variants::NicheFilling { .. } |
                    layout::Variants::Tagged { .. } => {
                        let op = v.to_op(self.ecx())?;
                        let idx = self.ecx().read_discriminant(op)?.1;
                        let inner = v.project_downcast(self.ecx(), idx)?;
                        trace!("walk_value: variant layout: {:#?}", inner.layout());
                        // recurse with the inner type
                        return self.visit_variant(v, idx, inner);
                    }
                    layout::Variants::Single { .. } => {}
                }

                // Even for single variants, we might be able to get a more refined type:
                // If it is a trait object, switch to the actual type that was used to create it.
                match v.layout().ty.sty {
                    ty::Dynamic(..) => {
                        // immediate trait objects are not a thing
                        let dest = v.to_op(self.ecx())?.to_mem_place();
                        let inner = self.ecx().unpack_dyn_trait(dest)?.1;
                        trace!("walk_value: dyn object layout: {:#?}", inner.layout);
                        // recurse with the inner type
                        return self.visit_field(v, 0, Value::from_mem_place(inner));
                    },
                    _ => {},
                };

                // If this is a scalar, visit it as such.
                // Things can be aggregates and have scalar layout at the same time, and that
                // is very relevant for `NonNull` and similar structs: We need to visit them
                // at their scalar layout *before* descending into their fields.
                // FIXME: We could avoid some redundant checks here. For newtypes wrapping
                // scalars, we do the same check on every "level" (e.g., first we check
                // MyNewtype and then the scalar in there).
                match v.layout().abi {
                    layout::Abi::Uninhabited => {
                        self.visit_uninhabited()?;
                    }
                    layout::Abi::Scalar(ref layout) => {
                        self.visit_scalar(v, layout)?;
                    }
                    // FIXME: Should we do something for ScalarPair? Vector?
                    _ => {}
                }

                // Check primitive types.  We do this after checking the scalar layout,
                // just to have that done as well.  Primitives can have varying layout,
                // so we check them separately and before aggregate handling.
                // It is CRITICAL that we get this check right, or we might be
                // validating the wrong thing!
                let primitive = match v.layout().fields {
                    // Primitives appear as Union with 0 fields - except for Boxes and fat pointers.
                    layout::FieldPlacement::Union(0) => true,
                    _ => v.layout().ty.builtin_deref(true).is_some(),
                };
                if primitive {
                    return self.visit_primitive(v);
                }

                // Proceed into the fields.
                match v.layout().fields {
                    layout::FieldPlacement::Union(fields) => {
                        // Empty unions are not accepted by rustc. That's great, it means we can
                        // use that as an unambiguous signal for detecting primitives.  Make sure
                        // we did not miss any primitive.
                        debug_assert!(fields > 0);
                        self.visit_union(v)
                    },
                    layout::FieldPlacement::Arbitrary { ref offsets, .. } => {
                        // Special handling needed for generators: All but the first field
                        // (which is the state) are actually implicitly `MaybeUninit`, i.e.,
                        // they may or may not be initialized, so we cannot visit them.
                        match v.layout().ty.sty {
                            ty::Generator(..) => {
                                let field = v.project_field(self.ecx(), 0)?;
                                self.visit_aggregate(v, std::iter::once(Ok(field)))?;
                                for i in 1..offsets.len() {
                                    let field = v.project_field(self.ecx(), i as u64)?;
                                    self.visit_generator_field(v, i, field)?;
                                }
                                Ok(())
                            }
                            _ => {
                                // FIXME: We collect in a vec because otherwise there are lifetime
                                // errors: Projecting to a field needs access to `ecx`.
                                let fields: Vec<EvalResult<'tcx, Self::V>> =
                                    (0..offsets.len()).map(|i| {
                                        v.project_field(self.ecx(), i as u64)
                                    })
                                    .collect();
                                self.visit_aggregate(v, fields.into_iter())
                            }
                        }
                    },
                    layout::FieldPlacement::Array { .. } => {
                        // Let's get an mplace first.
                        let mplace = if v.layout().is_zst() {
                            // it's a ZST, the memory content cannot matter
                            MPlaceTy::dangling(v.layout(), self.ecx())
                        } else {
                            // non-ZST array/slice/str cannot be immediate
                            v.to_op(self.ecx())?.to_mem_place()
                        };
                        // Now we can go over all the fields.
                        let iter = self.ecx().mplace_array_fields(mplace)?
                            .map(|f| f.and_then(|f| {
                                Ok(Value::from_mem_place(f))
                            }));
                        self.visit_aggregate(v, iter)
                    }
                }
            }
        }
    }
}

make_value_visitor!(ValueVisitor,);
make_value_visitor!(MutValueVisitor,mut);
<commit_msg>miri value visitor: use  in macro<commit_after>//! Visitor for a run-time value with a given layout: Traverse enums, structs and other compound
//! types until we arrive at the leaves, with custom handling for primitive types.

use rustc::ty::layout::{self, TyLayout, VariantIdx};
use rustc::ty;
use rustc::mir::interpret::{
    EvalResult,
};

use super::{
    Machine, EvalContext, MPlaceTy, OpTy,
};

// A thing that we can project into, and that has a layout.
// This wouldn't have to depend on `Machine` but with the current type inference,
// that's just more convenient to work with (avoids repeating all the `Machine` bounds).
pub trait Value<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>: Copy
{
    /// Get this value's layout.
    fn layout(&self) -> TyLayout<'tcx>;

    /// Make this into an `OpTy`.
    fn to_op(
        self,
        ecx: &EvalContext<'a, 'mir, 'tcx, M>,
    ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>>;

    /// Create this from an `MPlaceTy`.
    fn from_mem_place(mplace: MPlaceTy<'tcx, M::PointerTag>) -> Self;

    /// Project to the given enum variant.
    fn project_downcast(
        self,
        ecx: &EvalContext<'a, 'mir, 'tcx, M>,
        variant: VariantIdx,
    ) -> EvalResult<'tcx, Self>;

    /// Project to the n-th field.
    fn project_field(
        self,
        ecx: &EvalContext<'a, 'mir, 'tcx, M>,
        field: u64,
    ) -> EvalResult<'tcx, Self>;
}

// Operands and memory-places are both values.
// Places in general are not due to `place_field` having to do `force_allocation`.
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M>
    for OpTy<'tcx, M::PointerTag>
{
    #[inline(always)]
    fn layout(&self) -> TyLayout<'tcx> {
        self.layout
    }

    #[inline(always)]
    fn to_op(
        self,
        _ecx: &EvalContext<'a, 'mir, 'tcx, M>,
    ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
        Ok(self)
    }

    #[inline(always)]
    fn from_mem_place(mplace: MPlaceTy<'tcx, M::PointerTag>) -> Self {
        mplace.into()
    }

    #[inline(always)]
    fn project_downcast(
        self,
        ecx: &EvalContext<'a, 'mir, 'tcx, M>,
        variant: VariantIdx,
    ) -> EvalResult<'tcx, Self> {
        ecx.operand_downcast(self, variant)
    }

    #[inline(always)]
    fn project_field(
        self,
        ecx: &EvalContext<'a, 'mir, 'tcx, M>,
        field: u64,
    ) -> EvalResult<'tcx, Self> {
        ecx.operand_field(self, field)
    }
}
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M>
    for MPlaceTy<'tcx, M::PointerTag>
{
    #[inline(always)]
    fn layout(&self) -> TyLayout<'tcx> {
        self.layout
    }

    #[inline(always)]
    fn to_op(
        self,
        _ecx: &EvalContext<'a, 'mir, 'tcx, M>,
    ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
        Ok(self.into())
    }

    #[inline(always)]
    fn from_mem_place(mplace: MPlaceTy<'tcx, M::PointerTag>) -> Self {
        mplace
    }

    #[inline(always)]
    fn project_downcast(
        self,
        ecx: &EvalContext<'a, 'mir, 'tcx, M>,
        variant: VariantIdx,
    ) -> EvalResult<'tcx, Self> {
        ecx.mplace_downcast(self, variant)
    }

    #[inline(always)]
    fn project_field(
        self,
        ecx: &EvalContext<'a, 'mir, 'tcx, M>,
        field: u64,
    ) -> EvalResult<'tcx, Self> {
        ecx.mplace_field(self, field)
    }
}

macro_rules! make_value_visitor {
    ($visitor_trait_name:ident, $($mutability:ident)?) => {
        // How to traverse a value and what to do when we are at the leaves.
        pub trait $visitor_trait_name<'a, 'mir, 'tcx: 'mir+'a, M: Machine<'a, 'mir, 'tcx>>: Sized {
            type V: Value<'a, 'mir, 'tcx, M>;

            /// The visitor must have an `EvalContext` in it.
            fn ecx(&$($mutability)? self)
                -> &$($mutability)? EvalContext<'a, 'mir, 'tcx, M>;

            // Recursive actions, ready to be overloaded.
            /// Visit the given value, dispatching as appropriate to more specialized visitors.
            #[inline(always)]
            fn visit_value(&mut self, v: Self::V) -> EvalResult<'tcx>
            {
                self.walk_value(v)
            }
            /// Visit the given value as a union.  No automatic recursion can happen here.
            #[inline(always)]
            fn visit_union(&mut self, _v: Self::V) -> EvalResult<'tcx>
            {
                Ok(())
            }
            /// Visit this vale as an aggregate, you are even getting an iterator yielding
            /// all the fields (still in an `EvalResult`, you have to do error handling yourself).
            /// Recurses into the fields.
            #[inline(always)]
            fn visit_aggregate(
                &mut self,
                v: Self::V,
                fields: impl Iterator<Item=EvalResult<'tcx, Self::V>>,
            ) -> EvalResult<'tcx> {
                self.walk_aggregate(v, fields)
            }

            /// Called each time we recurse down to a field of a "product-like" aggregate
            /// (structs, tuples, arrays and the like, but not enums), passing in old and new value.
            /// This gives the visitor the chance to track the stack of nested fields that
            /// we are descending through.
            #[inline(always)]
            fn visit_field(
                &mut self,
                _old_val: Self::V,
                _field: usize,
                new_val: Self::V,
            ) -> EvalResult<'tcx> {
                self.visit_value(new_val)
            }

            /// Called for recursing into the field of a generator.  These are not known to be
            /// initialized, so we treat them like unions.
            #[inline(always)]
            fn visit_generator_field(
                &mut self,
                _old_val: Self::V,
                _field: usize,
                new_val: Self::V,
            ) -> EvalResult<'tcx> {
                self.visit_union(new_val)
            }

            /// Called when recursing into an enum variant.
            #[inline(always)]
            fn visit_variant(
                &mut self,
                _old_val: Self::V,
                _variant: VariantIdx,
                new_val: Self::V,
            ) -> EvalResult<'tcx> {
                self.visit_value(new_val)
            }

            /// Called whenever we reach a value with uninhabited layout.
            /// Recursing to fields will *always* continue after this!  This is not meant to control
            /// whether and how we descend recursively/ into the scalar's fields if there are any,
            /// it is meant to provide the chance for additional checks when a value of uninhabited
            /// layout is detected.
            #[inline(always)]
            fn visit_uninhabited(&mut self) -> EvalResult<'tcx>
            { Ok(()) }
            /// Called whenever we reach a value with scalar layout.
            /// We do NOT provide a `ScalarMaybeUndef` here to avoid accessing memory if the
            /// visitor is not even interested in scalars.
            /// Recursing to fields will *always* continue after this!  This is not meant to control
            /// whether and how we descend recursively/ into the scalar's fields if there are any,
            /// it is meant to provide the chance for additional checks when a value of scalar
            /// layout is detected.
            #[inline(always)]
            fn visit_scalar(&mut self, _v: Self::V, _layout: &layout::Scalar) -> EvalResult<'tcx>
            { Ok(()) }

            /// Called whenever we reach a value of primitive type.  There can be no recursion
            /// below such a value.  This is the leaf function.
            /// We do *not* provide an `ImmTy` here because some implementations might want
            /// to write to the place this primitive lives in.
            #[inline(always)]
            fn visit_primitive(&mut self, _v: Self::V) -> EvalResult<'tcx>
            { Ok(()) }

            // Default recursors. Not meant to be overloaded.
            fn walk_aggregate(
                &mut self,
                v: Self::V,
                fields: impl Iterator<Item=EvalResult<'tcx, Self::V>>,
            ) -> EvalResult<'tcx> {
                // Now iterate over it.
                for (idx, field_val) in fields.enumerate() {
                    self.visit_field(v, idx, field_val?)?;
                }
                Ok(())
            }
            fn walk_value(&mut self, v: Self::V) -> EvalResult<'tcx>
            {
                trace!("walk_value: type: {}", v.layout().ty);
                // If this is a multi-variant layout, we have find the right one and proceed with
                // that.
                match v.layout().variants {
                    layout::Variants::NicheFilling { .. } |
                    layout::Variants::Tagged { .. } => {
                        let op = v.to_op(self.ecx())?;
                        let idx = self.ecx().read_discriminant(op)?.1;
                        let inner = v.project_downcast(self.ecx(), idx)?;
                        trace!("walk_value: variant layout: {:#?}", inner.layout());
                        // recurse with the inner type
                        return self.visit_variant(v, idx, inner);
                    }
                    layout::Variants::Single { .. } => {}
                }

                // Even for single variants, we might be able to get a more refined type:
                // If it is a trait object, switch to the actual type that was used to create it.
                match v.layout().ty.sty {
                    ty::Dynamic(..) => {
                        // immediate trait objects are not a thing
                        let dest = v.to_op(self.ecx())?.to_mem_place();
                        let inner = self.ecx().unpack_dyn_trait(dest)?.1;
                        trace!("walk_value: dyn object layout: {:#?}", inner.layout);
                        // recurse with the inner type
                        return self.visit_field(v, 0, Value::from_mem_place(inner));
                    },
                    _ => {},
                };

                // If this is a scalar, visit it as such.
                // Things can be aggregates and have scalar layout at the same time, and that
                // is very relevant for `NonNull` and similar structs: We need to visit them
                // at their scalar layout *before* descending into their fields.
                // FIXME: We could avoid some redundant checks here. For newtypes wrapping
                // scalars, we do the same check on every "level" (e.g., first we check
                // MyNewtype and then the scalar in there).
                match v.layout().abi {
                    layout::Abi::Uninhabited => {
                        self.visit_uninhabited()?;
                    }
                    layout::Abi::Scalar(ref layout) => {
                        self.visit_scalar(v, layout)?;
                    }
                    // FIXME: Should we do something for ScalarPair? Vector?
                    _ => {}
                }

                // Check primitive types.  We do this after checking the scalar layout,
                // just to have that done as well.  Primitives can have varying layout,
                // so we check them separately and before aggregate handling.
                // It is CRITICAL that we get this check right, or we might be
                // validating the wrong thing!
                let primitive = match v.layout().fields {
                    // Primitives appear as Union with 0 fields - except for Boxes and fat pointers.
                    layout::FieldPlacement::Union(0) => true,
                    _ => v.layout().ty.builtin_deref(true).is_some(),
                };
                if primitive {
                    return self.visit_primitive(v);
                }

                // Proceed into the fields.
                match v.layout().fields {
                    layout::FieldPlacement::Union(fields) => {
                        // Empty unions are not accepted by rustc. That's great, it means we can
                        // use that as an unambiguous signal for detecting primitives.  Make sure
                        // we did not miss any primitive.
                        debug_assert!(fields > 0);
                        self.visit_union(v)
                    },
                    layout::FieldPlacement::Arbitrary { ref offsets, .. } => {
                        // Special handling needed for generators: All but the first field
                        // (which is the state) are actually implicitly `MaybeUninit`, i.e.,
                        // they may or may not be initialized, so we cannot visit them.
                        match v.layout().ty.sty {
                            ty::Generator(..) => {
                                let field = v.project_field(self.ecx(), 0)?;
                                self.visit_aggregate(v, std::iter::once(Ok(field)))?;
                                for i in 1..offsets.len() {
                                    let field = v.project_field(self.ecx(), i as u64)?;
                                    self.visit_generator_field(v, i, field)?;
                                }
                                Ok(())
                            }
                            _ => {
                                // FIXME: We collect in a vec because otherwise there are lifetime
                                // errors: Projecting to a field needs access to `ecx`.
                                let fields: Vec<EvalResult<'tcx, Self::V>> =
                                    (0..offsets.len()).map(|i| {
                                        v.project_field(self.ecx(), i as u64)
                                    })
                                    .collect();
                                self.visit_aggregate(v, fields.into_iter())
                            }
                        }
                    },
                    layout::FieldPlacement::Array { .. } => {
                        // Let's get an mplace first.
                        let mplace = if v.layout().is_zst() {
                            // it's a ZST, the memory content cannot matter
                            MPlaceTy::dangling(v.layout(), self.ecx())
                        } else {
                            // non-ZST array/slice/str cannot be immediate
                            v.to_op(self.ecx())?.to_mem_place()
                        };
                        // Now we can go over all the fields.
                        let iter = self.ecx().mplace_array_fields(mplace)?
                            .map(|f| f.and_then(|f| {
                                Ok(Value::from_mem_place(f))
                            }));
                        self.visit_aggregate(v, iter)
                    }
                }
            }
        }
    }
}

make_value_visitor!(ValueVisitor,);
make_value_visitor!(MutValueVisitor,mut);
<|endoftext|>


<commit_before>// This file is part of the uutils coreutils package.
//
// (c) Alan Andrade <alan.andradec@gmail.com>
// (c) Jian Zeng <anonymousknight96 AT gmail.com>
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.

// spell-checker:ignore (ToDO) passwd

#[macro_use]
extern crate uucore;
use uucore::entries::{get_groups_gnu, gid2grp, Locate, Passwd};

use clap::{crate_version, App, Arg};

static ABOUT: &str = "display current group names";
static OPT_USER: &str = "user";

fn get_usage() -> String {
    format!("{0} [USERNAME]", executable!())
}

pub fn uumain(args: impl uucore::Args) -> i32 {
    let usage = get_usage();

    let matches = App::new(executable!())
        .version(crate_version!())
        .about(ABOUT)
        .usage(&usage[..])
        .arg(Arg::with_name(OPT_USER))
        .get_matches_from(args);

    match matches.value_of(OPT_USER) {
        None => {
            println!(
                "{}",
                get_groups_gnu(None)
                    .unwrap()
                    .iter()
                    .map(|&g| gid2grp(g).unwrap())
                    .collect::<Vec<_>>()
                    .join(" ")
            );
            0
        }
        Some(user) => {
            if let Ok(p) = Passwd::locate(user) {
                println!(
                    "{}",
                    p.belongs_to()
                        .iter()
                        .map(|&g| gid2grp(g).unwrap())
                        .collect::<Vec<_>>()
                        .join(" ")
                );
                0
            } else {
                crash!(1, "unknown user {}", user);
            }
        }
    }
}
<commit_msg>groups: fix to pass GNU Testsuite `groups-dash.sh`<commit_after>// This file is part of the uutils coreutils package.
//
// (c) Alan Andrade <alan.andradec@gmail.com>
// (c) Jian Zeng <anonymousknight96 AT gmail.com>
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.

// spell-checker:ignore (ToDO) passwd

#[macro_use]
extern crate uucore;
use uucore::entries::{get_groups_gnu, gid2grp, Locate, Passwd};

use clap::{crate_version, App, Arg};

static ABOUT: &str = "display current group names";
static OPT_USER: &str = "user";

fn get_usage() -> String {
    format!("{0} [USERNAME]", executable!())
}

pub fn uumain(args: impl uucore::Args) -> i32 {
    let usage = get_usage();

    let matches = App::new(executable!())
        .version(crate_version!())
        .about(ABOUT)
        .usage(&usage[..])
        .arg(Arg::with_name(OPT_USER))
        .get_matches_from(args);

    match matches.value_of(OPT_USER) {
        None => {
            println!(
                "{}",
                get_groups_gnu(None)
                    .unwrap()
                    .iter()
                    .map(|&g| gid2grp(g).unwrap())
                    .collect::<Vec<_>>()
                    .join(" ")
            );
            0
        }
        Some(user) => {
            if let Ok(p) = Passwd::locate(user) {
                println!(
                    "{}",
                    p.belongs_to()
                        .iter()
                        .map(|&g| gid2grp(g).unwrap())
                        .collect::<Vec<_>>()
                        .join(" ")
                );
                0
            } else {
                crash!(1, "'{}': no such user", user);
            }
        }
    }
}
<|endoftext|>


<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/. */

#[crate_id = "github.com/mozilla/servo"];
#[comment = "The Servo Parallel Browser Project"];
#[license = "MPL"];

#[feature(globs, macro_rules, managed_boxes, thread_local)];

extern mod alert;
extern mod azure;
extern mod geom;
extern mod gfx;
#[cfg(not(target_os="android"))]
extern mod glfw;
#[cfg(target_os="android")]
extern mod glut;
extern mod js;
extern mod layers;
extern mod opengles;
extern mod png;
#[cfg(target_os="android")]
extern mod rustuv;
extern mod script;
extern mod servo_net = "net";
extern mod servo_msg = "msg";
extern mod servo_util = "util";
extern mod style;
extern mod sharegl;
extern mod stb_image;

extern mod extra;
extern mod green;
extern mod native;

#[cfg(target_os="macos")]
extern mod core_graphics;
#[cfg(target_os="macos")]
extern mod core_text;

#[cfg(not(test))]
use compositing::{CompositorChan, CompositorTask};
#[cfg(not(test))]
use constellation::Constellation;
#[cfg(not(test))]
use servo_msg::constellation_msg::InitLoadUrlMsg;

#[cfg(not(test))]
use servo_net::image_cache_task::{ImageCacheTask, SyncImageCacheTask};
#[cfg(not(test))]
use servo_net::resource_task::ResourceTask;
#[cfg(not(test))]
use servo_util::time::Profiler;

#[cfg(not(test))]
use servo_util::opts;
#[cfg(not(test))]
use servo_util::url::parse_url;

#[cfg(not(test))]
use std::os;
#[cfg(not(test))]
use extra::url::Url;
#[cfg(not(test), target_os="android")]
use std::str;
#[cfg(not(test))]
use std::task::TaskOpts;

#[path="compositing/compositor_task.rs"]
pub mod compositing;

pub mod macros;

pub mod css {
    mod node_util;

    pub mod select;
    pub mod matching;
    pub mod node_style;
}

pub mod constellation;
pub mod pipeline;

pub mod layout {
    pub mod block;
    pub mod box_;
    pub mod construct;
    pub mod context;
    pub mod display_list_builder;
    pub mod floats;
    pub mod flow;
    pub mod flow_list;
    pub mod layout_task;
    pub mod inline;
    pub mod model;
    pub mod parallel;
    pub mod text;
    pub mod util;
    pub mod incremental;
    pub mod wrapper;
    pub mod extra;
}

pub mod windowing;

#[path="platform/mod.rs"]
pub mod platform;

#[path = "util/mod.rs"]
pub mod util;

#[cfg(not(test), target_os="linux")]
#[cfg(not(test), target_os="macos")]
#[start]
fn start(argc: int, argv: **u8) -> int {
    native::start(argc, argv, proc() {
        opts::from_cmdline_args(os::args()).map(run);
    })
}

#[cfg(not(test), target_os="android")]
#[no_mangle]
pub extern "C" fn android_start(argc: int, argv: **u8) -> int {
    native::start(argc, argv, proc() {
        let mut args:~[~str] = ~[];
        for i in range(0u, argc as uint) {
            unsafe {
                args.push(str::raw::from_c_str(*argv.offset(i as int) as *i8));
            }
        }
        opts::from_cmdline_args(os::args()).map(run);
    })
}

#[cfg(not(test))]
fn run(opts: opts::Opts) {
    let mut pool = green::SchedPool::new(green::PoolConfig::new());

    let (compositor_port, compositor_chan) = CompositorChan::new();
    let profiler_chan = Profiler::create(opts.profiler_period);

    let opts_clone = opts.clone();
    let profiler_chan_clone = profiler_chan.clone();

    let (result_port, result_chan) = Chan::new();
    pool.spawn(TaskOpts::new(), proc() {
        let opts = &opts_clone;
        // Create a Servo instance.
        let resource_task = ResourceTask();
        // If we are emitting an output file, then we need to block on
        // image load or we risk emitting an output file missing the
        // image.
        let image_cache_task = if opts.output_file.is_some() {
                SyncImageCacheTask(resource_task.clone())
            } else {
                ImageCacheTask(resource_task.clone())
            };
        let constellation_chan = Constellation::start(compositor_chan,
                                                      opts,
                                                      resource_task,
                                                      image_cache_task,
                                                      profiler_chan_clone);

        // Send the URL command to the constellation.
        for filename in opts.urls.iter() {
            let url = if filename.starts_with("data:") {
                // As a hack for easier command-line testing,
                // assume that data URLs are not URL-encoded.
                Url::new(~"data", None, ~"", None,
                    filename.slice_from(5).to_owned(), ~[], None)
            } else {
                parse_url(*filename, None)
            };

            constellation_chan.send(InitLoadUrlMsg(url));
        }

        // Send the constallation Chan as the result
        result_chan.send(constellation_chan);
    });

    let constellation_chan = result_port.recv();

    debug!("preparing to enter main loop");
    CompositorTask::create(opts,
                           compositor_port,
                           constellation_chan,
                           profiler_chan);

    pool.shutdown();
}

<commit_msg>Fix Android argument handling<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/. */

#[crate_id = "github.com/mozilla/servo"];
#[comment = "The Servo Parallel Browser Project"];
#[license = "MPL"];

#[feature(globs, macro_rules, managed_boxes, thread_local)];

extern mod alert;
extern mod azure;
extern mod geom;
extern mod gfx;
#[cfg(not(target_os="android"))]
extern mod glfw;
#[cfg(target_os="android")]
extern mod glut;
extern mod js;
extern mod layers;
extern mod opengles;
extern mod png;
#[cfg(target_os="android")]
extern mod rustuv;
extern mod script;
extern mod servo_net = "net";
extern mod servo_msg = "msg";
extern mod servo_util = "util";
extern mod style;
extern mod sharegl;
extern mod stb_image;

extern mod extra;
extern mod green;
extern mod native;

#[cfg(target_os="macos")]
extern mod core_graphics;
#[cfg(target_os="macos")]
extern mod core_text;

#[cfg(not(test))]
use compositing::{CompositorChan, CompositorTask};
#[cfg(not(test))]
use constellation::Constellation;
#[cfg(not(test))]
use servo_msg::constellation_msg::InitLoadUrlMsg;

#[cfg(not(test))]
use servo_net::image_cache_task::{ImageCacheTask, SyncImageCacheTask};
#[cfg(not(test))]
use servo_net::resource_task::ResourceTask;
#[cfg(not(test))]
use servo_util::time::Profiler;

#[cfg(not(test))]
use servo_util::opts;
#[cfg(not(test))]
use servo_util::url::parse_url;

#[cfg(not(test))]
use std::os;
#[cfg(not(test))]
use extra::url::Url;
#[cfg(not(test), target_os="android")]
use std::str;
#[cfg(not(test))]
use std::task::TaskOpts;

#[path="compositing/compositor_task.rs"]
pub mod compositing;

pub mod macros;

pub mod css {
    mod node_util;

    pub mod select;
    pub mod matching;
    pub mod node_style;
}

pub mod constellation;
pub mod pipeline;

pub mod layout {
    pub mod block;
    pub mod box_;
    pub mod construct;
    pub mod context;
    pub mod display_list_builder;
    pub mod floats;
    pub mod flow;
    pub mod flow_list;
    pub mod layout_task;
    pub mod inline;
    pub mod model;
    pub mod parallel;
    pub mod text;
    pub mod util;
    pub mod incremental;
    pub mod wrapper;
    pub mod extra;
}

pub mod windowing;

#[path="platform/mod.rs"]
pub mod platform;

#[path = "util/mod.rs"]
pub mod util;

#[cfg(not(test), target_os="linux")]
#[cfg(not(test), target_os="macos")]
#[start]
fn start(argc: int, argv: **u8) -> int {
    native::start(argc, argv, proc() {
        opts::from_cmdline_args(os::args()).map(run);
    })
}

#[cfg(not(test), target_os="android")]
#[no_mangle]
pub extern "C" fn android_start(argc: int, argv: **u8) -> int {
    native::start(argc, argv, proc() {
        let mut args:~[~str] = ~[];
        for i in range(0u, argc as uint) {
            unsafe {
                args.push(str::raw::from_c_str(*argv.offset(i as int) as *i8));
            }
        }
        opts::from_cmdline_args(args).map(run);
    })
}

#[cfg(not(test))]
fn run(opts: opts::Opts) {
    let mut pool = green::SchedPool::new(green::PoolConfig::new());

    let (compositor_port, compositor_chan) = CompositorChan::new();
    let profiler_chan = Profiler::create(opts.profiler_period);

    let opts_clone = opts.clone();
    let profiler_chan_clone = profiler_chan.clone();

    let (result_port, result_chan) = Chan::new();
    pool.spawn(TaskOpts::new(), proc() {
        let opts = &opts_clone;
        // Create a Servo instance.
        let resource_task = ResourceTask();
        // If we are emitting an output file, then we need to block on
        // image load or we risk emitting an output file missing the
        // image.
        let image_cache_task = if opts.output_file.is_some() {
                SyncImageCacheTask(resource_task.clone())
            } else {
                ImageCacheTask(resource_task.clone())
            };
        let constellation_chan = Constellation::start(compositor_chan,
                                                      opts,
                                                      resource_task,
                                                      image_cache_task,
                                                      profiler_chan_clone);

        // Send the URL command to the constellation.
        for filename in opts.urls.iter() {
            let url = if filename.starts_with("data:") {
                // As a hack for easier command-line testing,
                // assume that data URLs are not URL-encoded.
                Url::new(~"data", None, ~"", None,
                    filename.slice_from(5).to_owned(), ~[], None)
            } else {
                parse_url(*filename, None)
            };

            constellation_chan.send(InitLoadUrlMsg(url));
        }

        // Send the constallation Chan as the result
        result_chan.send(constellation_chan);
    });

    let constellation_chan = result_port.recv();

    debug!("preparing to enter main loop");
    CompositorTask::create(opts,
                           compositor_port,
                           constellation_chan,
                           profiler_chan);

    pool.shutdown();
}

<|endoftext|>


<commit_before>#![cfg(test)]

extern crate esprit;
extern crate estree;
extern crate joker;
extern crate serde_json;

// From 'rustc-test' crate.
// Mirrors Rust's internal 'libtest'.
// https://doc.rust-lang.org/1.1.0/test/index.html
extern crate test;

extern crate unjson;

use esprit::script;
use estree::IntoScript;
use joker::track::Untrack;
use serde_json::value::Value;
use std::ffi::OsStr;
use std::fs::{File, read_dir};
use std::io::Read;
use std::path::Path;
use std::{thread, env};
use test::{TestDesc, TestDescAndFn, TestName, TestFn, Bencher, TDynBenchFn, test_main};
use test::ShouldPanic::No;
use unjson::Unjson;

struct DynBenchFn<F> {
    run: F
}

impl<F: Fn(&mut Bencher) + Send + 'static> TDynBenchFn for DynBenchFn<F> {
    fn run(&self, harness: &mut Bencher) {
        (self.run)(harness);
    }
}

fn add_bench<F: Fn(&mut Bencher) + Send + 'static>(tests: &mut Vec<TestDescAndFn>, name: String, ignore: bool, f: F) {
    tests.push(TestDescAndFn {
        desc: TestDesc {
            name: TestName::DynTestName(name),
            ignore: ignore,
            should_panic: No
        },
        testfn: TestFn::DynBenchFn(Box::new(DynBenchFn { run: f }))
    });
}

fn integration_tests(target: &mut Vec<TestDescAndFn>, ignore: bool) {
    let root = Path::new(env!("CARGO_MANIFEST_DIR"));

    let fixtures = {
        let mut fixtures = root.to_path_buf();
        fixtures.push("tests");
        fixtures.push("esprima");
        fixtures.push("test");
        fixtures.push("3rdparty");
        fixtures
    };

    let syntax = fixtures.join("syntax");

    let files =
        read_dir(syntax).unwrap()
        .map(|dir| dir.unwrap().path())
        .filter(|path| path.extension() == Some(OsStr::new("json")))
        .map(|tree_path| {
            let mut source_path = fixtures.join(tree_path.file_name().unwrap());
            source_path.set_extension("js");
            let name = source_path.strip_prefix(&root).unwrap().to_str().unwrap().to_string();

            (tree_path, source_path, name)
        });

    if ignore {
        // Fast path for ignored tests needs only their names
        for (_, _, name) in files {
            add_bench(target, name, true, |_| {});
        }
        return;
    }

    let tests =
        files
        .map(|(tree_path, source_path, name)| {
            let tree_name = tree_path.strip_prefix(&root).unwrap().to_str().unwrap().to_string();

            // Read & parse each JSON in dedicated thread
            let thread = thread::Builder::new().name(tree_name.clone()).spawn(move || {
                let mut source = String::new();
                File::open(source_path).unwrap().read_to_string(&mut source).unwrap();

                println!("Parsing JSON {}...", tree_name);
                let expected_ast = {
                    let v: Value = serde_json::de::from_reader(File::open(&tree_path).unwrap()).unwrap();
                    v.into_object().unwrap().into_script().map_err(|err| {
                        format!("failed to deserialize script: {}", err)
                    }).unwrap()
                };
                println!("Done parsing {}", tree_name);
                (source, expected_ast)
            }).unwrap();

            (name, thread)
        })
        // First collect to evaluate iterator and spawn threads
        .collect::<Vec<_>>()
        .into_iter()
        .map(|(name, thread)| {
            let (source, expected_ast) = thread.join().unwrap();
            (name, source, expected_ast)
        })
         // Then collect results from threads so that they don't affect benchmark numbers
        .collect::<Vec<_>>();

    for (name, source, expected_ast) in tests {
        add_bench(target, name, false, move |mut bench| {
            let mut result = None;
            bench.iter(|| {
                result = Some(script(&source[..]))
            });
            match result.unwrap() {
                Ok(mut actual_ast) => {
                    actual_ast.untrack();
                    assert!(actual_ast == expected_ast, "integration test got wrong result");
                }
                Err(actual_err) => {
                    panic!("integration test failed to parse:\n{:#?}", actual_err);
                }
            }
        });
    }
}

fn main() {
    let args: Vec<_> = env::args().collect();
    let bench = args.contains(&"--bench".to_string());
    let ignore_integration_tests = !bench && env::var_os("ESTREE_INTEGRATION_TESTS") == None;
    if ignore_integration_tests {
        println!("note: Run with `ESTREE_INTEGRATION_TESTS=1` to run with integration tests (much slower).");
    }
    thread::Builder::new().name("bench".to_string()).spawn(move || {
        let mut tests = Vec::new();
        integration_tests(&mut tests, ignore_integration_tests);
        test_main(&args, tests);
    }).unwrap().join().unwrap();
}
<commit_msg>Restore custom minimal stack size<commit_after>#![cfg(test)]

extern crate esprit;
extern crate estree;
extern crate joker;
extern crate serde_json;

// From 'rustc-test' crate.
// Mirrors Rust's internal 'libtest'.
// https://doc.rust-lang.org/1.1.0/test/index.html
extern crate test;

extern crate unjson;

use esprit::script;
use estree::IntoScript;
use joker::track::Untrack;
use serde_json::value::Value;
use std::ffi::OsStr;
use std::fs::{File, read_dir};
use std::io::Read;
use std::path::Path;
use std::{thread, env};
use test::{TestDesc, TestDescAndFn, TestName, TestFn, Bencher, TDynBenchFn, test_main};
use test::ShouldPanic::No;
use unjson::Unjson;

struct DynBenchFn<F> {
    run: F
}

impl<F: Fn(&mut Bencher) + Send + 'static> TDynBenchFn for DynBenchFn<F> {
    fn run(&self, harness: &mut Bencher) {
        (self.run)(harness);
    }
}

fn add_bench<F: Fn(&mut Bencher) + Send + 'static>(tests: &mut Vec<TestDescAndFn>, name: String, ignore: bool, f: F) {
    tests.push(TestDescAndFn {
        desc: TestDesc {
            name: TestName::DynTestName(name),
            ignore: ignore,
            should_panic: No
        },
        testfn: TestFn::DynBenchFn(Box::new(DynBenchFn { run: f }))
    });
}

fn integration_tests(target: &mut Vec<TestDescAndFn>, ignore: bool) {
    let root = Path::new(env!("CARGO_MANIFEST_DIR"));

    let fixtures = {
        let mut fixtures = root.to_path_buf();
        fixtures.push("tests");
        fixtures.push("esprima");
        fixtures.push("test");
        fixtures.push("3rdparty");
        fixtures
    };

    let syntax = fixtures.join("syntax");

    let files =
        read_dir(syntax).unwrap()
        .map(|dir| dir.unwrap().path())
        .filter(|path| path.extension() == Some(OsStr::new("json")))
        .map(|tree_path| {
            let mut source_path = fixtures.join(tree_path.file_name().unwrap());
            source_path.set_extension("js");
            let name = source_path.strip_prefix(&root).unwrap().to_str().unwrap().to_string();

            (tree_path, source_path, name)
        });

    if ignore {
        // Fast path for ignored tests needs only their names
        for (_, _, name) in files {
            add_bench(target, name, true, |_| {});
        }
        return;
    }

    let stack_size =
        std::cmp::max(
            // standard Rust env variable
            env::var("RUST_MIN_STACK")
            .ok()
            .and_then(|s| s.parse().ok())
            .unwrap_or_default(),
            // ...but with custom minimal value
            4 * 1024 * 1024
        );

    let tests =
        files
        .map(|(tree_path, source_path, name)| {
            let tree_name = tree_path.strip_prefix(&root).unwrap().to_str().unwrap().to_string();

            // Read & parse each JSON in dedicated thread
            let thread =
                thread::Builder::new()
                .name(tree_name.clone())
                .stack_size(stack_size)
                .spawn(move || {
                    let mut source = String::new();
                    File::open(source_path).unwrap().read_to_string(&mut source).unwrap();

                    println!("Parsing JSON {}...", tree_name);
                    let expected_ast = {
                        let v: Value = serde_json::de::from_reader(File::open(&tree_path).unwrap()).unwrap();
                        v.into_object().unwrap().into_script().map_err(|err| {
                            format!("failed to deserialize script: {}", err)
                        }).unwrap()
                    };
                    println!("Done parsing {}", tree_name);
                    (source, expected_ast)
                })
                .unwrap();

            (name, thread)
        })
        // First collect to evaluate iterator and spawn threads
        .collect::<Vec<_>>()
        .into_iter()
        .map(|(name, thread)| {
            let (source, expected_ast) = thread.join().unwrap();
            (name, source, expected_ast)
        })
         // Then collect results from threads so that they don't affect benchmark numbers
        .collect::<Vec<_>>();

    for (name, source, expected_ast) in tests {
        add_bench(target, name, false, move |mut bench| {
            let mut result = None;
            bench.iter(|| {
                result = Some(script(&source[..]))
            });
            match result.unwrap() {
                Ok(mut actual_ast) => {
                    actual_ast.untrack();
                    assert!(actual_ast == expected_ast, "integration test got wrong result");
                }
                Err(actual_err) => {
                    panic!("integration test failed to parse:\n{:#?}", actual_err);
                }
            }
        });
    }
}

fn main() {
    let args: Vec<_> = env::args().collect();
    let bench = args.contains(&"--bench".to_string());
    let ignore_integration_tests = !bench && env::var_os("ESTREE_INTEGRATION_TESTS") == None;
    if ignore_integration_tests {
        println!("note: Run with `ESTREE_INTEGRATION_TESTS=1` to run with integration tests (much slower).");
    }
    thread::Builder::new().name("bench".to_string()).spawn(move || {
        let mut tests = Vec::new();
        integration_tests(&mut tests, ignore_integration_tests);
        test_main(&args, tests);
    }).unwrap().join().unwrap();
}
<|endoftext|>


<commit_before>//! A set of builders to generate Rust source for PHF data structures at
//! compile time.
//!
//! The provided builders are intended to be used in a Cargo build script to
//! generate a Rust source file that will be included in a library at build
//! time.
//!
//! # Examples
//!
//! build.rs
//!
//! ```rust,no_run
//! extern crate phf_codegen;
//!
//! use std::fs::File;
//! use std::io::{BufWriter, Write};
//! use std::path::AsPath;
//! use std::env;
//!
//! fn main() {
//!     let path = env::var_os("OUT_DIR").unwrap().as_path().join("codegen.rs");
//!     let mut file = BufWriter::new(File::create(&path).unwrap());
//!
//!     write!(&mut file, "static KEYWORDS: phf::Map<&'static str, Keyword> = ").unwrap();
//!     phf_codegen::Map::new()
//!         .entry("loop", "Keyword::Loop")
//!         .entry("continue", "Keyword::Continue")
//!         .entry("break", "Keyword::Break")
//!         .entry("fn", "Keyword::Fn")
//!         .entry("extern", "Keyword::Extern")
//!         .build(&mut file)
//!         .unwrap();
//!     write!(&mut file, ";\n").unwrap();
//! }
//! ```
//!
//! lib.rs
//!
//! ```ignore
//! extern crate phf;
//!
//! #[derive(Clone)]
//! enum Keyword {
//!     Loop,
//!     Continue,
//!     Break,
//!     Fn,
//!     Extern,
//! }
//!
//! include!(concat!(env!("OUT_DIR"), "/codegen.rs"));
//!
//! pub fn parse_keyword(keyword: &str) -> Option<Keyword> {
//!     KEYWORDS.get(keyword).cloned()
//! }
//! ```
#![doc(html_root_url="http://sfackler.github.io/rust-phf/doc")]
#![feature(io)]

extern crate phf_shared;
extern crate phf_generator;

use phf_shared::PhfHash;
use std::collections::HashSet;
use std::fmt;
use std::hash::Hash;
use std::io;
use std::io::prelude::*;

/// A builder for the `phf::Map` type.
pub struct Map<K> {
    keys: Vec<K>,
    values: Vec<String>,
}

impl<K: Hash+PhfHash+Eq+fmt::Debug> Map<K> {
    /// Creates a new `phf::Map` builder.
    pub fn new() -> Map<K> {
        Map {
            keys: vec![],
            values: vec![],
        }
    }

    /// Adds an entry to the builder.
    ///
    /// `value` will be written exactly as provided in the constructed source.
    pub fn entry(&mut self, key: K, value: &str) -> &mut Map<K> {
        self.keys.push(key);
        self.values.push(value.to_string());
        self
    }

    /// Constructs a `phf::Map`, outputting Rust source to the provided writer.
    ///
    /// # Panics
    ///
    /// Panics if there are any duplicate keys.
    pub fn build<W: Write>(&self, w: &mut W) -> io::Result<()> {
        let mut set = HashSet::new();
        for key in &self.keys {
            if !set.insert(key) {
                panic!("duplicate key `{:?}`", key);
            }
        }

        let state = phf_generator::generate_hash(&self.keys);

        try!(write!(w, "::phf::Map {{
    key: {},
    disps: &[
",
                    state.key));
        for &(d1, d2) in &state.disps {
            try!(write!(w, "
        ({}, {}),",
                        d1, d2));
        }
        try!(write!(w, "
    ],
    entries: &[
"));
        for &idx in &state.map {
            try!(write!(w, "
        ({:?}, {}),",
                        &self.keys[idx], &self.values[idx]));
        }
        write!(w, "
    ]
}}")
    }
}

/// A builder for the `phf::Set` type.
pub struct Set<T> {
    map: Map<T>
}

impl<T: Hash+PhfHash+Eq+fmt::Debug> Set<T> {
    /// Constructs a new `phf::Set` builder.
    pub fn new() -> Set<T> {
        Set {
            map: Map::new()
        }
    }

    /// Adds an entry to the builder.
    pub fn entry(&mut self, entry: T) -> &mut Set<T> {
        self.map.entry(entry, "()");
        self
    }

    /// Constructs a `phf::Set`, outputting Rust source to the provided writer.
    ///
    /// # Panics
    ///
    /// Panics if there are any duplicate entries.
    pub fn build<W: Write>(&self, w: &mut W) -> io::Result<()> {
        try!(write!(w, "::phf::Set {{ map: "));
        try!(self.map.build(w));
        write!(w, " }}")
    }
}

/// A builder for the `phf::OrderedMap` type.
pub struct OrderedMap<K> {
    keys: Vec<K>,
    values: Vec<String>,
}

impl<K: Hash+PhfHash+Eq+fmt::Debug> OrderedMap<K> {
    /// Constructs a enw `phf::OrderedMap` builder.
    pub fn new() -> OrderedMap<K> {
        OrderedMap {
            keys: vec![],
            values: vec![],
        }
    }

    /// Adds an entry to the builder.
    ///
    /// `value` will be written exactly as provided in the constructed source.
    pub fn entry(&mut self, key: K, value: &str) -> &mut OrderedMap<K> {
        self.keys.push(key);
        self.values.push(value.to_string());
        self
    }

    /// Constructs a `phf::OrderedMap`, outputting Rust source to the provided
    /// writer.
    ///
    /// # Panics
    ///
    /// Panics if there are any duplicate keys.
    pub fn build<W: Write>(&self, w: &mut W) -> io::Result<()> {
        let mut set = HashSet::new();
        for key in &self.keys {
            if !set.insert(key) {
                panic!("duplicate key `{:?}`", key);
            }
        }

        let state = phf_generator::generate_hash(&self.keys);

        try!(write!(w, "::phf::OrderedMap {{
    key: {},
    disps: &[",
                    state.key));
        for &(d1, d2) in &state.disps {
            try!(write!(w, "
        ({}, {}),",
                        d1, d2));
        }
        try!(write!(w, "
    ],
    idxs: &["));
        for &idx in &state.map {
            try!(write!(w, "
        {},",
                        idx));
        }
        try!(write!(w, "
    ],
    entries: &["));
        for (key, value) in self.keys.iter().zip(self.values.iter()) {
            try!(write!(w, "
        ({:?}, {}),",
                        key, value));
        }
        write!(w, "
    ]
}}")
    }
}

/// A builder for the `phf::OrderedSet` type.
pub struct OrderedSet<T> {
    map: OrderedMap<T>
}

impl<T: Hash+PhfHash+Eq+fmt::Debug> OrderedSet<T> {
    /// Constructs a new `phf::OrderedSet` builder.
    pub fn new() -> OrderedSet<T> {
        OrderedSet {
            map: OrderedMap::new()
        }
    }

    /// Adds an entry to the builder.
    pub fn entry(&mut self, entry: T) -> &mut OrderedSet<T> {
        self.map.entry(entry, "()");
        self
    }

    /// Constructs a `phf::OrderedSet`, outputting Rust source to the provided
    /// writer.
    ///
    /// # Panics
    ///
    /// Panics if there are any duplicate entries.
    pub fn build<W: Write>(&self, w: &mut W) -> io::Result<()> {
        try!(write!(w, "::phf::OrderedSet {{ map: "));
        try!(self.map.build(w));
        write!(w, " }}")
    }
}
<commit_msg>Fix whitespace in codegen<commit_after>//! A set of builders to generate Rust source for PHF data structures at
//! compile time.
//!
//! The provided builders are intended to be used in a Cargo build script to
//! generate a Rust source file that will be included in a library at build
//! time.
//!
//! # Examples
//!
//! build.rs
//!
//! ```rust,no_run
//! extern crate phf_codegen;
//!
//! use std::fs::File;
//! use std::io::{BufWriter, Write};
//! use std::path::AsPath;
//! use std::env;
//!
//! fn main() {
//!     let path = env::var_os("OUT_DIR").unwrap().as_path().join("codegen.rs");
//!     let mut file = BufWriter::new(File::create(&path).unwrap());
//!
//!     write!(&mut file, "static KEYWORDS: phf::Map<&'static str, Keyword> = ").unwrap();
//!     phf_codegen::Map::new()
//!         .entry("loop", "Keyword::Loop")
//!         .entry("continue", "Keyword::Continue")
//!         .entry("break", "Keyword::Break")
//!         .entry("fn", "Keyword::Fn")
//!         .entry("extern", "Keyword::Extern")
//!         .build(&mut file)
//!         .unwrap();
//!     write!(&mut file, ";\n").unwrap();
//! }
//! ```
//!
//! lib.rs
//!
//! ```ignore
//! extern crate phf;
//!
//! #[derive(Clone)]
//! enum Keyword {
//!     Loop,
//!     Continue,
//!     Break,
//!     Fn,
//!     Extern,
//! }
//!
//! include!(concat!(env!("OUT_DIR"), "/codegen.rs"));
//!
//! pub fn parse_keyword(keyword: &str) -> Option<Keyword> {
//!     KEYWORDS.get(keyword).cloned()
//! }
//! ```
#![doc(html_root_url="http://sfackler.github.io/rust-phf/doc")]
#![feature(io)]

extern crate phf_shared;
extern crate phf_generator;

use phf_shared::PhfHash;
use std::collections::HashSet;
use std::fmt;
use std::hash::Hash;
use std::io;
use std::io::prelude::*;

/// A builder for the `phf::Map` type.
pub struct Map<K> {
    keys: Vec<K>,
    values: Vec<String>,
}

impl<K: Hash+PhfHash+Eq+fmt::Debug> Map<K> {
    /// Creates a new `phf::Map` builder.
    pub fn new() -> Map<K> {
        Map {
            keys: vec![],
            values: vec![],
        }
    }

    /// Adds an entry to the builder.
    ///
    /// `value` will be written exactly as provided in the constructed source.
    pub fn entry(&mut self, key: K, value: &str) -> &mut Map<K> {
        self.keys.push(key);
        self.values.push(value.to_string());
        self
    }

    /// Constructs a `phf::Map`, outputting Rust source to the provided writer.
    ///
    /// # Panics
    ///
    /// Panics if there are any duplicate keys.
    pub fn build<W: Write>(&self, w: &mut W) -> io::Result<()> {
        let mut set = HashSet::new();
        for key in &self.keys {
            if !set.insert(key) {
                panic!("duplicate key `{:?}`", key);
            }
        }

        let state = phf_generator::generate_hash(&self.keys);

        try!(write!(w, "::phf::Map {{
    key: {},
    disps: &[",
                    state.key));
        for &(d1, d2) in &state.disps {
            try!(write!(w, "
        ({}, {}),",
                        d1, d2));
        }
        try!(write!(w, "
    ],
    entries: &["));
        for &idx in &state.map {
            try!(write!(w, "
        ({:?}, {}),",
                        &self.keys[idx], &self.values[idx]));
        }
        write!(w, "
    ]
}}")
    }
}

/// A builder for the `phf::Set` type.
pub struct Set<T> {
    map: Map<T>
}

impl<T: Hash+PhfHash+Eq+fmt::Debug> Set<T> {
    /// Constructs a new `phf::Set` builder.
    pub fn new() -> Set<T> {
        Set {
            map: Map::new()
        }
    }

    /// Adds an entry to the builder.
    pub fn entry(&mut self, entry: T) -> &mut Set<T> {
        self.map.entry(entry, "()");
        self
    }

    /// Constructs a `phf::Set`, outputting Rust source to the provided writer.
    ///
    /// # Panics
    ///
    /// Panics if there are any duplicate entries.
    pub fn build<W: Write>(&self, w: &mut W) -> io::Result<()> {
        try!(write!(w, "::phf::Set {{ map: "));
        try!(self.map.build(w));
        write!(w, " }}")
    }
}

/// A builder for the `phf::OrderedMap` type.
pub struct OrderedMap<K> {
    keys: Vec<K>,
    values: Vec<String>,
}

impl<K: Hash+PhfHash+Eq+fmt::Debug> OrderedMap<K> {
    /// Constructs a enw `phf::OrderedMap` builder.
    pub fn new() -> OrderedMap<K> {
        OrderedMap {
            keys: vec![],
            values: vec![],
        }
    }

    /// Adds an entry to the builder.
    ///
    /// `value` will be written exactly as provided in the constructed source.
    pub fn entry(&mut self, key: K, value: &str) -> &mut OrderedMap<K> {
        self.keys.push(key);
        self.values.push(value.to_string());
        self
    }

    /// Constructs a `phf::OrderedMap`, outputting Rust source to the provided
    /// writer.
    ///
    /// # Panics
    ///
    /// Panics if there are any duplicate keys.
    pub fn build<W: Write>(&self, w: &mut W) -> io::Result<()> {
        let mut set = HashSet::new();
        for key in &self.keys {
            if !set.insert(key) {
                panic!("duplicate key `{:?}`", key);
            }
        }

        let state = phf_generator::generate_hash(&self.keys);

        try!(write!(w, "::phf::OrderedMap {{
    key: {},
    disps: &[",
                    state.key));
        for &(d1, d2) in &state.disps {
            try!(write!(w, "
        ({}, {}),",
                        d1, d2));
        }
        try!(write!(w, "
    ],
    idxs: &["));
        for &idx in &state.map {
            try!(write!(w, "
        {},",
                        idx));
        }
        try!(write!(w, "
    ],
    entries: &["));
        for (key, value) in self.keys.iter().zip(self.values.iter()) {
            try!(write!(w, "
        ({:?}, {}),",
                        key, value));
        }
        write!(w, "
    ]
}}")
    }
}

/// A builder for the `phf::OrderedSet` type.
pub struct OrderedSet<T> {
    map: OrderedMap<T>
}

impl<T: Hash+PhfHash+Eq+fmt::Debug> OrderedSet<T> {
    /// Constructs a new `phf::OrderedSet` builder.
    pub fn new() -> OrderedSet<T> {
        OrderedSet {
            map: OrderedMap::new()
        }
    }

    /// Adds an entry to the builder.
    pub fn entry(&mut self, entry: T) -> &mut OrderedSet<T> {
        self.map.entry(entry, "()");
        self
    }

    /// Constructs a `phf::OrderedSet`, outputting Rust source to the provided
    /// writer.
    ///
    /// # Panics
    ///
    /// Panics if there are any duplicate entries.
    pub fn build<W: Write>(&self, w: &mut W) -> io::Result<()> {
        try!(write!(w, "::phf::OrderedSet {{ map: "));
        try!(self.map.build(w));
        write!(w, " }}")
    }
}
<|endoftext|>


<commit_before>use hashing::hash;

const SSZ_CHUNK_SIZE: usize = 128;
const HASHSIZE: usize = 32;

pub trait TreeHash {
    fn hash_tree_root_internal(&self) -> Vec<u8>;
    fn hash_tree_root(&self) -> Vec<u8> {
        let mut result = self.hash_tree_root_internal();
        if result.len() < HASHSIZE {
            zpad(&mut result, HASHSIZE);
        }
        result
    }
}

/// Returns a 32 byte hash of 'list' - a vector of byte vectors.
/// Note that this will consume 'list'.
pub fn merkle_hash(list: &mut Vec<Vec<u8>>) -> Vec<u8> {
    // flatten list
    let (mut chunk_size, mut chunkz) = list_to_blob(list);

    // get data_len as bytes. It will hashed will the merkle root
    let mut datalen = list.len().to_le_bytes().to_vec();
    zpad(&mut datalen, 32);

    // Tree-hash
    while chunkz.len() > HASHSIZE {
        let mut new_chunkz: Vec<u8> = Vec::new();

        for two_chunks in chunkz.chunks(chunk_size * 2) {
            if two_chunks.len() == chunk_size {
                // Odd number of chunks
                let mut c = two_chunks.to_vec();
                c.append(&mut vec![0; SSZ_CHUNK_SIZE]);
                new_chunkz.append(&mut hash(&c));
            } else {
                // Hash two chuncks together
                new_chunkz.append(&mut hash(two_chunks));
            }
        }

        chunk_size = HASHSIZE;
        chunkz = new_chunkz;
    }

    chunkz.append(&mut datalen);
    hash(&chunkz)
}

fn list_to_blob(list: &mut Vec<Vec<u8>>) -> (usize, Vec<u8>) {
    let chunk_size = if list.is_empty() || list[0].len() < SSZ_CHUNK_SIZE {
        SSZ_CHUNK_SIZE
    } else {
        list[0].len()
    };

    let items_per_chunk = SSZ_CHUNK_SIZE / list[0].len();
    let chunk_count = list.len() / items_per_chunk;

    let mut chunkz = Vec::new();
    if list.is_empty() {
        // handle and empty list
        chunkz.append(&mut vec![0; SSZ_CHUNK_SIZE]);
    } else if list[0].len() <= SSZ_CHUNK_SIZE {
        // just create a blob here; we'll divide into
        // chunked slices when we merklize
        let mut chunk = Vec::with_capacity(chunk_size);
        let mut item_count_in_chunk = 0;
        chunkz.reserve(chunk_count * chunk_size);
        for item in list.iter_mut() {
            item_count_in_chunk += 1;
            chunk.append(item);

            // completed chunk?
            if item_count_in_chunk == items_per_chunk {
                zpad(&mut chunk, chunk_size);
                chunkz.append(&mut chunk);
                item_count_in_chunk = 0;
            }
        }

        // left-over uncompleted chunk?
        if item_count_in_chunk != 0 {
            zpad(&mut chunk, chunk_size);
            chunkz.append(&mut chunk);
        }
    } else {
        // chunks larger than SSZ_CHUNK_SIZE
        chunkz.reserve(chunk_count * chunk_size);
        for item in list.iter_mut() {
            chunkz.append(item);
        }
    }

    (chunk_size, chunkz)
}

/// right pads with zeros making 'bytes' 'size' in length
fn zpad(bytes: &mut Vec<u8>, size: usize) {
    if bytes.len() < size {
        bytes.resize(size, 0);
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_merkle_hash() {
        let data1 = vec![1; 100];
        let data2 = vec![2; 100];
        let data3 = vec![3; 100];
        let mut list = vec![data1, data2, data3];
        let result = merkle_hash(&mut list);

        //note: should test againt a known test hash value
        assert_eq!(HASHSIZE, result.len());
    }
}
<commit_msg>fixed a bug in TreeHash.rs/list_to_blob<commit_after>use hashing::hash;

const SSZ_CHUNK_SIZE: usize = 128;
const HASHSIZE: usize = 32;

pub trait TreeHash {
    fn hash_tree_root_internal(&self) -> Vec<u8>;
    fn hash_tree_root(&self) -> Vec<u8> {
        let mut result = self.hash_tree_root_internal();
        if result.len() < HASHSIZE {
            zpad(&mut result, HASHSIZE);
        }
        result
    }
}

/// Returns a 32 byte hash of 'list' - a vector of byte vectors.
/// Note that this will consume 'list'.
pub fn merkle_hash(list: &mut Vec<Vec<u8>>) -> Vec<u8> {
    // flatten list
    let (mut chunk_size, mut chunkz) = list_to_blob(list);

    // get data_len as bytes. It will hashed will the merkle root
    let mut datalen = list.len().to_le_bytes().to_vec();
    zpad(&mut datalen, 32);

    // Tree-hash
    while chunkz.len() > HASHSIZE {
        let mut new_chunkz: Vec<u8> = Vec::new();

        for two_chunks in chunkz.chunks(chunk_size * 2) {
            if two_chunks.len() == chunk_size {
                // Odd number of chunks
                let mut c = two_chunks.to_vec();
                c.append(&mut vec![0; SSZ_CHUNK_SIZE]);
                new_chunkz.append(&mut hash(&c));
            } else {
                // Hash two chuncks together
                new_chunkz.append(&mut hash(two_chunks));
            }
        }

        chunk_size = HASHSIZE;
        chunkz = new_chunkz;
    }

    chunkz.append(&mut datalen);
    hash(&chunkz)
}

fn list_to_blob(list: &mut Vec<Vec<u8>>) -> (usize, Vec<u8>) {
    let chunk_size = if list.is_empty() || list[0].len() < SSZ_CHUNK_SIZE {
        SSZ_CHUNK_SIZE
    } else {
        list[0].len()
    };

    let (items_per_chunk, chunk_count) = if list.is_empty() {
        (1, 1)
    } else {
        let items_per_chunk = SSZ_CHUNK_SIZE / list[0].len();
        let chunk_count = list.len() / items_per_chunk;
        (items_per_chunk, chunk_count)
    };

    let mut chunkz = Vec::new();
    if list.is_empty() {
        // handle and empty list
        chunkz.append(&mut vec![0; SSZ_CHUNK_SIZE]);
    } else if list[0].len() <= SSZ_CHUNK_SIZE {
        // just create a blob here; we'll divide into
        // chunked slices when we merklize
        let mut chunk = Vec::with_capacity(chunk_size);
        let mut item_count_in_chunk = 0;
        chunkz.reserve(chunk_count * chunk_size);
        for item in list.iter_mut() {
            item_count_in_chunk += 1;
            chunk.append(item);

            // completed chunk?
            if item_count_in_chunk == items_per_chunk {
                zpad(&mut chunk, chunk_size);
                chunkz.append(&mut chunk);
                item_count_in_chunk = 0;
            }
        }

        // left-over uncompleted chunk?
        if item_count_in_chunk != 0 {
            zpad(&mut chunk, chunk_size);
            chunkz.append(&mut chunk);
        }
    } else {
        // chunks larger than SSZ_CHUNK_SIZE
        chunkz.reserve(chunk_count * chunk_size);
        for item in list.iter_mut() {
            chunkz.append(item);
        }
    }

    (chunk_size, chunkz)
}

/// right pads with zeros making 'bytes' 'size' in length
fn zpad(bytes: &mut Vec<u8>, size: usize) {
    if bytes.len() < size {
        bytes.resize(size, 0);
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_merkle_hash() {
        let data1 = vec![1; 100];
        let data2 = vec![2; 100];
        let data3 = vec![3; 100];
        let mut list = vec![data1, data2, data3];
        let result = merkle_hash(&mut list);

        //note: should test againt a known test hash value
        assert_eq!(HASHSIZE, result.len());
    }
}
<|endoftext|>


<commit_before>use na::*;
use std::num::*;
mod test;

#[test]
fn test_initialize_clustering() {
    const loc_i: usize = 0 as usize;
    const loc_j: usize = 0 as usize;
    const G1: GridPoint = GridPoint
    {i: loc_i, j: loc_j,
        density: 0.0, new_data_time: 0, last_data_time: 0,
        last_density: 0.0};
    let result = initialize_clustering(Mat2::new(G1, G1, G1, G1));
    assert_eq!(Ok(()), result);
}

#[test]
fn test_which_grid() {
    let val = (3.1, 1.1);
    let i_rn = (0.0, 10.0);
    let j_rn = (-2.0, 2.0);
    let i_bins = 10 as usize;
    let j_bins = 4 as usize;

    let result = GridHelpers::which_grid(val, i_rn, j_rn, i_bins, j_bins).unwrap();
    assert_eq!(3, result.0);
    assert_eq!(3, result.1);
}

mod GridHelpers {
    pub fn which_grid(val: (f64, f64), i_range: (f64, f64), j_range: (f64, f64), i_bins: usize, j_bins: usize) -> Result<(usize, usize), String> {
        let i_size = (i_range.1 - i_range.0) / i_bins as f64;
        let i_number_of_sizes = ((val.0 - i_range.0) / i_size) as usize;
        let j_size = (j_range.1 - j_range.0) / j_bins as f64;
        let j_number_of_sizes = ((val.1 - j_range.0) / j_size) as usize;

        assert!(i_number_of_sizes < i_bins);
        assert!(j_number_of_sizes < j_bins);

        Ok((i_number_of_sizes, j_number_of_sizes))
    }
}

pub trait GridSpace {
    fn update_grid_pt_density(&mut self, val_to_add: (f64, f64), current_time: u32, lambda: f64) -> Result<(), String>;

    fn compute_decay_factor_at_time(&self, t_n: u32, t_l: u32, lambda: f64) -> f64 {
        lambda.powf((t_n - t_l) as f64)
    }

}

pub struct GridPoint {
    i: usize,
    j: usize,
    density: f64,
    last_density: f64,
    new_data_time: u32,
    last_data_time: u32,
}

pub struct DStreamProps {
    c_m: f64,
    c_l: f64,
    lambda: f64,
    beta: f64,
    i_bins: usize,
    j_bins: usize,
    i_range: (f64, f64),
    j_range: (f64, f64),
}

impl GridSpace for GridPoint {

    //TODO
    fn update_grid_pt_density(&mut self, val_to_add: (f64, f64), current_time: u32, lambda: f64) -> Result<(), String> {
        let coeff = self.compute_decay_factor_at_time(self.new_data_time, self.last_data_time, lambda);
        let new_density = coeff * self.last_density + 1.0;

        self.last_density = self.density;
        self.density = new_density;

        self.last_data_time = self.new_data_time;
        self.new_data_time = current_time;

        Ok(())
    }
}

pub fn initialize_clustering(grid_list: Mat2<GridPoint>) -> Result<(), String> {
    //update density of all grids in grid_list
    //assign each dense grid to a distinct cluster
    //label all other grids as NO_CLASS; bad grids!
    /*
    do until no change in cluster labels
          foreach cluster c
            foreach outside grid g of c
                foreach neighboring grid h of g
                    if h belongs to cluster c'
                        if |c| > |c'| label all grids in c' as c
                        else label all grids in c as c'
                    else if (h is translational) label h as in c
    end do
    */
    Ok(())
}

pub fn adjust_clustering(grid_list: Mat2<GridPoint>) -> Result<(), String> {
    //update the density of all grids in grid_list
    /*
    foreach grid g whose attribute (dense/sparse/transitional) is changed since last call to adjust_clustering()
        if g is a sparse grid
            delete g from its cluster c, label g as NO_CLASS
            if (c becomes unconnected) split c into two clusters
        else if g is a dense grid
            among all neighboring grids of g, find out the grid h whoe cluster c_h has the largest size
            if h is a dense grid
                if (g is labelled as NO_CLASS) label g as in c_h
                else if (g is in cluster c and |c| > |c_h|)
                    label all grids in c_h as in c
                else if (g is in cluster c and |c| <= |c_h|)
                    label all grids in c as in c_h
            else if h is a transitional grid
                if ((g is NO_CLASS) and (h is an outside grid if g is added to c_h)) label g as in c_h
                else if (g is in cluster c and |c| >= |c_h|)
                    move h from cluster c_h to c
        else if (g is transitional grid)
            among neighboring clusters of g, find the largest one c'
            satisfying that g is an outside grid if added to it and
            label g as in c'
    */

    Ok(())
}<commit_msg>wip basic tests for value put<commit_after>use na::{Mat2, DMat};
//use na;
use std::num::*;
mod test;

#[test]
fn test_which_grid() {
    let loc = (-6., 6.);
    let i_rn = (-10.0, 10.0);
    let j_rn = (-10.0, 10.0);
    let i_bins = 10 as usize;
    let j_bins = 10 as usize;

    let result = grid_helpers::which_grid(loc, i_rn, j_rn, i_bins, j_bins).unwrap();
    assert_eq!((2, 8), result);

}

mod grid_helpers {
    pub fn which_grid(val: (f64, f64), i_range: (f64, f64), j_range: (f64, f64), i_bins: usize, j_bins: usize) -> Result<(usize, usize), String> {
        let i_size = (i_range.1 - i_range.0) / i_bins as f64;
        let i_number_of_sizes = ((val.0 - i_range.0) / i_size) as usize;
        let j_size = (j_range.1 - j_range.0) / j_bins as f64;
        let j_number_of_sizes = ((val.1 - j_range.0) / j_size) as usize;

        assert!(i_number_of_sizes < i_bins);
        assert!(j_number_of_sizes < j_bins);

        Ok((i_number_of_sizes, j_number_of_sizes))
    }
}

pub trait DensityGrid {

    fn compute_decay_factor_at_time(&self, t_n: u32, t_l: u32, lambda: f64) -> f64 {
        lambda.powf((t_n - t_l) as f64)
    }
}

pub trait DensityGridSpace {

    fn put(&mut self, loc2d: (f64, f64), val: f64) -> Result<(), String>;

}

#[derive(Debug)]
#[derive(Copy)]
#[derive(Clone)]
pub struct GridPoint {
    i: usize, //location
    j: usize,
    density: f64,
    last_density: f64,
    new_data_time: u32,
    last_data_time: u32,
}

pub struct DStreamProps {
    c_m: f64,
    c_l: f64,
    lambda: f64,
    beta: f64,
    i_bins: usize,
    j_bins: usize,
    i_range: (f64, f64),
    j_range: (f64, f64),
}

pub struct TheGrid {
    mat: DMat<GridPoint>,
    props: DStreamProps,
}

impl Default for DStreamProps {
    fn default() -> DStreamProps {
        DStreamProps {
            c_m: 3.0,
            c_l: 0.8,
            lambda: 0.998,
            beta: 0.3,
            i_bins: 10 as usize,
            j_bins: 10 as usize,
            i_range: (-10.0, 10.0),
            j_range: (-10.0, 10.0),
        }
    }
}

impl DensityGrid for GridPoint {

}

impl DensityGridSpace for TheGrid {

    fn put(&mut self, loc2d: (f64, f64), val: f64) -> Result<(), String> {

//        println!("{}", self.density);
//        let props: DStreamProps = DStreamProps { ..Default::default() };
//        let idxs = grid_helpers::which_grid(val, props.i_range, props.j_range, props.i_bins, props.j_bins);
//        let res_update = self.update_grid_pt_density(val, 0, props.lambda);
//        println!("{}", self.density);

        if ((loc2d.0 <= self.props.i_range.1) && (loc2d.0 >= self.props.i_range.0) && (loc2d.1 <= self.props.j_range.1) && (loc2d.1 >= self.props.j_range.0)) {
            println!("valid!");
            let idxs = grid_helpers::which_grid(loc2d, self.props.i_range, self.props.j_range, self.props.i_bins, self.props.j_bins).unwrap();
            let gp = &self.mat[idxs];

            Ok(())
        } else {
            println!("invalid");
            Err(String::from("Invalid range"))
        }
    }
}
#[test]
fn test_put() {

    let mut grid_pt_1: GridPoint = GridPoint {i: 0, j: 0,
        density: 0.0, new_data_time: 0, last_data_time: 0,
        last_density: 0.0};

    let mut grid_pt_2: GridPoint = GridPoint {i: 1, j: 0,
        density: 0.0, new_data_time: 0, last_data_time: 0,
        last_density: 0.0};

    let mut grid_pt_3: GridPoint = GridPoint {i: 0, j: 1,
        density: 0.0, new_data_time: 0, last_data_time: 0,
        last_density: 0.0};

    let mut grid_pt_4: GridPoint = GridPoint {i: 1, j: 1,
        density: 0.0, new_data_time: 0, last_data_time: 0,
        last_density: 0.0};

    let mut v = Vec::new();
    for i in 0..100 {
        v.push(grid_pt_1)
    }

    let mut mat_thing = DMat::from_col_vec(
        10,
        10,
        &v
    );

    for i in 0..10 {

        for j in 0..10 {

            let mut g1= GridPoint
            {i: i, j: j,
                density: 0.0, new_data_time: 0, last_data_time: 0,
                last_density: 0.0};

            mat_thing[(i,j)] = g1;
        }

    }

    let mut the_grid = TheGrid {mat: mat_thing, props: DStreamProps { ..Default::default() }};

    let res_put = the_grid.put((-6.0, 6.0), 100.0).unwrap();

    for i in 0..10 {

        for j in 0..10 {
            let gp: &GridPoint = &the_grid.mat[(i as usize, j as usize)];
            assert_eq!(0.0, gp.density)
        }
    }
}

#[test]
fn test_initialize_clustering() {
    const loc_i: usize = 0 as usize;
    const loc_j: usize = 0 as usize;
    const G1: GridPoint = GridPoint
    {i: loc_i, j: loc_j,
        density: 0.0, new_data_time: 0, last_data_time: 0,
        last_density: 0.0};
    let result = initialize_clustering(DMat::from_row_vec(2,2, &[G1, G1, G1, G1]));
    assert_eq!(Ok(()), result);
}

pub fn initialize_clustering(grid_list: DMat<GridPoint>) -> Result<(), String> {
    //update density of all grids in grid_list
    //assign each dense grid to a distinct cluster
    //label all other grids as NO_CLASS; bad grids!
    /*
    do until no change in cluster labels
          foreach cluster c
            foreach outside grid g of c
                foreach neighboring grid h of g
                    if h belongs to cluster c'
                        if |c| > |c'| label all grids in c' as c
                        else label all grids in c as c'
                    else if (h is translational) label h as in c
    end do
    */
    Ok(())
}

pub fn adjust_clustering(grid_list: DMat<GridPoint>) -> Result<(), String> {
    //update the density of all grids in grid_list
    /*
    foreach grid g whose attribute (dense/sparse/transitional) is changed since last call to adjust_clustering()
        if g is a sparse grid
            delete g from its cluster c, label g as NO_CLASS
            if (c becomes unconnected) split c into two clusters
        else if g is a dense grid
            among all neighboring grids of g, find out the grid h whoe cluster c_h has the largest size
            if h is a dense grid
                if (g is labelled as NO_CLASS) label g as in c_h
                else if (g is in cluster c and |c| > |c_h|)
                    label all grids in c_h as in c
                else if (g is in cluster c and |c| <= |c_h|)
                    label all grids in c as in c_h
            else if h is a transitional grid
                if ((g is NO_CLASS) and (h is an outside grid if g is added to c_h)) label g as in c_h
                else if (g is in cluster c and |c| >= |c_h|)
                    move h from cluster c_h to c
        else if (g is transitional grid)
            among neighboring clusters of g, find the largest one c'
            satisfying that g is an outside grid if added to it and
            label g as in c'
    */

    Ok(())
}<|endoftext|>