/// Apply operations while allowing dropping of values
Apply operations while allowing dropping of values
Apply operations while allowing dropping of values
fn absorb_second(&mut self, op: Operation<K, V, M>, other: &Self) {
        // # Safety (for cast):
        //
        // See the module-level documentation for left_right::aliasing.
        // NoDrop and DoDrop are both private, therefore this cast is (likely) sound.
        //
        // # Safety (for NoDrop -> DoDrop):
        //
        // It is safe for us to drop values the second time each operation has been
        // performed, since if they are dropped here, they were also dropped in the first
        // application of the operation, which removed the only other alias.
        //
        // FIXME: This is where the non-determinism of Hash and PartialEq hits us (#78).
        let inner: &mut Inner<K, V, M, S, crate::aliasing::DoDrop> =
            unsafe { &mut *(self as *mut _ as *mut _) };
        // Safety note for calls to .change_drop():
        //
        //   we're turning a NoDrop into DoDrop, so we must be prepared for a drop.
        //   if absorb_first dropped its alias, then `value` is the only alias
        //   if absorb_first did not drop its alias, then `value` will not be dropped here either,
        //   and at the end of scope we revert to `NoDrop`, so all is well.
        let hasher = other.data.hasher();
        match op {
            Operation::Replace(key, value) => {
                let v = inner.data.entry(key).or_insert_with(ValuesInner::new);
                v.clear();
                v.shrink_to_fit();
                v.push(unsafe { value.change_drop() }, hasher);
            }
            Operation::Clear(key) => {
                inner
                    .data
                    .entry(key)
                    .or_insert_with(ValuesInner::new)
                    .clear();
            }
            Operation::Add(key, value) => {
                // safety (below):
                //   we're turning a NoDrop into DoDrop, so we must be prepared for a drop.
                //   if absorb_first dropped the value, then `value` is the only alias
                //   if absorb_first did not drop the value, then `value` will not be dropped here
                //   either, and at the end of scope we revert to `NoDrop`, so all is well.
                inner
                    .data
                    .entry(key)
                    .or_insert_with(ValuesInner::new)
                    .push(unsafe { value.change_drop() }, hasher);
            }
            Operation::RemoveEntry(key) => {
                #[cfg(not(feature = "indexed"))]
                inner.data.remove(&key);
                #[cfg(feature = "indexed")]
                inner.data.swap_remove(&key);
            }
            Operation::Purge => {
                inner.data.clear();
            }
            #[cfg(feature = "eviction")]
            Operation::EmptyAt(indices) => {
                for &index in indices.iter().rev() {
                    inner.data.swap_remove_index(index);
                }
            }
            Operation::RemoveValue(key, value) => {
                if let Some(e) = inner.data.get_mut(&key) {
                    // find the first entry that matches all fields
                    e.swap_remove(&value);
                }
            }
            Operation::Retain(key, mut predicate) => {
                if let Some(e) = inner.data.get_mut(&key) {
                    let mut first = true;
                    e.retain(move |v| {
                        let retain = predicate.eval(&*v, first);
                        first = false;
                        retain
                    });
                }
            }
            Operation::Fit(key) => match key {
                Some(ref key) => {
                    if let Some(e) = inner.data.get_mut(key) {
                        e.shrink_to_fit();
                    }
                }
                None => {
                    for value_set in inner.data.values_mut() {
                        value_set.shrink_to_fit();
                    }
                }
            },
            Operation::Reserve(key, additional) => match inner.data.entry(key) {
                Entry::Occupied(mut entry) => {
                    entry.get_mut().reserve(additional, hasher);
                }
                Entry::Vacant(entry) => {
                    entry.insert(ValuesInner::with_capacity_and_hasher(additional, hasher));
                }
            },
            Operation::MarkReady => {
                inner.ready = true;
            }
            Operation::SetMeta(m) => {
                inner.meta = m;
            }
        }
    }
fn absorb_second ( & mut self , op : Operation < K , V , M > , other : & Self ) { // # Safety (for cast): // // See the module-level documentation for left_right::aliasing. // NoDrop and DoDrop are both private, therefore this cast is (likely) sound. // // # Safety (for NoDrop -> DoDrop): // // It is safe for us to drop values the second time each operation has been // performed, since if they are dropped here, they were also dropped in the first // application of the operation, which removed the only other alias. // // FIXME: This is where the non-determinism of Hash and PartialEq hits us (#78). let inner : & mut Inner < K , V , M , S , crate :: aliasing :: DoDrop > = unsafe { & mut * ( self as * mut _ as * mut _ ) } ; // Safety note for calls to .change_drop(): // //   we're turning a NoDrop into DoDrop, so we must be prepared for a drop. //   if absorb_first dropped its alias, then `value` is the only alias //   if absorb_first did not drop its alias, then `value` will not be dropped here either, //   and at the end of scope we revert to `NoDrop`, so all is well. let hasher = other . data . hasher ( ) ; match op { Operation :: Replace ( key , value ) => { let v = inner . data . entry ( key ) . or_insert_with ( ValuesInner :: new ) ; v . clear ( ) ; v . shrink_to_fit ( ) ; v . push ( unsafe { value . change_drop ( ) } , hasher ) ; } Operation :: Clear ( key ) => { inner . data . entry ( key ) . or_insert_with ( ValuesInner :: new ) . clear ( ) ; } Operation :: Add ( key , value ) => { // safety (below): //   we're turning a NoDrop into DoDrop, so we must be prepared for a drop. //   if absorb_first dropped the value, then `value` is the only alias //   if absorb_first did not drop the value, then `value` will not be dropped here //   either, and at the end of scope we revert to `NoDrop`, so all is well. inner . data . entry ( key ) . or_insert_with ( ValuesInner :: new ) . push ( unsafe { value . change_drop ( ) } , hasher ) ; } Operation :: RemoveEntry ( key ) => { # [ cfg ( not ( feature " " ) ) ] inner . data . remove ( & key ) ; # [ cfg ( feature " " ) ] inner . data . swap_remove ( & key ) ; } Operation :: Purge => { inner . data . clear ( ) ; } # [ cfg ( feature " " ) ] Operation :: EmptyAt ( indices ) => { for & index in indices . iter ( ) . rev ( ) { inner . data . swap_remove_index ( index ) ; } } Operation :: RemoveValue ( key , value ) => { if let Some ( e ) = inner . data . get_mut ( & key ) { // find the first entry that matches all fields e . swap_remove ( & value ) ; } } Operation :: Retain ( key , mut predicate ) => { if let Some ( e ) = inner . data . get_mut ( & key ) { let mut first = true ; e . retain ( move | v | { let retain = predicate . eval ( & * v , first ) ; first = false ; retain } ) ; } } Operation :: Fit ( key ) => match key { Some ( ref key ) => { if let Some ( e ) = inner . data . get_mut ( key ) { e . shrink_to_fit ( ) ; } } None => { for value_set in inner . data . values_mut ( ) { value_set . shrink_to_fit ( ) ; } } } , Operation :: Reserve ( key , additional ) => match inner . data . entry ( key ) { Entry :: Occupied ( mut entry ) => { entry . get_mut ( ) . reserve ( additional , hasher ) ; } Entry :: Vacant ( entry ) => { entry . insert ( ValuesInner :: with_capacity_and_hasher ( additional , hasher ) ) ; } } , Operation :: MarkReady => { inner . ready = true ; } Operation :: SetMeta ( m ) => { inner . meta = m ; } } }
Apply operations while allowing dropping of values
Apply operations while allowing dropping of values
&mut self
op
Operation<K, V, M>
other
&Self