1pub struct ReadableKeyPath<Root, Value> {
3 pub get: Box<dyn for<'a> Fn(&'a Root) -> &'a Value>,
4}
5
6impl<Root, Value> ReadableKeyPath<Root, Value> {
7 pub fn new(get: impl for<'a> Fn(&'a Root) -> &'a Value + 'static) -> Self {
8 Self { get: Box::new(get) }
9 }
10 pub fn get<'a>(&self, root: &'a Root) -> &'a Value {
11 (self.get)(root)
12 }
13
14 pub fn iter<'a>(&'a self, slice: &'a [Root]) -> impl Iterator<Item = &'a Value> + 'a {
16 slice.iter().map(move |root| (self.get)(root))
17 }
18}
19
20impl<Root, Mid> ReadableKeyPath<Root, Mid>
21where
22 Root: 'static,
23 Mid: 'static,
24{
25 pub fn compose<Value>(self, mid: ReadableKeyPath<Mid, Value>) -> ReadableKeyPath<Root, Value>
26 where
27 Value: 'static,
28 {
29 ReadableKeyPath::new(move |r: &Root| {
30 let mid_ref: &Mid = (self.get)(r);
31 (mid.get)(mid_ref)
32 })
33 }
34}
35
36pub struct WritableKeyPath<Root, Value> {
37 pub get: Box<dyn for<'a> Fn(&'a Root) -> &'a Value>,
38 pub get_mut: Box<dyn for<'a> Fn(&'a mut Root) -> &'a mut Value>,
39}
40
41impl<Root, Value> WritableKeyPath<Root, Value> {
42 pub fn new(
43 get: impl for<'a> Fn(&'a Root) -> &'a Value + 'static,
44 get_mut: impl for<'a> Fn(&'a mut Root) -> &'a mut Value + 'static,
45 ) -> Self {
46 Self {
47 get: Box::new(get),
48 get_mut: Box::new(get_mut),
49 }
50 }
51
52 pub fn try_get<'a>(&self, root: &'a Root) -> &'a Value {
53 (self.get)(root)
54 }
55
56 pub fn try_get_mut<'a>(&self, root: &'a mut Root) -> &'a mut Value {
57 (self.get_mut)(root)
58 }
59
60 pub fn iter<'a>(&'a self, slice: &'a [Root]) -> impl Iterator<Item = &'a Value> + 'a {
62 slice.iter().map(move |root| (self.get)(root))
63 }
64
65 pub fn iter_mut<'a>(
67 &'a self,
68 slice: &'a mut [Root],
69 ) -> impl Iterator<Item = &'a mut Value> + 'a {
70 slice.iter_mut().map(move |root| (self.get_mut)(root))
71 }
72}
73
74impl<Root, Mid> WritableKeyPath<Root, Mid>
77where
78 Root: 'static,
79 Mid: 'static,
80{
81 pub fn compose<Value>(self, mid: WritableKeyPath<Mid, Value>) -> WritableKeyPath<Root, Value>
82 where
83 Value: 'static,
84 {
85 WritableKeyPath::new(
86 move |r: &Root| {
87 let mid_ref: &Mid = (self.get)(r);
88 (mid.get)(mid_ref)
89 },
90 move |r: &mut Root| {
91 let mid_ref: &mut Mid = (self.get_mut)(r);
92 (mid.get_mut)(mid_ref)
93 },
94 )
95 }
96}
97
98pub struct FailableReadableKeyPath<Root, Value> {
99 pub get: Box<dyn for<'a> Fn(&'a Root) -> Option<&'a Value>>,
100}
101
102impl<Root, Value> FailableReadableKeyPath<Root, Value> {
103 pub fn new(get: impl for<'a> Fn(&'a Root) -> Option<&'a Value> + 'static) -> Self {
104 Self { get: Box::new(get) }
105 }
106 pub fn try_get<'a>(&self, root: &'a Root) -> Option<&'a Value> {
107 (self.get)(root)
108 }
109
110 pub fn iter<'a>(&'a self, slice: &'a [Root]) -> impl Iterator<Item = Option<&'a Value>> + 'a {
112 slice.iter().map(move |root| (self.get)(root))
113 }
114}
115
116impl<Root, Mid> FailableReadableKeyPath<Root, Mid>
117where
118 Root: 'static,
119 Mid: 'static,
120{
121 pub fn compose<Value>(
122 self,
123 mid: FailableReadableKeyPath<Mid, Value>,
124 ) -> FailableReadableKeyPath<Root, Value>
125 where
126 Value: 'static,
127 {
128 FailableReadableKeyPath::new(move |r: &Root| (self.get)(r).and_then(|m: &Mid| (mid.get)(m)))
129 }
130}
131
132pub struct FailableWritableKeyPath<Root, Value> {
133 pub get: Box<dyn for<'a> Fn(&'a Root) -> Option<&'a Value>>,
134 pub get_mut: Box<dyn for<'a> Fn(&'a mut Root) -> Option<&'a mut Value>>,
135}
136
137impl<Root, Value> FailableWritableKeyPath<Root, Value> {
138 pub fn new(
139 get: impl for<'a> Fn(&'a Root) -> Option<&'a Value> + 'static,
140 get_mut: impl for<'a> Fn(&'a mut Root) -> Option<&'a mut Value> + 'static,
141 ) -> Self {
142 Self {
143 get: Box::new(get),
144 get_mut: Box::new(get_mut),
145 }
146 }
147
148 pub fn try_get<'a>(&self, root: &'a Root) -> Option<&'a Value> {
149 (self.get)(root)
150 }
151
152 pub fn try_get_mut<'a>(&self, root: &'a mut Root) -> Option<&'a mut Value> {
153 (self.get_mut)(root)
154 }
155
156 pub fn iter<'a>(&'a self, slice: &'a [Root]) -> impl Iterator<Item = Option<&'a Value>> + 'a {
157 slice.iter().map(move |root| (self.get)(root))
158 }
159
160 pub fn iter_mut<'a>(
162 &'a self,
163 slice: &'a mut [Root],
164 ) -> impl Iterator<Item = Option<&'a mut Value>> + 'a {
165 slice.iter_mut().map(move |root| (self.get_mut)(root))
166 }
167}
168
169impl<Root, Mid> FailableWritableKeyPath<Root, Mid>
170where
171 Root: 'static,
172 Mid: 'static,
173{
174 pub fn compose<Value>(
175 self,
176 mid: FailableWritableKeyPath<Mid, Value>,
177 ) -> FailableWritableKeyPath<Root, Value>
178 where
179 Value: 'static,
180 {
181 FailableWritableKeyPath::new(
182 move |r: &Root| (self.get)(r).and_then(|m: &Mid| (mid.get)(m)),
183 move |r: &mut Root| (self.get_mut)(r).and_then(|m: &mut Mid| (mid.get_mut)(m)),
184 )
185 }
186}
187
188pub struct EnumKeyPath<Enum, Inner> {
189 pub extract: fn(&Enum) -> Option<&Inner>,
190 pub embed: fn(Inner) -> Enum,
191}
192
193impl<Enum, Inner> EnumKeyPath<Enum, Inner> {
194 pub fn new(extract: fn(&Enum) -> Option<&Inner>, embed: fn(Inner) -> Enum) -> Self {
195 Self { extract, embed }
196 }
197
198 pub fn extract<'a>(&self, e: &'a Enum) -> Option<&'a Inner> {
199 (self.extract)(e)
200 }
201
202 pub fn embed(&self, inner: Inner) -> Enum {
203 (self.embed)(inner)
204 }
205}
206
207#[macro_export]
208macro_rules! enum_keypath {
209 ($enum:ident :: $variant:ident ( $inner:ty )) => {{
211 EnumKeyPath::<$enum, $inner>::new(
212 |root: &$enum| {
213 if let $enum::$variant(inner) = root {
214 Some(inner)
215 } else {
216 None
217 }
218 },
219 |inner: $inner| $enum::$variant(inner),
220 )
221 }};
222 ($enum:ident :: $variant:ident) => {{
224 EnumKeyPath::<$enum, ()>::new(
225 |root: &$enum| {
226 if let $enum::$variant = root {
227 Some(&())
228 } else {
229 None
230 }
231 },
232 |_| $enum::$variant,
233 )
234 }};
235}
236
237#[macro_export]
242macro_rules! readable_keypath {
243 ($Root:ty, $field:ident) => {
244 ReadableKeyPath::new(|root: &$Root| &root.$field)
245 };
246}
247
248#[macro_export]
256macro_rules! writable_keypath {
257 ($Root:ty, $field:ident) => {
258 WritableKeyPath::new(
259 |root: &$Root| &root.$field,
260 |root: &mut $Root| &mut root.$field,
261 )
262 };
263}