linearize/
copy_map.rs

1use {
2    crate::{
3        iter::{Iter, IterMut},
4        map::iters::{IntoIter, IntoValues},
5        storage::CopyStorage,
6        Linearize, Linearized, StaticMap,
7    },
8    core::{
9        array::TryFromSliceError,
10        borrow::{Borrow, BorrowMut},
11        cmp::Ordering,
12        fmt::{Debug, Formatter},
13        hash::{Hash, Hasher},
14        mem,
15        ops::{Deref, DerefMut, Index, IndexMut},
16    },
17};
18
19/// A copyable, array-backed map with complex keys.
20///
21/// This type is identical to [StaticMap] except that it always implements `Copy` and
22/// requires the values to implement `Copy`. This type exists due to limitations of the
23/// rust type system. It will be removed in a future version of this crate.
24#[repr(transparent)]
25pub struct StaticCopyMap<L, T>(
26    /// The underlying `[T; L::LENGTH]`.
27    pub <L as Linearize>::CopyStorage<T>,
28)
29where
30    L: Linearize + ?Sized,
31    T: Copy;
32
33impl<L, T> StaticCopyMap<L, T>
34where
35    L: Linearize + ?Sized,
36    T: Copy,
37{
38    /// Creates a map from a callback.
39    ///
40    /// # Example
41    ///
42    /// ```rust
43    /// # use linearize::StaticCopyMap;
44    /// let map = StaticCopyMap::from_fn(|l: bool| l as u32);
45    /// ```
46    #[inline]
47    pub fn from_fn(cb: impl FnMut(L) -> T) -> Self
48    where
49        L: Sized,
50    {
51        StaticMap::<L, T>::from_fn(cb).into_copy()
52    }
53
54    /// Creates a map from a reference to the underlying storage.
55    ///
56    /// Due to limitations of the rust type system, the underlying type is opaque in code
57    /// that is generic over `L`. However, in code with concrete `L`s, this function can
58    /// be used to turn any `[T; L::LENGTH]` into a map.
59    ///
60    /// # Example
61    ///
62    /// ```rust
63    /// # use linearize::StaticCopyMap;
64    /// let array = [0, 1];
65    /// let map = StaticCopyMap::from_ref(&array);
66    /// assert_eq!(map[false], 0);
67    /// assert_eq!(map[true], 1);
68    /// ```
69    #[inline]
70    pub const fn from_ref(storage: &L::CopyStorage<T>) -> &Self {
71        unsafe {
72            // SAFETY: Self is a transparent wrapper around L::CopyStorage<T>.
73            mem::transmute(storage)
74        }
75    }
76
77    /// Creates a map from a mutable reference to the underlying storage.
78    ///
79    /// Due to limitations of the rust type system, the underlying type is opaque in code
80    /// that is generic over `L`. However, in code with concrete `L`s, this function can
81    /// be used to turn any `[T; L::LENGTH]` into a map.
82    ///
83    /// # Example
84    ///
85    /// ```rust
86    /// # use linearize::StaticCopyMap;
87    /// let mut array = [0, 1];
88    /// let map = StaticCopyMap::from_mut(&mut array);
89    /// map[false] = 1;
90    /// map[true] = 0;
91    /// assert_eq!(array, [1, 0]);
92    /// ```
93    #[inline]
94    pub fn from_mut(storage: &mut L::CopyStorage<T>) -> &mut Self {
95        unsafe {
96            // SAFETY: Self is a transparent wrapper around L::CopyStorage<T>.
97            mem::transmute(storage)
98        }
99    }
100
101    /// Fallibly collects an iterator into a map. Returns Err if some key is not produced by
102    /// the iterator.
103    ///
104    /// # Example
105    ///
106    /// ```rust
107    /// use linearize::StaticCopyMap;
108    /// let map = StaticCopyMap::try_from_iter([(false, 0), (true, 1)]);
109    /// assert_eq!(map, Ok(StaticCopyMap([0, 1])));
110    ///
111    /// let map = StaticCopyMap::try_from_iter([(false, 0)]);
112    /// assert_eq!(map, Err(StaticCopyMap([Some(0), None])));
113    /// ```
114    #[inline]
115    pub fn try_from_iter(
116        iter: impl IntoIterator<Item = (L, T)>,
117    ) -> Result<Self, StaticCopyMap<L, Option<T>>>
118    where
119        L: Sized,
120    {
121        match StaticMap::try_from_iter(iter) {
122            Ok(map) => Ok(map.into_copy()),
123            Err(map) => Err(map.into_copy()),
124        }
125    }
126
127    /// Converts this map to a [StaticMap].
128    ///
129    /// This is a zero-cost conversion.
130    ///
131    /// # Example
132    ///
133    /// ```rust
134    /// # use linearize::{static_copy_map, StaticCopyMap, StaticMap};
135    /// let map: StaticCopyMap<_, _> = static_copy_map! {
136    ///     false => 0,
137    ///     true => 1,
138    /// };
139    /// let map: StaticMap<_, _> = map.into_static_map();
140    /// assert_eq!(map[false], 0);
141    /// assert_eq!(map[true], 1);
142    /// ```
143    #[inline]
144    pub fn into_static_map(self) -> StaticMap<L, T> {
145        StaticMap(self.0.into_storage())
146    }
147
148    /// Converts a [StaticMap] to a [StaticCopyMap].
149    ///
150    /// This is a zero-cost conversion.
151    ///
152    /// # Example
153    ///
154    /// ```rust
155    /// # use linearize::{static_map, StaticCopyMap, StaticMap};
156    /// let map: StaticMap<_, _> = static_map! {
157    ///     false => 0,
158    ///     true => 1,
159    /// };
160    /// let map: StaticCopyMap<_, _> = StaticCopyMap::from_static_map(map);
161    /// assert_eq!(map[false], 0);
162    /// assert_eq!(map[true], 1);
163    /// ```
164    #[inline]
165    pub fn from_static_map(map: StaticMap<L, T>) -> Self {
166        map.into_copy()
167    }
168
169    /// Converts a reference to this map to a reference to a [StaticMap].
170    ///
171    /// This is a zero-cost re-interpretation conversion.
172    ///
173    /// # Example
174    ///
175    /// ```rust
176    /// # use linearize::{static_copy_map, StaticCopyMap, StaticMap};
177    /// let map: StaticCopyMap<_, _> = static_copy_map! {
178    ///     false => 0,
179    ///     true => 1,
180    /// };
181    /// let map: &StaticMap<_, _> = map.as_copy();
182    /// assert_eq!(map[false], 0);
183    /// assert_eq!(map[true], 1);
184    /// ```
185    #[inline]
186    pub fn as_static_map(&self) -> &StaticMap<L, T>
187    where
188        T: Copy,
189    {
190        StaticMap::from_ref(self.0.as_storage())
191    }
192
193    /// Converts a mutable reference to this map to a mutable reference to a [StaticMap].
194    ///
195    /// This is a zero-cost re-interpretation conversion.
196    ///
197    /// # Example
198    ///
199    /// ```rust
200    /// # use linearize::{static_copy_map, StaticCopyMap, StaticMap};
201    /// let mut map: StaticCopyMap<_, _> = static_copy_map! {
202    ///     false => 0,
203    ///     true => 1,
204    /// };
205    /// assert_eq!(map[false], 0);
206    /// assert_eq!(map[true], 1);
207    /// {
208    ///     let map: &mut StaticMap<_, _> = map.as_static_map_mut();
209    ///     map[false] = 1;
210    ///     map[true] = 0;
211    /// }
212    /// assert_eq!(map[false], 1);
213    /// assert_eq!(map[true], 0);
214    /// ```
215    #[inline]
216    pub fn as_static_map_mut(&mut self) -> &mut StaticMap<L, T>
217    where
218        T: Copy,
219    {
220        StaticMap::from_mut(self.0.as_storage_mut())
221    }
222
223    /// Remaps the values of this type.
224    ///
225    /// # Example
226    ///
227    /// ```rust
228    /// # use linearize::{static_copy_map, StaticCopyMap, StaticMap};
229    /// let map: StaticCopyMap<_, u8> = static_copy_map! {
230    ///     false => 0,
231    ///     true => 1,
232    /// };
233    /// assert_eq!(map[false], 0);
234    /// assert_eq!(map[true], 1);
235    /// let map = map.map(|b, v| b as u8 + v);
236    /// assert_eq!(map[false], 0);
237    /// assert_eq!(map[true], 2);
238    /// ```
239    #[inline]
240    pub fn map<U>(self, map: impl FnMut(L, T) -> U) -> StaticCopyMap<L, U>
241    where
242        L: Sized,
243        U: Copy,
244    {
245        self.into_static_map().map(map).into_copy()
246    }
247
248    /// Remaps the values of this type without retrieving the keys.
249    ///
250    /// If you don't need access to the keys, this function can be more efficient.
251    ///
252    /// # Example
253    ///
254    /// ```rust
255    /// # use linearize::{static_copy_map, StaticCopyMap, StaticMap};
256    /// let map: StaticCopyMap<_, u8> = static_copy_map! {
257    ///     false => 0,
258    ///     true => 1,
259    /// };
260    /// assert_eq!(map[false], 0);
261    /// assert_eq!(map[true], 1);
262    /// let map = map.map_values(|v| 3 * v);
263    /// assert_eq!(map[false], 0);
264    /// assert_eq!(map[true], 3);
265    /// ```
266    #[inline]
267    pub fn map_values<U>(self, map: impl FnMut(T) -> U) -> StaticCopyMap<L, U>
268    where
269        U: Copy,
270    {
271        self.into_static_map().map_values(map).into_copy()
272    }
273
274    /// Consumes the map and returns an iterator over the values.
275    ///
276    /// # Example
277    ///
278    /// ```rust
279    /// # use linearize::{static_copy_map, StaticCopyMap};
280    /// let mut map: StaticCopyMap<_, u8> = static_copy_map! {
281    ///     false => 0,
282    ///     true => 1,
283    /// };
284    /// let mut iter = map.into_values();
285    /// assert_eq!(iter.next(), Some(0));
286    /// assert_eq!(iter.next(), Some(1));
287    /// assert_eq!(iter.next(), None);
288    /// ```   
289    pub fn into_values(self) -> IntoValues<L, T>
290    where
291        L: Sized,
292    {
293        self.into_static_map().into_values()
294    }
295}
296
297impl<L, T> Deref for StaticCopyMap<L, T>
298where
299    L: Linearize + ?Sized,
300    T: Copy,
301{
302    type Target = StaticMap<L, T>;
303
304    #[inline]
305    fn deref(&self) -> &Self::Target {
306        StaticMap::from_ref(self.0.as_storage())
307    }
308}
309
310impl<L, T> DerefMut for StaticCopyMap<L, T>
311where
312    L: Linearize + ?Sized,
313    T: Copy,
314{
315    #[inline]
316    fn deref_mut(&mut self) -> &mut Self::Target {
317        StaticMap::from_mut(self.0.as_storage_mut())
318    }
319}
320
321impl<L, T> Clone for StaticCopyMap<L, T>
322where
323    L: Linearize + ?Sized,
324    T: Copy,
325{
326    #[inline]
327    fn clone(&self) -> Self {
328        *self
329    }
330}
331
332impl<L, T> Index<&'_ L> for StaticCopyMap<L, T>
333where
334    L: Linearize + ?Sized,
335    T: Copy,
336{
337    type Output = T;
338
339    #[inline]
340    fn index(&self, index: &L) -> &Self::Output {
341        self.deref().index(index)
342    }
343}
344
345impl<L, T> Index<L> for StaticCopyMap<L, T>
346where
347    L: Linearize,
348    T: Copy,
349{
350    type Output = T;
351
352    #[inline]
353    fn index(&self, index: L) -> &Self::Output {
354        self.deref().index(index)
355    }
356}
357
358impl<L, T> Index<Linearized<L>> for StaticCopyMap<L, T>
359where
360    L: Linearize + ?Sized,
361    T: Copy,
362{
363    type Output = T;
364
365    fn index(&self, index: Linearized<L>) -> &Self::Output {
366        self.deref().index(index)
367    }
368}
369
370impl<L, T> IndexMut<&'_ L> for StaticCopyMap<L, T>
371where
372    L: Linearize + ?Sized,
373    T: Copy,
374{
375    #[inline]
376    fn index_mut(&mut self, index: &L) -> &mut Self::Output {
377        self.deref_mut().index_mut(index)
378    }
379}
380
381impl<L, T> IndexMut<L> for StaticCopyMap<L, T>
382where
383    L: Linearize,
384    T: Copy,
385{
386    #[inline]
387    fn index_mut(&mut self, index: L) -> &mut Self::Output {
388        self.deref_mut().index_mut(index)
389    }
390}
391
392impl<L, T> IndexMut<Linearized<L>> for StaticCopyMap<L, T>
393where
394    L: Linearize + ?Sized,
395    T: Copy,
396{
397    fn index_mut(&mut self, index: Linearized<L>) -> &mut Self::Output {
398        self.deref_mut().index_mut(index)
399    }
400}
401
402impl<L, T> Copy for StaticCopyMap<L, T>
403where
404    L: Linearize + ?Sized,
405    T: Copy,
406{
407}
408
409impl<L, T> FromIterator<(L, T)> for StaticCopyMap<L, T>
410where
411    L: Linearize,
412    T: Default,
413    T: Copy,
414{
415    #[inline]
416    fn from_iter<I: IntoIterator<Item = (L, T)>>(iter: I) -> Self {
417        StaticMap::<L, T>::from_iter(iter).into_copy()
418    }
419}
420
421impl<'a, L, T> FromIterator<(&'a L, T)> for StaticCopyMap<L, T>
422where
423    L: Linearize,
424    T: Default,
425    T: Copy,
426{
427    #[inline]
428    fn from_iter<I: IntoIterator<Item = (&'a L, T)>>(iter: I) -> Self {
429        let mut res = StaticCopyMap::<L, Option<T>>::default();
430        for (k, v) in iter {
431            res[k] = Some(v);
432        }
433        res.map_values(|v| v.unwrap_or_default())
434    }
435}
436
437impl<L, T> AsMut<[T]> for StaticCopyMap<L, T>
438where
439    L: Linearize + ?Sized,
440    T: Copy,
441{
442    #[inline]
443    fn as_mut(&mut self) -> &mut [T] {
444        self.deref_mut().as_mut()
445    }
446}
447
448impl<L, T> AsRef<[T]> for StaticCopyMap<L, T>
449where
450    L: Linearize + ?Sized,
451    T: Copy,
452{
453    #[inline]
454    fn as_ref(&self) -> &[T] {
455        self.deref().as_ref()
456    }
457}
458
459impl<L, T> Borrow<[T]> for StaticCopyMap<L, T>
460where
461    L: Linearize + ?Sized,
462    T: Copy,
463{
464    #[inline]
465    fn borrow(&self) -> &[T] {
466        self.deref().borrow()
467    }
468}
469
470impl<L, T> BorrowMut<[T]> for StaticCopyMap<L, T>
471where
472    L: Linearize + ?Sized,
473    T: Copy,
474{
475    #[inline]
476    fn borrow_mut(&mut self) -> &mut [T] {
477        self.deref_mut().borrow_mut()
478    }
479}
480
481impl<L, T> Debug for StaticCopyMap<L, T>
482where
483    L: Linearize,
484    L: Debug,
485    T: Debug,
486    T: Copy,
487{
488    #[inline]
489    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
490        self.deref().fmt(f)
491    }
492}
493
494impl<L, T> Default for StaticCopyMap<L, T>
495where
496    L: Linearize + ?Sized,
497    T: Default,
498    T: Copy,
499{
500    #[inline]
501    fn default() -> Self {
502        StaticMap::<L, T>::default().into_copy()
503    }
504}
505
506impl<L, T> Eq for StaticCopyMap<L, T>
507where
508    L: Linearize + ?Sized,
509    T: Eq,
510    T: Copy,
511{
512}
513
514impl<L, T> Hash for StaticCopyMap<L, T>
515where
516    L: Linearize + ?Sized,
517    T: Hash,
518    T: Copy,
519{
520    #[inline]
521    fn hash<H: Hasher>(&self, state: &mut H) {
522        self.deref().hash(state)
523    }
524}
525
526impl<L, T> Ord for StaticCopyMap<L, T>
527where
528    L: Linearize + ?Sized,
529    T: Ord,
530    T: Copy,
531{
532    #[inline]
533    fn cmp(&self, other: &Self) -> Ordering {
534        self.deref().cmp(other)
535    }
536
537    #[inline]
538    fn max(self, other: Self) -> Self
539    where
540        Self: Sized,
541    {
542        self.into_static_map()
543            .max(other.into_static_map())
544            .into_copy()
545    }
546
547    #[inline]
548    fn min(self, other: Self) -> Self
549    where
550        Self: Sized,
551    {
552        self.into_static_map()
553            .min(other.into_static_map())
554            .into_copy()
555    }
556
557    #[inline]
558    fn clamp(self, min: Self, max: Self) -> Self
559    where
560        Self: Sized,
561        Self: PartialOrd,
562    {
563        self.into_static_map()
564            .clamp(min.into_static_map(), max.into_static_map())
565            .into_copy()
566    }
567}
568
569impl<L, T> PartialEq for StaticCopyMap<L, T>
570where
571    L: Linearize + ?Sized,
572    T: PartialEq,
573    T: Copy,
574{
575    #[inline]
576    fn eq(&self, other: &Self) -> bool {
577        self.deref().eq(other)
578    }
579}
580
581impl<L, T> PartialOrd for StaticCopyMap<L, T>
582where
583    L: Linearize + ?Sized,
584    T: PartialOrd,
585    T: Copy,
586{
587    #[inline]
588    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
589        self.deref().partial_cmp(other)
590    }
591}
592
593impl<'a, L, T> TryFrom<&'a [T]> for &'a StaticCopyMap<L, T>
594where
595    L: Linearize + ?Sized,
596    T: Copy,
597{
598    type Error = TryFromSliceError;
599
600    #[inline]
601    fn try_from(value: &'a [T]) -> Result<Self, Self::Error> {
602        <&StaticMap<L, T>>::try_from(value).map(|v| v.as_copy())
603    }
604}
605
606impl<'a, L, T> TryFrom<&'a mut [T]> for &'a mut StaticCopyMap<L, T>
607where
608    L: Linearize + ?Sized,
609    T: Copy,
610{
611    type Error = TryFromSliceError;
612
613    #[inline]
614    fn try_from(value: &'a mut [T]) -> Result<Self, Self::Error> {
615        <&mut StaticMap<L, T>>::try_from(value).map(|v| v.as_copy_mut())
616    }
617}
618
619impl<L, T> TryFrom<&[T]> for StaticCopyMap<L, T>
620where
621    L: Linearize + ?Sized,
622    T: Copy,
623{
624    type Error = TryFromSliceError;
625
626    #[inline]
627    fn try_from(value: &[T]) -> Result<Self, Self::Error> {
628        StaticMap::try_from(value).map(|v| v.into_copy())
629    }
630}
631
632impl<L, T> TryFrom<&mut [T]> for StaticCopyMap<L, T>
633where
634    L: Linearize + ?Sized,
635    T: Copy,
636{
637    type Error = TryFromSliceError;
638
639    #[inline]
640    fn try_from(value: &mut [T]) -> Result<Self, Self::Error> {
641        StaticMap::try_from(value).map(|v| v.into_copy())
642    }
643}
644
645#[cfg(feature = "std")]
646impl<L, T> TryFrom<Vec<T>> for StaticCopyMap<L, T>
647where
648    L: Linearize + ?Sized,
649    T: Copy,
650{
651    type Error = Vec<T>;
652
653    #[inline]
654    fn try_from(value: Vec<T>) -> Result<Self, Self::Error> {
655        StaticMap::try_from(value).map(|v| v.into_copy())
656    }
657}
658
659impl<L, T> Extend<(L, T)> for StaticCopyMap<L, T>
660where
661    L: Linearize,
662    T: Copy,
663{
664    #[inline]
665    fn extend<I: IntoIterator<Item = (L, T)>>(&mut self, iter: I) {
666        self.deref_mut().extend(iter);
667    }
668}
669
670impl<'a, L, T> Extend<(&'a L, &'a T)> for StaticCopyMap<L, T>
671where
672    L: Linearize + ?Sized,
673    T: Clone,
674    T: Copy,
675{
676    #[inline]
677    fn extend<I: IntoIterator<Item = (&'a L, &'a T)>>(&mut self, iter: I) {
678        self.deref_mut().extend(iter);
679    }
680}
681
682impl<'a, L, T> IntoIterator for &'a StaticCopyMap<L, T>
683where
684    L: Linearize,
685    T: 'a,
686    T: Copy,
687{
688    type Item = (L, &'a T);
689    type IntoIter = Iter<'a, L, T>;
690
691    #[inline]
692    fn into_iter(self) -> Self::IntoIter {
693        self.deref().into_iter()
694    }
695}
696
697impl<'a, L, T> IntoIterator for &'a mut StaticCopyMap<L, T>
698where
699    L: Linearize,
700    T: Copy,
701{
702    type Item = (L, &'a mut T);
703    type IntoIter = IterMut<'a, L, T>;
704
705    #[inline]
706    fn into_iter(self) -> Self::IntoIter {
707        self.deref_mut().into_iter()
708    }
709}
710
711impl<L, T> IntoIterator for StaticCopyMap<L, T>
712where
713    L: Linearize,
714    T: Copy,
715{
716    type Item = (L, T);
717    type IntoIter = IntoIter<L, T>;
718
719    #[inline]
720    fn into_iter(self) -> Self::IntoIter {
721        self.into_static_map().into_iter()
722    }
723}
724
725impl<L, T> From<StaticMap<L, T>> for StaticCopyMap<L, T>
726where
727    L: Linearize,
728    T: Copy,
729{
730    #[inline]
731    fn from(value: StaticMap<L, T>) -> Self {
732        value.into_copy()
733    }
734}
735
736impl<L, T> AsRef<StaticMap<L, T>> for StaticCopyMap<L, T>
737where
738    L: Linearize,
739    T: Copy,
740{
741    fn as_ref(&self) -> &StaticMap<L, T> {
742        self.as_static_map()
743    }
744}
745
746impl<L, T> AsMut<StaticMap<L, T>> for StaticCopyMap<L, T>
747where
748    L: Linearize,
749    T: Copy,
750{
751    fn as_mut(&mut self) -> &mut StaticMap<L, T> {
752        self.as_static_map_mut()
753    }
754}
755
756impl<L, T> Borrow<StaticMap<L, T>> for StaticCopyMap<L, T>
757where
758    L: Linearize,
759    T: Copy,
760{
761    fn borrow(&self) -> &StaticMap<L, T> {
762        self.as_static_map()
763    }
764}
765
766impl<L, T> BorrowMut<StaticMap<L, T>> for StaticCopyMap<L, T>
767where
768    L: Linearize,
769    T: Copy,
770{
771    fn borrow_mut(&mut self) -> &mut StaticMap<L, T> {
772        self.as_static_map_mut()
773    }
774}