<commit_before>//! This module specifies the type based interner for constants.
//!
//! After a const evaluation has computed a value, before we destroy the const evaluator's session
//! memory, we need to extract all memory allocations to the global memory pool so they stay around.

use rustc::ty::layout::LayoutOf;
use rustc::ty::{Ty, TyCtxt, ParamEnv, self};
use rustc::mir::interpret::{
    InterpResult, ErrorHandled,
};
use rustc::hir;
use rustc::hir::def_id::DefId;
use super::validity::RefTracking;
use rustc_data_structures::fx::FxHashSet;

use syntax::ast::Mutability;
use syntax_pos::Span;

use super::{
    ValueVisitor, MemoryKind, Pointer, AllocId, MPlaceTy, InterpError, Scalar,
};
use crate::const_eval::{CompileTimeInterpreter, CompileTimeEvalContext};

struct InternVisitor<'rt, 'a: 'rt, 'mir: 'rt, 'tcx: 'a+'rt+'mir> {
    /// previously encountered safe references
    ref_tracking: &'rt mut RefTracking<(MPlaceTy<'tcx>, Mutability, InternMode)>,
    ecx: &'rt mut CompileTimeEvalContext<'a, 'mir, 'tcx>,
    param_env: ParamEnv<'tcx>,
    /// The root node of the value that we're looking at. This field is never mutated and only used
    /// for sanity assertions that will ICE when `const_qualif` screws up.
    mode: InternMode,
    /// This field stores the mutability of the value *currently* being checked.
    /// It is set to mutable when an `UnsafeCell` is encountered
    /// When recursing across a reference, we don't recurse but store the
    /// value to be checked in `ref_tracking` together with the mutability at which we are checking
    /// the value.
    /// When encountering an immutable reference, we treat everything as immutable that is behind
    /// it.
    mutability: Mutability,
    /// A list of all encountered relocations. After type-based interning, we traverse this list to
    /// also intern allocations that are only referenced by a raw pointer or inside a union.
    leftover_relocations: &'rt mut FxHashSet<AllocId>,
}

#[derive(Copy, Clone, Debug, PartialEq, Hash, Eq)]
enum InternMode {
    /// Mutable references must in fact be immutable due to their surrounding immutability in a
    /// `static`. In a `static mut` we start out as mutable and thus can also contain further `&mtu`
    /// that will actually be treated as mutable.
    Static,
    /// UnsafeCell is OK in the value of a constant, but not behind references in a constant
    ConstBase,
    /// `UnsafeCell` ICEs
    Const,
}

/// Signalling data structure to ensure we don't recurse
/// into the memory of other constants or statics
struct IsStaticOrFn;

impl<'rt, 'a, 'mir, 'tcx> InternVisitor<'rt, 'a, 'mir, 'tcx> {
    /// Intern an allocation without looking at its children
    fn intern_shallow(
        &mut self,
        ptr: Pointer,
        mutability: Mutability,
    ) -> InterpResult<'tcx, Option<IsStaticOrFn>> {
        trace!(
            "InternVisitor::intern {:?} with {:?}",
            ptr, mutability,
        );
        // remove allocation
        let tcx = self.ecx.tcx;
        let memory = self.ecx.memory_mut();
        let (kind, mut alloc) = match memory.alloc_map.remove(&ptr.alloc_id) {
            Some(entry) => entry,
            None => {
                // if the pointer is dangling (neither in local nor global memory), we leave it
                // to validation to error. The `delay_span_bug` ensures that we don't forget such
                // a check in validation.
                if tcx.alloc_map.lock().get(ptr.alloc_id).is_none() {
                    tcx.sess.delay_span_bug(self.ecx.tcx.span, "tried to intern dangling pointer");
                }
                // treat dangling pointers like other statics
                // just to stop trying to recurse into them
                return Ok(Some(IsStaticOrFn));
            },
        };
        // This match is just a canary for future changes to `MemoryKind`, which most likely need
        // changes in this function.
        match kind {
            MemoryKind::Stack | MemoryKind::Vtable => {},
        }
        // Ensure llvm knows to only put this into immutable memory if the value is immutable either
        // by being behind a reference or by being part of a static or const without interior
        // mutability
        alloc.mutability = mutability;
        // link the alloc id to the actual allocation
        let alloc = tcx.intern_const_alloc(alloc);
        self.leftover_relocations.extend(alloc.relocations.iter().map(|&(_, ((), reloc))| reloc));
        tcx.alloc_map.lock().set_alloc_id_memory(ptr.alloc_id, alloc);
        Ok(None)
    }
}

impl<'rt, 'a, 'mir, 'tcx>
    ValueVisitor<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>
for
    InternVisitor<'rt, 'a, 'mir, 'tcx>
{
    type V = MPlaceTy<'tcx>;

    #[inline(always)]
    fn ecx(&self) -> &CompileTimeEvalContext<'a, 'mir, 'tcx> {
        &self.ecx
    }

    fn visit_aggregate(
        &mut self,
        mplace: MPlaceTy<'tcx>,
        fields: impl Iterator<Item=InterpResult<'tcx, Self::V>>,
    ) -> InterpResult<'tcx> {
        if let Some(def) = mplace.layout.ty.ty_adt_def() {
            if Some(def.did) == self.ecx.tcx.lang_items().unsafe_cell_type() {
                // We are crossing over an `UnsafeCell`, we can mutate again
                let old = std::mem::replace(&mut self.mutability, Mutability::Mutable);
                assert_ne!(
                    self.mode, InternMode::Const,
                    "UnsafeCells are not allowed behind references in constants. This should have \
                    been prevented statically by const qualification. If this were allowed one \
                    would be able to change a constant at one use site and other use sites may \
                    arbitrarily decide to change, too.",
                );
                let walked = self.walk_aggregate(mplace, fields);
                self.mutability = old;
                return walked;
            }
        }
        self.walk_aggregate(mplace, fields)
    }

    fn visit_primitive(&mut self, mplace: MPlaceTy<'tcx>) -> InterpResult<'tcx> {
        // Handle Reference types, as these are the only relocations supported by const eval.
        // Raw pointers (and boxes) are handled by the `leftover_relocations` logic.
        let ty = mplace.layout.ty;
        if let ty::Ref(_, _, mutability) = ty.sty {
            let value = self.ecx.read_immediate(mplace.into())?;
            // Handle trait object vtables
            if let Ok(meta) = value.to_meta() {
                let layout = self.ecx.layout_of(ty.builtin_deref(true).unwrap().ty)?;
                if layout.is_unsized() {
                    if let ty::Dynamic(..) = self.ecx.tcx.struct_tail(layout.ty).sty {
                        if let Ok(vtable) = meta.unwrap().to_ptr() {
                            // explitly choose `Immutable` here, since vtables are immutable, even
                            // if the reference of the fat pointer is mutable
                            self.intern_shallow(vtable, Mutability::Immutable)?;
                        }
                    }
                }
            }
            let mplace = self.ecx.ref_to_mplace(value)?;
            // Check if we have encountered this pointer+layout combination before.
            // Only recurse for allocation-backed pointers.
            if let Scalar::Ptr(ptr) = mplace.ptr {
                // In the future we will probably allow `& &mut T`, and thus will want to merge
                // `mutability` with `self.mutability` to only choose `Mutable` if both are
                // `Mutable`.

                // We do not have any `frozen` logic here, because it's essentially equivalent to
                // the mutability except for the outermost item. Only `UnsafeCell` can "unfreeze",
                // and we check that in `visit_aggregate`.
                // This is not an inherent limitation, but one that we know to be true, because
                // const qualification enforces it. We can lift it in the future.
                match (self.mode, mutability) {
                    // immutable references are fine everywhere
                    (_, hir::Mutability::MutImmutable) => {},
                    // all is "good and well" in the unsoundness of `static mut`

                    // mutable references are ok in `static`. Either they are treated as immutable
                    // because they are behind an immutable one, or they are behind an `UnsafeCell`
                    // and thus ok.
                    (InternMode::Static, hir::Mutability::MutMutable) => {},
                    // we statically prevent `&mut T` via `const_qualif` and double check this here
                    (InternMode::ConstBase, hir::Mutability::MutMutable) |
                    (InternMode::Const, hir::Mutability::MutMutable) =>
                        bug!("const qualif failed to prevent mutable references"),
                }
                let mutability = match (self.mutability, mutability) {
                    // The only way a mutable reference actually works as a mutable reference is
                    // by being in a `static mut` directly or behind another mutable reference.
                    // If there's an immutable reference or we are inside a static, then our
                    // mutable reference is equivalent to an immutable one. As an example:
                    // `&&mut Foo` is semantically equivalent to `&&Foo`
                    (Mutability::Mutable, hir::Mutability::MutMutable) => Mutability::Mutable,
                    _ => Mutability::Immutable,
                };
                let intern_mutability = intern_mutability(
                    self.ecx.tcx.tcx,
                    self.param_env,
                    mplace.layout.ty,
                    self.ecx.tcx.span,
                    mutability,
                );
                // Recursing behind references changes the intern mode for constants in order to
                // cause assertions to trigger if we encounter any `UnsafeCell`s.
                let mode = match self.mode {
                    InternMode::ConstBase => InternMode::Const,
                    other => other,
                };
                match self.intern_shallow(ptr, intern_mutability)? {
                    // No need to recurse, these are interned already and statics may have
                    // cycles, so we don't want to recurse there
                    Some(IsStaticOrFn) => {},
                    // intern everything referenced by this value. The mutability is taken from the
                    // reference. It is checked above that mutable references only happen in
                    // `static mut`
                    None => self.ref_tracking.track((mplace, mutability, mode), || ()),
                }
            }
        }
        Ok(())
    }
}

/// Figure out the mutability of the allocation.
/// Mutable if it has interior mutability *anywhere* in the type.
fn intern_mutability<'a, 'tcx>(
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
    param_env: ParamEnv<'tcx>,
    ty: Ty<'tcx>,
    span: Span,
    mutability: Mutability,
) -> Mutability {
    let has_interior_mutability = !ty.is_freeze(tcx, param_env, span);
    if has_interior_mutability {
        Mutability::Mutable
    } else {
        mutability
    }
}

pub fn intern_const_alloc_recursive(
    ecx: &mut CompileTimeEvalContext<'a, 'mir, 'tcx>,
    def_id: DefId,
    ret: MPlaceTy<'tcx>,
    // FIXME(oli-obk): can we scrap the param env? I think we can, the final value of a const eval
    // must always be monomorphic, right?
    param_env: ty::ParamEnv<'tcx>,
) -> InterpResult<'tcx> {
    let tcx = ecx.tcx;
    let (mutability, base_intern_mode) = match tcx.static_mutability(def_id) {
        Some(hir::Mutability::MutImmutable) => (Mutability::Immutable, InternMode::Static),
        None => (Mutability::Immutable, InternMode::ConstBase),
        // `static mut` doesn't care about interior mutability, it's mutable anyway
        Some(hir::Mutability::MutMutable) => (Mutability::Mutable, InternMode::Static),
    };

    // type based interning
    let mut ref_tracking = RefTracking::new((ret, mutability, base_intern_mode));
    let leftover_relocations = &mut FxHashSet::default();

    let alloc_mutability = intern_mutability(
        tcx.tcx, param_env, ret.layout.ty, tcx.span, mutability,
    );

    // start with the outermost allocation
    InternVisitor {
        ref_tracking: &mut ref_tracking,
        ecx,
        mode: base_intern_mode,
        leftover_relocations,
        param_env,
        mutability,
    }.intern_shallow(ret.ptr.to_ptr()?, alloc_mutability)?;

    while let Some(((mplace, mutability, mode), _)) = ref_tracking.todo.pop() {
        let interned = InternVisitor {
            ref_tracking: &mut ref_tracking,
            ecx,
            mode,
            leftover_relocations,
            param_env,
            mutability,
        }.visit_value(mplace);
        if let Err(error) = interned {
            // This can happen when e.g. the tag of an enum is not a valid discriminant. We do have
            // to read enum discriminants in order to find references in enum variant fields.
            if let InterpError::ValidationFailure(_) = error.kind {
                let err = crate::const_eval::error_to_const_error(&ecx, error);
                match err.struct_error(ecx.tcx, "it is undefined behavior to use this value") {
                    Ok(mut diag) => {
                        diag.note("The rules on what exactly is undefined behavior aren't clear, \
                            so this check might be overzealous. Please open an issue on the rust \
                            compiler repository if you believe it should not be considered \
                            undefined behavior",
                        );
                        diag.emit();
                    }
                    Err(ErrorHandled::TooGeneric) |
                    Err(ErrorHandled::Reported) => {},
                }
            }
        }
    }

    // Intern the rest of the allocations as mutable. These might be inside unions, padding, raw
    // pointers, ... So we can't intern them according to their type rules

    let mut todo: Vec<_> = leftover_relocations.iter().cloned().collect();
    while let Some(alloc_id) = todo.pop() {
        if let Some((_, alloc)) = ecx.memory_mut().alloc_map.remove(&alloc_id) {
            // We can't call the `intern` method here, as its logic is tailored to safe references.
            // So we hand-roll the interning logic here again
            let alloc = tcx.intern_const_alloc(alloc);
            tcx.alloc_map.lock().set_alloc_id_memory(alloc_id, alloc);
            for &(_, ((), reloc)) in alloc.relocations.iter() {
                if leftover_relocations.insert(reloc) {
                    todo.push(reloc);
                }
            }
        } else if ecx.memory().dead_alloc_map.contains_key(&alloc_id) {
            // dangling pointer
            return err!(ValidationFailure(
                "encountered dangling pointer in final constant".into(),
            ))
        }
    }
    Ok(())
}
<commit_msg>The future is now<commit_after>//! This module specifies the type based interner for constants.
//!
//! After a const evaluation has computed a value, before we destroy the const evaluator's session
//! memory, we need to extract all memory allocations to the global memory pool so they stay around.

use rustc::ty::layout::LayoutOf;
use rustc::ty::{Ty, TyCtxt, ParamEnv, self};
use rustc::mir::interpret::{
    InterpResult, ErrorHandled,
};
use rustc::hir;
use rustc::hir::def_id::DefId;
use super::validity::RefTracking;
use rustc_data_structures::fx::FxHashSet;

use syntax::ast::Mutability;
use syntax_pos::Span;

use super::{
    ValueVisitor, MemoryKind, Pointer, AllocId, MPlaceTy, InterpError, Scalar,
};
use crate::const_eval::{CompileTimeInterpreter, CompileTimeEvalContext};

struct InternVisitor<'rt, 'a: 'rt, 'mir: 'rt, 'tcx: 'a+'rt+'mir> {
    /// previously encountered safe references
    ref_tracking: &'rt mut RefTracking<(MPlaceTy<'tcx>, Mutability, InternMode)>,
    ecx: &'rt mut CompileTimeEvalContext<'a, 'mir, 'tcx>,
    param_env: ParamEnv<'tcx>,
    /// The root node of the value that we're looking at. This field is never mutated and only used
    /// for sanity assertions that will ICE when `const_qualif` screws up.
    mode: InternMode,
    /// This field stores the mutability of the value *currently* being checked.
    /// It is set to mutable when an `UnsafeCell` is encountered
    /// When recursing across a reference, we don't recurse but store the
    /// value to be checked in `ref_tracking` together with the mutability at which we are checking
    /// the value.
    /// When encountering an immutable reference, we treat everything as immutable that is behind
    /// it.
    mutability: Mutability,
    /// A list of all encountered relocations. After type-based interning, we traverse this list to
    /// also intern allocations that are only referenced by a raw pointer or inside a union.
    leftover_relocations: &'rt mut FxHashSet<AllocId>,
}

#[derive(Copy, Clone, Debug, PartialEq, Hash, Eq)]
enum InternMode {
    /// Mutable references must in fact be immutable due to their surrounding immutability in a
    /// `static`. In a `static mut` we start out as mutable and thus can also contain further `&mtu`
    /// that will actually be treated as mutable.
    Static,
    /// UnsafeCell is OK in the value of a constant, but not behind references in a constant
    ConstBase,
    /// `UnsafeCell` ICEs
    Const,
}

/// Signalling data structure to ensure we don't recurse
/// into the memory of other constants or statics
struct IsStaticOrFn;

impl<'rt, 'a, 'mir, 'tcx> InternVisitor<'rt, 'a, 'mir, 'tcx> {
    /// Intern an allocation without looking at its children
    fn intern_shallow(
        &mut self,
        ptr: Pointer,
        mutability: Mutability,
    ) -> InterpResult<'tcx, Option<IsStaticOrFn>> {
        trace!(
            "InternVisitor::intern {:?} with {:?}",
            ptr, mutability,
        );
        // remove allocation
        let tcx = self.ecx.tcx;
        let memory = self.ecx.memory_mut();
        let (kind, mut alloc) = match memory.alloc_map.remove(&ptr.alloc_id) {
            Some(entry) => entry,
            None => {
                // if the pointer is dangling (neither in local nor global memory), we leave it
                // to validation to error. The `delay_span_bug` ensures that we don't forget such
                // a check in validation.
                if tcx.alloc_map.lock().get(ptr.alloc_id).is_none() {
                    tcx.sess.delay_span_bug(self.ecx.tcx.span, "tried to intern dangling pointer");
                }
                // treat dangling pointers like other statics
                // just to stop trying to recurse into them
                return Ok(Some(IsStaticOrFn));
            },
        };
        // This match is just a canary for future changes to `MemoryKind`, which most likely need
        // changes in this function.
        match kind {
            MemoryKind::Stack | MemoryKind::Vtable => {},
        }
        // Ensure llvm knows to only put this into immutable memory if the value is immutable either
        // by being behind a reference or by being part of a static or const without interior
        // mutability
        alloc.mutability = mutability;
        // link the alloc id to the actual allocation
        let alloc = tcx.intern_const_alloc(alloc);
        self.leftover_relocations.extend(alloc.relocations.iter().map(|&(_, ((), reloc))| reloc));
        tcx.alloc_map.lock().set_alloc_id_memory(ptr.alloc_id, alloc);
        Ok(None)
    }
}

impl<'rt, 'a, 'mir, 'tcx>
    ValueVisitor<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>
for
    InternVisitor<'rt, 'a, 'mir, 'tcx>
{
    type V = MPlaceTy<'tcx>;

    #[inline(always)]
    fn ecx(&self) -> &CompileTimeEvalContext<'a, 'mir, 'tcx> {
        &self.ecx
    }

    fn visit_aggregate(
        &mut self,
        mplace: MPlaceTy<'tcx>,
        fields: impl Iterator<Item=InterpResult<'tcx, Self::V>>,
    ) -> InterpResult<'tcx> {
        if let Some(def) = mplace.layout.ty.ty_adt_def() {
            if Some(def.did) == self.ecx.tcx.lang_items().unsafe_cell_type() {
                // We are crossing over an `UnsafeCell`, we can mutate again
                let old = std::mem::replace(&mut self.mutability, Mutability::Mutable);
                assert_ne!(
                    self.mode, InternMode::Const,
                    "UnsafeCells are not allowed behind references in constants. This should have \
                    been prevented statically by const qualification. If this were allowed one \
                    would be able to change a constant at one use site and other use sites may \
                    arbitrarily decide to change, too.",
                );
                let walked = self.walk_aggregate(mplace, fields);
                self.mutability = old;
                return walked;
            }
        }
        self.walk_aggregate(mplace, fields)
    }

    fn visit_primitive(&mut self, mplace: MPlaceTy<'tcx>) -> InterpResult<'tcx> {
        // Handle Reference types, as these are the only relocations supported by const eval.
        // Raw pointers (and boxes) are handled by the `leftover_relocations` logic.
        let ty = mplace.layout.ty;
        if let ty::Ref(_, _, mutability) = ty.sty {
            let value = self.ecx.read_immediate(mplace.into())?;
            // Handle trait object vtables
            if let Ok(meta) = value.to_meta() {
                let layout = self.ecx.layout_of(ty.builtin_deref(true).unwrap().ty)?;
                if layout.is_unsized() {
                    if let ty::Dynamic(..) = self.ecx.tcx.struct_tail(layout.ty).sty {
                        if let Ok(vtable) = meta.unwrap().to_ptr() {
                            // explitly choose `Immutable` here, since vtables are immutable, even
                            // if the reference of the fat pointer is mutable
                            self.intern_shallow(vtable, Mutability::Immutable)?;
                        }
                    }
                }
            }
            let mplace = self.ecx.ref_to_mplace(value)?;
            // Check if we have encountered this pointer+layout combination before.
            // Only recurse for allocation-backed pointers.
            if let Scalar::Ptr(ptr) = mplace.ptr {
                // We do not have any `frozen` logic here, because it's essentially equivalent to
                // the mutability except for the outermost item. Only `UnsafeCell` can "unfreeze",
                // and we check that in `visit_aggregate`.
                // This is not an inherent limitation, but one that we know to be true, because
                // const qualification enforces it. We can lift it in the future.
                match (self.mode, mutability) {
                    // immutable references are fine everywhere
                    (_, hir::Mutability::MutImmutable) => {},
                    // all is "good and well" in the unsoundness of `static mut`

                    // mutable references are ok in `static`. Either they are treated as immutable
                    // because they are behind an immutable one, or they are behind an `UnsafeCell`
                    // and thus ok.
                    (InternMode::Static, hir::Mutability::MutMutable) => {},
                    // we statically prevent `&mut T` via `const_qualif` and double check this here
                    (InternMode::ConstBase, hir::Mutability::MutMutable) |
                    (InternMode::Const, hir::Mutability::MutMutable) =>
                        bug!("const qualif failed to prevent mutable references"),
                }
                let mutability = match (self.mutability, mutability) {
                    // The only way a mutable reference actually works as a mutable reference is
                    // by being in a `static mut` directly or behind another mutable reference.
                    // If there's an immutable reference or we are inside a static, then our
                    // mutable reference is equivalent to an immutable one. As an example:
                    // `&&mut Foo` is semantically equivalent to `&&Foo`
                    (Mutability::Mutable, hir::Mutability::MutMutable) => Mutability::Mutable,
                    _ => Mutability::Immutable,
                };
                let intern_mutability = intern_mutability(
                    self.ecx.tcx.tcx,
                    self.param_env,
                    mplace.layout.ty,
                    self.ecx.tcx.span,
                    mutability,
                );
                // Recursing behind references changes the intern mode for constants in order to
                // cause assertions to trigger if we encounter any `UnsafeCell`s.
                let mode = match self.mode {
                    InternMode::ConstBase => InternMode::Const,
                    other => other,
                };
                match self.intern_shallow(ptr, intern_mutability)? {
                    // No need to recurse, these are interned already and statics may have
                    // cycles, so we don't want to recurse there
                    Some(IsStaticOrFn) => {},
                    // intern everything referenced by this value. The mutability is taken from the
                    // reference. It is checked above that mutable references only happen in
                    // `static mut`
                    None => self.ref_tracking.track((mplace, mutability, mode), || ()),
                }
            }
        }
        Ok(())
    }
}

/// Figure out the mutability of the allocation.
/// Mutable if it has interior mutability *anywhere* in the type.
fn intern_mutability<'a, 'tcx>(
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
    param_env: ParamEnv<'tcx>,
    ty: Ty<'tcx>,
    span: Span,
    mutability: Mutability,
) -> Mutability {
    let has_interior_mutability = !ty.is_freeze(tcx, param_env, span);
    if has_interior_mutability {
        Mutability::Mutable
    } else {
        mutability
    }
}

pub fn intern_const_alloc_recursive(
    ecx: &mut CompileTimeEvalContext<'a, 'mir, 'tcx>,
    def_id: DefId,
    ret: MPlaceTy<'tcx>,
    // FIXME(oli-obk): can we scrap the param env? I think we can, the final value of a const eval
    // must always be monomorphic, right?
    param_env: ty::ParamEnv<'tcx>,
) -> InterpResult<'tcx> {
    let tcx = ecx.tcx;
    let (mutability, base_intern_mode) = match tcx.static_mutability(def_id) {
        Some(hir::Mutability::MutImmutable) => (Mutability::Immutable, InternMode::Static),
        None => (Mutability::Immutable, InternMode::ConstBase),
        // `static mut` doesn't care about interior mutability, it's mutable anyway
        Some(hir::Mutability::MutMutable) => (Mutability::Mutable, InternMode::Static),
    };

    // type based interning
    let mut ref_tracking = RefTracking::new((ret, mutability, base_intern_mode));
    let leftover_relocations = &mut FxHashSet::default();

    let alloc_mutability = intern_mutability(
        tcx.tcx, param_env, ret.layout.ty, tcx.span, mutability,
    );

    // start with the outermost allocation
    InternVisitor {
        ref_tracking: &mut ref_tracking,
        ecx,
        mode: base_intern_mode,
        leftover_relocations,
        param_env,
        mutability,
    }.intern_shallow(ret.ptr.to_ptr()?, alloc_mutability)?;

    while let Some(((mplace, mutability, mode), _)) = ref_tracking.todo.pop() {
        let interned = InternVisitor {
            ref_tracking: &mut ref_tracking,
            ecx,
            mode,
            leftover_relocations,
            param_env,
            mutability,
        }.visit_value(mplace);
        if let Err(error) = interned {
            // This can happen when e.g. the tag of an enum is not a valid discriminant. We do have
            // to read enum discriminants in order to find references in enum variant fields.
            if let InterpError::ValidationFailure(_) = error.kind {
                let err = crate::const_eval::error_to_const_error(&ecx, error);
                match err.struct_error(ecx.tcx, "it is undefined behavior to use this value") {
                    Ok(mut diag) => {
                        diag.note("The rules on what exactly is undefined behavior aren't clear, \
                            so this check might be overzealous. Please open an issue on the rust \
                            compiler repository if you believe it should not be considered \
                            undefined behavior",
                        );
                        diag.emit();
                    }
                    Err(ErrorHandled::TooGeneric) |
                    Err(ErrorHandled::Reported) => {},
                }
            }
        }
    }

    // Intern the rest of the allocations as mutable. These might be inside unions, padding, raw
    // pointers, ... So we can't intern them according to their type rules

    let mut todo: Vec<_> = leftover_relocations.iter().cloned().collect();
    while let Some(alloc_id) = todo.pop() {
        if let Some((_, alloc)) = ecx.memory_mut().alloc_map.remove(&alloc_id) {
            // We can't call the `intern` method here, as its logic is tailored to safe references.
            // So we hand-roll the interning logic here again
            let alloc = tcx.intern_const_alloc(alloc);
            tcx.alloc_map.lock().set_alloc_id_memory(alloc_id, alloc);
            for &(_, ((), reloc)) in alloc.relocations.iter() {
                if leftover_relocations.insert(reloc) {
                    todo.push(reloc);
                }
            }
        } else if ecx.memory().dead_alloc_map.contains_key(&alloc_id) {
            // dangling pointer
            return err!(ValidationFailure(
                "encountered dangling pointer in final constant".into(),
            ))
        }
    }
    Ok(())
}
<|endoftext|>


<commit_before><commit_msg>Tweak the logic of block hulls interacting with walls<commit_after><|endoftext|>


<commit_before>use arch::context::Context;
use arch::memory;

use collections::string::ToString;

use common::event::MouseEvent;
use common::time::{self, Duration};

use core::{cmp, mem, ptr, slice};

use graphics::display::VBEMODEINFO;

use super::{Packet, Pipe, Setup};
use super::desc::*;

pub trait Hci {
    fn msg(&mut self, address: u8, endpoint: u8, pipe: Pipe, msgs: &[Packet]) -> usize;

    fn descriptor(&mut self,
                         address: u8,
                         descriptor_type: u8,
                         descriptor_index: u8,
                         descriptor_ptr: usize,
                         descriptor_len: usize) {
        self.msg(address, 0, Pipe::Control, &[
            Packet::Setup(&Setup::get_descriptor(descriptor_type, descriptor_index, 0, descriptor_len as u16)),
            Packet::In(&mut unsafe { slice::from_raw_parts_mut(descriptor_ptr as *mut u8, descriptor_len as usize) }),
            Packet::Out(&[])
        ]);
    }

    unsafe fn device(&mut self, address: u8) where Self: Sized + 'static {
        self.msg(0, 0, Pipe::Control, &[
            Packet::Setup(&Setup::set_address(address)),
            Packet::In(&mut [])
        ]);

        let mut desc_dev = box DeviceDescriptor::default();
        self.descriptor(address,
                        DESC_DEV,
                        0,
                        (&mut *desc_dev as *mut DeviceDescriptor) as usize,
                        mem::size_of_val(&*desc_dev));
        //debugln!("{:#?}", *desc_dev);

        if desc_dev.manufacturer_string > 0 {
            let mut desc_str = box StringDescriptor::default();
            self.descriptor(address,
                            DESC_STR,
                            desc_dev.manufacturer_string,
                            (&mut *desc_str as *mut StringDescriptor) as usize,
                            mem::size_of_val(&*desc_str));
            debugln!("Manufacturer: {}", desc_str.str());
        }

        if desc_dev.product_string > 0 {
            let mut desc_str = box StringDescriptor::default();
            self.descriptor(address,
                            DESC_STR,
                            desc_dev.product_string,
                            (&mut *desc_str as *mut StringDescriptor) as usize,
                            mem::size_of_val(&*desc_str));
            debugln!("Product: {}", desc_str.str());
        }

        if desc_dev.serial_string > 0 {
            let mut desc_str = box StringDescriptor::default();
            self.descriptor(address,
                            DESC_STR,
                            desc_dev.serial_string,
                            (&mut *desc_str as *mut StringDescriptor) as usize,
                            mem::size_of_val(&*desc_str));
            debugln!("Serial: {}", desc_str.str());
        }

        for configuration in 0..(*desc_dev).configurations {
            let desc_cfg_len = 1023;
            let desc_cfg_buf = memory::alloc(desc_cfg_len) as *mut u8;
            for i in 0..desc_cfg_len as isize {
                ptr::write(desc_cfg_buf.offset(i), 0);
            }
            self.descriptor(address,
                            DESC_CFG,
                            configuration,
                            desc_cfg_buf as usize,
                            desc_cfg_len);

            let desc_cfg = ptr::read(desc_cfg_buf as *const ConfigDescriptor);
            //debugln!("{:#?}", desc_cfg);

            if desc_cfg.string > 0 {
                let mut desc_str = box StringDescriptor::default();
                self.descriptor(address,
                                DESC_STR,
                                desc_cfg.string,
                                (&mut *desc_str as *mut StringDescriptor) as usize,
                                mem::size_of_val(&*desc_str));
                //debugln!("Configuration: {}", desc_str.str());
            }

            let mut hid = false;

            let mut i = desc_cfg.length as isize;
            while i < desc_cfg.total_length as isize {
                let length = ptr::read(desc_cfg_buf.offset(i));
                let descriptor_type = ptr::read(desc_cfg_buf.offset(i + 1));
                match descriptor_type {
                    DESC_INT => {
                        let desc_int = ptr::read(desc_cfg_buf.offset(i) as *const InterfaceDescriptor);
                        //debugln!("{:#?}", desc_int);

                        if desc_int.string > 0 {
                            let mut desc_str = box StringDescriptor::default();
                            self.descriptor(address,
                                            DESC_STR,
                                            desc_int.string,
                                            (&mut *desc_str as *mut StringDescriptor) as usize,
                                            mem::size_of_val(&*desc_str));
                            //debugln!("Interface: {}", desc_str.str());
                        }
                    }
                    DESC_END => {
                        let desc_end = ptr::read(desc_cfg_buf.offset(i) as *const EndpointDescriptor);
                        //debugln!("{:#?}", desc_end);

                        let endpoint = desc_end.address & 0xF;
                        let in_len = desc_end.max_packet_size as usize;

                        if hid {
                            let this = self as *mut Hci;
                            Context::spawn("kuhci_hid".to_string(), box move || {
                                debugln!("Starting HID driver");

                                let in_ptr = memory::alloc(in_len) as *mut u8;

                                loop {
                                    for i in 0..in_len as isize {
                                        ptr::write(in_ptr.offset(i), 0);
                                    }

                                    if (*this).msg(address, endpoint, Pipe::Isochronous, &[
                                        Packet::In(&mut slice::from_raw_parts_mut(in_ptr, in_len))
                                    ]) > 0 {
                                        let buttons = ptr::read(in_ptr.offset(0) as *const u8) as usize;
                                        let x = ptr::read(in_ptr.offset(1) as *const u16) as usize;
                                        let y = ptr::read(in_ptr.offset(3) as *const u16) as usize;

                                        let mode_info = &*VBEMODEINFO;
                                        let mouse_x = (x * mode_info.xresolution as usize) / 32768;
                                        let mouse_y = (y * mode_info.yresolution as usize) / 32768;

                                        let mouse_event = MouseEvent {
                                            x: cmp::max(0, cmp::min(mode_info.xresolution as i32 - 1, mouse_x as i32)),
                                            y: cmp::max(0, cmp::min(mode_info.yresolution as i32 - 1, mouse_y as i32)),
                                            left_button: buttons & 1 == 1,
                                            middle_button: buttons & 4 == 4,
                                            right_button: buttons & 2 == 2,
                                        };
                                        ::env().events.send(mouse_event.to_event());
                                    }

                                    Duration::new(0, 10 * time::NANOS_PER_MILLI).sleep();
                                }
                            });
                        }
                    }
                    DESC_HID => {
                        //let desc_hid = &*(desc_cfg_buf.offset(i) as *const HIDDescriptor);
                        //debugln!("{:#?}", desc_hid);
                        hid = true;
                    }
                    _ => {
                        debugln!("Unknown Descriptor Length {} Type {:X}", length as usize, descriptor_type);
                    }
                }
                i += length as isize;
            }

            memory::unalloc(desc_cfg_buf as usize);
        }
    }
}
<commit_msg>Jump out of HID driver<commit_after>use arch::context::Context;
use arch::memory;

use collections::string::ToString;

use common::event::MouseEvent;
use common::time::{self, Duration};

use core::{cmp, mem, ptr, slice};

use graphics::display::VBEMODEINFO;

use super::{Packet, Pipe, Setup};
use super::desc::*;

pub trait Hci {
    fn msg(&mut self, address: u8, endpoint: u8, pipe: Pipe, msgs: &[Packet]) -> usize;

    fn descriptor(&mut self,
                         address: u8,
                         descriptor_type: u8,
                         descriptor_index: u8,
                         descriptor_ptr: usize,
                         descriptor_len: usize) {
        self.msg(address, 0, Pipe::Control, &[
            Packet::Setup(&Setup::get_descriptor(descriptor_type, descriptor_index, 0, descriptor_len as u16)),
            Packet::In(&mut unsafe { slice::from_raw_parts_mut(descriptor_ptr as *mut u8, descriptor_len as usize) }),
            Packet::Out(&[])
        ]);
    }

    unsafe fn device(&mut self, address: u8) where Self: Sized + 'static {
        self.msg(0, 0, Pipe::Control, &[
            Packet::Setup(&Setup::set_address(address)),
            Packet::In(&mut [])
        ]);

        let mut desc_dev = box DeviceDescriptor::default();
        self.descriptor(address,
                        DESC_DEV,
                        0,
                        (&mut *desc_dev as *mut DeviceDescriptor) as usize,
                        mem::size_of_val(&*desc_dev));
        //debugln!("{:#?}", *desc_dev);

        if desc_dev.manufacturer_string > 0 {
            let mut desc_str = box StringDescriptor::default();
            self.descriptor(address,
                            DESC_STR,
                            desc_dev.manufacturer_string,
                            (&mut *desc_str as *mut StringDescriptor) as usize,
                            mem::size_of_val(&*desc_str));
            debugln!("Manufacturer: {}", desc_str.str());
        }

        if desc_dev.product_string > 0 {
            let mut desc_str = box StringDescriptor::default();
            self.descriptor(address,
                            DESC_STR,
                            desc_dev.product_string,
                            (&mut *desc_str as *mut StringDescriptor) as usize,
                            mem::size_of_val(&*desc_str));
            debugln!("Product: {}", desc_str.str());
        }

        if desc_dev.serial_string > 0 {
            let mut desc_str = box StringDescriptor::default();
            self.descriptor(address,
                            DESC_STR,
                            desc_dev.serial_string,
                            (&mut *desc_str as *mut StringDescriptor) as usize,
                            mem::size_of_val(&*desc_str));
            debugln!("Serial: {}", desc_str.str());
        }

        for configuration in 0..(*desc_dev).configurations {
            let desc_cfg_len = 1023;
            let desc_cfg_buf = memory::alloc(desc_cfg_len) as *mut u8;
            for i in 0..desc_cfg_len as isize {
                ptr::write(desc_cfg_buf.offset(i), 0);
            }
            self.descriptor(address,
                            DESC_CFG,
                            configuration,
                            desc_cfg_buf as usize,
                            desc_cfg_len);

            let desc_cfg = ptr::read(desc_cfg_buf as *const ConfigDescriptor);
            //debugln!("{:#?}", desc_cfg);

            if desc_cfg.string > 0 {
                let mut desc_str = box StringDescriptor::default();
                self.descriptor(address,
                                DESC_STR,
                                desc_cfg.string,
                                (&mut *desc_str as *mut StringDescriptor) as usize,
                                mem::size_of_val(&*desc_str));
                //debugln!("Configuration: {}", desc_str.str());
            }

            let mut hid = false;

            let mut i = desc_cfg.length as isize;
            while i < desc_cfg.total_length as isize {
                let length = ptr::read(desc_cfg_buf.offset(i));
                let descriptor_type = ptr::read(desc_cfg_buf.offset(i + 1));
                match descriptor_type {
                    DESC_INT => {
                        let desc_int = ptr::read(desc_cfg_buf.offset(i) as *const InterfaceDescriptor);
                        //debugln!("{:#?}", desc_int);

                        if desc_int.string > 0 {
                            let mut desc_str = box StringDescriptor::default();
                            self.descriptor(address,
                                            DESC_STR,
                                            desc_int.string,
                                            (&mut *desc_str as *mut StringDescriptor) as usize,
                                            mem::size_of_val(&*desc_str));
                            //debugln!("Interface: {}", desc_str.str());
                        }
                    }
                    DESC_END => {
                        let desc_end = ptr::read(desc_cfg_buf.offset(i) as *const EndpointDescriptor);
                        //debugln!("{:#?}", desc_end);

                        let endpoint = desc_end.address & 0xF;
                        let in_len = desc_end.max_packet_size as usize;

                        if hid {
                            let this = self as *mut Hci;
                            Context::spawn("kuhci_hid".to_string(), box move || {
                                debugln!("Starting HID driver");

                                let in_ptr = memory::alloc(in_len) as *mut u8;

                                loop {
                                    for i in 0..in_len as isize {
                                        ptr::write(in_ptr.offset(i), 0);
                                    }

                                    if (*this).msg(address, endpoint, Pipe::Isochronous, &[
                                        Packet::In(&mut slice::from_raw_parts_mut(in_ptr, in_len))
                                    ]) > 0 {
                                        let buttons = ptr::read(in_ptr.offset(0) as *const u8) as usize;
                                        let x = ptr::read(in_ptr.offset(1) as *const u16) as usize;
                                        let y = ptr::read(in_ptr.offset(3) as *const u16) as usize;

                                        let mode_info = &*VBEMODEINFO;
                                        let mouse_x = (x * mode_info.xresolution as usize) / 32768;
                                        let mouse_y = (y * mode_info.yresolution as usize) / 32768;

                                        let mouse_event = MouseEvent {
                                            x: cmp::max(0, cmp::min(mode_info.xresolution as i32 - 1, mouse_x as i32)),
                                            y: cmp::max(0, cmp::min(mode_info.yresolution as i32 - 1, mouse_y as i32)),
                                            left_button: buttons & 1 == 1,
                                            middle_button: buttons & 4 == 4,
                                            right_button: buttons & 2 == 2,
                                        };
                                        ::env().events.send(mouse_event.to_event());
                                    }

                                    Duration::new(0, 10 * time::NANOS_PER_MILLI).sleep();

                                    debugln!("HID Support disabled");
                                    break;
                                }
                            });
                        }
                    }
                    DESC_HID => {
                        //let desc_hid = &*(desc_cfg_buf.offset(i) as *const HIDDescriptor);
                        //debugln!("{:#?}", desc_hid);
                        hid = true;
                    }
                    _ => {
                        debugln!("Unknown Descriptor Length {} Type {:X}", length as usize, descriptor_type);
                    }
                }
                i += length as isize;
            }

            memory::unalloc(desc_cfg_buf as usize);
        }
    }
}
<|endoftext|>


<commit_before>/**
 * Program to an 'interface', not an 'implementation'.
 *
 * http://joshldavis.com/2013/07/01/program-to-an-interface-fool/
 *
 * @author: Josh Davis
 * @date: 2013-07-01
 */

/**
 * Imagine you are Guy Montag from the book, Fahrenheit 451 (F451 from here on out).
 * As everyone knows, books in F451 are forbidden.
 * It's the job of firefighters to set them on fire whenever they come across them.
 * Therefore thinking in terms of OOP, a book has a method called `burn()`.
 */
struct Book {
	title: ~str,
	author: ~str,
}

struct Log {
	wood_type: ~str,
}

trait Burns {
	fn burn(&self);
}

impl Burns for Log {
	fn burn(&self) {
		println!("The {} log is burning!", self.wood_type);
	}
}

impl Burns for Book {
	fn burn(&self) {
		println!("The book \"{}\" by {} is burning!", self.title, self.author);
	}
}

/**
 * This is where the power of programming to an interface comes in.
 * Rather than expecting a Book object or a Log object, we just take in any object with any type (we call the type T) that implements the Burns interface.
 */
fn start_fire<T: Burns>(item: T) {
	item.burn();
}

fn main() {
	let lg = Log {
	wood_type: ~"Oak",
	};
	let book = Book {
		title: ~"The Brothers Karamazov",
		author: ~"Fyodor Dostoevsky",
	};

	// Burn the oak log!
	start_fire(lg);

	// Burn the book!
	start_fire(book);
}

<commit_msg>Add interface example for enum tuple<commit_after>/**
 * Program to an 'interface', not an 'implementation'.
 *
 * http://joshldavis.com/2013/07/01/program-to-an-interface-fool/
 *
 * @author: Josh Davis
 * @date: 2013-07-01
 */

/**
 * Imagine you are Guy Montag from the book, Fahrenheit 451 (F451 from here on out).
 * As everyone knows, books in F451 are forbidden.
 * It's the job of firefighters to set them on fire whenever they come across them.
 * Therefore thinking in terms of OOP, a book has a method called `burn()`.
 */
struct Book {
	title: ~str,
	author: ~str,
}

struct Log {
	wood_type: ~str,
}

trait Burns {
	fn burn(&self);
}

impl Burns for Log {
	fn burn(&self) {
		println!("The {} log is burning!", self.wood_type);
	}
}

impl Burns for Book {
	fn burn(&self) {
		println!("The book \"{}\" by {} is burning!", self.title, self.author);
	}
}

struct Incunable(Book);

impl Burns for Incunable {
	fn burn(&self) {
		let book: &Book = match *self {
			Incunable(ref book) => book
		};
		println!("The incunable \"{}\" by {} is burning!", book.title, book.author);
	}
}

/**
 * This is where the power of programming to an interface comes in.
 * Rather than expecting a Book object or a Log object, we just take in any object with any type (we call the type T) that implements the Burns interface.
 */
fn start_fire<T: Burns>(item: T) {
	item.burn();
}

fn main() {
	let lg = Log {
		wood_type: ~"Oak",
	};
	let book = Book {
		title: ~"The Brothers Karamazov",
		author: ~"Fyodor Dostoevsky",
	};
	let nuremberg_chronicle = Book {
		title: ~"Liber Chronicarum",
		author: ~"Hartmann Schedel",
	};
	let incunable = Incunable(nuremberg_chronicle);
	// Burn the oak log!
	start_fire(lg);

	// Burn the book!
	start_fire(book);
	start_fire(incunable);
}

<|endoftext|>


<commit_before>use std::thread;
use std::sync::mpsc;
use websocket::{Server, Message, Sender, Receiver};
use websocket::server::sender;
use websocket::stream::WebSocketStream;
use std::io::prelude::*;
use std::fs::OpenOptions;
use std::num::ToPrimitive;
use rustc_serialize::json::{Json, ToJson};
use std::mem::replace;

use value::{Value, Tuple};
use index;
use flow::{Changes, Flow};
use compiler::compile;

trait FromJson {
    fn from_json(json: &Json, next_eid: &mut u64) -> Self;
}

impl ToJson for Value {
    fn to_json(&self) -> Json {
        match *self {
            Value::Bool(bool) => Json::Boolean(bool),
            Value::String(ref string) => Json::String(string.clone()),
            Value::Float(float) => Json::F64(float),
            Value::Tuple(ref tuple) => tuple.to_json(),
            Value::Relation(ref relation) => Json::Object(vec![
                ("relation".to_string(), relation.iter().map(ToJson::to_json).collect::<Vec<_>>().to_json())
                ].into_iter().collect()),
        }
    }
}

impl FromJson for Value {
    fn from_json(json: &Json, next_eid: &mut u64) -> Self {
        match *json {
            Json::Boolean(bool) => Value::Bool(bool),
            Json::String(ref string) => Value::String(string.clone()),
            Json::F64(float) => Value::Float(float),
            Json::I64(int) => Value::Float(int.to_f64().unwrap()),
            Json::U64(uint) => Value::Float(uint.to_f64().unwrap()),
            Json::Array(ref array) => Value::Tuple(array.iter().map(|j| Value::from_json(j, next_eid)).collect()),
            Json::Object(ref object) => {
                assert!(object.len() == 1);
                match object.get("eid") {
                    Some(value) => {
                        assert_eq!(value.as_string().unwrap(), "auto");
                        let eid = next_eid.to_f64().unwrap();
                        *next_eid += 1;
                        Value::Float(eid)
                    }
                    None => {
                        let relation: Vec<Tuple> = FromJson::from_json(&object["relation"], next_eid);
                        Value::Relation(relation.into_iter().collect())
                    }
                }
            },
            _ => panic!("Cannot decode {:?} as Value", json),
        }
    }
}

impl<T: FromJson> FromJson for Vec<T> {
    fn from_json(json: &Json, next_eid: &mut u64) -> Self {
        json.as_array().unwrap().iter().map(|t| FromJson::from_json(t, next_eid)).collect()
    }
}

pub struct Event {
    changes: Changes,
}

// TODO need to change encoding to list of changes instead of object

impl ToJson for Event {
    fn to_json(&self) -> Json {
        Json::Object(vec![
            ("changes".to_string(), Json::Array(
                self.changes.iter().map(|&(ref view_id, ref view_changes)| {
                    Json::Array(vec![
                        view_id.to_json(),
                        view_changes.inserted.to_json(),
                        view_changes.removed.to_json(),
                        ])
                }).collect())
            )].into_iter().collect())
    }
}

impl FromJson for Event {
    fn from_json(json: &Json, next_eid: &mut u64) -> Self {
        Event{
            changes: json.as_object().unwrap()["changes"]
            .as_array().unwrap().iter().map(|change| {
                let change = change.as_array().unwrap();
                assert_eq!(change.len(), 3);
                let view_id = change[0].as_string().unwrap().to_string();
                let inserted = FromJson::from_json(&change[1], next_eid);
                let removed = FromJson::from_json(&change[2], next_eid);
                (view_id, index::Changes{inserted: inserted, removed: removed})
            }).collect()
        }
    }
}

pub enum ServerEvent {
    Message(String),
    NewClient(sender::Sender<WebSocketStream>),
}

// TODO holy crap why is everything blocking? this is a mess
pub fn serve() -> mpsc::Receiver<ServerEvent> {
    let (event_sender, event_receiver) = mpsc::channel();
    thread::spawn(move || {
        let server = Server::bind("0.0.0.0:2794").unwrap();
        for connection in server {
            let event_sender = event_sender.clone();
            thread::spawn(move || {
                // accept request
                let request = connection.unwrap().read_request().unwrap();
                request.validate().unwrap();
                let response = request.accept();
                let (mut sender, mut receiver) = response.send().unwrap().split();

                let ip = sender.get_mut().peer_addr().unwrap();
                println!("Connection from {}", ip);
                ::std::io::stdout().flush().unwrap(); // TODO is this actually necessary?

                // hand over sender
                event_sender.send(ServerEvent::NewClient(sender)).unwrap();

                // handle messages
                for message in receiver.incoming_messages() {
                    let message = message.unwrap();
                    match message {
                        Message::Text(text) => {
                            event_sender.send(ServerEvent::Message(text)).unwrap();
                        }
                        _ => println!("Unknown message: {:?}", message)
                    }
                }
            });
        }
    });
    event_receiver
}

// TODO arbitrary limit - needs tuning
static MAX_BATCH_SIZE: usize = 100;

fn recv_batch(event_receiver: &mpsc::Receiver<ServerEvent>, server_events: &mut Vec<ServerEvent>) {
    server_events.push(event_receiver.recv().unwrap()); // block until first event
    for _ in 0..MAX_BATCH_SIZE {
        match event_receiver.try_recv() {
            Ok(event) => server_events.push(event),
            Err(mpsc::TryRecvError::Empty) => break,
            Err(mpsc::TryRecvError::Disconnected) => panic!(),
        }
    }
}

pub fn compile_and_run(flow: Flow) -> (Flow, Changes) {
    let mut new_flow = compile(flow);
    new_flow.run();
    let changes = {
        let Flow {ref mut changes, ..} = new_flow;
        replace(changes, Vec::new())
    };
    (new_flow, changes)
}

pub fn run() {
    let empty_flow = Flow::new();
    let next_eid = &mut 0;
    let mut flow = Flow::new();

    time!("reading saved state", {
        let mut events = OpenOptions::new().create(true).open("./events").unwrap();
        let mut old_events = String::new();
        events.read_to_string(&mut old_events).unwrap();
        for line in old_events.lines() {
            let json = Json::from_str(&line).unwrap();
            let event: Event = FromJson::from_json(&json, next_eid);
            flow.change(event.changes);
        }
        drop(events);
        let (new_flow, _changes) = compile_and_run(flow);
        flow = new_flow;
        });

    let mut events = OpenOptions::new().write(true).append(true).open("./events").unwrap();
    let mut senders: Vec<sender::Sender<_>> = Vec::new();
    let mut server_events: Vec<ServerEvent> = Vec::with_capacity(MAX_BATCH_SIZE);
    let event_receiver = serve();
    loop {
        recv_batch(&event_receiver, &mut server_events);
        println!("batch size: {:?}", server_events.len());

        time!("entire batch", {
            for event in server_events.drain() {
                match event {
                    ServerEvent::NewClient(mut sender) => {
                        time!("sending initial state", {
                            let changes = flow.changes_since(&empty_flow);
                            let text = format!("{}", Event{changes: changes}.to_json());
                            match sender.send_message(Message::Text(text)) {
                                Ok(_) => (),
                                Err(error) => println!("Send error: {}", error),
                            };
                            senders.push(sender)
                        })
                    }
                    ServerEvent::Message(input_text) => {
                        time!("sending update", {
                            println!("{:?}", input_text);
                            let json = Json::from_str(&input_text).unwrap();
                            let input_event: Event = FromJson::from_json(&json, next_eid);
                            events.write_all(input_text.as_bytes()).unwrap();
                            events.write_all("\n".as_bytes()).unwrap();
                            flow.change(input_event.changes);
                        })
                    }
                }
            }

            let (new_flow, changes) = compile_and_run(flow);
            flow = new_flow;
            let output_event = Event{changes: changes};
            let output_text = format!("{}", output_event.to_json());
            events.flush().unwrap();
            for sender in senders.iter_mut() {
                match sender.send_message(Message::Text(output_text.clone())) {
                    Ok(_) => (),
                    Err(error) => println!("Send error: {}", error),
                };
            }
        })
    }
}
<commit_msg>Remove outdated todo<commit_after>use std::thread;
use std::sync::mpsc;
use websocket::{Server, Message, Sender, Receiver};
use websocket::server::sender;
use websocket::stream::WebSocketStream;
use std::io::prelude::*;
use std::fs::OpenOptions;
use std::num::ToPrimitive;
use rustc_serialize::json::{Json, ToJson};
use std::mem::replace;

use value::{Value, Tuple};
use index;
use flow::{Changes, Flow};
use compiler::compile;

trait FromJson {
    fn from_json(json: &Json, next_eid: &mut u64) -> Self;
}

impl ToJson for Value {
    fn to_json(&self) -> Json {
        match *self {
            Value::Bool(bool) => Json::Boolean(bool),
            Value::String(ref string) => Json::String(string.clone()),
            Value::Float(float) => Json::F64(float),
            Value::Tuple(ref tuple) => tuple.to_json(),
            Value::Relation(ref relation) => Json::Object(vec![
                ("relation".to_string(), relation.iter().map(ToJson::to_json).collect::<Vec<_>>().to_json())
                ].into_iter().collect()),
        }
    }
}

impl FromJson for Value {
    fn from_json(json: &Json, next_eid: &mut u64) -> Self {
        match *json {
            Json::Boolean(bool) => Value::Bool(bool),
            Json::String(ref string) => Value::String(string.clone()),
            Json::F64(float) => Value::Float(float),
            Json::I64(int) => Value::Float(int.to_f64().unwrap()),
            Json::U64(uint) => Value::Float(uint.to_f64().unwrap()),
            Json::Array(ref array) => Value::Tuple(array.iter().map(|j| Value::from_json(j, next_eid)).collect()),
            Json::Object(ref object) => {
                assert!(object.len() == 1);
                match object.get("eid") {
                    Some(value) => {
                        assert_eq!(value.as_string().unwrap(), "auto");
                        let eid = next_eid.to_f64().unwrap();
                        *next_eid += 1;
                        Value::Float(eid)
                    }
                    None => {
                        let relation: Vec<Tuple> = FromJson::from_json(&object["relation"], next_eid);
                        Value::Relation(relation.into_iter().collect())
                    }
                }
            },
            _ => panic!("Cannot decode {:?} as Value", json),
        }
    }
}

impl<T: FromJson> FromJson for Vec<T> {
    fn from_json(json: &Json, next_eid: &mut u64) -> Self {
        json.as_array().unwrap().iter().map(|t| FromJson::from_json(t, next_eid)).collect()
    }
}

pub struct Event {
    changes: Changes,
}

impl ToJson for Event {
    fn to_json(&self) -> Json {
        Json::Object(vec![
            ("changes".to_string(), Json::Array(
                self.changes.iter().map(|&(ref view_id, ref view_changes)| {
                    Json::Array(vec![
                        view_id.to_json(),
                        view_changes.inserted.to_json(),
                        view_changes.removed.to_json(),
                        ])
                }).collect())
            )].into_iter().collect())
    }
}

impl FromJson for Event {
    fn from_json(json: &Json, next_eid: &mut u64) -> Self {
        Event{
            changes: json.as_object().unwrap()["changes"]
            .as_array().unwrap().iter().map(|change| {
                let change = change.as_array().unwrap();
                assert_eq!(change.len(), 3);
                let view_id = change[0].as_string().unwrap().to_string();
                let inserted = FromJson::from_json(&change[1], next_eid);
                let removed = FromJson::from_json(&change[2], next_eid);
                (view_id, index::Changes{inserted: inserted, removed: removed})
            }).collect()
        }
    }
}

pub enum ServerEvent {
    Message(String),
    NewClient(sender::Sender<WebSocketStream>),
}

// TODO holy crap why is everything blocking? this is a mess
pub fn serve() -> mpsc::Receiver<ServerEvent> {
    let (event_sender, event_receiver) = mpsc::channel();
    thread::spawn(move || {
        let server = Server::bind("0.0.0.0:2794").unwrap();
        for connection in server {
            let event_sender = event_sender.clone();
            thread::spawn(move || {
                // accept request
                let request = connection.unwrap().read_request().unwrap();
                request.validate().unwrap();
                let response = request.accept();
                let (mut sender, mut receiver) = response.send().unwrap().split();

                let ip = sender.get_mut().peer_addr().unwrap();
                println!("Connection from {}", ip);
                ::std::io::stdout().flush().unwrap(); // TODO is this actually necessary?

                // hand over sender
                event_sender.send(ServerEvent::NewClient(sender)).unwrap();

                // handle messages
                for message in receiver.incoming_messages() {
                    let message = message.unwrap();
                    match message {
                        Message::Text(text) => {
                            event_sender.send(ServerEvent::Message(text)).unwrap();
                        }
                        _ => println!("Unknown message: {:?}", message)
                    }
                }
            });
        }
    });
    event_receiver
}

// TODO arbitrary limit - needs tuning
static MAX_BATCH_SIZE: usize = 100;

fn recv_batch(event_receiver: &mpsc::Receiver<ServerEvent>, server_events: &mut Vec<ServerEvent>) {
    server_events.push(event_receiver.recv().unwrap()); // block until first event
    for _ in 0..MAX_BATCH_SIZE {
        match event_receiver.try_recv() {
            Ok(event) => server_events.push(event),
            Err(mpsc::TryRecvError::Empty) => break,
            Err(mpsc::TryRecvError::Disconnected) => panic!(),
        }
    }
}

pub fn compile_and_run(flow: Flow) -> (Flow, Changes) {
    let mut new_flow = compile(flow);
    new_flow.run();
    let changes = {
        let Flow {ref mut changes, ..} = new_flow;
        replace(changes, Vec::new())
    };
    (new_flow, changes)
}

pub fn run() {
    let empty_flow = Flow::new();
    let next_eid = &mut 0;
    let mut flow = Flow::new();

    time!("reading saved state", {
        let mut events = OpenOptions::new().create(true).open("./events").unwrap();
        let mut old_events = String::new();
        events.read_to_string(&mut old_events).unwrap();
        for line in old_events.lines() {
            let json = Json::from_str(&line).unwrap();
            let event: Event = FromJson::from_json(&json, next_eid);
            flow.change(event.changes);
        }
        drop(events);
        let (new_flow, _changes) = compile_and_run(flow);
        flow = new_flow;
        });

    let mut events = OpenOptions::new().write(true).append(true).open("./events").unwrap();
    let mut senders: Vec<sender::Sender<_>> = Vec::new();
    let mut server_events: Vec<ServerEvent> = Vec::with_capacity(MAX_BATCH_SIZE);
    let event_receiver = serve();
    loop {
        recv_batch(&event_receiver, &mut server_events);
        println!("batch size: {:?}", server_events.len());

        time!("entire batch", {
            for event in server_events.drain() {
                match event {
                    ServerEvent::NewClient(mut sender) => {
                        time!("sending initial state", {
                            let changes = flow.changes_since(&empty_flow);
                            let text = format!("{}", Event{changes: changes}.to_json());
                            match sender.send_message(Message::Text(text)) {
                                Ok(_) => (),
                                Err(error) => println!("Send error: {}", error),
                            };
                            senders.push(sender)
                        })
                    }
                    ServerEvent::Message(input_text) => {
                        time!("sending update", {
                            println!("{:?}", input_text);
                            let json = Json::from_str(&input_text).unwrap();
                            let input_event: Event = FromJson::from_json(&json, next_eid);
                            events.write_all(input_text.as_bytes()).unwrap();
                            events.write_all("\n".as_bytes()).unwrap();
                            flow.change(input_event.changes);
                        })
                    }
                }
            }

            let (new_flow, changes) = compile_and_run(flow);
            flow = new_flow;
            let output_event = Event{changes: changes};
            let output_text = format!("{}", output_event.to_json());
            events.flush().unwrap();
            for sender in senders.iter_mut() {
                match sender.send_message(Message::Text(output_text.clone())) {
                    Ok(_) => (),
                    Err(error) => println!("Send error: {}", error),
                };
            }
        })
    }
}
<|endoftext|>


<commit_before>use std::fmt;

#[derive(PartialEq)]
pub struct Clock {
    hours: i32,
    minutes: i32,
}

impl Clock {
    pub fn new(hours: i32, minutes: i32) -> Self {
        return Clock { hours, minutes };
    }

    pub fn add_minutes(&self, minutes: i32) -> Self {
        return Clock::new(self.hours, self.minutes + minutes);
    }

    pub fn to_string(&self) -> String {
        return format!("{}:{}", self.hours, self.minutes);
    }
}

impl fmt::Display for Clock {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "({}:{})", self.hours, self.minutes)
    }
}

impl fmt::Debug for Clock {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "({}:{})", self.hours, self.minutes)
    }
}
<commit_msg>to_string unnecessary with Display trait<commit_after>use std::fmt;

#[derive(PartialEq)]
pub struct Clock {
    hours: i32,
    minutes: i32,
}

impl Clock {
    pub fn new(hours: i32, minutes: i32) -> Self {
        return Clock { hours, minutes };
    }

    pub fn add_minutes(&self, minutes: i32) -> Self {
        return Clock::new(self.hours, self.minutes + minutes);
    }
}

impl fmt::Display for Clock {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "({}:{})", self.hours, self.minutes)
    }
}

impl fmt::Debug for Clock {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "({}:{})", self.hours, self.minutes)
    }
}
<|endoftext|>


<commit_before>// CITA
// Copyright 2016-2017 Cryptape Technologies LLC.

// This program is free software: you can redistribute it
// and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any
// later version.

// This program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

//! Node manager.

use super::ContractCallExt;
use super::{encode_contract_name, to_address_vec, to_u256_vec};
use cita_types::{Address, H160};
use largest_remainder_method::apportion;
use libexecutor::executor::{EconomicalModel, Executor};
use rand::{Rng, SeedableRng, StdRng};
use rustc_hex::ToHex;
use std::iter;
use std::str::FromStr;
use types::reserved_addresses;

const LIST_NODE: &'static [u8] = &*b"listNode()";
const LIST_STAKE: &'static [u8] = *&b"listStake()";
/// Each epoch is divided into 1000 slots, each slot represent one opportunity of block proposer
const EPOCH: u64 = 1000;

lazy_static! {
    static ref LIST_NODE_ENCODED: Vec<u8> = encode_contract_name(LIST_NODE);
    static ref LIST_STAKE_ENCODED: Vec<u8> = encode_contract_name(LIST_STAKE);
    static ref CONTRACT_ADDRESS: H160 = H160::from_str(reserved_addresses::NODE_MANAGER).unwrap();
}

pub fn party_seats<T>(parties: Vec<T>, seats: &[u64]) -> Vec<T>
where
    T: Clone,
{
    let mut party_seats: Vec<T> = Vec::new();
    let seats_len = seats.len();
    for (index, party) in parties.into_iter().enumerate() {
        if index < seats_len {
            party_seats.extend(iter::repeat(party).take(seats[index] as usize));
        }
    }
    party_seats
}

pub fn shuffle<T>(node_vec: &mut Vec<T>, rng_seed: u64) {
    let seed: &[_] = &[rng_seed as usize];
    let mut rng: StdRng = SeedableRng::from_seed(seed);

    for i in 0..node_vec.len() {
        let j: usize = rng.gen::<usize>() % (i + 1);
        node_vec.swap(i, j);
    }
}

/// Configuration items from system contract
pub struct NodeManager<'a> {
    executor: &'a Executor,
    rng_seed: u64,
}

impl<'a> NodeManager<'a> {
    pub fn new(executor: &'a Executor, rng_seed: u64) -> Self {
        NodeManager { executor, rng_seed }
    }

    pub fn nodes(&self) -> Vec<Address> {
        let output = self
            .executor
            .call_method_latest(&*CONTRACT_ADDRESS, &*LIST_NODE_ENCODED.as_slice());

        trace!(
            "node manager output: {:?}",
            ToHex::to_hex(output.as_slice())
        );

        let nodes: Vec<Address> = to_address_vec(&output);
        trace!("node manager nodes: {:?}", nodes);
        nodes
    }

    pub fn stakes(&self) -> Vec<u64> {
        let output = self
            .executor
            .call_method_latest(&*CONTRACT_ADDRESS, &*LIST_STAKE_ENCODED.as_slice());

        trace!("stakes output: {:?}", ToHex::to_hex(output.as_slice()));

        let stakes: Vec<u64> = to_u256_vec(&output).iter().map(|i| i.low_u64()).collect();
        trace!("node manager stakes: {:?}", stakes);
        stakes
    }

    pub fn shuffled_stake_nodes(&self) -> Vec<Address> {
        let mut stake_nodes = self.stake_nodes();
        shuffle(&mut stake_nodes, self.rng_seed);
        stake_nodes
    }

    pub fn stake_nodes(&self) -> Vec<Address> {
        let nodes = self.nodes();
        if let EconomicalModel::Quota = *self.executor.economical_model.read() {
            return nodes;
        }
        let stakes = self.stakes();
        let total = stakes.iter().fold(0, |acc, &x| acc + x);

        if total == 0 {
            return nodes;
        }
        let total_seats = apportion(&stakes, EPOCH);
        party_seats(nodes, &total_seats)
    }
}

#[cfg(test)]
mod tests {
    extern crate logger;
    extern crate mktemp;

    use super::{party_seats, NodeManager};
    use cita_types::H160;
    use std::str::FromStr;
    use tests::helpers::init_executor;

    #[test]
    fn test_node_manager_contract() {
        let executor = init_executor(vec![
            (
                "NodeManager.nodes",
                concat!(
                    "0x50ad2b9d6946d9c75ae978534043e3021ee1bfb1,",
                    "0xeeb3a71c4046f63a941013f826fccc503be26b77,",
                    "0xa2bbb65d4f8c3ada29f7471abe416e18061127f3,",
                    "0x72eb1e258c9cdccebb7b62930a35cfb6ef4cd24b"
                ),
            ),
            ("NodeManager.stakes", "1,1,1,1"),
        ]);
        let node_manager = NodeManager::new(&executor, executor.genesis_header().timestamp());
        let nodes = node_manager.nodes();

        assert_eq!(
            nodes,
            vec![
                H160::from_str("50ad2b9d6946d9c75ae978534043e3021ee1bfb1").unwrap(),
                H160::from_str("eeb3a71c4046f63a941013f826fccc503be26b77").unwrap(),
                H160::from_str("a2bbb65d4f8c3ada29f7471abe416e18061127f3").unwrap(),
                H160::from_str("72eb1e258c9cdccebb7b62930a35cfb6ef4cd24b").unwrap(),
            ]
        )
    }

    #[test]
    fn test_party_seats() {
        let parties = vec!["a", "b", "c"];
        let seats = vec![3, 5, 2, 2, 1];
        assert_eq!(
            party_seats(parties, &seats),
            vec!["a", "a", "a", "b", "b", "b", "b", "b", "c", "c"]
        );

        let parties = vec!["a", "b"];
        let seats = vec![2, 1];
        assert_eq!(party_seats(parties, &seats), vec!["a", "a", "b"]);

        let parties = vec!["a", "b", "c"];
        let seats = vec![2, 2];
        assert_eq!(party_seats(parties, &seats), vec!["a", "a", "b", "b"]);
    }
}
<commit_msg>Add shuffle test<commit_after>// CITA
// Copyright 2016-2017 Cryptape Technologies LLC.

// This program is free software: you can redistribute it
// and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any
// later version.

// This program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

//! Node manager.

use super::ContractCallExt;
use super::{encode_contract_name, to_address_vec, to_u256_vec};
use cita_types::{Address, H160};
use largest_remainder_method::apportion;
use libexecutor::executor::{EconomicalModel, Executor};
use rand::{Rng, SeedableRng, StdRng};
use rustc_hex::ToHex;
use std::iter;
use std::str::FromStr;
use types::reserved_addresses;

const LIST_NODE: &'static [u8] = &*b"listNode()";
const LIST_STAKE: &'static [u8] = *&b"listStake()";
/// Each epoch is divided into 1000 slots, each slot represent one opportunity of block proposer
const EPOCH: u64 = 1000;

lazy_static! {
    static ref LIST_NODE_ENCODED: Vec<u8> = encode_contract_name(LIST_NODE);
    static ref LIST_STAKE_ENCODED: Vec<u8> = encode_contract_name(LIST_STAKE);
    static ref CONTRACT_ADDRESS: H160 = H160::from_str(reserved_addresses::NODE_MANAGER).unwrap();
}

pub fn party_seats<T>(parties: Vec<T>, seats: &[u64]) -> Vec<T>
where
    T: Clone,
{
    let mut party_seats: Vec<T> = Vec::new();
    let seats_len = seats.len();
    for (index, party) in parties.into_iter().enumerate() {
        if index < seats_len {
            party_seats.extend(iter::repeat(party).take(seats[index] as usize));
        }
    }
    party_seats
}

pub fn shuffle<T>(items: &mut Vec<T>, rng_seed: u64) {
    let seed: &[_] = &[rng_seed as usize];
    let mut rng: StdRng = SeedableRng::from_seed(seed);

    for i in 0..items.len() {
        let j: usize = rng.gen::<usize>() % (i + 1);
        items.swap(i, j);
    }
}

/// Configuration items from system contract
pub struct NodeManager<'a> {
    executor: &'a Executor,
    rng_seed: u64,
}

impl<'a> NodeManager<'a> {
    pub fn new(executor: &'a Executor, rng_seed: u64) -> Self {
        NodeManager { executor, rng_seed }
    }

    pub fn nodes(&self) -> Vec<Address> {
        let output = self
            .executor
            .call_method_latest(&*CONTRACT_ADDRESS, &*LIST_NODE_ENCODED.as_slice());

        trace!(
            "node manager output: {:?}",
            ToHex::to_hex(output.as_slice())
        );

        let nodes: Vec<Address> = to_address_vec(&output);
        trace!("node manager nodes: {:?}", nodes);
        nodes
    }

    pub fn stakes(&self) -> Vec<u64> {
        let output = self
            .executor
            .call_method_latest(&*CONTRACT_ADDRESS, &*LIST_STAKE_ENCODED.as_slice());

        trace!("stakes output: {:?}", ToHex::to_hex(output.as_slice()));

        let stakes: Vec<u64> = to_u256_vec(&output).iter().map(|i| i.low_u64()).collect();
        trace!("node manager stakes: {:?}", stakes);
        stakes
    }

    pub fn shuffled_stake_nodes(&self) -> Vec<Address> {
        let mut stake_nodes = self.stake_nodes();
        shuffle(&mut stake_nodes, self.rng_seed);
        stake_nodes
    }

    pub fn stake_nodes(&self) -> Vec<Address> {
        let nodes = self.nodes();
        if let EconomicalModel::Quota = *self.executor.economical_model.read() {
            return nodes;
        }
        let stakes = self.stakes();
        let total = stakes.iter().fold(0, |acc, &x| acc + x);

        if total == 0 {
            return nodes;
        }
        let total_seats = apportion(&stakes, EPOCH);
        party_seats(nodes, &total_seats)
    }
}

#[cfg(test)]
mod tests {
    extern crate logger;
    extern crate mktemp;

    use super::{party_seats, shuffle, NodeManager};
    use cita_types::H160;
    use std::str::FromStr;
    use tests::helpers::init_executor;

    #[test]
    fn test_node_manager_contract() {
        let executor = init_executor(vec![
            (
                "NodeManager.nodes",
                concat!(
                    "0x50ad2b9d6946d9c75ae978534043e3021ee1bfb1,",
                    "0xeeb3a71c4046f63a941013f826fccc503be26b77,",
                    "0xa2bbb65d4f8c3ada29f7471abe416e18061127f3,",
                    "0x72eb1e258c9cdccebb7b62930a35cfb6ef4cd24b"
                ),
            ),
            ("NodeManager.stakes", "1,1,1,1"),
        ]);
        let node_manager = NodeManager::new(&executor, executor.genesis_header().timestamp());
        let nodes = node_manager.nodes();

        assert_eq!(
            nodes,
            vec![
                H160::from_str("50ad2b9d6946d9c75ae978534043e3021ee1bfb1").unwrap(),
                H160::from_str("eeb3a71c4046f63a941013f826fccc503be26b77").unwrap(),
                H160::from_str("a2bbb65d4f8c3ada29f7471abe416e18061127f3").unwrap(),
                H160::from_str("72eb1e258c9cdccebb7b62930a35cfb6ef4cd24b").unwrap(),
            ]
        )
    }

    #[test]
    fn test_party_seats() {
        let parties = vec!["a", "b", "c"];
        let seats = vec![3, 5, 2, 2, 1];
        assert_eq!(
            party_seats(parties, &seats),
            vec!["a", "a", "a", "b", "b", "b", "b", "b", "c", "c"]
        );

        let parties = vec!["a", "b"];
        let seats = vec![2, 1];
        assert_eq!(party_seats(parties, &seats), vec!["a", "a", "b"]);

        let parties = vec!["a", "b", "c"];
        let seats = vec![2, 2];
        assert_eq!(party_seats(parties, &seats), vec!["a", "a", "b", "b"]);
    }

    #[test]
    fn test_shuffle() {
        let mut items = vec![1, 1, 1, 1, 1, 2, 2, 2, 2, 2];
        shuffle(&mut items, 998);
        assert_eq!(items, vec![2, 1, 1, 2, 1, 2, 2, 1, 1, 2]);

        let mut items2 = vec![1; 50];
        items2.extend(vec![2; 50].iter());
        items2.extend(vec![3; 50].iter());
        shuffle(&mut items2, 1024);
        assert_eq!(
            items2,
            vec![
                2, 2, 1, 3, 2, 3, 1, 2, 1, 1, 1, 1, 3, 3, 1, 3, 3, 3, 1, 2, 3, 3, 3, 1, 1, 2, 2, 2,
                2, 3, 1, 3, 3, 3, 3, 1, 3, 3, 1, 3, 1, 2, 2, 1, 2, 2, 2, 1, 2, 3, 3, 1, 2, 2, 1, 2,
                1, 3, 3, 2, 2, 1, 1, 1, 1, 2, 3, 2, 1, 3, 3, 2, 2, 2, 2, 2, 2, 3, 1, 1, 1, 3, 1, 1,
                2, 1, 1, 2, 3, 1, 3, 3, 2, 2, 1, 2, 2, 1, 3, 3, 3, 1, 3, 3, 3, 1, 1, 1, 3, 1, 2, 1,
                2, 2, 1, 2, 1, 3, 3, 2, 1, 2, 2, 3, 1, 2, 2, 1, 3, 1, 3, 3, 2, 1, 3, 2, 3, 1, 3, 3,
                1, 3, 1, 2, 3, 3, 2, 2, 2, 2,
            ]
        );
    }
}
<|endoftext|>