Skip to main content

recasting/
lib.rs

1//! This crate supplies the `Recast` and `Recaster` traits. These are intended
2//! for the translation of arena indexes like those in the `triple_arena` crate,
3//! however they can be used for any purpose of one-to-one recasting of values.
4//!
5//! A [Recaster] is the storage type defining the old-to-new mapping that some
6//! domain remapping operation produces, and [Recast] is what walks a structure
7//! and applies that mapping to every `Item` it finds.
8//!
9//! [Recast] is implemented here for the primitive integer types (including the
10//! `NonZero` variants), `bool`, `char`, `f32`, `f64`, and for many wrappers and
11//! collections that forward to the impls of whatever they contain. [Recaster]
12//! is implemented for the standard collection types `HashMap` and `BTreeMap`,
13//! which can act directly as an `Item` to `Item` mapping. Note that for the
14//! [Recast] (not their [Recaster]) implementations of `HashMap` and `BTreeMap`,
15//! only the values of the maps are recast and never the keys, because
16//! changing a key in place would break the ordering or hashing invariant of the
17//! map. The same reasoning is why there are no impls for set types like
18//! `HashSet`. Such a collection has to be drained into a new one instead, with
19//! each key or element recast on the way. The same reasoning applies to
20//! downstream maps like `triple_arena::Arena`.
21//!
22//! Note that there are "alloc" and "std" feature flags that can be turned off
23
24// Disclaimer: there is some LLM generated code, but besides some localized fixes, I have kept any
25// plain vibe coding to the tests folder and extraneous things. See all commits mentioning "LLM".
26
27#![cfg_attr(not(feature = "std"), no_std)]
28#![deny(rustdoc::broken_intra_doc_links)]
29#![deny(rustdoc::private_intra_doc_links)]
30
31use core::{
32    marker::PhantomData,
33    num::{
34        NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize, NonZeroU8,
35        NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize,
36    },
37};
38
39#[cfg(feature = "alloc")]
40extern crate alloc;
41
42/// A trait implemented for structures that have `Item`s that should be
43/// `Recast`ed by a `Recaster`.
44///
45/// `Recast` was designed for structures with their own virtual address spaces,
46/// with the `Item`s being virtual addresses. For example, arenas from the
47/// `triple_arena` crate have entries that can be referenced by `Ptr`s. The
48/// `Ptr`s are indexes that must remain stable, otherwise copies of them will
49/// become invalid. The `CompactArenaTrait` arenas from `triple_arena` have a
50/// problem where they should be compressed before being serialized, or else
51/// unused interior capacity will be forced upon the deserialized arenas in
52/// order to keep stable `Ptr`s. If the plain `ArenaTrait::compress` function is
53/// used, for example, the `Ptr` indexes are translated each to a new value, but
54/// all external `Ptr`s and the `Ptr`s in the entries would remain untranslated
55/// to the new mapping.
56///
57/// ```
58/// use triple_arena::{Arena, ptr_struct, traits::*};
59///
60/// // the `P0` `Ptr` type
61/// ptr_struct!(P0);
62///
63/// let mut a: Arena<P0, (u64, Option<P0>)> = Arena::new();
64/// let p_1 = a.insert((1, None));
65/// let p_2 = a.insert((2, None));
66/// let p_7 = a.insert((7, None));
67/// let p_42 = a.insert((42, Some(p_7)));
68/// // create some unallocated internal entries
69/// a.remove(p_1).unwrap().allow();
70/// a.remove(p_2).unwrap().allow();
71///
72/// assert_eq!(a.get(p_7), Some(&(7, None)));
73/// assert_eq!(a.get(p_42), Some(&(42, Some(p_7))));
74///
75/// // translate all the entries and their `Ptr` keys to new locations
76/// a.compress(false).allow();
77///
78/// // the external copies `p_7` and `p_42` no longer work
79/// assert_eq!(a.get(p_7), None);
80/// assert_eq!(a.get(p_42), None);
81///
82/// // manually get the entry where 42 ends up
83/// let entry42: (u64, Option<P0>) = *a.vals().nth(1).unwrap();
84/// // the copy of `p_7` also was not changed even though it was inside
85/// // the arena, only the `Ptr`s by which entries are referenced has
86/// // changed, and anything inside the custom `(u64, Option<P0>)` values is left
87/// // unchanged
88/// assert_eq!(a.get(entry42.1.unwrap()), None);
89/// ```
90///
91/// We could use `compress_with` and manually recast all `Ptr`s
92/// inside and outside the arena, but this quickly gets untenable as the
93/// complexity of the datastructure increases. Here is an automated version with
94/// `Recast`:
95///
96/// ```
97/// use triple_arena::{Arena, DirectArena, HeapBacking, ptr_struct, traits::*};
98///
99/// // quick reimplementation of the example from `ArenaTrait::compress_with`
100/// fn compress_recaster<P: Ptr, T, A: CompactArenaTrait<P, T>>(
101///     this: &mut A,
102///     reset_generation: bool,
103/// ) -> DirectArena<P, P, HeapBacking> {
104///     let mut recaster = DirectArena::<P, P, HeapBacking>::new();
105///     recaster.clone_from_with(this, |_, _| P::invalid()).unwrap();
106///     this.compress_with(reset_generation, |q, _, p| recaster[q] = p)
107///         .allow();
108///     recaster
109/// }
110///
111/// ptr_struct!(P0);
112///
113/// // the structs from `ptr_struct` automatically have `Recast<Self>`
114/// // implemented, which looks like:
115/// //
116/// //impl Recast<Self> for P0 {
117/// //    #[inline]
118/// //    fn recast<R: Recaster<Item = P0>>(&mut self, recaster: &R)
119/// //        -> Result<(), <R as Recaster>::Item> {
120/// //        recaster.recast_item(self)
121/// //    }
122/// //}
123///
124/// impl Recast<P0> for (u64, Option<P0>) {
125///     fn recast<R: Recaster<Item = P0>>(
126///         &mut self,
127///         recaster: &R,
128///     ) -> Result<(), <R as Recaster>::Item> {
129///         // this calls the impl of `Recast` for `Option<T>`, which calls
130///         // the `Recast<Self> for P0` impl
131///         self.1.recast(recaster)?;
132///         // `self.0` does not have any `P0`s inside of it, but if there
133///         // are any fields with `P0`s, they should also have `recast`
134///         // called.
135///         //self.0.recast(recaster)?;
136///         Ok(())
137///     }
138/// }
139///
140/// let mut a: Arena<P0, (u64, Option<P0>)> = Arena::new();
141/// let p_1 = a.insert((1, None));
142/// let p_2 = a.insert((2, None));
143/// let mut p_7 = a.insert((7, None));
144/// let mut p_42 = a.insert((42, Some(p_7)));
145/// // create some unallocated internal entries
146/// a.remove(p_1).unwrap().allow();
147/// a.remove(p_2).unwrap().allow();
148///
149/// assert_eq!(a.get(p_7), Some(&(7, None)));
150/// assert_eq!(a.get(p_42), Some(&(42, Some(p_7))));
151///
152/// let old_p_7 = p_7;
153///
154/// // translate all the entries and their `Ptr` keys to new locations,
155/// // this time with `compress_recaster` which returns a
156/// // `DirectArena<P0, P0>`, which implements `Recaster`. This recaster maps
157/// // old `Ptr`s to their new indexes.
158/// let recaster = compress_recaster(&mut a, false);
159///
160/// // recast all external `Ptr`s, keeping `old_p_7` unrecast for the sake of
161/// // example
162/// p_7.recast(&recaster).unwrap();
163/// p_42.recast(&recaster).unwrap();
164///
165/// // now `p_7` and `p_42` work again, however note that we forgot
166/// // to recast the arena itself, this is very important to remember
167/// // if the entries in the arena or whatever map we are using has
168/// // `Item`s in its values
169/// assert_eq!(a.get(p_7), Some(&(7, None)));
170/// assert_eq!(a.get(p_42), Some(&(42, Some(old_p_7))));
171///
172/// a.recast(&recaster).unwrap();
173///
174/// assert_eq!(a.get(p_42), Some(&(42, Some(p_7))));
175/// ```
176///
177/// Now for a more advanced example with multiple `Item` types
178///
179/// ```
180/// use triple_arena::{Arena, DirectArena, HeapBacking, ptr_struct, traits::*};
181///
182/// // quick reimplementation of the example from `ArenaTrait::compress_with`
183/// fn compress_recaster<P: Ptr, T, A: CompactArenaTrait<P, T>>(
184///     this: &mut A,
185///     reset_generation: bool,
186/// ) -> DirectArena<P, P, HeapBacking> {
187///     let mut recaster = DirectArena::<P, P, HeapBacking>::new();
188///     recaster.clone_from_with(this, |_, _| P::invalid()).unwrap();
189///     this.compress_with(reset_generation, |q, _, p| recaster[q] = p)
190///         .allow();
191///     recaster
192/// }
193///
194/// // Multiple `Ptr` types. Usually, there needs to be one `Item`
195/// // type per address space that can be recast.
196/// ptr_struct!(P0; Q1);
197///
198/// // An example user structure. Preferably, these things should be
199/// // designed so that all the `Ptr`s are self contained, which
200/// // means that only one top level `recast` call needs to be made
201/// // to map them all.
202/// #[derive(Debug, PartialEq, Eq)]
203/// struct Entry(u64, Vec<P0>, Q1);
204/// struct Structure {
205///     // The arena defining the domain for `P0` `Item`s.
206///     p0_arena: Arena<P0, Entry>,
207///     // some `P0`s that are stored externally to the arena
208///     external: Vec<P0>,
209///     // An arena that is keyed by `Q1` instead of `P0`. If there are
210///     // multiple arenas, `HashMap`s, `BTreeMap`s, or any kind of
211///     // virtual-address-space capable types within the same structure,
212///     // they should each have their own wrapper `Item`s implementing
213///     // `Recast<Self>`. If for some reason there is a need for address
214///     // space duplication, e.g. a `HashSet<P0>` companion to a
215///     // `Arena<P0, ...>`, then the hash set needs to be emptied into a
216///     // new one, with each `P0` recast with the recaster for the
217///     // principal address space.
218///     q1_arena: Arena<Q1, i32>,
219/// }
220///
221/// impl Recast<P0> for Entry {
222///     fn recast<R: Recaster<Item = P0>>(
223///         &mut self,
224///         recaster: &R,
225///     ) -> Result<(), <R as Recaster>::Item> {
226///         // we can do this because of the `impl` of `Recast` for `Vec`, which
227///         // recasts all the entries
228///         self.1.recast(recaster)?;
229///         // the `.0` and `.2` fields are left untouched, since they
230///         // do not have `P0` values that would need to be recast
231///         Ok(())
232///     }
233/// }
234///
235/// // Because we used an external associated type for the `Recast` trait,
236/// // we can `impl` multiple times to be able to recast the same struct
237/// // with recasters of different `Item`s.
238/// impl Recast<Q1> for Entry {
239///     fn recast<R: Recaster<Item = Q1>>(
240///         &mut self,
241///         recaster: &R,
242///     ) -> Result<(), <R as Recaster>::Item> {
243///         // recast the `Q1`
244///         self.2.recast(recaster)?;
245///         Ok(())
246///     }
247/// }
248///
249/// impl Recast<P0> for Structure {
250///     fn recast<R: Recaster<Item = P0>>(
251///         &mut self,
252///         recaster: &R,
253///     ) -> Result<(), <R as Recaster>::Item> {
254///         self.p0_arena.recast(recaster)?;
255///         // `external` has some `P0`s we need to recast so that they
256///         // agree with elsewhere in the structure.
257///         self.external.recast(recaster)?;
258///         Ok(())
259///     }
260/// }
261///
262/// impl Recast<Q1> for Structure {
263///     fn recast<R: Recaster<Item = Q1>>(
264///         &mut self,
265///         recaster: &R,
266///     ) -> Result<(), <R as Recaster>::Item> {
267///         // the `Entry`s have `Q1` in them, this will delegate to the
268///         // `Recast<Q1> for Entry` impl
269///         self.p0_arena.recast(recaster)?;
270///         Ok(())
271///     }
272/// }
273///
274/// impl Structure {
275///     fn recast_q1(&mut self) -> Result<DirectArena<Q1, Q1>, Q1> {
276///         let recaster = compress_recaster(&mut self.q1_arena, false);
277///         // Immediately afterwards, we need to recast all the values.
278///         self.recast(&recaster)?;
279///         // it is encouraged to have all the relevant `Item`s self
280///         // contained within `Structure` so that only one call is
281///         // needed at the user level, but if needed we could also
282///         // return the `recaster` for recasting things external to
283///         // the structure.
284///         Ok(recaster)
285///     }
286///
287///     fn recast_p0(&mut self) -> Result<DirectArena<P0, P0>, P0> {
288///         let recaster = compress_recaster(&mut self.p0_arena, false);
289///         // Note an `Err` gets propagated upwards by `recast` if it encounters
290///         // a `P0` that was not contained as a key in the `p0_arena`
291///         // upon the call to acquire a recaster. If `Structure` is
292///         // using some kind of convention where invalid items could
293///         // be kept, they need to be purged by some routine here before
294///         // the `recast` call, or a custom `Recaster` could be defined to be a no-op on
295///         // unknown keys.
296///         self.recast(&recaster)?;
297///         Ok(recaster)
298///     }
299///
300///     // for preparation before serialization or whatever purpose
301///     // the recasting has
302///     fn compress_all(&mut self) {
303///         self.recast_q1().unwrap();
304///         self.recast_p0().unwrap();
305///     }
306/// }
307///
308/// let mut structure = Structure {
309///     p0_arena: Arena::new(),
310///     external: vec![],
311///     q1_arena: Arena::new(),
312/// };
313/// // do some random inserts and removals
314/// let q1_0 = structure.q1_arena.insert(-1);
315/// let mut q1_1 = structure.q1_arena.insert(-2);
316/// structure.q1_arena.remove(q1_0).unwrap().allow();
317/// let p0_0 = structure.p0_arena.insert(Entry(1, vec![], q1_1));
318/// let mut p0_1 = structure.p0_arena.insert(Entry(2, vec![], q1_1));
319/// let mut p0_2 = structure.p0_arena.insert(Entry(42, vec![p0_1], q1_1));
320/// structure.p0_arena.remove(p0_0).unwrap().allow();
321///
322/// let p0_recaster = structure.recast_p0().unwrap();
323/// let q1_recaster = structure.recast_q1().unwrap();
324///
325/// // now everything within the `Structure` is recast, but note
326/// // that the items we kept outside are invalid now and would
327/// // need to be recast to be used for the new mapping
328///
329/// let old_q1_1 = q1_1;
330/// q1_1.recast(&q1_recaster).unwrap();
331///
332/// assert!(structure.q1_arena.get(old_q1_1).is_none());
333/// assert_eq!(structure.q1_arena.get(q1_1), Some(-2).as_ref());
334///
335/// let old_p0_1 = p0_1;
336/// let old_p0_2 = p0_2;
337/// p0_1.recast(&p0_recaster).unwrap();
338/// p0_2.recast(&p0_recaster).unwrap();
339///
340/// // the complicated structure relations and `Ptr` validities
341/// // are preserved despite the `Ptr`s all changing
342/// assert_eq!(
343///     *structure.p0_arena.get(p0_2).unwrap(),
344///     Entry(42, vec![p0_1], q1_1)
345/// );
346/// assert_ne!(old_p0_1, p0_1);
347/// assert_ne!(old_p0_2, p0_2);
348/// assert_ne!(old_q1_1, q1_1);
349/// structure.compress_all();
350/// ```
351pub trait Recast<Item> {
352    /// Rewrites all the `<R as Recaster>::Item`s of `self` according to
353    /// [recast_item](Recaster::recast_item).
354    ///
355    /// # Errors
356    ///
357    /// If the recaster encounters an item it does not recognize, it returns
358    /// that item. Note that the state of `self` from before the `recast` may be
359    /// unrecoverable (the structure can remain partially recast), and errors
360    /// should only be encountered if these traits were used wrongly.
361    fn recast<R: Recaster<Item = Item>>(
362        &mut self,
363        recaster: &R,
364    ) -> Result<(), <R as Recaster>::Item>;
365}
366
367/// This is a no-op, it exists so that generic and composite types such as
368/// `Result<(), E>` can be recast
369impl<I> Recast<I> for () {
370    #[inline]
371    fn recast<R: Recaster<Item = I>>(
372        &mut self,
373        _recaster: &R,
374    ) -> Result<(), <R as Recaster>::Item> {
375        Ok(())
376    }
377}
378
379/// This is a no-op
380impl<I, T> Recast<I> for PhantomData<T> {
381    #[inline]
382    fn recast<R: Recaster<Item = I>>(
383        &mut self,
384        _recaster: &R,
385    ) -> Result<(), <R as Recaster>::Item> {
386        Ok(())
387    }
388}
389
390// These are the leaf impls that actually invoke the recaster, every other impl
391// forwards
392macro_rules! impl_self_recast {
393    ($($t:ident)*) => {
394        $(
395            /// Forwards directly to [recast_item](Recaster::recast_item)
396            impl Recast<$t> for $t {
397                #[inline]
398                fn recast<R: Recaster<Item = $t>>(&mut self, recaster: &R)
399                    -> Result<(), <R as Recaster>::Item> {
400                    recaster.recast_item(self)
401                }
402            }
403        )*
404    };
405}
406
407impl_self_recast!(
408    usize u8 u16 u32 u64 u128 NonZeroUsize NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128
409    isize i8 i16 i32 i64 i128 NonZeroIsize NonZeroI8 NonZeroI16 NonZeroI32 NonZeroI64 NonZeroI128
410    bool char f32 f64
411);
412
413impl<I, T: Recast<I> + ?Sized> Recast<I> for &mut T {
414    #[inline]
415    fn recast<R: Recaster<Item = I>>(&mut self, recaster: &R) -> Result<(), <R as Recaster>::Item> {
416        Recast::recast(*self, recaster)
417    }
418}
419
420impl<I, T: Recast<I> + ?Sized> Recast<I> for core::cell::Cell<T> {
421    #[inline]
422    fn recast<R: Recaster<Item = I>>(&mut self, recaster: &R) -> Result<(), <R as Recaster>::Item> {
423        Recast::recast(self.get_mut(), recaster)
424    }
425}
426
427impl<I, T: Recast<I> + ?Sized> Recast<I> for core::cell::RefCell<T> {
428    #[inline]
429    fn recast<R: Recaster<Item = I>>(&mut self, recaster: &R) -> Result<(), <R as Recaster>::Item> {
430        Recast::recast(self.get_mut(), recaster)
431    }
432}
433
434#[cfg(feature = "alloc")]
435impl<I, T: Recast<I> + ?Sized> Recast<I> for alloc::boxed::Box<T> {
436    #[inline]
437    fn recast<R: Recaster<Item = I>>(&mut self, recaster: &R) -> Result<(), <R as Recaster>::Item> {
438        Recast::recast(self.as_mut(), recaster)
439    }
440}
441
442/// Recasts the `Some` value, a `None` is a no-op
443impl<I, T: Recast<I>> Recast<I> for Option<T> {
444    #[inline]
445    fn recast<R: Recaster<Item = I>>(&mut self, recaster: &R) -> Result<(), <R as Recaster>::Item> {
446        if let Some(t) = self {
447            t.recast(recaster)?;
448        }
449        Ok(())
450    }
451}
452
453/// Recasts whichever variant is active
454impl<I, T: Recast<I>, E: Recast<I>> Recast<I> for Result<T, E> {
455    #[inline]
456    fn recast<R: Recaster<Item = I>>(&mut self, recaster: &R) -> Result<(), <R as Recaster>::Item> {
457        match self {
458            Ok(o) => o.recast(recaster),
459            Err(e) => e.recast(recaster),
460        }
461    }
462}
463
464macro_rules! tuple_recast {
465    ($($i:tt $t:tt),+) => {
466        impl<Z, $($t: Recast<Z>,)+> Recast<Z> for ($($t,)+) {
467            #[inline]
468            fn recast<R: Recaster<Item = Z>>(&mut self, recaster: &R)
469                -> Result<(), <R as Recaster>::Item> {
470                $(
471                    self.$i.recast(recaster)?;
472                )+
473                Ok(())
474            }
475        }
476    };
477}
478
479tuple_recast!(0 A);
480tuple_recast!(0 A, 1 B);
481tuple_recast!(0 A, 1 B, 2 C);
482tuple_recast!(0 A, 1 B, 2 C, 3 D);
483tuple_recast!(0 A, 1 B, 2 C, 3 D, 4 E);
484tuple_recast!(0 A, 1 B, 2 C, 3 D, 4 E, 5 F);
485tuple_recast!(0 A, 1 B, 2 C, 3 D, 4 E, 5 F, 6 G);
486tuple_recast!(0 A, 1 B, 2 C, 3 D, 4 E, 5 F, 6 G, 7 H);
487tuple_recast!(0 A, 1 B, 2 C, 3 D, 4 E, 5 F, 6 G, 7 H, 8 I);
488tuple_recast!(0 A, 1 B, 2 C, 3 D, 4 E, 5 F, 6 G, 7 H, 8 I, 9 J);
489tuple_recast!(0 A, 1 B, 2 C, 3 D, 4 E, 5 F, 6 G, 7 H, 8 I, 9 J, 10 K);
490tuple_recast!(0 A, 1 B, 2 C, 3 D, 4 E, 5 F, 6 G, 7 H, 8 I, 9 J, 10 K, 11 L);
491
492impl<I, T: Recast<I>, const N: usize> Recast<I> for [T; N] {
493    fn recast<R: Recaster<Item = I>>(&mut self, recaster: &R) -> Result<(), <R as Recaster>::Item> {
494        for t in self {
495            t.recast(recaster)?;
496        }
497        Ok(())
498    }
499}
500
501impl<I, T: Recast<I>> Recast<I> for [T] {
502    fn recast<R: Recaster<Item = I>>(&mut self, recaster: &R) -> Result<(), <R as Recaster>::Item> {
503        for t in self {
504            t.recast(recaster)?;
505        }
506        Ok(())
507    }
508}
509
510#[cfg(feature = "alloc")]
511impl<I, T: Recast<I>> Recast<I> for alloc::vec::Vec<T> {
512    fn recast<R: Recaster<Item = I>>(&mut self, recaster: &R) -> Result<(), <R as Recaster>::Item> {
513        for t in self {
514            t.recast(recaster)?;
515        }
516        Ok(())
517    }
518}
519
520#[cfg(feature = "alloc")]
521impl<I, T: Recast<I>> Recast<I> for alloc::collections::VecDeque<T> {
522    fn recast<R: Recaster<Item = I>>(&mut self, recaster: &R) -> Result<(), <R as Recaster>::Item> {
523        for t in self {
524            t.recast(recaster)?;
525        }
526        Ok(())
527    }
528}
529
530#[cfg(feature = "alloc")]
531impl<I, T: Recast<I>> Recast<I> for alloc::collections::LinkedList<T> {
532    fn recast<R: Recaster<Item = I>>(&mut self, recaster: &R) -> Result<(), <R as Recaster>::Item> {
533        for t in self {
534            t.recast(recaster)?;
535        }
536        Ok(())
537    }
538}
539
540/// Only the values are recast, the keys are left alone because changing them in
541/// place would break the ordering invariant of the map
542#[cfg(feature = "alloc")]
543impl<I, K, V: Recast<I>> Recast<I> for alloc::collections::BTreeMap<K, V> {
544    fn recast<R: Recaster<Item = I>>(&mut self, recaster: &R) -> Result<(), <R as Recaster>::Item> {
545        for t in self.values_mut() {
546            t.recast(recaster)?;
547        }
548        Ok(())
549    }
550}
551
552/// Only the values are recast, the keys are left alone because changing them in
553/// place would break the hashing invariant of the map
554#[cfg(feature = "std")]
555impl<I, K, V: Recast<I>> Recast<I> for std::collections::HashMap<K, V> {
556    fn recast<R: Recaster<Item = I>>(&mut self, recaster: &R) -> Result<(), <R as Recaster>::Item> {
557        for t in self.values_mut() {
558            t.recast(recaster)?;
559        }
560        Ok(())
561    }
562}
563
564/// A trait implemented for structures that can act as a `Recaster` in
565/// `Recast`ing `Item`s.
566///
567/// Most end users will get a `Recaster` from some method on a collection or
568/// some free function, see the `Recast` documentation for that. Here is
569/// an example of actually implementing a `Recaster`.
570///
571/// ```
572/// use std::collections::HashMap;
573///
574/// use recasting::{Recast, Recaster};
575///
576/// // there is an existing `impl<I, K, V: Recast<I>> Recast<I> for HashMap<K, V>`,
577/// // we will use a wrapper and implement it for only `i64` `Item`s for the sake of
578/// // example
579/// struct MyRecaster(HashMap<i64, i64>);
580///
581/// impl Recaster for MyRecaster {
582///     type Item = i64;
583///
584///     fn recast_item(&self, item: &mut Self::Item) -> Result<(), Self::Item> {
585///         if let Some(res) = self.0.get(item) {
586///             *item = *res;
587///             Ok(())
588///         } else {
589///             // alternatively, we could make this a no-op or use
590///             // other behavior depending on our intentions
591///             Err(*item)
592///         }
593///     }
594/// }
595///
596/// struct Structure {
597///     keyed_map: HashMap<i64, String>,
598/// }
599///
600/// impl Structure {
601///     fn insert(&mut self, i: i64, s: &str) {
602///         self.keyed_map.insert(i, s.to_owned());
603///     }
604///
605///     fn get(&self, i: i64) -> Option<&str> {
606///         self.keyed_map.get(&i).map(|s| s.as_str())
607///     }
608///
609///     // some arbitrary key remapping we are choosing for an example
610///     fn sub42<F: FnMut(i64, i64)>(&mut self, mut map: F) {
611///         let mut new = HashMap::new();
612///         for (key, val) in self.keyed_map.drain() {
613///             new.insert(key - 42, val);
614///             // closure through which we can
615///             // see the old and new keys
616///             map(key, key - 42);
617///         }
618///         self.keyed_map = new;
619///     }
620///
621///     fn sub42_recaster(&mut self) -> MyRecaster {
622///         let mut map = HashMap::new();
623///         self.sub42(|old, new| {
624///             map.insert(old, new);
625///         });
626///         MyRecaster(map)
627///     }
628/// }
629///
630/// let mut structure = Structure {
631///     keyed_map: HashMap::new(),
632/// };
633///
634/// let mut keys = vec![0, 1337, -10];
635/// structure.insert(keys[0], "test");
636/// structure.insert(keys[1], "hello");
637/// structure.insert(keys[2], "world");
638///
639/// let recaster = structure.sub42_recaster();
640/// // this goes through the `Recast` impl for `Vec` and calls
641/// // `Recast<i64>` with `<MyRecaster as Recaster>::recast_item`
642/// keys.recast(&recaster).unwrap();
643///
644/// assert_eq!(&keys, &[-42, 1295, -52]);
645/// assert_eq!(structure.get(keys[0]).unwrap(), "test");
646/// assert_eq!(structure.get(keys[1]).unwrap(), "hello");
647/// assert_eq!(structure.get(keys[2]).unwrap(), "world");
648/// ```
649pub trait Recaster {
650    /// The kind of item that this recaster maps
651    type Item;
652
653    /// Recasts an `item` based off of `self`.
654    ///
655    /// # Errors
656    ///
657    /// Returns an `Err` with a copy of `item` if it could not be handled. An
658    /// implementation is free to instead leave unrecognized items alone and
659    /// return `Ok`, or use interior mutability in `self`.
660    fn recast_item(&self, item: &mut Self::Item) -> Result<(), Self::Item>;
661}
662
663/// Maps each item to the value that the map has for it as a key, returning an
664/// `Err` with a clone of the item if the map does not contain it
665#[cfg(feature = "alloc")]
666impl<K: Ord + Clone> Recaster for alloc::collections::BTreeMap<K, K> {
667    type Item = K;
668
669    fn recast_item(&self, item: &mut Self::Item) -> Result<(), Self::Item> {
670        if let Some(res) = self.get(item) {
671            *item = res.clone();
672            Ok(())
673        } else {
674            Err(item.clone())
675        }
676    }
677}
678
679/// Maps each item to the value that the map has for it as a key, returning an
680/// `Err` with a clone of the item if the map does not contain it
681#[cfg(feature = "std")]
682impl<K: Eq + core::hash::Hash + Clone> Recaster for std::collections::HashMap<K, K> {
683    type Item = K;
684
685    fn recast_item(&self, item: &mut Self::Item) -> Result<(), Self::Item> {
686        if let Some(res) = self.get(item) {
687            *item = res.clone();
688            Ok(())
689        } else {
690            Err(item.clone())
691        }
692    }
693}