composable_indexes/index/
premap.rs

1//! A combinator that transforms the input type of an index using a mapping function.
2//! This allows reusing existing indexes with different data types by pre-processing the input.
3//!
4//! # Example
5//!
6//! ```rust
7//! use composable_indexes::{Collection, index};
8//!
9//! struct Person { first_name: String, last_name: String, age: u32 }
10//!
11//! // Index by age (owned value).
12//! index::PremapOwned::new(|p: &Person| p.age, index::BTree::<u32>::new());
13//!
14//! // Index by full name (owned value)
15//! index::PremapOwned::new(|p: &Person| (p.first_name.clone(), p.last_name.clone()), index::BTree::<(String, String)>::new());
16//! ```
17
18use crate::{
19    ShallowClone,
20    core::{Index, Insert, Remove, Seal, Update},
21};
22
23#[doc(hidden)]
24pub struct GenericPremap<In, InnerIn, F, Inner> {
25    f: F,
26    inner: Inner,
27    _phantom: core::marker::PhantomData<(In, InnerIn)>,
28}
29
30impl<In, InnerIn, F, Inner> Clone for GenericPremap<In, InnerIn, F, Inner>
31where
32    F: Copy,
33    Inner: Clone,
34{
35    fn clone(&self) -> Self {
36        GenericPremap {
37            f: self.f,
38            inner: self.inner.clone(),
39            _phantom: core::marker::PhantomData,
40        }
41    }
42}
43
44impl<In, InnerIn, F, Inner> ShallowClone for GenericPremap<In, InnerIn, F, Inner>
45where
46    Inner: ShallowClone,
47    F: Copy,
48{
49}
50
51/// Higher-order index that maps input values before passing them to an inner index.
52pub type Premap<In, InnerIn, Inner> = GenericPremap<In, InnerIn, fn(&In) -> &InnerIn, Inner>;
53
54/// Higher-order index that maps input values before passing them to an inner index, using owned values.
55pub type PremapOwned<In, InnerIn, Inner> = GenericPremap<In, InnerIn, fn(&In) -> InnerIn, Inner>;
56
57impl<In, InnerIn, Inner> Premap<In, InnerIn, Inner> {
58    pub fn new(f: fn(&In) -> &InnerIn, inner: Inner) -> Self {
59        Premap {
60            f,
61            inner,
62            _phantom: core::marker::PhantomData,
63        }
64    }
65}
66
67impl<In, InnerIn, Inner> PremapOwned<In, InnerIn, Inner> {
68    pub fn new(f: fn(&In) -> InnerIn, inner: Inner) -> Self {
69        PremapOwned {
70            f,
71            inner,
72            _phantom: core::marker::PhantomData,
73        }
74    }
75}
76
77// Index implementation for reference-based premap
78impl<In, InnerIn, Inner> Index<In> for Premap<In, InnerIn, Inner>
79where
80    Inner: Index<InnerIn>,
81{
82    #[inline]
83    fn insert(&mut self, seal: Seal, op: &Insert<In>) {
84        self.inner.insert(
85            seal,
86            &Insert {
87                key: op.key,
88                new: (self.f)(op.new),
89            },
90        );
91    }
92
93    #[inline]
94    fn update(&mut self, seal: Seal, op: &Update<In>) {
95        self.inner.update(
96            seal,
97            &Update {
98                key: op.key,
99                new: (self.f)(op.new),
100                existing: (self.f)(op.existing),
101            },
102        );
103    }
104
105    #[inline]
106    fn remove(&mut self, seal: Seal, op: &Remove<In>) {
107        self.inner.remove(
108            seal,
109            &Remove {
110                key: op.key,
111                existing: (self.f)(op.existing),
112            },
113        );
114    }
115}
116
117// Index implementation for owned-based premap
118impl<In, InnerIn, Inner> Index<In> for PremapOwned<In, InnerIn, Inner>
119where
120    Inner: Index<InnerIn>,
121{
122    #[inline]
123    fn insert(&mut self, seal: Seal, op: &Insert<In>) {
124        self.inner.insert(
125            seal,
126            &Insert {
127                key: op.key,
128                new: &(self.f)(op.new),
129            },
130        );
131    }
132
133    #[inline]
134    fn update(&mut self, seal: Seal, op: &Update<In>) {
135        self.inner.update(
136            seal,
137            &Update {
138                key: op.key,
139                new: &(self.f)(op.new),
140                existing: &(self.f)(op.existing),
141            },
142        );
143    }
144
145    #[inline]
146    fn remove(&mut self, seal: Seal, op: &Remove<In>) {
147        self.inner.remove(
148            seal,
149            &Remove {
150                key: op.key,
151                existing: &(self.f)(op.existing),
152            },
153        );
154    }
155}
156
157impl<In, InnerIn, F, Inner> GenericPremap<In, InnerIn, F, Inner> {
158    #[inline]
159    pub fn inner(&self) -> &Inner {
160        &self.inner
161    }
162}
163
164impl<In, InnerIn, F, Inner> core::ops::Deref for GenericPremap<In, InnerIn, F, Inner> {
165    type Target = Inner;
166
167    fn deref(&self) -> &Self::Target {
168        &self.inner
169    }
170}