<commit_before>use std::mem;

use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
use rustc::mir;
use rustc::ty::{
    self,
    layout::{self, Align, LayoutOf, Size, TyLayout},
};

use rand::RngCore;

use crate::*;

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}

pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    /// Gets an instance for a path.
    fn resolve_path(&self, path: &[&str]) -> InterpResult<'tcx, ty::Instance<'tcx>> {
        let this = self.eval_context_ref();
        this.tcx
            .crates()
            .iter()
            .find(|&&krate| this.tcx.original_crate_name(krate).as_str() == path[0])
            .and_then(|krate| {
                let krate = DefId {
                    krate: *krate,
                    index: CRATE_DEF_INDEX,
                };
                let mut items = this.tcx.item_children(krate);
                let mut path_it = path.iter().skip(1).peekable();

                while let Some(segment) = path_it.next() {
                    for item in mem::replace(&mut items, Default::default()).iter() {
                        if item.ident.name.as_str() == *segment {
                            if path_it.peek().is_none() {
                                return Some(ty::Instance::mono(this.tcx.tcx, item.res.def_id()));
                            }

                            items = this.tcx.item_children(item.res.def_id());
                            break;
                        }
                    }
                }
                None
            })
            .ok_or_else(|| {
                let path = path.iter().map(|&s| s.to_owned()).collect();
                err_unsup!(PathNotFound(path)).into()
            })
    }

    /// Write a 0 of the appropriate size to `dest`.
    fn write_null(&mut self, dest: PlaceTy<'tcx, Tag>) -> InterpResult<'tcx> {
        self.eval_context_mut().write_scalar(Scalar::from_int(0, dest.layout.size), dest)
    }

    /// Test if this immediate equals 0.
    fn is_null(&self, val: Scalar<Tag>) -> InterpResult<'tcx, bool> {
        let this = self.eval_context_ref();
        let null = Scalar::from_int(0, this.memory().pointer_size());
        this.ptr_eq(val, null)
    }

    /// Turn a Scalar into an Option<NonNullScalar>
    fn test_null(&self, val: Scalar<Tag>) -> InterpResult<'tcx, Option<Scalar<Tag>>> {
        let this = self.eval_context_ref();
        Ok(if this.is_null(val)? {
            None
        } else {
            Some(val)
        })
    }

    /// Get the `Place` for a local
    fn local_place(&mut self, local: mir::Local) -> InterpResult<'tcx, PlaceTy<'tcx, Tag>> {
        let this = self.eval_context_mut();
        let place = mir::Place { base: mir::PlaceBase::Local(local), projection: Box::new([]) };
        this.eval_place(&place)
    }

    /// Generate some random bytes, and write them to `dest`.
    fn gen_random(
        &mut self,
        ptr: Scalar<Tag>,
        len: usize,
    ) -> InterpResult<'tcx>  {
        // Some programs pass in a null pointer and a length of 0
        // to their platform's random-generation function (e.g. getrandom())
        // on Linux. For compatibility with these programs, we don't perform
        // any additional checks - it's okay if the pointer is invalid,
        // since we wouldn't actually be writing to it.
        if len == 0 {
            return Ok(());
        }
        let this = self.eval_context_mut();

        let ptr = this.memory().check_ptr_access(
            ptr,
            Size::from_bytes(len as u64),
            Align::from_bytes(1).unwrap()
        )?.expect("we already checked for size 0");

        let mut data = vec![0; len];

        if this.machine.communicate {
            // Fill the buffer using the host's rng.
            getrandom::getrandom(&mut data)
                .map_err(|err| err_unsup_format!("getrandom failed: {}", err))?;
        }
        else {
            let rng = this.memory_mut().extra.rng.get_mut();
            rng.fill_bytes(&mut data);
        }

        let tcx = &{this.tcx.tcx};
        this.memory_mut().get_mut(ptr.alloc_id)?.write_bytes(tcx, ptr, &data)
    }

    /// Visits the memory covered by `place`, sensitive to freezing: the 3rd parameter
    /// will be true if this is frozen, false if this is in an `UnsafeCell`.
    fn visit_freeze_sensitive(
        &self,
        place: MPlaceTy<'tcx, Tag>,
        size: Size,
        mut action: impl FnMut(Pointer<Tag>, Size, bool) -> InterpResult<'tcx>,
    ) -> InterpResult<'tcx> {
        let this = self.eval_context_ref();
        trace!("visit_frozen(place={:?}, size={:?})", *place, size);
        debug_assert_eq!(size,
            this.size_and_align_of_mplace(place)?
            .map(|(size, _)| size)
            .unwrap_or_else(|| place.layout.size)
        );
        // Store how far we proceeded into the place so far. Everything to the left of
        // this offset has already been handled, in the sense that the frozen parts
        // have had `action` called on them.
        let mut end_ptr = place.ptr.assert_ptr();
        // Called when we detected an `UnsafeCell` at the given offset and size.
        // Calls `action` and advances `end_ptr`.
        let mut unsafe_cell_action = |unsafe_cell_ptr: Scalar<Tag>, unsafe_cell_size: Size| {
            let unsafe_cell_ptr = unsafe_cell_ptr.assert_ptr();
            debug_assert_eq!(unsafe_cell_ptr.alloc_id, end_ptr.alloc_id);
            debug_assert_eq!(unsafe_cell_ptr.tag, end_ptr.tag);
            // We assume that we are given the fields in increasing offset order,
            // and nothing else changes.
            let unsafe_cell_offset = unsafe_cell_ptr.offset;
            let end_offset = end_ptr.offset;
            assert!(unsafe_cell_offset >= end_offset);
            let frozen_size = unsafe_cell_offset - end_offset;
            // Everything between the end_ptr and this `UnsafeCell` is frozen.
            if frozen_size != Size::ZERO {
                action(end_ptr, frozen_size, /*frozen*/true)?;
            }
            // This `UnsafeCell` is NOT frozen.
            if unsafe_cell_size != Size::ZERO {
                action(unsafe_cell_ptr, unsafe_cell_size, /*frozen*/false)?;
            }
            // Update end end_ptr.
            end_ptr = unsafe_cell_ptr.wrapping_offset(unsafe_cell_size, this);
            // Done
            Ok(())
        };
        // Run a visitor
        {
            let mut visitor = UnsafeCellVisitor {
                ecx: this,
                unsafe_cell_action: |place| {
                    trace!("unsafe_cell_action on {:?}", place.ptr);
                    // We need a size to go on.
                    let unsafe_cell_size = this.size_and_align_of_mplace(place)?
                        .map(|(size, _)| size)
                        // for extern types, just cover what we can
                        .unwrap_or_else(|| place.layout.size);
                    // Now handle this `UnsafeCell`, unless it is empty.
                    if unsafe_cell_size != Size::ZERO {
                        unsafe_cell_action(place.ptr, unsafe_cell_size)
                    } else {
                        Ok(())
                    }
                },
            };
            visitor.visit_value(place)?;
        }
        // The part between the end_ptr and the end of the place is also frozen.
        // So pretend there is a 0-sized `UnsafeCell` at the end.
        unsafe_cell_action(place.ptr.ptr_wrapping_offset(size, this), Size::ZERO)?;
        // Done!
        return Ok(());

        /// Visiting the memory covered by a `MemPlace`, being aware of
        /// whether we are inside an `UnsafeCell` or not.
        struct UnsafeCellVisitor<'ecx, 'mir, 'tcx, F>
            where F: FnMut(MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
        {
            ecx: &'ecx MiriEvalContext<'mir, 'tcx>,
            unsafe_cell_action: F,
        }

        impl<'ecx, 'mir, 'tcx, F>
            ValueVisitor<'mir, 'tcx, Evaluator<'tcx>>
        for
            UnsafeCellVisitor<'ecx, 'mir, 'tcx, F>
        where
            F: FnMut(MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
        {
            type V = MPlaceTy<'tcx, Tag>;

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

            // Hook to detect `UnsafeCell`.
            fn visit_value(&mut self, v: MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
            {
                trace!("UnsafeCellVisitor: {:?} {:?}", *v, v.layout.ty);
                let is_unsafe_cell = match v.layout.ty.kind {
                    ty::Adt(adt, _) => Some(adt.did) == self.ecx.tcx.lang_items().unsafe_cell_type(),
                    _ => false,
                };
                if is_unsafe_cell {
                    // We do not have to recurse further, this is an `UnsafeCell`.
                    (self.unsafe_cell_action)(v)
                } else if self.ecx.type_is_freeze(v.layout.ty) {
                    // This is `Freeze`, there cannot be an `UnsafeCell`
                    Ok(())
                } else {
                    // We want to not actually read from memory for this visit. So, before
                    // walking this value, we have to make sure it is not a
                    // `Variants::Multiple`.
                    match v.layout.variants {
                        layout::Variants::Multiple { .. } => {
                            // A multi-variant enum, or generator, or so.
                            // Treat this like a union: without reading from memory,
                            // we cannot determine the variant we are in. Reading from
                            // memory would be subject to Stacked Borrows rules, leading
                            // to all sorts of "funny" recursion.
                            // We only end up here if the type is *not* freeze, so we just call the
                            // `UnsafeCell` action.
                            (self.unsafe_cell_action)(v)
                        }
                        layout::Variants::Single { .. } => {
                            // Proceed further, try to find where exactly that `UnsafeCell`
                            // is hiding.
                            self.walk_value(v)
                        }
                    }
                }
            }

            // Make sure we visit aggregrates in increasing offset order.
            fn visit_aggregate(
                &mut self,
                place: MPlaceTy<'tcx, Tag>,
                fields: impl Iterator<Item=InterpResult<'tcx, MPlaceTy<'tcx, Tag>>>,
            ) -> InterpResult<'tcx> {
                match place.layout.fields {
                    layout::FieldPlacement::Array { .. } => {
                        // For the array layout, we know the iterator will yield sorted elements so
                        // we can avoid the allocation.
                        self.walk_aggregate(place, fields)
                    }
                    layout::FieldPlacement::Arbitrary { .. } => {
                        // Gather the subplaces and sort them before visiting.
                        let mut places = fields.collect::<InterpResult<'tcx, Vec<MPlaceTy<'tcx, Tag>>>>()?;
                        places.sort_by_key(|place| place.ptr.assert_ptr().offset);
                        self.walk_aggregate(place, places.into_iter().map(Ok))
                    }
                    layout::FieldPlacement::Union { .. } => {
                        // Uh, what?
                        bug!("a union is not an aggregate we should ever visit")
                    }
                }
            }

            // We have to do *something* for unions.
            fn visit_union(&mut self, v: MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
            {
                // With unions, we fall back to whatever the type says, to hopefully be consistent
                // with LLVM IR.
                // FIXME: are we consistent, and is this really the behavior we want?
                let frozen = self.ecx.type_is_freeze(v.layout.ty);
                if frozen {
                    Ok(())
                } else {
                    (self.unsafe_cell_action)(v)
                }
            }

            // We should never get to a primitive, but always short-circuit somewhere above.
            fn visit_primitive(&mut self, _v: MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
            {
                bug!("we should always short-circuit before coming to a primitive")
            }
        }
    }

    /// Helper function to get a `libc` constant as a `Scalar`.
    fn eval_libc(&mut self, name: &str) -> InterpResult<'tcx, Scalar<Tag>> {
        self.eval_context_mut()
            .eval_path_scalar(&["libc", name])?
            .ok_or_else(|| err_unsup_format!("Path libc::{} cannot be resolved.", name))?
            .not_undef()
    }

    /// Helper function to get a `libc` constant as an `i32`.
    fn eval_libc_i32(&mut self, name: &str) -> InterpResult<'tcx, i32> {
        self.eval_libc(name)?.to_i32()
    }

    // Writes several `ImmTy`s contiguosly into memory. This is useful when you have to pack
    // different values into an struct.
    fn write_immediates(
        &mut self,
        ptr: &Pointer<Tag>,
        imms: &[ImmTy<'tcx, Tag>],
    ) -> InterpResult<'tcx> {
        let this = self.eval_context_mut();

        let tcx = &{ this.tcx.tcx };

        let allocation = this.memory_mut().get_mut(ptr.alloc_id)?;
        let mut offset = Size::from_bytes(0);

        for imm in imms {
            let size = imm.layout.size;
            allocation.write_scalar(
                tcx,
                ptr.offset(offset, tcx)?,
                imm.to_scalar()?.into(),
                size,
            )?;
            offset += size;
        }

        Ok(())
    }

    fn libc_ty_layout(&mut self, name: &str) -> InterpResult<'tcx, TyLayout<'tcx>> {
        let this = self.eval_context_mut();
        let tcx = &{ this.tcx.tcx };
        let ty = this.resolve_path(&["libc", name])?.ty(*tcx);
        this.layout_of(ty)
    }
}
<commit_msg>Group libc helper functions<commit_after>use std::mem;

use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
use rustc::mir;
use rustc::ty::{
    self,
    layout::{self, Align, LayoutOf, Size, TyLayout},
};

use rand::RngCore;

use crate::*;

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}

pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    /// Gets an instance for a path.
    fn resolve_path(&self, path: &[&str]) -> InterpResult<'tcx, ty::Instance<'tcx>> {
        let this = self.eval_context_ref();
        this.tcx
            .crates()
            .iter()
            .find(|&&krate| this.tcx.original_crate_name(krate).as_str() == path[0])
            .and_then(|krate| {
                let krate = DefId {
                    krate: *krate,
                    index: CRATE_DEF_INDEX,
                };
                let mut items = this.tcx.item_children(krate);
                let mut path_it = path.iter().skip(1).peekable();

                while let Some(segment) = path_it.next() {
                    for item in mem::replace(&mut items, Default::default()).iter() {
                        if item.ident.name.as_str() == *segment {
                            if path_it.peek().is_none() {
                                return Some(ty::Instance::mono(this.tcx.tcx, item.res.def_id()));
                            }

                            items = this.tcx.item_children(item.res.def_id());
                            break;
                        }
                    }
                }
                None
            })
            .ok_or_else(|| {
                let path = path.iter().map(|&s| s.to_owned()).collect();
                err_unsup!(PathNotFound(path)).into()
            })
    }

    /// Write a 0 of the appropriate size to `dest`.
    fn write_null(&mut self, dest: PlaceTy<'tcx, Tag>) -> InterpResult<'tcx> {
        self.eval_context_mut().write_scalar(Scalar::from_int(0, dest.layout.size), dest)
    }

    /// Test if this immediate equals 0.
    fn is_null(&self, val: Scalar<Tag>) -> InterpResult<'tcx, bool> {
        let this = self.eval_context_ref();
        let null = Scalar::from_int(0, this.memory().pointer_size());
        this.ptr_eq(val, null)
    }

    /// Turn a Scalar into an Option<NonNullScalar>
    fn test_null(&self, val: Scalar<Tag>) -> InterpResult<'tcx, Option<Scalar<Tag>>> {
        let this = self.eval_context_ref();
        Ok(if this.is_null(val)? {
            None
        } else {
            Some(val)
        })
    }

    /// Get the `Place` for a local
    fn local_place(&mut self, local: mir::Local) -> InterpResult<'tcx, PlaceTy<'tcx, Tag>> {
        let this = self.eval_context_mut();
        let place = mir::Place { base: mir::PlaceBase::Local(local), projection: Box::new([]) };
        this.eval_place(&place)
    }

    /// Generate some random bytes, and write them to `dest`.
    fn gen_random(
        &mut self,
        ptr: Scalar<Tag>,
        len: usize,
    ) -> InterpResult<'tcx>  {
        // Some programs pass in a null pointer and a length of 0
        // to their platform's random-generation function (e.g. getrandom())
        // on Linux. For compatibility with these programs, we don't perform
        // any additional checks - it's okay if the pointer is invalid,
        // since we wouldn't actually be writing to it.
        if len == 0 {
            return Ok(());
        }
        let this = self.eval_context_mut();

        let ptr = this.memory().check_ptr_access(
            ptr,
            Size::from_bytes(len as u64),
            Align::from_bytes(1).unwrap()
        )?.expect("we already checked for size 0");

        let mut data = vec![0; len];

        if this.machine.communicate {
            // Fill the buffer using the host's rng.
            getrandom::getrandom(&mut data)
                .map_err(|err| err_unsup_format!("getrandom failed: {}", err))?;
        }
        else {
            let rng = this.memory_mut().extra.rng.get_mut();
            rng.fill_bytes(&mut data);
        }

        let tcx = &{this.tcx.tcx};
        this.memory_mut().get_mut(ptr.alloc_id)?.write_bytes(tcx, ptr, &data)
    }

    /// Visits the memory covered by `place`, sensitive to freezing: the 3rd parameter
    /// will be true if this is frozen, false if this is in an `UnsafeCell`.
    fn visit_freeze_sensitive(
        &self,
        place: MPlaceTy<'tcx, Tag>,
        size: Size,
        mut action: impl FnMut(Pointer<Tag>, Size, bool) -> InterpResult<'tcx>,
    ) -> InterpResult<'tcx> {
        let this = self.eval_context_ref();
        trace!("visit_frozen(place={:?}, size={:?})", *place, size);
        debug_assert_eq!(size,
            this.size_and_align_of_mplace(place)?
            .map(|(size, _)| size)
            .unwrap_or_else(|| place.layout.size)
        );
        // Store how far we proceeded into the place so far. Everything to the left of
        // this offset has already been handled, in the sense that the frozen parts
        // have had `action` called on them.
        let mut end_ptr = place.ptr.assert_ptr();
        // Called when we detected an `UnsafeCell` at the given offset and size.
        // Calls `action` and advances `end_ptr`.
        let mut unsafe_cell_action = |unsafe_cell_ptr: Scalar<Tag>, unsafe_cell_size: Size| {
            let unsafe_cell_ptr = unsafe_cell_ptr.assert_ptr();
            debug_assert_eq!(unsafe_cell_ptr.alloc_id, end_ptr.alloc_id);
            debug_assert_eq!(unsafe_cell_ptr.tag, end_ptr.tag);
            // We assume that we are given the fields in increasing offset order,
            // and nothing else changes.
            let unsafe_cell_offset = unsafe_cell_ptr.offset;
            let end_offset = end_ptr.offset;
            assert!(unsafe_cell_offset >= end_offset);
            let frozen_size = unsafe_cell_offset - end_offset;
            // Everything between the end_ptr and this `UnsafeCell` is frozen.
            if frozen_size != Size::ZERO {
                action(end_ptr, frozen_size, /*frozen*/true)?;
            }
            // This `UnsafeCell` is NOT frozen.
            if unsafe_cell_size != Size::ZERO {
                action(unsafe_cell_ptr, unsafe_cell_size, /*frozen*/false)?;
            }
            // Update end end_ptr.
            end_ptr = unsafe_cell_ptr.wrapping_offset(unsafe_cell_size, this);
            // Done
            Ok(())
        };
        // Run a visitor
        {
            let mut visitor = UnsafeCellVisitor {
                ecx: this,
                unsafe_cell_action: |place| {
                    trace!("unsafe_cell_action on {:?}", place.ptr);
                    // We need a size to go on.
                    let unsafe_cell_size = this.size_and_align_of_mplace(place)?
                        .map(|(size, _)| size)
                        // for extern types, just cover what we can
                        .unwrap_or_else(|| place.layout.size);
                    // Now handle this `UnsafeCell`, unless it is empty.
                    if unsafe_cell_size != Size::ZERO {
                        unsafe_cell_action(place.ptr, unsafe_cell_size)
                    } else {
                        Ok(())
                    }
                },
            };
            visitor.visit_value(place)?;
        }
        // The part between the end_ptr and the end of the place is also frozen.
        // So pretend there is a 0-sized `UnsafeCell` at the end.
        unsafe_cell_action(place.ptr.ptr_wrapping_offset(size, this), Size::ZERO)?;
        // Done!
        return Ok(());

        /// Visiting the memory covered by a `MemPlace`, being aware of
        /// whether we are inside an `UnsafeCell` or not.
        struct UnsafeCellVisitor<'ecx, 'mir, 'tcx, F>
            where F: FnMut(MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
        {
            ecx: &'ecx MiriEvalContext<'mir, 'tcx>,
            unsafe_cell_action: F,
        }

        impl<'ecx, 'mir, 'tcx, F>
            ValueVisitor<'mir, 'tcx, Evaluator<'tcx>>
        for
            UnsafeCellVisitor<'ecx, 'mir, 'tcx, F>
        where
            F: FnMut(MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
        {
            type V = MPlaceTy<'tcx, Tag>;

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

            // Hook to detect `UnsafeCell`.
            fn visit_value(&mut self, v: MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
            {
                trace!("UnsafeCellVisitor: {:?} {:?}", *v, v.layout.ty);
                let is_unsafe_cell = match v.layout.ty.kind {
                    ty::Adt(adt, _) => Some(adt.did) == self.ecx.tcx.lang_items().unsafe_cell_type(),
                    _ => false,
                };
                if is_unsafe_cell {
                    // We do not have to recurse further, this is an `UnsafeCell`.
                    (self.unsafe_cell_action)(v)
                } else if self.ecx.type_is_freeze(v.layout.ty) {
                    // This is `Freeze`, there cannot be an `UnsafeCell`
                    Ok(())
                } else {
                    // We want to not actually read from memory for this visit. So, before
                    // walking this value, we have to make sure it is not a
                    // `Variants::Multiple`.
                    match v.layout.variants {
                        layout::Variants::Multiple { .. } => {
                            // A multi-variant enum, or generator, or so.
                            // Treat this like a union: without reading from memory,
                            // we cannot determine the variant we are in. Reading from
                            // memory would be subject to Stacked Borrows rules, leading
                            // to all sorts of "funny" recursion.
                            // We only end up here if the type is *not* freeze, so we just call the
                            // `UnsafeCell` action.
                            (self.unsafe_cell_action)(v)
                        }
                        layout::Variants::Single { .. } => {
                            // Proceed further, try to find where exactly that `UnsafeCell`
                            // is hiding.
                            self.walk_value(v)
                        }
                    }
                }
            }

            // Make sure we visit aggregrates in increasing offset order.
            fn visit_aggregate(
                &mut self,
                place: MPlaceTy<'tcx, Tag>,
                fields: impl Iterator<Item=InterpResult<'tcx, MPlaceTy<'tcx, Tag>>>,
            ) -> InterpResult<'tcx> {
                match place.layout.fields {
                    layout::FieldPlacement::Array { .. } => {
                        // For the array layout, we know the iterator will yield sorted elements so
                        // we can avoid the allocation.
                        self.walk_aggregate(place, fields)
                    }
                    layout::FieldPlacement::Arbitrary { .. } => {
                        // Gather the subplaces and sort them before visiting.
                        let mut places = fields.collect::<InterpResult<'tcx, Vec<MPlaceTy<'tcx, Tag>>>>()?;
                        places.sort_by_key(|place| place.ptr.assert_ptr().offset);
                        self.walk_aggregate(place, places.into_iter().map(Ok))
                    }
                    layout::FieldPlacement::Union { .. } => {
                        // Uh, what?
                        bug!("a union is not an aggregate we should ever visit")
                    }
                }
            }

            // We have to do *something* for unions.
            fn visit_union(&mut self, v: MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
            {
                // With unions, we fall back to whatever the type says, to hopefully be consistent
                // with LLVM IR.
                // FIXME: are we consistent, and is this really the behavior we want?
                let frozen = self.ecx.type_is_freeze(v.layout.ty);
                if frozen {
                    Ok(())
                } else {
                    (self.unsafe_cell_action)(v)
                }
            }

            // We should never get to a primitive, but always short-circuit somewhere above.
            fn visit_primitive(&mut self, _v: MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
            {
                bug!("we should always short-circuit before coming to a primitive")
            }
        }
    }

    /// Helper function to get a `libc` constant as a `Scalar`.
    fn eval_libc(&mut self, name: &str) -> InterpResult<'tcx, Scalar<Tag>> {
        self.eval_context_mut()
            .eval_path_scalar(&["libc", name])?
            .ok_or_else(|| err_unsup_format!("Path libc::{} cannot be resolved.", name))?
            .not_undef()
    }

    /// Helper function to get a `libc` constant as an `i32`.
    fn eval_libc_i32(&mut self, name: &str) -> InterpResult<'tcx, i32> {
        self.eval_libc(name)?.to_i32()
    }

    /// Helper function to get the `TyLayout` of a `libc` type
    fn libc_ty_layout(&mut self, name: &str) -> InterpResult<'tcx, TyLayout<'tcx>> {
        let this = self.eval_context_mut();
        let tcx = &{ this.tcx.tcx };
        let ty = this.resolve_path(&["libc", name])?.ty(*tcx);
        this.layout_of(ty)
    }

    // Writes several `ImmTy`s contiguosly into memory. This is useful when you have to pack
    // different values into a struct.
    fn write_immediates(
        &mut self,
        ptr: &Pointer<Tag>,
        imms: &[ImmTy<'tcx, Tag>],
    ) -> InterpResult<'tcx> {
        let this = self.eval_context_mut();

        let tcx = &{ this.tcx.tcx };

        let allocation = this.memory_mut().get_mut(ptr.alloc_id)?;
        let mut offset = Size::from_bytes(0);

        for imm in imms {
            let size = imm.layout.size;
            allocation.write_scalar(
                tcx,
                ptr.offset(offset, tcx)?,
                imm.to_scalar()?.into(),
                size,
            )?;
            offset += size;
        }

        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::str;

use crate::core::Message;

use crate::reflect::EnumDescriptor;
use crate::reflect::EnumValueDescriptor;
use crate::reflect::MessageDescriptor;
use crate::reflect::ReflectValueBox;
use crate::reflect::RuntimeFieldType;
use crate::reflect::RuntimeTypeBox;
use crate::reflect::RuntimeTypeDynamic;
use crate::text_format::lexer::int;
use crate::text_format::lexer::Loc;
use crate::text_format::lexer::ParserLanguage;
use crate::text_format::lexer::StrLitDecodeError;
use crate::text_format::lexer::Tokenizer;
use crate::text_format::lexer::TokenizerError;

#[derive(Debug)]
pub enum ParseError {
    TokenizerError(TokenizerError),
    StrLitDecodeError(StrLitDecodeError),
    UnknownField(String),
    UnknownEnumValue(String),
    MapFieldIsSpecifiedMoreThanOnce(String),
    IntegerOverflow,
    ExpectingBool,
    MessageNotInitialized,
}

impl From<TokenizerError> for ParseError {
    fn from(e: TokenizerError) -> Self {
        ParseError::TokenizerError(e)
    }
}

impl From<StrLitDecodeError> for ParseError {
    fn from(e: StrLitDecodeError) -> Self {
        ParseError::StrLitDecodeError(e)
    }
}

impl From<int::Overflow> for ParseError {
    fn from(_: int::Overflow) -> Self {
        ParseError::IntegerOverflow
    }
}

#[derive(Debug)]
pub struct ParseErrorWithLoc {
    error: ParseError,
    loc: Loc,
}

impl fmt::Display for ParseErrorWithLoc {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}: {:?}", self.loc, self.error)
    }
}

impl std::error::Error for ParseErrorWithLoc {}

pub type ParseResult<A> = Result<A, ParseError>;
pub type ParseWithLocResult<A> = Result<A, ParseErrorWithLoc>;

#[derive(Clone)]
struct Parser<'a> {
    tokenizer: Tokenizer<'a>,
}

impl<'a> Parser<'a> {
    // Text format

    fn next_field_name(&mut self) -> ParseResult<String> {
        Ok(self.tokenizer.next_ident()?)
    }

    fn read_colon(&mut self) -> ParseResult<()> {
        Ok(self.tokenizer.next_symbol_expect_eq(':')?)
    }

    fn read_enum<'e>(&mut self, e: &'e EnumDescriptor) -> ParseResult<&'e EnumValueDescriptor> {
        self.read_colon()?;

        // TODO: read integer?
        let ident = self.tokenizer.next_ident()?;
        let value = match e.get_value_by_name(&ident) {
            Some(value) => value,
            None => return Err(ParseError::UnknownEnumValue(ident)),
        };
        Ok(value)
    }

    fn read_u64(&mut self) -> ParseResult<u64> {
        self.read_colon()?;

        Ok(self.tokenizer.next_int_lit()?)
    }

    fn read_u32(&mut self) -> ParseResult<u32> {
        self.read_colon()?;

        let int_lit = self.tokenizer.next_int_lit()?;
        let value_u32 = int_lit as u32;
        if value_u32 as u64 != int_lit {
            return Err(ParseError::IntegerOverflow);
        }
        Ok(value_u32)
    }

    fn read_i64(&mut self) -> ParseResult<i64> {
        self.read_colon()?;

        if self.tokenizer.next_symbol_if_eq('-')? {
            let int_lit = self.tokenizer.next_int_lit()?;
            Ok(int::neg(int_lit)?)
        } else {
            let int_lit = self.tokenizer.next_int_lit()?;
            if int_lit > i64::max_value() as u64 {
                return Err(ParseError::IntegerOverflow);
            }
            Ok(int_lit as i64)
        }
    }

    fn read_i32(&mut self) -> ParseResult<i32> {
        let value = self.read_i64()?;
        if value < i32::min_value() as i64 || value > i32::max_value() as i64 {
            return Err(ParseError::IntegerOverflow);
        }
        Ok(value as i32)
    }

    fn read_f64(&mut self) -> ParseResult<f64> {
        self.read_colon()?;

        let minus = self.tokenizer.next_symbol_if_eq('-')?;

        let value = if let Ok(value) = self.tokenizer.next_int_lit() {
            value as f64
        } else {
            self.tokenizer.next_float_lit()?
        };

        Ok(if minus { -value } else { value })
    }

    fn read_f32(&mut self) -> ParseResult<f32> {
        Ok(self.read_f64()? as f32)
    }

    fn read_bool(&mut self) -> ParseResult<bool> {
        self.read_colon()?;

        if self.tokenizer.next_ident_if_eq("true")? {
            Ok(true)
        } else if self.tokenizer.next_ident_if_eq("false")? {
            Ok(false)
        } else {
            Err(ParseError::ExpectingBool)
        }
    }

    fn read_string(&mut self) -> ParseResult<String> {
        self.read_colon()?;

        Ok(self
            .tokenizer
            .next_str_lit()
            .and_then(|s| s.decode_utf8().map_err(From::from))?)
    }

    fn read_bytes(&mut self) -> ParseResult<Vec<u8>> {
        self.read_colon()?;

        Ok(self
            .tokenizer
            .next_str_lit()
            .and_then(|s| s.decode_bytes().map_err(From::from))?)
    }

    fn read_message(
        &mut self,
        descriptor: &'static MessageDescriptor,
    ) -> ParseResult<Box<dyn Message>> {
        let mut message = descriptor.new_instance();

        let symbol = self.tokenizer.next_symbol_expect_eq_oneof(&['{', '<'])?;
        let terminator = if symbol == '{' { '}' } else { '>' };
        while !self.tokenizer.lookahead_is_symbol(terminator)? {
            self.merge_field(&mut *message, descriptor)?;
        }
        self.tokenizer.next_symbol_expect_eq(terminator)?;
        Ok(message)
    }

    fn read_map_entry(
        &mut self,
        k: &dyn RuntimeTypeDynamic,
        v: &dyn RuntimeTypeDynamic,
    ) -> ParseResult<(ReflectValueBox, ReflectValueBox)> {
        let key_field_name: &str = "key";
        let value_field_name: &str = "value";

        let mut key = None;
        let mut value = None;
        self.tokenizer.next_symbol_expect_eq('{')?;
        while !self.tokenizer.lookahead_is_symbol('}')? {
            let ident = self.next_field_name()?;
            let (field, field_type) = if ident == key_field_name {
                (&mut key, k)
            } else if ident == value_field_name {
                (&mut value, v)
            } else {
                return Err(ParseError::UnknownField(ident));
            };

            if let Some(..) = *field {
                return Err(ParseError::MapFieldIsSpecifiedMoreThanOnce(ident));
            }

            let field_value = self.read_value_of_type(field_type)?;

            *field = Some(field_value);
        }
        self.tokenizer.next_symbol_expect_eq('}')?;
        let key = match key {
            Some(key) => key,
            None => k.default_value_ref().to_box(),
        };
        let value = match value {
            Some(value) => value,
            None => v.default_value_ref().to_box(),
        };
        Ok((key, value))
    }

    fn read_value_of_type(&mut self, t: &dyn RuntimeTypeDynamic) -> ParseResult<ReflectValueBox> {
        Ok(match t.to_box() {
            RuntimeTypeBox::Enum(d) => ReflectValueBox::Enum(d, self.read_enum(d)?.value()),
            RuntimeTypeBox::U32 => ReflectValueBox::U32(self.read_u32()?),
            RuntimeTypeBox::U64 => ReflectValueBox::U64(self.read_u64()?),
            RuntimeTypeBox::I32 => ReflectValueBox::I32(self.read_i32()?),
            RuntimeTypeBox::I64 => ReflectValueBox::I64(self.read_i64()?),
            RuntimeTypeBox::F32 => ReflectValueBox::F32(self.read_f32()?),
            RuntimeTypeBox::F64 => ReflectValueBox::F64(self.read_f64()?),
            RuntimeTypeBox::Bool => ReflectValueBox::Bool(self.read_bool()?),
            RuntimeTypeBox::String | RuntimeTypeBox::Chars => {
                ReflectValueBox::String(self.read_string()?)
            }
            RuntimeTypeBox::VecU8 | RuntimeTypeBox::CarllercheBytes => {
                ReflectValueBox::Bytes(self.read_bytes()?)
            }
            RuntimeTypeBox::Message(m) => ReflectValueBox::Message(self.read_message(m)?),
        })
    }

    fn merge_field(
        &mut self,
        message: &mut dyn Message,
        descriptor: &MessageDescriptor,
    ) -> ParseResult<()> {
        let field_name = self.next_field_name()?;

        let field = match descriptor.get_field_by_name(&field_name) {
            Some(field) => field,
            None => {
                // TODO: shouldn't unknown fields be quietly skipped?
                return Err(ParseError::UnknownField(field_name));
            }
        };

        match field.runtime_field_type() {
            RuntimeFieldType::Singular(t) => {
                let value = self.read_value_of_type(t)?;
                field.set_singular_field(message, value);
            }
            RuntimeFieldType::Repeated(t) => {
                let value = self.read_value_of_type(t)?;
                field.mut_repeated(message).push(value);
            }
            RuntimeFieldType::Map(k, v) => {
                let (k, v) = self.read_map_entry(k, v)?;
                field.mut_map(message).insert(k, v);
            }
        };

        Ok(())
    }

    fn merge_inner(&mut self, message: &mut dyn Message) -> ParseResult<()> {
        loop {
            if self.tokenizer.syntax_eof()? {
                break;
            }
            let descriptor = message.descriptor();
            self.merge_field(message, descriptor)?;
        }
        Ok(())
    }

    fn merge(&mut self, message: &mut dyn Message) -> ParseWithLocResult<()> {
        match self.merge_inner(message) {
            Ok(()) => Ok(()),
            Err(error) => Err(ParseErrorWithLoc {
                error,
                loc: self.tokenizer.loc(),
            }),
        }
    }
}

/// Parse text format message.
///
/// This function does not check if message required fields are set.
pub fn merge_from_str(message: &mut dyn Message, input: &str) -> ParseWithLocResult<()> {
    let mut parser = Parser {
        tokenizer: Tokenizer::new(input, ParserLanguage::TextFormat),
    };
    parser.merge(message)
}

/// Parse text format message.
pub fn parse_from_str<M: Message>(input: &str) -> ParseWithLocResult<M> {
    let mut m = M::new();
    merge_from_str(&mut m, input)?;
    if let Err(_) = m.check_initialized() {
        return Err(ParseErrorWithLoc {
            error: ParseError::MessageNotInitialized,
            loc: Loc::start(),
        });
    }
    Ok(m)
}
<commit_msg>Rename text_format::ParseError<commit_after>use std::fmt;
use std::str;

use crate::core::Message;

use crate::reflect::EnumDescriptor;
use crate::reflect::EnumValueDescriptor;
use crate::reflect::MessageDescriptor;
use crate::reflect::ReflectValueBox;
use crate::reflect::RuntimeFieldType;
use crate::reflect::RuntimeTypeBox;
use crate::reflect::RuntimeTypeDynamic;
use crate::text_format::lexer::int;
use crate::text_format::lexer::Loc;
use crate::text_format::lexer::ParserLanguage;
use crate::text_format::lexer::StrLitDecodeError;
use crate::text_format::lexer::Tokenizer;
use crate::text_format::lexer::TokenizerError;

#[derive(Debug)]
pub enum ParseErrorWithoutLoc {
    TokenizerError(TokenizerError),
    StrLitDecodeError(StrLitDecodeError),
    UnknownField(String),
    UnknownEnumValue(String),
    MapFieldIsSpecifiedMoreThanOnce(String),
    IntegerOverflow,
    ExpectingBool,
    MessageNotInitialized,
}

impl From<TokenizerError> for ParseErrorWithoutLoc {
    fn from(e: TokenizerError) -> Self {
        ParseErrorWithoutLoc::TokenizerError(e)
    }
}

impl From<StrLitDecodeError> for ParseErrorWithoutLoc {
    fn from(e: StrLitDecodeError) -> Self {
        ParseErrorWithoutLoc::StrLitDecodeError(e)
    }
}

impl From<int::Overflow> for ParseErrorWithoutLoc {
    fn from(_: int::Overflow) -> Self {
        ParseErrorWithoutLoc::IntegerOverflow
    }
}

#[derive(Debug)]
pub struct ParseError {
    error: ParseErrorWithoutLoc,
    loc: Loc,
}

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}: {:?}", self.loc, self.error)
    }
}

impl std::error::Error for ParseError {}

pub type ParseResult<A> = Result<A, ParseErrorWithoutLoc>;
pub type ParseWithLocResult<A> = Result<A, ParseError>;

#[derive(Clone)]
struct Parser<'a> {
    tokenizer: Tokenizer<'a>,
}

impl<'a> Parser<'a> {
    // Text format

    fn next_field_name(&mut self) -> ParseResult<String> {
        Ok(self.tokenizer.next_ident()?)
    }

    fn read_colon(&mut self) -> ParseResult<()> {
        Ok(self.tokenizer.next_symbol_expect_eq(':')?)
    }

    fn read_enum<'e>(&mut self, e: &'e EnumDescriptor) -> ParseResult<&'e EnumValueDescriptor> {
        self.read_colon()?;

        // TODO: read integer?
        let ident = self.tokenizer.next_ident()?;
        let value = match e.get_value_by_name(&ident) {
            Some(value) => value,
            None => return Err(ParseErrorWithoutLoc::UnknownEnumValue(ident)),
        };
        Ok(value)
    }

    fn read_u64(&mut self) -> ParseResult<u64> {
        self.read_colon()?;

        Ok(self.tokenizer.next_int_lit()?)
    }

    fn read_u32(&mut self) -> ParseResult<u32> {
        self.read_colon()?;

        let int_lit = self.tokenizer.next_int_lit()?;
        let value_u32 = int_lit as u32;
        if value_u32 as u64 != int_lit {
            return Err(ParseErrorWithoutLoc::IntegerOverflow);
        }
        Ok(value_u32)
    }

    fn read_i64(&mut self) -> ParseResult<i64> {
        self.read_colon()?;

        if self.tokenizer.next_symbol_if_eq('-')? {
            let int_lit = self.tokenizer.next_int_lit()?;
            Ok(int::neg(int_lit)?)
        } else {
            let int_lit = self.tokenizer.next_int_lit()?;
            if int_lit > i64::max_value() as u64 {
                return Err(ParseErrorWithoutLoc::IntegerOverflow);
            }
            Ok(int_lit as i64)
        }
    }

    fn read_i32(&mut self) -> ParseResult<i32> {
        let value = self.read_i64()?;
        if value < i32::min_value() as i64 || value > i32::max_value() as i64 {
            return Err(ParseErrorWithoutLoc::IntegerOverflow);
        }
        Ok(value as i32)
    }

    fn read_f64(&mut self) -> ParseResult<f64> {
        self.read_colon()?;

        let minus = self.tokenizer.next_symbol_if_eq('-')?;

        let value = if let Ok(value) = self.tokenizer.next_int_lit() {
            value as f64
        } else {
            self.tokenizer.next_float_lit()?
        };

        Ok(if minus { -value } else { value })
    }

    fn read_f32(&mut self) -> ParseResult<f32> {
        Ok(self.read_f64()? as f32)
    }

    fn read_bool(&mut self) -> ParseResult<bool> {
        self.read_colon()?;

        if self.tokenizer.next_ident_if_eq("true")? {
            Ok(true)
        } else if self.tokenizer.next_ident_if_eq("false")? {
            Ok(false)
        } else {
            Err(ParseErrorWithoutLoc::ExpectingBool)
        }
    }

    fn read_string(&mut self) -> ParseResult<String> {
        self.read_colon()?;

        Ok(self
            .tokenizer
            .next_str_lit()
            .and_then(|s| s.decode_utf8().map_err(From::from))?)
    }

    fn read_bytes(&mut self) -> ParseResult<Vec<u8>> {
        self.read_colon()?;

        Ok(self
            .tokenizer
            .next_str_lit()
            .and_then(|s| s.decode_bytes().map_err(From::from))?)
    }

    fn read_message(
        &mut self,
        descriptor: &'static MessageDescriptor,
    ) -> ParseResult<Box<dyn Message>> {
        let mut message = descriptor.new_instance();

        let symbol = self.tokenizer.next_symbol_expect_eq_oneof(&['{', '<'])?;
        let terminator = if symbol == '{' { '}' } else { '>' };
        while !self.tokenizer.lookahead_is_symbol(terminator)? {
            self.merge_field(&mut *message, descriptor)?;
        }
        self.tokenizer.next_symbol_expect_eq(terminator)?;
        Ok(message)
    }

    fn read_map_entry(
        &mut self,
        k: &dyn RuntimeTypeDynamic,
        v: &dyn RuntimeTypeDynamic,
    ) -> ParseResult<(ReflectValueBox, ReflectValueBox)> {
        let key_field_name: &str = "key";
        let value_field_name: &str = "value";

        let mut key = None;
        let mut value = None;
        self.tokenizer.next_symbol_expect_eq('{')?;
        while !self.tokenizer.lookahead_is_symbol('}')? {
            let ident = self.next_field_name()?;
            let (field, field_type) = if ident == key_field_name {
                (&mut key, k)
            } else if ident == value_field_name {
                (&mut value, v)
            } else {
                return Err(ParseErrorWithoutLoc::UnknownField(ident));
            };

            if let Some(..) = *field {
                return Err(ParseErrorWithoutLoc::MapFieldIsSpecifiedMoreThanOnce(ident));
            }

            let field_value = self.read_value_of_type(field_type)?;

            *field = Some(field_value);
        }
        self.tokenizer.next_symbol_expect_eq('}')?;
        let key = match key {
            Some(key) => key,
            None => k.default_value_ref().to_box(),
        };
        let value = match value {
            Some(value) => value,
            None => v.default_value_ref().to_box(),
        };
        Ok((key, value))
    }

    fn read_value_of_type(&mut self, t: &dyn RuntimeTypeDynamic) -> ParseResult<ReflectValueBox> {
        Ok(match t.to_box() {
            RuntimeTypeBox::Enum(d) => ReflectValueBox::Enum(d, self.read_enum(d)?.value()),
            RuntimeTypeBox::U32 => ReflectValueBox::U32(self.read_u32()?),
            RuntimeTypeBox::U64 => ReflectValueBox::U64(self.read_u64()?),
            RuntimeTypeBox::I32 => ReflectValueBox::I32(self.read_i32()?),
            RuntimeTypeBox::I64 => ReflectValueBox::I64(self.read_i64()?),
            RuntimeTypeBox::F32 => ReflectValueBox::F32(self.read_f32()?),
            RuntimeTypeBox::F64 => ReflectValueBox::F64(self.read_f64()?),
            RuntimeTypeBox::Bool => ReflectValueBox::Bool(self.read_bool()?),
            RuntimeTypeBox::String | RuntimeTypeBox::Chars => {
                ReflectValueBox::String(self.read_string()?)
            }
            RuntimeTypeBox::VecU8 | RuntimeTypeBox::CarllercheBytes => {
                ReflectValueBox::Bytes(self.read_bytes()?)
            }
            RuntimeTypeBox::Message(m) => ReflectValueBox::Message(self.read_message(m)?),
        })
    }

    fn merge_field(
        &mut self,
        message: &mut dyn Message,
        descriptor: &MessageDescriptor,
    ) -> ParseResult<()> {
        let field_name = self.next_field_name()?;

        let field = match descriptor.get_field_by_name(&field_name) {
            Some(field) => field,
            None => {
                // TODO: shouldn't unknown fields be quietly skipped?
                return Err(ParseErrorWithoutLoc::UnknownField(field_name));
            }
        };

        match field.runtime_field_type() {
            RuntimeFieldType::Singular(t) => {
                let value = self.read_value_of_type(t)?;
                field.set_singular_field(message, value);
            }
            RuntimeFieldType::Repeated(t) => {
                let value = self.read_value_of_type(t)?;
                field.mut_repeated(message).push(value);
            }
            RuntimeFieldType::Map(k, v) => {
                let (k, v) = self.read_map_entry(k, v)?;
                field.mut_map(message).insert(k, v);
            }
        };

        Ok(())
    }

    fn merge_inner(&mut self, message: &mut dyn Message) -> ParseResult<()> {
        loop {
            if self.tokenizer.syntax_eof()? {
                break;
            }
            let descriptor = message.descriptor();
            self.merge_field(message, descriptor)?;
        }
        Ok(())
    }

    fn merge(&mut self, message: &mut dyn Message) -> ParseWithLocResult<()> {
        match self.merge_inner(message) {
            Ok(()) => Ok(()),
            Err(error) => Err(ParseError {
                error,
                loc: self.tokenizer.loc(),
            }),
        }
    }
}

/// Parse text format message.
///
/// This function does not check if message required fields are set.
pub fn merge_from_str(message: &mut dyn Message, input: &str) -> ParseWithLocResult<()> {
    let mut parser = Parser {
        tokenizer: Tokenizer::new(input, ParserLanguage::TextFormat),
    };
    parser.merge(message)
}

/// Parse text format message.
pub fn parse_from_str<M: Message>(input: &str) -> ParseWithLocResult<M> {
    let mut m = M::new();
    merge_from_str(&mut m, input)?;
    if let Err(_) = m.check_initialized() {
        return Err(ParseError {
            error: ParseErrorWithoutLoc::MessageNotInitialized,
            loc: Loc::start(),
        });
    }
    Ok(m)
}
<|endoftext|>


<commit_before>use std::io::{self, Read, Write};

use futures::{Future, Poll};

/// A future which will copy all data from a reader into a writer.
///
/// Created by the [`copy`] function, this future will resolve to the number of
/// bytes copied or an error if one happens.
///
/// [`copy`]: fn.copy.html
pub struct Copy<R, W> {
    reader: R,
    read_done: bool,
    writer: W,
    pos: usize,
    cap: usize,
    amt: u64,
    buf: Box<[u8]>,
}

/// Creates a future which represents copying all the bytes from one object to
/// another.
///
/// The returned future will copy all the bytes read from `reader` into the
/// `writer` specified. This future will only complete once the `reader` has hit
/// EOF and all bytes have been written to and flushed from the `writer`
/// provided.
///
/// On success the number of bytes is returned and the `reader` and `writer` are
/// consumed. On error the error is returned and the I/O objects are consumed as
/// well.
pub fn copy<R, W>(reader: R, writer: W) -> Copy<R, W>
    where R: Read,
          W: Write,
{
    Copy {
        reader: reader,
        read_done: false,
        writer: writer,
        amt: 0,
        pos: 0,
        cap: 0,
        buf: Box::new([0; 2048]),
    }
}

impl<R, W> Future for Copy<R, W>
    where R: Read,
          W: Write,
{
    type Item = u64;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<u64, io::Error> {
        loop {
            // If our buffer is empty, then we need to read some data to
            // continue.
            if self.pos == self.cap && !self.read_done {
                let n = try_nb!(self.reader.read(&mut self.buf));
                if n == 0 {
                    self.read_done = true;
                } else {
                    self.pos = 0;
                    self.cap = n;
                }
            }

            // If our buffer has some data, let's write it out!
            while self.pos < self.cap {
                let i = try_nb!(self.writer.write(&self.buf[self.pos..self.cap]));
                self.pos += i;
                self.amt += i as u64;
            }

            // If we've written al the data and we've seen EOF, flush out the
            // data and finish the transfer.
            // done with the entire transfer.
            if self.pos == self.cap && self.read_done {
                try_nb!(self.writer.flush());
                return Ok(self.amt.into())
            }
        }
    }
}
<commit_msg>Fix typo in non-doc comment in copy.rs<commit_after>use std::io::{self, Read, Write};

use futures::{Future, Poll};

/// A future which will copy all data from a reader into a writer.
///
/// Created by the [`copy`] function, this future will resolve to the number of
/// bytes copied or an error if one happens.
///
/// [`copy`]: fn.copy.html
pub struct Copy<R, W> {
    reader: R,
    read_done: bool,
    writer: W,
    pos: usize,
    cap: usize,
    amt: u64,
    buf: Box<[u8]>,
}

/// Creates a future which represents copying all the bytes from one object to
/// another.
///
/// The returned future will copy all the bytes read from `reader` into the
/// `writer` specified. This future will only complete once the `reader` has hit
/// EOF and all bytes have been written to and flushed from the `writer`
/// provided.
///
/// On success the number of bytes is returned and the `reader` and `writer` are
/// consumed. On error the error is returned and the I/O objects are consumed as
/// well.
pub fn copy<R, W>(reader: R, writer: W) -> Copy<R, W>
    where R: Read,
          W: Write,
{
    Copy {
        reader: reader,
        read_done: false,
        writer: writer,
        amt: 0,
        pos: 0,
        cap: 0,
        buf: Box::new([0; 2048]),
    }
}

impl<R, W> Future for Copy<R, W>
    where R: Read,
          W: Write,
{
    type Item = u64;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<u64, io::Error> {
        loop {
            // If our buffer is empty, then we need to read some data to
            // continue.
            if self.pos == self.cap && !self.read_done {
                let n = try_nb!(self.reader.read(&mut self.buf));
                if n == 0 {
                    self.read_done = true;
                } else {
                    self.pos = 0;
                    self.cap = n;
                }
            }

            // If our buffer has some data, let's write it out!
            while self.pos < self.cap {
                let i = try_nb!(self.writer.write(&self.buf[self.pos..self.cap]));
                self.pos += i;
                self.amt += i as u64;
            }

            // If we've written all the data and we've seen EOF, flush out the
            // data and finish the transfer.
            // done with the entire transfer.
            if self.pos == self.cap && self.read_done {
                try_nb!(self.writer.flush());
                return Ok(self.amt.into())
            }
        }
    }
}
<|endoftext|>


<commit_before>mod partially_persistent_nonindexed_set {
  use std::sync::{Arc};
  use std::sync::atomic::{AtomicBool, Ordering};
  use std::cmp::min;
  use std::collections::HashSet;
  use std::hash::Hash;
  use std::mem;
  use std::cell::{UnsafeCell};
  use std::marker;use std::fmt::Debug;
use std::io::Write;
macro_rules! printlnerr(
    ($($arg:tt)*) => { {
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

  #[derive (Clone, Debug)]
  struct Entry <K: Clone + Eq> {
    key: K,
    insertion: bool,
  }
  //using Vec< in this buffer type has unnecessary indirection, but I was unable to find
  //a library that does the job safely without it.
  //Compare Arc<[Entry<K>]>, which could behave unsafely if I
  //didn't initialize it, but would waste time if I did.
  #[derive (Debug)]
  struct BufferInner <K: Clone + Eq> {
    data: Vec<Entry <K>>,
    marker: AtomicBool,
  }
  #[derive (Clone, Debug)]
  struct Buffer <K: Clone + Eq> {
    data: Arc <UnsafeCell <BufferInner <K> >>,
    deletions: usize,
  }

  #[derive (Debug)]
  pub struct Snapshot <K: Clone + Eq> {
    buffer: Buffer <K>,
    used_length: usize,
  }
  #[derive (Debug)]
  pub struct SnapshotIter <'a, K: Clone + Eq + Hash + 'a> {
    snapshot: & 'a Snapshot <K>,
    position: usize,
    ignore: HashSet <K>,
  }

  #[derive (Debug)]
  pub struct Set <K: Clone + Eq> {
    live_buffer: Buffer <K>,
    next_buffer: Buffer <K>,
    next_transfer_index: usize,
    potential_next_buffer_usage: usize,
    operating: bool,
  }
  unsafe impl<K: Clone + Eq + Sync> Send for Snapshot <K>{}
  unsafe impl<K: Clone + Eq + Sync> Sync for Snapshot <K>{}
  impl<K: Clone + Eq + Hash> Snapshot <K> {
    pub fn iter <'a> (& 'a self)->SnapshotIter <'a, K> {
      //this Acquire should sync with at least the Release performed just after the
      //last insertion into this buffer.
      //To make sure we only need to do this once, at the beginning of iteration,
      //we deliberately unimplemented Send for the iterator type
      unsafe {(*self.buffer.data.get()).marker.load (Ordering::Acquire)};

      SnapshotIter {
        snapshot: self,
        position: self.used_length,
        ignore: HashSet::with_capacity(self.buffer.deletions),
      }
    }
  }
  impl<'a, K> !marker::Send for SnapshotIter <'a, K> {}
  impl<'a, K: Clone + Eq + Hash> SnapshotIter <'a, K> {
    /// Do a single iteration step, which MAY return an iteration result,
    /// and is guaranteed to finish in O(1) time (worst-case except for bad luck with hashing).
    pub fn step (&mut self)->Option <Option <K>> {
      if self.position == 0 {return Some (None);}
      self.position -= 1;
      let entry = unsafe {& (*self.snapshot.buffer.data.get()).data [self.position]};
      if entry.insertion == false {
        self.ignore.insert (entry.key.clone());
      }
      else if !self.ignore.contains (& entry.key) {
        return Some (Some (entry.key.clone()));
      }
      None
    }
  }
  impl<'a, K: Clone + Eq + Hash > Iterator for SnapshotIter <'a, K> {
    type Item = K;
    fn next (&mut self)->Option <K> {
      loop {
        if let Some (result) = self.step() {return result;}
      }
    }
  }
  impl<K: Clone + Eq + Debug> Set <K> {
    pub fn new()->Set <K> {
      Set {
        live_buffer: Buffer {data: Arc::new (UnsafeCell::new (BufferInner {data: Vec::new (), marker: AtomicBool::new(false)})), deletions: 0},
        next_buffer: Buffer {data: Arc::new (UnsafeCell::new (BufferInner {data: Vec:: with_capacity(2), marker: AtomicBool::new(false)})), deletions: 0},
        next_transfer_index: 0,
        potential_next_buffer_usage: 0,
        operating: false,
      }
    }
    /// Adds a value to the set.
    ///
    /// Complexity: O(1) worst-case if K does not implement Drop, O(1) amortized otherwise.
    pub fn insert <F: Fn (& K)->bool> (&mut self, key: K, currently_existent: & F) {
      assert!(!self.operating, "Attempt to call PartiallyPersistentNonindexedSet::insert() from inside its own existence checker callback; what ghastly code led to this situation?");
      self.operating = true;
      self.make_room (currently_existent);
      let live_data = unsafe {self.live_buffer.data.get().as_mut().unwrap()};
      live_data.data.push (Entry {key: key, insertion: true});
      self.potential_next_buffer_usage += 1;
      live_data.marker.store (false, Ordering::Release);
      self.operating = false;
    }
    /// Removes a value from the set.
    ///
    /// Complexity: O(1) worst-case if K does not implement Drop, O(1) amortized otherwise.
    pub fn remove <F: Fn (& K)->bool> (&mut self, key: K, currently_existent: & F) {
      assert!(!self.operating, "Attempt to call PartiallyPersistentNonindexedSet::insert() from inside its own existence checker callback; what ghastly code led to this situation?");
      self.operating = true;
      self.make_room (currently_existent);
      let live_data = unsafe {self.live_buffer.data.get().as_mut().unwrap()};
      let next_data = unsafe {self.next_buffer.data.get().as_mut().unwrap()};
      self.live_buffer.deletions += 1;
      live_data.data.push (Entry {key: key.clone(), insertion: false});
      // the next buffer doesn't necessarily have an insertion
      // corresponding to this deletion, so this could be wasteful. However,
      // it would also be wasteful to look up whether the insertion is there
      // (we currently get away with not even being ABLE to do so)
      self.next_buffer.deletions += 1;
      next_data.data.push (Entry {key: key, insertion: false});
      self.potential_next_buffer_usage += 1;
      live_data.marker.store (false, Ordering::Release);
      self.operating = false;
    }
    /// Takes out a snapshot to the current state of the set.
    ///
    /// These snapshots can safely be passed to other threads
    /// even as you continue to modify the set.
    ///
    /// Complexity: O(1) worst-case if K does not implement Drop, O(1) amortized otherwise.
    pub fn snapshot (&self)->Snapshot <K> {
      Snapshot {buffer: self.live_buffer.clone(), used_length: unsafe {(*self.live_buffer.data.get()).data.len()}}
    }

    //After let ops = operations_before_reset_possibly_needed operations, there may be in next buffer: current live insertions - current legit live deletions - ops insertions, and current next deletions + ops deletions. We want deletions/insertions <= 1/6 on reset, so…
    //(Next deletions + ops)/(live insertions - legit deletions - ops) <= 1/6
    //next deletions + ops <= (live insertions - legit deletions - ops)/3
    //6 (next deletions + ops) <= live insertions - legit deletions - ops
    //7 ops <= live insertions - legit deletions - 6 next deletions
    //it's okay to overestimate legit deletions, resulting in the following more strict condition on ops:
    //7 ops <= live insertions - live deletions - 6 next deletions
    //ops <= ((live insertions - live deletions - 6 next deletions)/7)
    //ops <= ((live insertions - live deletions - 6 next deletions)/7).floor()
    //But actually we have to tolerate one extra deletion to deal with
    //the case where a deletion is added immediately after a reset.
    //After reset + deletion, new ops could be forced as low as
    //new ops <= (((live insertions - legit deletions - ops) - ops - 7)/7).floor()
    //we also need to obey the condition
    //(new ops + 1)*X >= ((live insertions - legit deletions) + ops + new ops)
    //(new ops)*(X+1) + X >= ((live insertions - legit deletions) + ops)
    //new ops >= ((live insertions - legit deletions) + ops - X)/(X+1)
    //(((live insertions - legit deletions - ops) - ops - 7)/7 >= ((live insertions - legit deletions) + ops - X)/(X+1)
    //(((live insertions - legit deletions - ops) - ops - 7)*(X+1) >= ((live insertions - legit deletions) + ops - X)*7
    //(live insertions - legit deletions)*(X + 1 - 7) + (7)*(X+1) >= ops*(7 + 2X + 2) - X*7
    //(live insertions - legit deletions)*(X + 1 - 7) + 7 >= ops*(7 + 2X + 2)

    //(live insertions - legit deletions - 2*ops)*(X) >= ops*(9) + (live insertions - legit deletions)*6 - 7
    //X >= (ops*(9) + (live insertions - legit deletions)*6 - 7)/(live insertions - legit deletions - 2*ops)
    //and ops can be up to 1/7 of that insertion count, so
    //X >= (Z*(9/7) + Z*6 - 7)/(Z - 2*Z/7)
    //X >= (Z*(51/7) - 7)/(5*Z/7)
    //X >= (Z*(51) - 49)/(5*Z)
    //X >= 51/5 >10
    fn make_room <F: Fn (& K)->bool> (&mut self, currently_existent: F) {
  const MAX_TRANSFER_SPEED: usize = 11;
      unsafe {assert!((*self.next_buffer.data.get()).data.len() <= self.potential_next_buffer_usage)};
      let live_data = unsafe {self.live_buffer.data.get().as_ref().unwrap()};
      let next_data = unsafe {self.next_buffer.data.get().as_mut().unwrap()};
      //printlnerr!("starting {:?} \n LIFE: {:?}\n NEXT: {:?}\n CAPACITIES: {} {} DELETIONS: {}/{} {}/{} ", self, live_data, next_data, live_data.data.capacity(), next_data.data.capacity(), self.live_buffer.deletions, live_data.data.len(), self.next_buffer.deletions, next_data.data.len());
      let buffer_pushes_before_reset_needed = min (
        live_data.data.capacity() - live_data.data.len(),
        next_data.data.capacity()/2 - self.potential_next_buffer_usage,
      );
      let current_insertions = live_data.data.len() - self.live_buffer.deletions;
      //let tolerable_deletions = (current_insertions*5)/12;
      //let deletions_before_reset_needed = tolerable_deletions - self.live_buffer.deletions;
      let deletions_before_reset_needed = (current_insertions + 7 - self.live_buffer.deletions - 6*self.next_buffer.deletions)/7;
      let operations_before_reset_possibly_needed = min (buffer_pushes_before_reset_needed, deletions_before_reset_needed);
      assert!(self.next_transfer_index <= live_data.data.len() );
      let transfer_steps_needed_before_reset_possible = live_data.data.len() + operations_before_reset_possibly_needed - self.next_transfer_index;
      //printlnerr!("NEEDED {:?} \n OPERATIONS: {:?}\n (buffer pushes): {:?}\n (deletions): {} {} ", transfer_steps_needed_before_reset_possible , operations_before_reset_possibly_needed , buffer_pushes_before_reset_needed , deletions_before_reset_needed , "something");
      assert!(transfer_steps_needed_before_reset_possible <= (operations_before_reset_possibly_needed + 1) * MAX_TRANSFER_SPEED);
      if transfer_steps_needed_before_reset_possible >operations_before_reset_possibly_needed * MAX_TRANSFER_SPEED {
        for _ in 0..MAX_TRANSFER_SPEED {
          if let Some (entry) = live_data.data.get (self.next_transfer_index) {
            if entry.insertion && currently_existent (& entry.key) {
              next_data.data.push ((*entry).clone());
            }
            self.next_transfer_index += 1;
          }
          else {break;}
        }
      }
      //printlnerr!("ending {:?} \n LIFE: {:?}\n NEXT: {:?}\n CAPACITIES: {} {} ", self, live_data, next_data, live_data.data.capacity(), next_data.data.capacity());
      if operations_before_reset_possibly_needed == 0 {
        self.next_transfer_index = 0;
        self.potential_next_buffer_usage = next_data.data.len() - self.next_buffer.deletions;
        mem::swap (&mut self.live_buffer, &mut self.next_buffer);
        //danger: after we overwrite self.next_buffer, we may have deallocated
        //the memory for live_data
        self.next_buffer = Buffer {
          data: Arc::new (UnsafeCell::new (BufferInner {data: Vec::with_capacity ((self.potential_next_buffer_usage + 1)*4), marker: AtomicBool::new(false)})), deletions: 0,
        };
      }
      //printlnerr!("ending {:?}", self);
      unsafe {
        assert!((*self.live_buffer.data.get()).data.len() < (*self.live_buffer.data.get()).data.capacity());
        assert!((*self.next_buffer.data.get()).data.len() <= self.potential_next_buffer_usage);
        assert!(self.potential_next_buffer_usage < (*self.next_buffer.data.get()).data.capacity()/2);
      }
    }
  }
#[cfg (test)]
mod tests {
use super::*; use std::collections::HashSet;
  #[quickcheck]
  fn test_operation_sequence (operations: Vec<(usize, bool)>)->bool {
    let mut existences: HashSet <usize> = HashSet::new();
    let mut set: Set <usize> = Set::new();
    for operation in operations {
      if existences.contains(& operation.0) != operation.1 {
        if operation.1 {
          existences.insert (operation.0);
          set.insert (operation.0, & | value | existences.contains (value));
        } else {
          existences.remove (& operation. 0);
          set.remove (operation.0, & | value | existences.contains (value));
        }
        let checker = existences.clone();
        let snapshot = set.snapshot();
        use std::thread;
        if !thread::spawn ( move | | {
          let checker_2 = snapshot.iter().collect();
          checker == checker_2
        }).join().unwrap() {return false;}

      }
    }
    true
}
//#[test]
fn hack () {

//test_operation_sequence ((0..100).map (| number | (number, true)).collect());
}}
}
<commit_msg>Tests retain a thread instead of spawning a new one each cycle<commit_after>mod partially_persistent_nonindexed_set {
  use std::sync::{Arc};
  use std::sync::atomic::{AtomicBool, Ordering};
  use std::cmp::min;
  use std::collections::HashSet;
  use std::hash::Hash;
  use std::mem;
  use std::cell::{UnsafeCell};
  use std::marker;use std::fmt::Debug;
use std::io::Write;
macro_rules! printlnerr(
    ($($arg:tt)*) => { {
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

  #[derive (Clone, Debug)]
  struct Entry <K: Clone + Eq> {
    key: K,
    insertion: bool,
  }
  //using Vec< in this buffer type has unnecessary indirection, but I was unable to find
  //a library that does the job safely without it.
  //Compare Arc<[Entry<K>]>, which could behave unsafely if I
  //didn't initialize it, but would waste time if I did.
  #[derive (Debug)]
  struct BufferInner <K: Clone + Eq> {
    data: Vec<Entry <K>>,
    marker: AtomicBool,
  }
  #[derive (Clone, Debug)]
  struct Buffer <K: Clone + Eq> {
    data: Arc <UnsafeCell <BufferInner <K> >>,
    deletions: usize,
  }

  #[derive (Debug)]
  pub struct Snapshot <K: Clone + Eq> {
    buffer: Buffer <K>,
    used_length: usize,
  }
  #[derive (Debug)]
  pub struct SnapshotIter <'a, K: Clone + Eq + Hash + 'a> {
    snapshot: & 'a Snapshot <K>,
    position: usize,
    ignore: HashSet <K>,
  }

  #[derive (Debug)]
  pub struct Set <K: Clone + Eq> {
    live_buffer: Buffer <K>,
    next_buffer: Buffer <K>,
    next_transfer_index: usize,
    potential_next_buffer_usage: usize,
    operating: bool,
  }
  unsafe impl<K: Clone + Eq + Sync> Send for Snapshot <K>{}
  unsafe impl<K: Clone + Eq + Sync> Sync for Snapshot <K>{}
  impl<K: Clone + Eq + Hash> Snapshot <K> {
    pub fn iter <'a> (& 'a self)->SnapshotIter <'a, K> {
      //this Acquire should sync with at least the Release performed just after the
      //last insertion into this buffer.
      //To make sure we only need to do this once, at the beginning of iteration,
      //we deliberately unimplemented Send for the iterator type
      unsafe {(*self.buffer.data.get()).marker.load (Ordering::Acquire)};

      SnapshotIter {
        snapshot: self,
        position: self.used_length,
        ignore: HashSet::with_capacity(self.buffer.deletions),
      }
    }
  }
  impl<'a, K> !marker::Send for SnapshotIter <'a, K> {}
  impl<'a, K: Clone + Eq + Hash> SnapshotIter <'a, K> {
    /// Do a single iteration step, which MAY return an iteration result,
    /// and is guaranteed to finish in O(1) time (worst-case except for bad luck with hashing).
    pub fn step (&mut self)->Option <Option <K>> {
      if self.position == 0 {return Some (None);}
      self.position -= 1;
      let entry = unsafe {& (*self.snapshot.buffer.data.get()).data [self.position]};
      if entry.insertion == false {
        self.ignore.insert (entry.key.clone());
      }
      else if !self.ignore.contains (& entry.key) {
        return Some (Some (entry.key.clone()));
      }
      None
    }
  }
  impl<'a, K: Clone + Eq + Hash > Iterator for SnapshotIter <'a, K> {
    type Item = K;
    fn next (&mut self)->Option <K> {
      loop {
        if let Some (result) = self.step() {return result;}
      }
    }
  }
  impl<K: Clone + Eq + Debug> Set <K> {
    pub fn new()->Set <K> {
      Set {
        live_buffer: Buffer {data: Arc::new (UnsafeCell::new (BufferInner {data: Vec::new (), marker: AtomicBool::new(false)})), deletions: 0},
        next_buffer: Buffer {data: Arc::new (UnsafeCell::new (BufferInner {data: Vec:: with_capacity(2), marker: AtomicBool::new(false)})), deletions: 0},
        next_transfer_index: 0,
        potential_next_buffer_usage: 0,
        operating: false,
      }
    }
    /// Adds a value to the set.
    ///
    /// Complexity: O(1) worst-case if K does not implement Drop, O(1) amortized otherwise.
    pub fn insert <F: Fn (& K)->bool> (&mut self, key: K, currently_existent: & F) {
      assert!(!self.operating, "Attempt to call PartiallyPersistentNonindexedSet::insert() from inside its own existence checker callback; what ghastly code led to this situation?");
      self.operating = true;
      self.make_room (currently_existent);
      let live_data = unsafe {self.live_buffer.data.get().as_mut().unwrap()};
      live_data.data.push (Entry {key: key, insertion: true});
      self.potential_next_buffer_usage += 1;
      live_data.marker.store (false, Ordering::Release);
      self.operating = false;
    }
    /// Removes a value from the set.
    ///
    /// Complexity: O(1) worst-case if K does not implement Drop, O(1) amortized otherwise.
    pub fn remove <F: Fn (& K)->bool> (&mut self, key: K, currently_existent: & F) {
      assert!(!self.operating, "Attempt to call PartiallyPersistentNonindexedSet::insert() from inside its own existence checker callback; what ghastly code led to this situation?");
      self.operating = true;
      self.make_room (currently_existent);
      let live_data = unsafe {self.live_buffer.data.get().as_mut().unwrap()};
      let next_data = unsafe {self.next_buffer.data.get().as_mut().unwrap()};
      self.live_buffer.deletions += 1;
      live_data.data.push (Entry {key: key.clone(), insertion: false});
      // the next buffer doesn't necessarily have an insertion
      // corresponding to this deletion, so this could be wasteful. However,
      // it would also be wasteful to look up whether the insertion is there
      // (we currently get away with not even being ABLE to do so)
      self.next_buffer.deletions += 1;
      next_data.data.push (Entry {key: key, insertion: false});
      self.potential_next_buffer_usage += 1;
      live_data.marker.store (false, Ordering::Release);
      self.operating = false;
    }
    /// Takes out a snapshot to the current state of the set.
    ///
    /// These snapshots can safely be passed to other threads
    /// even as you continue to modify the set.
    ///
    /// Complexity: O(1) worst-case if K does not implement Drop, O(1) amortized otherwise.
    pub fn snapshot (&self)->Snapshot <K> {
      Snapshot {buffer: self.live_buffer.clone(), used_length: unsafe {(*self.live_buffer.data.get()).data.len()}}
    }

    //After let ops = operations_before_reset_possibly_needed operations, there may be in next buffer: current live insertions - current legit live deletions - ops insertions, and current next deletions + ops deletions. We want deletions/insertions <= 1/6 on reset, so…
    //(Next deletions + ops)/(live insertions - legit deletions - ops) <= 1/6
    //next deletions + ops <= (live insertions - legit deletions - ops)/3
    //6 (next deletions + ops) <= live insertions - legit deletions - ops
    //7 ops <= live insertions - legit deletions - 6 next deletions
    //it's okay to overestimate legit deletions, resulting in the following more strict condition on ops:
    //7 ops <= live insertions - live deletions - 6 next deletions
    //ops <= ((live insertions - live deletions - 6 next deletions)/7)
    //ops <= ((live insertions - live deletions - 6 next deletions)/7).floor()
    //But actually we have to tolerate one extra deletion to deal with
    //the case where a deletion is added immediately after a reset.
    //After reset + deletion, new ops could be forced as low as
    //new ops <= (((live insertions - legit deletions - ops) - ops - 7)/7).floor()
    //we also need to obey the condition
    //(new ops + 1)*X >= ((live insertions - legit deletions) + ops + new ops)
    //(new ops)*(X+1) + X >= ((live insertions - legit deletions) + ops)
    //new ops >= ((live insertions - legit deletions) + ops - X)/(X+1)
    //(((live insertions - legit deletions - ops) - ops - 7)/7 >= ((live insertions - legit deletions) + ops - X)/(X+1)
    //(((live insertions - legit deletions - ops) - ops - 7)*(X+1) >= ((live insertions - legit deletions) + ops - X)*7
    //(live insertions - legit deletions)*(X + 1 - 7) + (7)*(X+1) >= ops*(7 + 2X + 2) - X*7
    //(live insertions - legit deletions)*(X + 1 - 7) + 7 >= ops*(7 + 2X + 2)

    //(live insertions - legit deletions - 2*ops)*(X) >= ops*(9) + (live insertions - legit deletions)*6 - 7
    //X >= (ops*(9) + (live insertions - legit deletions)*6 - 7)/(live insertions - legit deletions - 2*ops)
    //and ops can be up to 1/7 of that insertion count, so
    //X >= (Z*(9/7) + Z*6 - 7)/(Z - 2*Z/7)
    //X >= (Z*(51/7) - 7)/(5*Z/7)
    //X >= (Z*(51) - 49)/(5*Z)
    //X >= 51/5 >10
    fn make_room <F: Fn (& K)->bool> (&mut self, currently_existent: F) {
  const MAX_TRANSFER_SPEED: usize = 11;
      unsafe {assert!((*self.next_buffer.data.get()).data.len() <= self.potential_next_buffer_usage)};
      let live_data = unsafe {self.live_buffer.data.get().as_ref().unwrap()};
      let next_data = unsafe {self.next_buffer.data.get().as_mut().unwrap()};
      //printlnerr!("starting {:?} \n LIFE: {:?}\n NEXT: {:?}\n CAPACITIES: {} {} DELETIONS: {}/{} {}/{} ", self, live_data, next_data, live_data.data.capacity(), next_data.data.capacity(), self.live_buffer.deletions, live_data.data.len(), self.next_buffer.deletions, next_data.data.len());
      let buffer_pushes_before_reset_needed = min (
        live_data.data.capacity() - live_data.data.len(),
        next_data.data.capacity()/2 - self.potential_next_buffer_usage,
      );
      let current_insertions = live_data.data.len() - self.live_buffer.deletions;
      //let tolerable_deletions = (current_insertions*5)/12;
      //let deletions_before_reset_needed = tolerable_deletions - self.live_buffer.deletions;
      let deletions_before_reset_needed = (current_insertions + 7 - self.live_buffer.deletions - 6*self.next_buffer.deletions)/7;
      let operations_before_reset_possibly_needed = min (buffer_pushes_before_reset_needed, deletions_before_reset_needed);
      assert!(self.next_transfer_index <= live_data.data.len() );
      let transfer_steps_needed_before_reset_possible = live_data.data.len() + operations_before_reset_possibly_needed - self.next_transfer_index;
      //printlnerr!("NEEDED {:?} \n OPERATIONS: {:?}\n (buffer pushes): {:?}\n (deletions): {} {} ", transfer_steps_needed_before_reset_possible , operations_before_reset_possibly_needed , buffer_pushes_before_reset_needed , deletions_before_reset_needed , "something");
      assert!(transfer_steps_needed_before_reset_possible <= (operations_before_reset_possibly_needed + 1) * MAX_TRANSFER_SPEED);
      if transfer_steps_needed_before_reset_possible >operations_before_reset_possibly_needed * MAX_TRANSFER_SPEED {
        for _ in 0..MAX_TRANSFER_SPEED {
          if let Some (entry) = live_data.data.get (self.next_transfer_index) {
            if entry.insertion && currently_existent (& entry.key) {
              next_data.data.push ((*entry).clone());
            }
            self.next_transfer_index += 1;
          }
          else {break;}
        }
      }
      //printlnerr!("ending {:?} \n LIFE: {:?}\n NEXT: {:?}\n CAPACITIES: {} {} ", self, live_data, next_data, live_data.data.capacity(), next_data.data.capacity());
      if operations_before_reset_possibly_needed == 0 {
        self.next_transfer_index = 0;
        self.potential_next_buffer_usage = next_data.data.len() - self.next_buffer.deletions;
        mem::swap (&mut self.live_buffer, &mut self.next_buffer);
        //danger: after we overwrite self.next_buffer, we may have deallocated
        //the memory for live_data
        self.next_buffer = Buffer {
          data: Arc::new (UnsafeCell::new (BufferInner {data: Vec::with_capacity ((self.potential_next_buffer_usage + 1)*4), marker: AtomicBool::new(false)})), deletions: 0,
        };
      }
      //printlnerr!("ending {:?}", self);
      unsafe {
        assert!((*self.live_buffer.data.get()).data.len() < (*self.live_buffer.data.get()).data.capacity());
        assert!((*self.next_buffer.data.get()).data.len() <= self.potential_next_buffer_usage);
        assert!(self.potential_next_buffer_usage < (*self.next_buffer.data.get()).data.capacity()/2);
      }
    }
  }
#[cfg (test)]
mod tests {
use super::*; use std::collections::HashSet;        use std::thread; use std::sync::mpsc::channel;
  #[quickcheck]
  fn test_operation_sequence (operations: Vec<(usize, bool)>)->bool {
    let mut existences: HashSet <usize> = HashSet::new();
    let mut set: Set <usize> = Set::new();

    let (send_snapshot, receive_snapshot) = channel::<Option <(Snapshot <usize>, HashSet <usize>)>>();
    let (send_results, receive_results) = channel();
    let check_thread = thread::spawn ( move | | {
      while let Some ((snapshot, checker)) = receive_snapshot.recv().unwrap() {
        let checker_2 = snapshot.iter().collect();
        send_results.send (checker == checker_2);
      }
    });
    for operation in operations {
      if existences.contains(& operation.0) != operation.1 {
        if operation.1 {
          existences.insert (operation.0);
          set.insert (operation.0, & | value | existences.contains (value));
        } else {
          existences.remove (& operation. 0);
          set.remove (operation.0, & | value | existences.contains (value));
        }
        let checker = existences.clone();
        let snapshot = set.snapshot();

        send_snapshot.send (Some ((snapshot, checker)));
        if ! receive_results.recv().unwrap() {send_snapshot.send (None); check_thread.join(); return false;}
      }
    }
    send_snapshot.send (None); check_thread.join();
    true
}
//#[test]
fn hack () {

//test_operation_sequence ((0..100).map (| number | (number, true)).collect());
}}
}
<|endoftext|>