key_paths_derive/lib.rs
1use proc_macro::TokenStream;
2use quote::{format_ident, quote};
3use syn::{Data, DeriveInput, Fields, Type, parse_macro_input};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6enum WrapperKind {
7 None,
8 Option,
9 Box,
10 Rc,
11 Arc,
12 Vec,
13 HashMap,
14 BTreeMap,
15 HashSet,
16 BTreeSet,
17 VecDeque,
18 LinkedList,
19 BinaryHeap,
20 // Nested container support
21 OptionBox,
22 OptionRc,
23 OptionArc,
24 BoxOption,
25 RcOption,
26 ArcOption,
27 VecOption,
28 OptionVec,
29 HashMapOption,
30 OptionHashMap,
31}
32
33#[proc_macro_derive(Keypaths)]
34pub fn derive_keypaths(input: TokenStream) -> TokenStream {
35 let input = parse_macro_input!(input as DeriveInput);
36 let name = input.ident;
37
38 let methods = match input.data {
39 Data::Struct(data_struct) => match data_struct.fields {
40 Fields::Named(fields_named) => {
41 let mut tokens = proc_macro2::TokenStream::new();
42 for field in fields_named.named.iter() {
43 let field_ident = field.ident.as_ref().unwrap();
44 let ty = &field.ty;
45
46 let r_fn = format_ident!("{}_r", field_ident);
47 let w_fn = format_ident!("{}_w", field_ident);
48 let fr_fn = format_ident!("{}_fr", field_ident);
49 let fw_fn = format_ident!("{}_fw", field_ident);
50 let fr_at_fn = format_ident!("{}_fr_at", field_ident);
51 let fw_at_fn = format_ident!("{}_fw_at", field_ident);
52 // Owned keypath method names
53 let o_fn = format_ident!("{}_o", field_ident);
54 let fo_fn = format_ident!("{}_fo", field_ident);
55
56 let (kind, inner_ty) = extract_wrapper_inner_type(ty);
57
58 match (kind, inner_ty) {
59 (WrapperKind::Option, Some(inner_ty)) => {
60 tokens.extend(quote! {
61 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
62 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
63 }
64 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
65 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
66 }
67 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
68 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.as_ref())
69 }
70 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
71 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#field_ident.as_mut())
72 }
73 // Owned keypath methods
74 pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
75 key_paths_core::KeyPaths::owned(|s: #name| s.#field_ident)
76 }
77 pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
78 key_paths_core::KeyPaths::failable_owned(|s: #name| s.#field_ident)
79 }
80 });
81 }
82 (WrapperKind::Vec, Some(inner_ty)) => {
83 tokens.extend(quote! {
84 pub fn #fr_at_fn(index: usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
85 key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.get(index))
86 }
87 pub fn #fw_at_fn(index: usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
88 key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.get_mut(index))
89 }
90 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
91 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
92 }
93 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
94 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
95 }
96 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
97 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.first())
98 }
99 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
100 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#field_ident.first_mut())
101 }
102 // Owned keypath methods
103 pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
104 key_paths_core::KeyPaths::owned(|s: #name| s.#field_ident)
105 }
106 pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
107 key_paths_core::KeyPaths::failable_owned(|s: #name| s.#field_ident.into_iter().next())
108 }
109 });
110 }
111 (WrapperKind::HashMap, Some(inner_ty)) => {
112 tokens.extend(quote! {
113 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
114 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
115 }
116 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
117 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
118 }
119 pub fn #fr_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
120 key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.get(&key))
121 }
122 pub fn #fw_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
123 key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.get_mut(&key))
124 }
125 pub fn #fr_at_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
126 key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.get(&key))
127 }
128 pub fn #fw_at_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
129 key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.get_mut(&key))
130 }
131 // Owned keypath methods
132 pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
133 key_paths_core::KeyPaths::owned(|s: #name| s.#field_ident)
134 }
135 pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
136 key_paths_core::KeyPaths::failable_owned(|s: #name| s.#field_ident.into_values().next())
137 }
138 });
139 }
140 (WrapperKind::Box, Some(inner_ty)) => {
141 tokens.extend(quote! {
142 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
143 key_paths_core::KeyPaths::readable(|s: &#name| &*s.#field_ident)
144 }
145 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
146 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut *s.#field_ident)
147 }
148 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
149 key_paths_core::KeyPaths::failable_readable(|s: &#name| Some(&*s.#field_ident))
150 }
151 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
152 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| Some(&mut *s.#field_ident))
153 }
154 // Owned keypath methods
155 pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
156 key_paths_core::KeyPaths::owned(|s: #name| *s.#field_ident)
157 }
158 pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
159 key_paths_core::KeyPaths::failable_owned(|s: #name| Some(*s.#field_ident))
160 }
161 });
162 }
163 (WrapperKind::Rc, Some(inner_ty)) | (WrapperKind::Arc, Some(inner_ty)) => {
164 tokens.extend(quote! {
165 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
166 key_paths_core::KeyPaths::readable(|s: &#name| &*s.#field_ident)
167 }
168 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
169 key_paths_core::KeyPaths::failable_readable(|s: &#name| Some(&*s.#field_ident))
170 }
171 // Owned keypath methods
172 pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
173 key_paths_core::KeyPaths::owned(|s: #name| (*s.#field_ident).clone())
174 }
175 pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
176 key_paths_core::KeyPaths::failable_owned(|s: #name| Some((*s.#field_ident).clone()))
177 }
178 });
179 }
180 (WrapperKind::BTreeMap, Some(inner_ty)) => {
181 tokens.extend(quote! {
182 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
183 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
184 }
185 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
186 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
187 }
188 // Owned keypath methods
189 pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
190 key_paths_core::KeyPaths::owned(|s: #name| s.#field_ident)
191 }
192 pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
193 key_paths_core::KeyPaths::failable_owned(|s: #name| s.#field_ident.into_values().next())
194 }
195 // Note: Key-based access methods for BTreeMap require the exact key type
196 // For now, we'll skip generating these methods to avoid generic constraint issues
197 });
198 }
199 (WrapperKind::HashSet, Some(inner_ty)) => {
200 tokens.extend(quote! {
201 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
202 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
203 }
204 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
205 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
206 }
207 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
208 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.iter().next())
209 }
210 // Owned keypath methods
211 pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
212 key_paths_core::KeyPaths::owned(|s: #name| s.#field_ident)
213 }
214 pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
215 key_paths_core::KeyPaths::failable_owned(|s: #name| s.#field_ident.into_iter().next())
216 }
217 });
218 }
219 (WrapperKind::BTreeSet, Some(inner_ty)) => {
220 tokens.extend(quote! {
221 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
222 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
223 }
224 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
225 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
226 }
227 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
228 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.iter().next())
229 }
230 // Owned keypath methods
231 pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
232 key_paths_core::KeyPaths::owned(|s: #name| s.#field_ident)
233 }
234 pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
235 key_paths_core::KeyPaths::failable_owned(|s: #name| s.#field_ident.into_iter().next())
236 }
237 });
238 }
239 (WrapperKind::VecDeque, Some(inner_ty)) => {
240 tokens.extend(quote! {
241 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
242 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
243 }
244 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
245 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
246 }
247 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
248 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.front())
249 }
250 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
251 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#field_ident.front_mut())
252 }
253 pub fn #fr_at_fn(index: usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
254 key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.get(index))
255 }
256 pub fn #fw_at_fn(index: usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
257 key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.get_mut(index))
258 }
259 // Owned keypath methods
260 pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
261 key_paths_core::KeyPaths::owned(|s: #name| s.#field_ident)
262 }
263 pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
264 key_paths_core::KeyPaths::failable_owned(|s: #name| s.#field_ident.into_iter().next())
265 }
266 });
267 }
268 (WrapperKind::LinkedList, Some(inner_ty)) => {
269 tokens.extend(quote! {
270 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
271 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
272 }
273 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
274 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
275 }
276 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
277 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.front())
278 }
279 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
280 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#field_ident.front_mut())
281 }
282 // Owned keypath methods
283 pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
284 key_paths_core::KeyPaths::owned(|s: #name| s.#field_ident)
285 }
286 pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
287 key_paths_core::KeyPaths::failable_owned(|s: #name| s.#field_ident.into_iter().next())
288 }
289 });
290 }
291 (WrapperKind::BinaryHeap, Some(inner_ty)) => {
292 tokens.extend(quote! {
293 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
294 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
295 }
296 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
297 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
298 }
299 // Owned keypath methods
300 pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
301 key_paths_core::KeyPaths::owned(|s: #name| s.#field_ident)
302 }
303 pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
304 key_paths_core::KeyPaths::failable_owned(|s: #name| s.#field_ident.into_iter().next())
305 }
306 // Note: BinaryHeap peek() returns &T, but we need &inner_ty
307 // For now, we'll skip failable methods for BinaryHeap to avoid type issues
308 });
309 }
310 // Nested container combinations - COMMENTED OUT FOR NOW
311 // TODO: Fix type mismatch issues in nested combinations
312 /*
313 (WrapperKind::OptionBox, Some(inner_ty)) => {
314 tokens.extend(quote! {
315 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
316 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
317 }
318 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
319 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
320 }
321 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
322 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.as_ref().map(|b| &**b))
323 }
324 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
325 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#field_ident.as_mut().map(|b| &mut **b))
326 }
327 });
328 }
329 (WrapperKind::OptionRc, Some(inner_ty)) => {
330 tokens.extend(quote! {
331 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
332 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
333 }
334 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
335 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.as_ref().map(|r| &**r))
336 }
337 });
338 }
339 (WrapperKind::OptionArc, Some(inner_ty)) => {
340 tokens.extend(quote! {
341 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
342 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
343 }
344 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
345 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.as_ref().map(|a| &**a))
346 }
347 });
348 }
349 (WrapperKind::BoxOption, Some(inner_ty)) => {
350 tokens.extend(quote! {
351 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
352 key_paths_core::KeyPaths::readable(|s: &#name| &*s.#field_ident)
353 }
354 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
355 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut *s.#field_ident)
356 }
357 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
358 key_paths_core::KeyPaths::failable_readable(|s: &#name| (*s.#field_ident).as_ref())
359 }
360 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
361 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| (*s.#field_ident).as_mut())
362 }
363 });
364 }
365 (WrapperKind::RcOption, Some(inner_ty)) => {
366 tokens.extend(quote! {
367 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
368 key_paths_core::KeyPaths::readable(|s: &#name| &*s.#field_ident)
369 }
370 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
371 key_paths_core::KeyPaths::failable_readable(|s: &#name| (*s.#field_ident).as_ref())
372 }
373 });
374 }
375 (WrapperKind::ArcOption, Some(inner_ty)) => {
376 tokens.extend(quote! {
377 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
378 key_paths_core::KeyPaths::readable(|s: &#name| &*s.#field_ident)
379 }
380 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
381 key_paths_core::KeyPaths::failable_readable(|s: &#name| (*s.#field_ident).as_ref())
382 }
383 });
384 }
385 (WrapperKind::VecOption, Some(inner_ty)) => {
386 tokens.extend(quote! {
387 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
388 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
389 }
390 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
391 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
392 }
393 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
394 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.first().and_then(|opt| opt.as_ref()))
395 }
396 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
397 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#field_ident.first_mut().and_then(|opt| opt.as_mut()))
398 }
399 pub fn #fr_at_fn(index: usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
400 key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.get(index).and_then(|opt| opt.as_ref()))
401 }
402 pub fn #fw_at_fn(index: usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
403 key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.get_mut(index).and_then(|opt| opt.as_mut()))
404 }
405 });
406 }
407 (WrapperKind::OptionVec, Some(inner_ty)) => {
408 tokens.extend(quote! {
409 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
410 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
411 }
412 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
413 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
414 }
415 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
416 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.as_ref().and_then(|v| v.first()))
417 }
418 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
419 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#field_ident.as_mut().and_then(|v| v.first_mut()))
420 }
421 pub fn #fr_at_fn(index: usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
422 key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.as_ref().and_then(|v| v.get(index)))
423 }
424 pub fn #fw_at_fn(index: usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
425 key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.as_mut().and_then(|v| v.get_mut(index)))
426 }
427 });
428 }
429 (WrapperKind::HashMapOption, Some(inner_ty)) => {
430 tokens.extend(quote! {
431 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
432 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
433 }
434 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
435 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
436 }
437 pub fn #fr_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> key_paths_core::KeyPaths<#name, #inner_ty> {
438 key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.get(&key).and_then(|opt| opt.as_ref()))
439 }
440 pub fn #fw_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> key_paths_core::KeyPaths<#name, #inner_ty> {
441 key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.get_mut(&key).and_then(|opt| opt.as_mut()))
442 }
443 pub fn #fr_at_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> key_paths_core::KeyPaths<#name, #inner_ty> {
444 key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.get(&key).and_then(|opt| opt.as_ref()))
445 }
446 pub fn #fw_at_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> key_paths_core::KeyPaths<#name, #inner_ty> {
447 key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.get_mut(&key).and_then(|opt| opt.as_mut()))
448 }
449 });
450 }
451 (WrapperKind::OptionHashMap, Some(inner_ty)) => {
452 tokens.extend(quote! {
453 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
454 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
455 }
456 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
457 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
458 }
459 pub fn #fr_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> key_paths_core::KeyPaths<#name, #inner_ty> {
460 key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.as_ref().and_then(|m| m.get(&key)))
461 }
462 pub fn #fw_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> key_paths_core::KeyPaths<#name, #inner_ty> {
463 key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.as_mut().and_then(|m| m.get_mut(&key)))
464 }
465 pub fn #fr_at_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> key_paths_core::KeyPaths<#name, #inner_ty> {
466 key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.as_ref().and_then(|m| m.get(&key)))
467 }
468 pub fn #fw_at_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> key_paths_core::KeyPaths<#name, #inner_ty> {
469 key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.as_mut().and_then(|m| m.get_mut(&key)))
470 }
471 });
472 }
473 */
474 (WrapperKind::None, None) => {
475 tokens.extend(quote! {
476 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
477 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
478 }
479 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
480 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
481 }
482 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #ty> {
483 key_paths_core::KeyPaths::failable_readable(|s: &#name| Some(&s.#field_ident))
484 }
485 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #ty> {
486 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| Some(&mut s.#field_ident))
487 }
488 // Owned keypath methods
489 pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
490 key_paths_core::KeyPaths::owned(|s: #name| s.#field_ident)
491 }
492 pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #ty> {
493 key_paths_core::KeyPaths::failable_owned(|s: #name| Some(s.#field_ident))
494 }
495 });
496 }
497 _ => {
498 tokens.extend(quote! {
499 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
500 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
501 }
502 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
503 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
504 }
505 // Owned keypath methods
506 pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
507 key_paths_core::KeyPaths::owned(|s: #name| s.#field_ident)
508 }
509 });
510 }
511 }
512 }
513 tokens
514 }
515 Fields::Unnamed(unnamed) => {
516 let mut tokens = proc_macro2::TokenStream::new();
517 for (idx, field) in unnamed.unnamed.iter().enumerate() {
518 let idx_lit = syn::Index::from(idx);
519 let ty = &field.ty;
520
521 let r_fn = format_ident!("f{}_r", idx);
522 let w_fn = format_ident!("f{}_w", idx);
523 let fr_fn = format_ident!("f{}_fr", idx);
524 let fw_fn = format_ident!("f{}_fw", idx);
525 let fr_at_fn = format_ident!("f{}_fr_at", idx);
526 let fw_at_fn = format_ident!("f{}_fw_at", idx);
527 // Owned keypath method names
528 let o_fn = format_ident!("f{}_o", idx);
529 let fo_fn = format_ident!("f{}_fo", idx);
530
531 let (kind, inner_ty) = extract_wrapper_inner_type(ty);
532
533 match (kind, inner_ty) {
534 (WrapperKind::Option, Some(inner_ty)) => {
535 tokens.extend(quote! {
536 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
537 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
538 }
539 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
540 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
541 }
542 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
543 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.as_ref())
544 }
545 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
546 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#idx_lit.as_mut())
547 }
548 // Owned keypath methods
549 pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
550 key_paths_core::KeyPaths::owned(|s: #name| s.#idx_lit)
551 }
552 pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
553 key_paths_core::KeyPaths::failable_owned(|s: #name| s.#idx_lit)
554 }
555 });
556 }
557 (WrapperKind::Vec, Some(inner_ty)) => {
558 tokens.extend(quote! {
559 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
560 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
561 }
562 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
563 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
564 }
565 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
566 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.first())
567 }
568 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
569 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#idx_lit.first_mut())
570 }
571 pub fn #fr_at_fn(index: &'static usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
572 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.get(*index))
573 }
574 pub fn #fw_at_fn(index: &'static usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
575 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#idx_lit.get_mut(*index))
576 }
577 // Owned keypath methods
578 pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
579 key_paths_core::KeyPaths::owned(|s: #name| s.#idx_lit)
580 }
581 pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
582 key_paths_core::KeyPaths::failable_owned(|s: #name| s.#idx_lit.into_iter().next())
583 }
584 });
585 }
586 (WrapperKind::HashMap, Some(inner_ty)) => {
587 tokens.extend(quote! {
588 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
589 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
590 }
591 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
592 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
593 }
594 pub fn #fr_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
595 key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#idx_lit.get(&key))
596 }
597 pub fn #fw_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
598 key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#idx_lit.get_mut(&key))
599 }
600 pub fn #fr_at_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
601 key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#idx_lit.get(&key))
602 }
603 pub fn #fw_at_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
604 key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#idx_lit.get_mut(&key))
605 }
606 // Owned keypath methods
607 pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
608 key_paths_core::KeyPaths::owned(|s: #name| s.#idx_lit)
609 }
610 pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
611 key_paths_core::KeyPaths::failable_owned(|s: #name| s.#idx_lit.into_values().next())
612 }
613 });
614 }
615 (WrapperKind::Box, Some(inner_ty)) => {
616 tokens.extend(quote! {
617 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
618 key_paths_core::KeyPaths::readable(|s: &#name| &*s.#idx_lit)
619 }
620 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
621 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut *s.#idx_lit)
622 }
623 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
624 key_paths_core::KeyPaths::failable_readable(|s: &#name| Some(&*s.#idx_lit))
625 }
626 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
627 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| Some(&mut *s.#idx_lit))
628 }
629 // Owned keypath methods
630 pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
631 key_paths_core::KeyPaths::owned(|s: #name| *s.#idx_lit)
632 }
633 pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
634 key_paths_core::KeyPaths::failable_owned(|s: #name| Some(*s.#idx_lit))
635 }
636 });
637 }
638 (WrapperKind::Rc, Some(inner_ty)) | (WrapperKind::Arc, Some(inner_ty)) => {
639 tokens.extend(quote! {
640 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
641 key_paths_core::KeyPaths::readable(|s: &#name| &*s.#idx_lit)
642 }
643 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
644 key_paths_core::KeyPaths::failable_readable(|s: &#name| Some(&*s.#idx_lit))
645 }
646 // Owned keypath methods
647 pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
648 key_paths_core::KeyPaths::owned(|s: #name| (*s.#idx_lit).clone())
649 }
650 pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
651 key_paths_core::KeyPaths::failable_owned(|s: #name| Some((*s.#idx_lit).clone()))
652 }
653 });
654 }
655 (WrapperKind::BTreeMap, Some(inner_ty)) => {
656 tokens.extend(quote! {
657 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
658 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
659 }
660 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
661 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
662 }
663 // Owned keypath methods
664 pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
665 key_paths_core::KeyPaths::owned(|s: #name| s.#idx_lit)
666 }
667 pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
668 key_paths_core::KeyPaths::failable_owned(|s: #name| s.#idx_lit.into_values().next())
669 }
670 // Note: Key-based access methods for BTreeMap require the exact key type
671 // For now, we'll skip generating these methods to avoid generic constraint issues
672 });
673 }
674 (WrapperKind::HashSet, Some(inner_ty)) => {
675 tokens.extend(quote! {
676 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
677 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
678 }
679 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
680 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
681 }
682 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
683 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.iter().next())
684 }
685 // Owned keypath methods
686 pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
687 key_paths_core::KeyPaths::owned(|s: #name| s.#idx_lit)
688 }
689 pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
690 key_paths_core::KeyPaths::failable_owned(|s: #name| s.#idx_lit.into_iter().next())
691 }
692 });
693 }
694 (WrapperKind::BTreeSet, Some(inner_ty)) => {
695 tokens.extend(quote! {
696 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
697 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
698 }
699 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
700 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
701 }
702 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
703 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.iter().next())
704 }
705 // Owned keypath methods
706 pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
707 key_paths_core::KeyPaths::owned(|s: #name| s.#idx_lit)
708 }
709 pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
710 key_paths_core::KeyPaths::failable_owned(|s: #name| s.#idx_lit.into_iter().next())
711 }
712 });
713 }
714 (WrapperKind::VecDeque, Some(inner_ty)) => {
715 tokens.extend(quote! {
716 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
717 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
718 }
719 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
720 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
721 }
722 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
723 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.front())
724 }
725 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
726 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#idx_lit.front_mut())
727 }
728 // Owned keypath methods
729 pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
730 key_paths_core::KeyPaths::owned(|s: #name| s.#idx_lit)
731 }
732 pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
733 key_paths_core::KeyPaths::failable_owned(|s: #name| s.#idx_lit.into_iter().next())
734 }
735 });
736 }
737 (WrapperKind::LinkedList, Some(inner_ty)) => {
738 tokens.extend(quote! {
739 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
740 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
741 }
742 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
743 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
744 }
745 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
746 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.front())
747 }
748 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
749 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#idx_lit.front_mut())
750 }
751 // Owned keypath methods
752 pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
753 key_paths_core::KeyPaths::owned(|s: #name| s.#idx_lit)
754 }
755 pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
756 key_paths_core::KeyPaths::failable_owned(|s: #name| s.#idx_lit.into_iter().next())
757 }
758 });
759 }
760 (WrapperKind::BinaryHeap, Some(inner_ty)) => {
761 tokens.extend(quote! {
762 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
763 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
764 }
765 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
766 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
767 }
768 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
769 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.peek())
770 }
771 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
772 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#idx_lit.peek_mut().map(|v| &mut **v))
773 }
774 // Owned keypath methods
775 pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
776 key_paths_core::KeyPaths::owned(|s: #name| s.#idx_lit)
777 }
778 pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
779 key_paths_core::KeyPaths::failable_owned(|s: #name| s.#idx_lit.into_iter().next())
780 }
781 });
782 }
783 // Nested container combinations for tuple structs - COMMENTED OUT FOR NOW
784 /*
785 (WrapperKind::OptionBox, Some(inner_ty)) => {
786 tokens.extend(quote! {
787 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
788 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
789 }
790 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
791 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
792 }
793 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
794 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.as_ref().map(|b| &**b))
795 }
796 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
797 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#idx_lit.as_mut().map(|b| &mut **b))
798 }
799 });
800 }
801 (WrapperKind::OptionRc, Some(inner_ty)) => {
802 tokens.extend(quote! {
803 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
804 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
805 }
806 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
807 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.as_ref().map(|r| &**r))
808 }
809 });
810 }
811 (WrapperKind::OptionArc, Some(inner_ty)) => {
812 tokens.extend(quote! {
813 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
814 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
815 }
816 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
817 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.as_ref().map(|a| &**a))
818 }
819 });
820 }
821 (WrapperKind::BoxOption, Some(inner_ty)) => {
822 tokens.extend(quote! {
823 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
824 key_paths_core::KeyPaths::readable(|s: &#name| &*s.#idx_lit)
825 }
826 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
827 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut *s.#idx_lit)
828 }
829 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
830 key_paths_core::KeyPaths::failable_readable(|s: &#name| (*s.#idx_lit).as_ref())
831 }
832 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
833 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| (*s.#idx_lit).as_mut())
834 }
835 });
836 }
837 (WrapperKind::RcOption, Some(inner_ty)) => {
838 tokens.extend(quote! {
839 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
840 key_paths_core::KeyPaths::readable(|s: &#name| &*s.#idx_lit)
841 }
842 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
843 key_paths_core::KeyPaths::failable_readable(|s: &#name| (*s.#idx_lit).as_ref())
844 }
845 });
846 }
847 (WrapperKind::ArcOption, Some(inner_ty)) => {
848 tokens.extend(quote! {
849 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
850 key_paths_core::KeyPaths::readable(|s: &#name| &*s.#idx_lit)
851 }
852 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
853 key_paths_core::KeyPaths::failable_readable(|s: &#name| (*s.#idx_lit).as_ref())
854 }
855 });
856 }
857 (WrapperKind::VecOption, Some(inner_ty)) => {
858 tokens.extend(quote! {
859 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
860 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
861 }
862 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
863 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
864 }
865 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
866 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.first().and_then(|opt| opt.as_ref()))
867 }
868 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
869 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#idx_lit.first_mut().and_then(|opt| opt.as_mut()))
870 }
871 });
872 }
873 (WrapperKind::OptionVec, Some(inner_ty)) => {
874 tokens.extend(quote! {
875 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
876 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
877 }
878 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
879 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
880 }
881 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
882 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.as_ref().and_then(|v| v.first()))
883 }
884 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
885 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#idx_lit.as_mut().and_then(|v| v.first_mut()))
886 }
887 });
888 }
889 (WrapperKind::HashMapOption, Some(inner_ty)) => {
890 tokens.extend(quote! {
891 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
892 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
893 }
894 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
895 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
896 }
897 pub fn #fr_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> key_paths_core::KeyPaths<#name, #inner_ty> {
898 key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#idx_lit.get(&key).and_then(|opt| opt.as_ref()))
899 }
900 pub fn #fw_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> key_paths_core::KeyPaths<#name, #inner_ty> {
901 key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#idx_lit.get_mut(&key).and_then(|opt| opt.as_mut()))
902 }
903 });
904 }
905 (WrapperKind::OptionHashMap, Some(inner_ty)) => {
906 tokens.extend(quote! {
907 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
908 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
909 }
910 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
911 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
912 }
913 pub fn #fr_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> key_paths_core::KeyPaths<#name, #inner_ty> {
914 key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#idx_lit.as_ref().and_then(|m| m.get(&key)))
915 }
916 pub fn #fw_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> key_paths_core::KeyPaths<#name, #inner_ty> {
917 key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#idx_lit.as_mut().and_then(|m| m.get_mut(&key)))
918 }
919 });
920 }
921 */
922 (WrapperKind::None, None) => {
923 tokens.extend(quote! {
924 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
925 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
926 }
927 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
928 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
929 }
930 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #ty> {
931 key_paths_core::KeyPaths::failable_readable(|s: &#name| Some(&s.#idx_lit))
932 }
933 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #ty> {
934 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| Some(&mut s.#idx_lit))
935 }
936 // Owned keypath methods
937 pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
938 key_paths_core::KeyPaths::owned(|s: #name| s.#idx_lit)
939 }
940 pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #ty> {
941 key_paths_core::KeyPaths::failable_owned(|s: #name| Some(s.#idx_lit))
942 }
943 });
944 }
945 _ => {
946 tokens.extend(quote! {
947 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
948 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
949 }
950 // Owned keypath methods
951 pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
952 key_paths_core::KeyPaths::owned(|s: #name| s.#idx_lit)
953 }
954 });
955 }
956 }
957 }
958 tokens
959 }
960 _ => quote! {
961 compile_error!("Keypaths derive supports only structs with named or unnamed fields");
962 },
963 },
964 Data::Enum(data_enum) => {
965 let mut tokens = proc_macro2::TokenStream::new();
966 for variant in data_enum.variants.iter() {
967 let v_ident = &variant.ident;
968 let snake = format_ident!("{}", to_snake_case(&v_ident.to_string()));
969 let r_fn = format_ident!("{}_case_r", snake);
970 let w_fn = format_ident!("{}_case_w", snake);
971 let _fr_fn = format_ident!("{}_case_fr", snake);
972 let _fw_fn = format_ident!("{}_case_fw", snake);
973 let fr_at_fn = format_ident!("{}_case_fr_at", snake);
974 let fw_at_fn = format_ident!("{}_case_fw_at", snake);
975
976 match &variant.fields {
977 Fields::Unit => {
978 tokens.extend(quote! {
979 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, ()> {
980 static UNIT: () = ();
981 key_paths_core::KeyPaths::readable_enum(
982 |_| #name::#v_ident,
983 |e: &#name| match e { #name::#v_ident => Some(&UNIT), _ => None }
984 )
985 }
986 });
987 }
988 Fields::Unnamed(unnamed) if unnamed.unnamed.len() == 1 => {
989 let field_ty = &unnamed.unnamed.first().unwrap().ty;
990 let (kind, inner_ty_opt) = extract_wrapper_inner_type(field_ty);
991
992 match (kind, inner_ty_opt) {
993 (WrapperKind::Option, Some(inner_ty)) => {
994 tokens.extend(quote! {
995 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
996 key_paths_core::KeyPaths::readable_enum(
997 #name::#v_ident,
998 |e: &#name| match e { #name::#v_ident(v) => v.as_ref(), _ => None }
999 )
1000 }
1001 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1002 key_paths_core::KeyPaths::writable_enum(
1003 #name::#v_ident,
1004 |e: &#name| match e { #name::#v_ident(v) => v.as_ref(), _ => None },
1005 |e: &mut #name| match e { #name::#v_ident(v) => v.as_mut(), _ => None },
1006 )
1007 }
1008 });
1009 }
1010 (WrapperKind::Vec, Some(inner_ty)) => {
1011 tokens.extend(quote! {
1012 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1013 key_paths_core::KeyPaths::readable_enum(
1014 #name::#v_ident,
1015 |e: &#name| match e { #name::#v_ident(v) => v.first(), _ => None }
1016 )
1017 }
1018 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1019 key_paths_core::KeyPaths::writable_enum(
1020 #name::#v_ident,
1021 |e: &#name| match e { #name::#v_ident(v) => v.first(), _ => None },
1022 |e: &mut #name| match e { #name::#v_ident(v) => v.first_mut(), _ => None },
1023 )
1024 }
1025 pub fn #fr_at_fn(index: &'static usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
1026 key_paths_core::KeyPaths::readable_enum(
1027 #name::#v_ident,
1028 |e: &#name| match e { #name::#v_ident(v) => v.get(*index), _ => None }
1029 )
1030 }
1031 pub fn #fw_at_fn(index: &'static usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
1032 key_paths_core::KeyPaths::writable_enum(
1033 #name::#v_ident,
1034 |e: &#name| match e { #name::#v_ident(v) => v.get(*index), _ => None },
1035 |e: &mut #name| match e { #name::#v_ident(v) => v.get_mut(*index), _ => None },
1036 )
1037 }
1038 });
1039 }
1040 (WrapperKind::HashMap, Some(inner_ty)) => {
1041 tokens.extend(quote! {
1042 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1043 key_paths_core::KeyPaths::readable_enum(
1044 #name::#v_ident,
1045 |e: &#name| match e { #name::#v_ident(v) => v.first().map(|(_, v)| v), _ => None }
1046 )
1047 }
1048 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1049 key_paths_core::KeyPaths::writable_enum(
1050 #name::#v_ident,
1051 |e: &#name| match e { #name::#v_ident(v) => v.first().map(|(_, v)| v), _ => None },
1052 |e: &mut #name| match e { #name::#v_ident(v) => v.first_mut().map(|(_, v)| v), _ => None },
1053 )
1054 }
1055 pub fn #fr_at_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: &'static K) -> key_paths_core::KeyPaths<#name, #inner_ty> {
1056 key_paths_core::KeyPaths::readable_enum(
1057 #name::#v_ident,
1058 |e: &#name| match e { #name::#v_ident(v) => v.get(key), _ => None }
1059 )
1060 }
1061 pub fn #fw_at_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: &'static K) -> key_paths_core::KeyPaths<#name, #inner_ty> {
1062 key_paths_core::KeyPaths::writable_enum(
1063 #name::#v_ident,
1064 |e: &#name| match e { #name::#v_ident(v) => v.get(key), _ => None },
1065 |e: &mut #name| match e { #name::#v_ident(v) => v.get_mut(key), _ => None },
1066 )
1067 }
1068 });
1069 }
1070 (WrapperKind::Box, Some(inner_ty)) => {
1071 tokens.extend(quote! {
1072 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1073 key_paths_core::KeyPaths::readable_enum(
1074 #name::#v_ident,
1075 |e: &#name| match e { #name::#v_ident(v) => Some(&*v), _ => None }
1076 )
1077 }
1078 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1079 key_paths_core::KeyPaths::writable_enum(
1080 #name::#v_ident,
1081 |e: &#name| match e { #name::#v_ident(v) => Some(&*v), _ => None },
1082 |e: &mut #name| match e { #name::#v_ident(v) => Some(&mut *v), _ => None },
1083 )
1084 }
1085 });
1086 }
1087 (WrapperKind::Rc, Some(inner_ty))
1088 | (WrapperKind::Arc, Some(inner_ty)) => {
1089 tokens.extend(quote! {
1090 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1091 key_paths_core::KeyPaths::readable_enum(
1092 #name::#v_ident,
1093 |e: &#name| match e { #name::#v_ident(v) => Some(&*v), _ => None }
1094 )
1095 }
1096 });
1097 }
1098 (WrapperKind::BTreeMap, Some(inner_ty)) => {
1099 tokens.extend(quote! {
1100 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1101 key_paths_core::KeyPaths::readable_enum(
1102 #name::#v_ident,
1103 |e: &#name| match e { #name::#v_ident(v) => v.first().map(|(_, v)| v), _ => None }
1104 )
1105 }
1106 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1107 key_paths_core::KeyPaths::writable_enum(
1108 #name::#v_ident,
1109 |e: &#name| match e { #name::#v_ident(v) => v.first().map(|(_, v)| v), _ => None },
1110 |e: &mut #name| match e { #name::#v_ident(v) => v.first_mut().map(|(_, v)| v), _ => None },
1111 )
1112 }
1113 });
1114 }
1115 (WrapperKind::HashSet, Some(inner_ty)) => {
1116 tokens.extend(quote! {
1117 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1118 key_paths_core::KeyPaths::readable_enum(
1119 #name::#v_ident,
1120 |e: &#name| match e { #name::#v_ident(v) => v.iter().next(), _ => None }
1121 )
1122 }
1123 });
1124 }
1125 (WrapperKind::BTreeSet, Some(inner_ty)) => {
1126 tokens.extend(quote! {
1127 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1128 key_paths_core::KeyPaths::readable_enum(
1129 #name::#v_ident,
1130 |e: &#name| match e { #name::#v_ident(v) => v.iter().next(), _ => None }
1131 )
1132 }
1133 });
1134 }
1135 (WrapperKind::VecDeque, Some(inner_ty)) => {
1136 tokens.extend(quote! {
1137 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1138 key_paths_core::KeyPaths::readable_enum(
1139 #name::#v_ident,
1140 |e: &#name| match e { #name::#v_ident(v) => v.front(), _ => None }
1141 )
1142 }
1143 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1144 key_paths_core::KeyPaths::writable_enum(
1145 #name::#v_ident,
1146 |e: &#name| match e { #name::#v_ident(v) => v.front(), _ => None },
1147 |e: &mut #name| match e { #name::#v_ident(v) => v.front_mut(), _ => None },
1148 )
1149 }
1150 });
1151 }
1152 (WrapperKind::LinkedList, Some(inner_ty)) => {
1153 tokens.extend(quote! {
1154 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1155 key_paths_core::KeyPaths::readable_enum(
1156 #name::#v_ident,
1157 |e: &#name| match e { #name::#v_ident(v) => v.front(), _ => None }
1158 )
1159 }
1160 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1161 key_paths_core::KeyPaths::writable_enum(
1162 #name::#v_ident,
1163 |e: &#name| match e { #name::#v_ident(v) => v.front(), _ => None },
1164 |e: &mut #name| match e { #name::#v_ident(v) => v.front_mut(), _ => None },
1165 )
1166 }
1167 });
1168 }
1169 (WrapperKind::BinaryHeap, Some(inner_ty)) => {
1170 tokens.extend(quote! {
1171 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1172 key_paths_core::KeyPaths::readable_enum(
1173 #name::#v_ident,
1174 |e: &#name| match e { #name::#v_ident(v) => v.peek(), _ => None }
1175 )
1176 }
1177 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1178 key_paths_core::KeyPaths::writable_enum(
1179 #name::#v_ident,
1180 |e: &#name| match e { #name::#v_ident(v) => v.peek(), _ => None },
1181 |e: &mut #name| match e { #name::#v_ident(v) => v.peek_mut().map(|v| &mut **v), _ => None },
1182 )
1183 }
1184 });
1185 }
1186 // Nested container combinations for enums - COMMENTED OUT FOR NOW
1187 /*
1188 (WrapperKind::OptionBox, Some(inner_ty)) => {
1189 tokens.extend(quote! {
1190 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1191 key_paths_core::KeyPaths::readable_enum(
1192 #name::#v_ident,
1193 |e: &#name| match e { #name::#v_ident(v) => v.as_ref().map(|b| &**b), _ => None }
1194 )
1195 }
1196 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1197 key_paths_core::KeyPaths::writable_enum(
1198 #name::#v_ident,
1199 |e: &#name| match e { #name::#v_ident(v) => v.as_ref().map(|b| &**b), _ => None },
1200 |e: &mut #name| match e { #name::#v_ident(v) => v.as_mut().map(|b| &mut **b), _ => None },
1201 )
1202 }
1203 });
1204 }
1205 (WrapperKind::OptionRc, Some(inner_ty)) => {
1206 tokens.extend(quote! {
1207 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1208 key_paths_core::KeyPaths::readable_enum(
1209 #name::#v_ident,
1210 |e: &#name| match e { #name::#v_ident(v) => v.as_ref().map(|r| &**r), _ => None }
1211 )
1212 }
1213 });
1214 }
1215 (WrapperKind::OptionArc, Some(inner_ty)) => {
1216 tokens.extend(quote! {
1217 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1218 key_paths_core::KeyPaths::readable_enum(
1219 #name::#v_ident,
1220 |e: &#name| match e { #name::#v_ident(v) => v.as_ref().map(|a| &**a), _ => None }
1221 )
1222 }
1223 });
1224 }
1225 (WrapperKind::BoxOption, Some(inner_ty)) => {
1226 tokens.extend(quote! {
1227 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #field_ty> {
1228 key_paths_core::KeyPaths::readable_enum(
1229 #name::#v_ident,
1230 |e: &#name| match e { #name::#v_ident(v) => Some(&*v), _ => None }
1231 )
1232 }
1233 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #field_ty> {
1234 key_paths_core::KeyPaths::writable_enum(
1235 #name::#v_ident,
1236 |e: &#name| match e { #name::#v_ident(v) => Some(&*v), _ => None },
1237 |e: &mut #name| match e { #name::#v_ident(v) => Some(&mut *v), _ => None },
1238 )
1239 }
1240 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1241 key_paths_core::KeyPaths::readable_enum(
1242 #name::#v_ident,
1243 |e: &#name| match e { #name::#v_ident(v) => (*v).as_ref(), _ => None }
1244 )
1245 }
1246 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1247 key_paths_core::KeyPaths::writable_enum(
1248 #name::#v_ident,
1249 |e: &#name| match e { #name::#v_ident(v) => (*v).as_ref(), _ => None },
1250 |e: &mut #name| match e { #name::#v_ident(v) => (*v).as_mut(), _ => None },
1251 )
1252 }
1253 });
1254 }
1255 (WrapperKind::RcOption, Some(inner_ty)) => {
1256 tokens.extend(quote! {
1257 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #field_ty> {
1258 key_paths_core::KeyPaths::readable_enum(
1259 #name::#v_ident,
1260 |e: &#name| match e { #name::#v_ident(v) => Some(&*v), _ => None }
1261 )
1262 }
1263 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1264 key_paths_core::KeyPaths::readable_enum(
1265 #name::#v_ident,
1266 |e: &#name| match e { #name::#v_ident(v) => (*v).as_ref(), _ => None }
1267 )
1268 }
1269 });
1270 }
1271 (WrapperKind::ArcOption, Some(inner_ty)) => {
1272 tokens.extend(quote! {
1273 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #field_ty> {
1274 key_paths_core::KeyPaths::readable_enum(
1275 #name::#v_ident,
1276 |e: &#name| match e { #name::#v_ident(v) => Some(&*v), _ => None }
1277 )
1278 }
1279 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1280 key_paths_core::KeyPaths::readable_enum(
1281 #name::#v_ident,
1282 |e: &#name| match e { #name::#v_ident(v) => (*v).as_ref(), _ => None }
1283 )
1284 }
1285 });
1286 }
1287 (WrapperKind::VecOption, Some(inner_ty)) => {
1288 tokens.extend(quote! {
1289 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1290 key_paths_core::KeyPaths::readable_enum(
1291 #name::#v_ident,
1292 |e: &#name| match e { #name::#v_ident(v) => v.first().and_then(|opt| opt.as_ref()), _ => None }
1293 )
1294 }
1295 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1296 key_paths_core::KeyPaths::writable_enum(
1297 #name::#v_ident,
1298 |e: &#name| match e { #name::#v_ident(v) => v.first().and_then(|opt| opt.as_ref()), _ => None },
1299 |e: &mut #name| match e { #name::#v_ident(v) => v.first_mut().and_then(|opt| opt.as_mut()), _ => None },
1300 )
1301 }
1302 });
1303 }
1304 (WrapperKind::OptionVec, Some(inner_ty)) => {
1305 tokens.extend(quote! {
1306 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1307 key_paths_core::KeyPaths::readable_enum(
1308 #name::#v_ident,
1309 |e: &#name| match e { #name::#v_ident(v) => v.as_ref().and_then(|vec| vec.first()), _ => None }
1310 )
1311 }
1312 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1313 key_paths_core::KeyPaths::writable_enum(
1314 #name::#v_ident,
1315 |e: &#name| match e { #name::#v_ident(v) => v.as_ref().and_then(|vec| vec.first()), _ => None },
1316 |e: &mut #name| match e { #name::#v_ident(v) => v.as_mut().and_then(|vec| vec.first_mut()), _ => None },
1317 )
1318 }
1319 });
1320 }
1321 (WrapperKind::HashMapOption, Some(inner_ty)) => {
1322 tokens.extend(quote! {
1323 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1324 key_paths_core::KeyPaths::readable_enum(
1325 #name::#v_ident,
1326 |e: &#name| match e { #name::#v_ident(v) => v.first().and_then(|(_, opt)| opt.as_ref()), _ => None }
1327 )
1328 }
1329 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1330 key_paths_core::KeyPaths::writable_enum(
1331 #name::#v_ident,
1332 |e: &#name| match e { #name::#v_ident(v) => v.first().and_then(|(_, opt)| opt.as_ref()), _ => None },
1333 |e: &mut #name| match e { #name::#v_ident(v) => v.first_mut().and_then(|(_, opt)| opt.as_mut()), _ => None },
1334 )
1335 }
1336 });
1337 }
1338 (WrapperKind::OptionHashMap, Some(inner_ty)) => {
1339 tokens.extend(quote! {
1340 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1341 key_paths_core::KeyPaths::readable_enum(
1342 #name::#v_ident,
1343 |e: &#name| match e { #name::#v_ident(v) => v.as_ref().and_then(|map| map.first().map(|(_, v)| v)), _ => None }
1344 )
1345 }
1346 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1347 key_paths_core::KeyPaths::writable_enum(
1348 #name::#v_ident,
1349 |e: &#name| match e { #name::#v_ident(v) => v.as_ref().and_then(|map| map.first().map(|(_, v)| v)), _ => None },
1350 |e: &mut #name| match e { #name::#v_ident(v) => v.as_mut().and_then(|map| map.first_mut().map(|(_, v)| v)), _ => None },
1351 )
1352 }
1353 });
1354 }
1355 */
1356 (WrapperKind::None, None) => {
1357 let inner_ty = field_ty;
1358 tokens.extend(quote! {
1359 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1360 key_paths_core::KeyPaths::readable_enum(
1361 #name::#v_ident,
1362 |e: &#name| match e { #name::#v_ident(v) => Some(v), _ => None }
1363 )
1364 }
1365 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1366 key_paths_core::KeyPaths::writable_enum(
1367 #name::#v_ident,
1368 |e: &#name| match e { #name::#v_ident(v) => Some(v), _ => None },
1369 |e: &mut #name| match e { #name::#v_ident(v) => Some(v), _ => None },
1370 )
1371 }
1372 });
1373 }
1374 _ => {
1375 tokens.extend(quote! {
1376 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #field_ty> {
1377 key_paths_core::KeyPaths::readable_enum(
1378 #name::#v_ident,
1379 |e: &#name| match e { #name::#v_ident(v) => Some(v), _ => None }
1380 )
1381 }
1382 });
1383 }
1384 }
1385 }
1386 _ => {
1387 tokens.extend(quote! {
1388 compile_error!("Casepaths derive supports only unit and single-field tuple variants");
1389 });
1390 }
1391 }
1392 }
1393 tokens
1394 }
1395 _ => quote! {
1396 compile_error!("Keypaths derive supports only structs and enums");
1397 },
1398 };
1399
1400 let expanded = quote! {
1401 impl #name {
1402 #methods
1403 }
1404 };
1405
1406 TokenStream::from(expanded)
1407}
1408
1409fn extract_wrapper_inner_type(ty: &Type) -> (WrapperKind, Option<Type>) {
1410 use syn::{GenericArgument, PathArguments};
1411
1412 if let Type::Path(tp) = ty {
1413 if let Some(seg) = tp.path.segments.last() {
1414 let ident_str = seg.ident.to_string();
1415
1416 if let PathArguments::AngleBracketed(ab) = &seg.arguments {
1417 let args: Vec<_> = ab.args.iter().collect();
1418
1419 // Handle map types (HashMap, BTreeMap) - they have K, V parameters
1420 if ident_str == "HashMap" || ident_str == "BTreeMap" {
1421 if let (Some(_key_arg), Some(value_arg)) = (args.get(0), args.get(1)) {
1422 if let GenericArgument::Type(inner) = value_arg {
1423 eprintln!("Detected {} type, extracting value type", ident_str);
1424 return match ident_str.as_str() {
1425 "HashMap" => (WrapperKind::HashMap, Some(inner.clone())),
1426 "BTreeMap" => (WrapperKind::BTreeMap, Some(inner.clone())),
1427 _ => (WrapperKind::None, None),
1428 };
1429 }
1430 }
1431 }
1432 // Handle single-parameter container types
1433 else if let Some(arg) = args.get(0) {
1434 if let GenericArgument::Type(inner) = arg {
1435 // Check for nested containers first
1436 let (inner_kind, inner_inner) = extract_wrapper_inner_type(inner);
1437
1438 // Handle nested combinations
1439 match (ident_str.as_str(), inner_kind) {
1440 ("Option", WrapperKind::Box) => {
1441 return (WrapperKind::OptionBox, inner_inner);
1442 }
1443 ("Option", WrapperKind::Rc) => {
1444 return (WrapperKind::OptionRc, inner_inner);
1445 }
1446 ("Option", WrapperKind::Arc) => {
1447 return (WrapperKind::OptionArc, inner_inner);
1448 }
1449 ("Option", WrapperKind::Vec) => {
1450 return (WrapperKind::OptionVec, inner_inner);
1451 }
1452 ("Option", WrapperKind::HashMap) => {
1453 return (WrapperKind::OptionHashMap, inner_inner);
1454 }
1455 ("Box", WrapperKind::Option) => {
1456 return (WrapperKind::BoxOption, inner_inner);
1457 }
1458 ("Rc", WrapperKind::Option) => {
1459 return (WrapperKind::RcOption, inner_inner);
1460 }
1461 ("Arc", WrapperKind::Option) => {
1462 return (WrapperKind::ArcOption, inner_inner);
1463 }
1464 ("Vec", WrapperKind::Option) => {
1465 return (WrapperKind::VecOption, inner_inner);
1466 }
1467 ("HashMap", WrapperKind::Option) => {
1468 return (WrapperKind::HashMapOption, inner_inner);
1469 }
1470 _ => {
1471 // Handle single-level containers
1472 return match ident_str.as_str() {
1473 "Option" => (WrapperKind::Option, Some(inner.clone())),
1474 "Box" => (WrapperKind::Box, Some(inner.clone())),
1475 "Rc" => (WrapperKind::Rc, Some(inner.clone())),
1476 "Arc" => (WrapperKind::Arc, Some(inner.clone())),
1477 "Vec" => (WrapperKind::Vec, Some(inner.clone())),
1478 "HashSet" => (WrapperKind::HashSet, Some(inner.clone())),
1479 "BTreeSet" => (WrapperKind::BTreeSet, Some(inner.clone())),
1480 "VecDeque" => (WrapperKind::VecDeque, Some(inner.clone())),
1481 "LinkedList" => (WrapperKind::LinkedList, Some(inner.clone())),
1482 "BinaryHeap" => (WrapperKind::BinaryHeap, Some(inner.clone())),
1483 _ => (WrapperKind::None, None),
1484 };
1485 }
1486 }
1487 }
1488 }
1489 }
1490 }
1491 }
1492 (WrapperKind::None, None)
1493}
1494
1495
1496fn to_snake_case(name: &str) -> String {
1497 let mut out = String::new();
1498 for (i, c) in name.chars().enumerate() {
1499 if c.is_uppercase() {
1500 if i != 0 {
1501 out.push('_');
1502 }
1503 out.push(c.to_ascii_lowercase());
1504 } else {
1505 out.push(c);
1506 }
1507 }
1508 out
1509}
1510
1511#[proc_macro_derive(WritableKeypaths)]
1512pub fn derive_writable_keypaths(input: TokenStream) -> TokenStream {
1513 let input = parse_macro_input!(input as DeriveInput);
1514 let name = input.ident;
1515
1516 let methods = match input.data {
1517 Data::Struct(data_struct) => match data_struct.fields {
1518 Fields::Named(fields_named) => {
1519 let mut tokens = proc_macro2::TokenStream::new();
1520 for field in fields_named.named.iter() {
1521 let field_ident = field.ident.as_ref().unwrap();
1522 let ty = &field.ty;
1523
1524 let w_fn = format_ident!("{}_w", field_ident);
1525 let fw_fn = format_ident!("{}_fw", field_ident);
1526 let fw_at_fn = format_ident!("{}_fw_at", field_ident);
1527
1528 let (kind, inner_ty) = extract_wrapper_inner_type(ty);
1529
1530 match (kind, inner_ty) {
1531 (WrapperKind::Option, Some(inner_ty)) => {
1532 tokens.extend(quote! {
1533 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1534 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
1535 }
1536 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1537 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#field_ident.as_mut())
1538 }
1539 });
1540 }
1541 (WrapperKind::Vec, Some(inner_ty)) => {
1542 tokens.extend(quote! {
1543 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1544 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
1545 }
1546 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1547 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#field_ident.first_mut())
1548 }
1549 pub fn #fw_at_fn(index: usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
1550 key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.get_mut(index))
1551 }
1552 });
1553 }
1554 (WrapperKind::HashMap, Some(inner_ty)) => {
1555 tokens.extend(quote! {
1556 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1557 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
1558 }
1559 pub fn #fw_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
1560 key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.get_mut(&key))
1561 }
1562 pub fn #fw_at_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
1563 key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.get_mut(&key))
1564 }
1565 });
1566 }
1567 (WrapperKind::Box, Some(inner_ty)) => {
1568 tokens.extend(quote! {
1569 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1570 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut *s.#field_ident)
1571 }
1572 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1573 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| Some(&mut *s.#field_ident))
1574 }
1575 });
1576 }
1577 (WrapperKind::Rc, Some(inner_ty)) | (WrapperKind::Arc, Some(inner_ty)) => {
1578 tokens.extend(quote! {
1579 // Note: Rc/Arc are not writable due to shared ownership
1580 // Only providing readable methods for these types
1581 });
1582 }
1583 (WrapperKind::BTreeMap, Some(inner_ty)) => {
1584 tokens.extend(quote! {
1585 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1586 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
1587 }
1588 pub fn #fw_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
1589 key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.get_mut(&key))
1590 }
1591 pub fn #fw_at_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
1592 key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.get_mut(&key))
1593 }
1594 });
1595 }
1596 (WrapperKind::HashSet, Some(inner_ty)) => {
1597 tokens.extend(quote! {
1598 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1599 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
1600 }
1601 // Note: HashSet doesn't have direct mutable access to elements
1602 // Only providing container-level writable access
1603 });
1604 }
1605 (WrapperKind::BTreeSet, Some(inner_ty)) => {
1606 tokens.extend(quote! {
1607 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1608 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
1609 }
1610 // Note: BTreeSet doesn't have direct mutable access to elements
1611 // Only providing container-level writable access
1612 });
1613 }
1614 (WrapperKind::VecDeque, Some(inner_ty)) => {
1615 tokens.extend(quote! {
1616 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1617 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
1618 }
1619 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1620 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#field_ident.front_mut())
1621 }
1622 pub fn #fw_at_fn(index: usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
1623 key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.get_mut(index))
1624 }
1625 });
1626 }
1627 (WrapperKind::LinkedList, Some(inner_ty)) => {
1628 tokens.extend(quote! {
1629 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1630 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
1631 }
1632 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1633 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#field_ident.front_mut())
1634 }
1635 });
1636 }
1637 (WrapperKind::BinaryHeap, Some(inner_ty)) => {
1638 tokens.extend(quote! {
1639 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1640 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
1641 }
1642 // Note: BinaryHeap peek_mut() returns PeekMut wrapper that doesn't allow direct mutable access
1643 // Only providing container-level writable access
1644 });
1645 }
1646 (WrapperKind::None, None) => {
1647 tokens.extend(quote! {
1648 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1649 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
1650 }
1651 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1652 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| Some(&mut s.#field_ident))
1653 }
1654 });
1655 }
1656 _ => {
1657 tokens.extend(quote! {
1658 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1659 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
1660 }
1661 });
1662 }
1663 }
1664 }
1665 tokens
1666 }
1667 Fields::Unnamed(unnamed) => {
1668 let mut tokens = proc_macro2::TokenStream::new();
1669 for (idx, field) in unnamed.unnamed.iter().enumerate() {
1670 let idx_lit = syn::Index::from(idx);
1671 let ty = &field.ty;
1672
1673 let w_fn = format_ident!("f{}_w", idx);
1674 let fw_fn = format_ident!("f{}_fw", idx);
1675 let fw_at_fn = format_ident!("f{}_fw_at", idx);
1676
1677 let (kind, inner_ty) = extract_wrapper_inner_type(ty);
1678
1679 match (kind, inner_ty) {
1680 (WrapperKind::Option, Some(inner_ty)) => {
1681 tokens.extend(quote! {
1682 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1683 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
1684 }
1685 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1686 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#idx_lit.as_mut())
1687 }
1688 });
1689 }
1690 (WrapperKind::Vec, Some(inner_ty)) => {
1691 tokens.extend(quote! {
1692 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1693 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
1694 }
1695 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1696 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#idx_lit.first_mut())
1697 }
1698 pub fn #fw_at_fn(index: &'static usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
1699 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#idx_lit.get_mut(*index))
1700 }
1701 });
1702 }
1703 (WrapperKind::HashMap, Some(inner_ty)) => {
1704 tokens.extend(quote! {
1705 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1706 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
1707 }
1708 pub fn #fw_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
1709 key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#idx_lit.get_mut(&key))
1710 }
1711 pub fn #fw_at_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
1712 key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#idx_lit.get_mut(&key))
1713 }
1714 });
1715 }
1716 (WrapperKind::Box, Some(inner_ty)) => {
1717 tokens.extend(quote! {
1718 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1719 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut *s.#idx_lit)
1720 }
1721 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1722 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| Some(&mut *s.#idx_lit))
1723 }
1724 });
1725 }
1726 (WrapperKind::Rc, Some(inner_ty)) | (WrapperKind::Arc, Some(inner_ty)) => {
1727 tokens.extend(quote! {
1728 // Note: Rc/Arc are not writable due to shared ownership
1729 // Only providing readable methods for these types
1730 });
1731 }
1732 (WrapperKind::BTreeMap, Some(inner_ty)) => {
1733 tokens.extend(quote! {
1734 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1735 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
1736 }
1737 pub fn #fw_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
1738 key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#idx_lit.get_mut(&key))
1739 }
1740 pub fn #fw_at_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
1741 key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#idx_lit.get_mut(&key))
1742 }
1743 });
1744 }
1745 (WrapperKind::HashSet, Some(inner_ty)) => {
1746 tokens.extend(quote! {
1747 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1748 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
1749 }
1750 // Note: HashSet doesn't have direct mutable access to elements
1751 // Only providing container-level writable access
1752 });
1753 }
1754 (WrapperKind::BTreeSet, Some(inner_ty)) => {
1755 tokens.extend(quote! {
1756 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1757 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
1758 }
1759 // Note: BTreeSet doesn't have direct mutable access to elements
1760 // Only providing container-level writable access
1761 });
1762 }
1763 (WrapperKind::VecDeque, Some(inner_ty)) => {
1764 tokens.extend(quote! {
1765 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1766 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
1767 }
1768 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1769 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#idx_lit.front_mut())
1770 }
1771 });
1772 }
1773 (WrapperKind::LinkedList, Some(inner_ty)) => {
1774 tokens.extend(quote! {
1775 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1776 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
1777 }
1778 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1779 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#idx_lit.front_mut())
1780 }
1781 });
1782 }
1783 (WrapperKind::BinaryHeap, Some(inner_ty)) => {
1784 tokens.extend(quote! {
1785 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1786 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
1787 }
1788 // Note: BinaryHeap peek_mut() returns PeekMut wrapper that doesn't allow direct mutable access
1789 // Only providing container-level writable access
1790 });
1791 }
1792 (WrapperKind::None, None) => {
1793 tokens.extend(quote! {
1794 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1795 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
1796 }
1797 pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1798 key_paths_core::KeyPaths::failable_writable(|s: &mut #name| Some(&mut s.#idx_lit))
1799 }
1800 });
1801 }
1802 _ => {
1803 tokens.extend(quote! {
1804 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1805 key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
1806 }
1807 });
1808 }
1809 }
1810 }
1811 tokens
1812 }
1813 _ => quote! {
1814 compile_error!("WritableKeypaths derive supports only structs with named or unnamed fields");
1815 },
1816 },
1817 _ => quote! {
1818 compile_error!("WritableKeypaths derive supports only structs");
1819 },
1820 };
1821
1822 let expanded = quote! {
1823 impl #name {
1824 #methods
1825 }
1826 };
1827
1828 TokenStream::from(expanded)
1829}
1830
1831#[proc_macro_derive(Keypath)]
1832pub fn derive_keypath(input: TokenStream) -> TokenStream {
1833 let input = parse_macro_input!(input as DeriveInput);
1834 let name = input.ident;
1835
1836 let methods = match input.data {
1837 Data::Struct(data_struct) => match data_struct.fields {
1838 Fields::Named(fields_named) => {
1839 let mut tokens = proc_macro2::TokenStream::new();
1840 for field in fields_named.named.iter() {
1841 let field_ident = field.ident.as_ref().unwrap();
1842 let ty = &field.ty;
1843
1844 let (kind, inner_ty) = extract_wrapper_inner_type(ty);
1845
1846 match (kind, inner_ty) {
1847 (WrapperKind::Option, Some(inner_ty)) => {
1848 // For Option<T>, return failable readable keypath to inner type
1849 tokens.extend(quote! {
1850 pub fn #field_ident() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1851 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.as_ref())
1852 }
1853 });
1854 }
1855 (WrapperKind::Vec, Some(inner_ty)) => {
1856 // For Vec<T>, return failable readable keypath to first element
1857 tokens.extend(quote! {
1858 pub fn #field_ident() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1859 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.first())
1860 }
1861 });
1862 }
1863 (WrapperKind::HashMap, Some(inner_ty)) => {
1864 // For HashMap<K,V>, return readable keypath to the container
1865 tokens.extend(quote! {
1866 pub fn #field_ident() -> key_paths_core::KeyPaths<#name, #ty> {
1867 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
1868 }
1869 });
1870 }
1871 (WrapperKind::BTreeMap, Some(inner_ty)) => {
1872 // For BTreeMap<K,V>, return readable keypath to the container
1873 tokens.extend(quote! {
1874 pub fn #field_ident() -> key_paths_core::KeyPaths<#name, #ty> {
1875 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
1876 }
1877 });
1878 }
1879 (WrapperKind::Box, Some(inner_ty)) => {
1880 // For Box<T>, return readable keypath to inner type
1881 tokens.extend(quote! {
1882 pub fn #field_ident() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1883 key_paths_core::KeyPaths::readable(|s: &#name| &*s.#field_ident)
1884 }
1885 });
1886 }
1887 (WrapperKind::Rc, Some(inner_ty)) | (WrapperKind::Arc, Some(inner_ty)) => {
1888 // For Rc<T>/Arc<T>, return readable keypath to inner type
1889 tokens.extend(quote! {
1890 pub fn #field_ident() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1891 key_paths_core::KeyPaths::readable(|s: &#name| &*s.#field_ident)
1892 }
1893 });
1894 }
1895 (WrapperKind::HashSet, Some(inner_ty)) => {
1896 // For HashSet<T>, return failable readable keypath to any element
1897 tokens.extend(quote! {
1898 pub fn #field_ident() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1899 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.iter().next())
1900 }
1901 });
1902 }
1903 (WrapperKind::BTreeSet, Some(inner_ty)) => {
1904 // For BTreeSet<T>, return failable readable keypath to any element
1905 tokens.extend(quote! {
1906 pub fn #field_ident() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1907 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.iter().next())
1908 }
1909 });
1910 }
1911 (WrapperKind::VecDeque, Some(inner_ty)) => {
1912 // For VecDeque<T>, return failable readable keypath to front element
1913 tokens.extend(quote! {
1914 pub fn #field_ident() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1915 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.front())
1916 }
1917 });
1918 }
1919 (WrapperKind::LinkedList, Some(inner_ty)) => {
1920 // For LinkedList<T>, return failable readable keypath to front element
1921 tokens.extend(quote! {
1922 pub fn #field_ident() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1923 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.front())
1924 }
1925 });
1926 }
1927 (WrapperKind::BinaryHeap, Some(inner_ty)) => {
1928 // For BinaryHeap<T>, return failable readable keypath to peek element
1929 tokens.extend(quote! {
1930 pub fn #field_ident() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1931 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.peek())
1932 }
1933 });
1934 }
1935 (WrapperKind::None, None) => {
1936 // For basic types, return readable keypath
1937 tokens.extend(quote! {
1938 pub fn #field_ident() -> key_paths_core::KeyPaths<#name, #ty> {
1939 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
1940 }
1941 });
1942 }
1943 _ => {
1944 // For unknown types, return readable keypath
1945 tokens.extend(quote! {
1946 pub fn #field_ident() -> key_paths_core::KeyPaths<#name, #ty> {
1947 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
1948 }
1949 });
1950 }
1951 }
1952 }
1953 tokens
1954 }
1955 Fields::Unnamed(unnamed) => {
1956 let mut tokens = proc_macro2::TokenStream::new();
1957 for (idx, field) in unnamed.unnamed.iter().enumerate() {
1958 let idx_lit = syn::Index::from(idx);
1959 let ty = &field.ty;
1960 let field_name = format_ident!("f{}", idx);
1961
1962 let (kind, inner_ty) = extract_wrapper_inner_type(ty);
1963
1964 match (kind, inner_ty) {
1965 (WrapperKind::Option, Some(inner_ty)) => {
1966 tokens.extend(quote! {
1967 pub fn #field_name() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1968 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.as_ref())
1969 }
1970 });
1971 }
1972 (WrapperKind::Vec, Some(inner_ty)) => {
1973 tokens.extend(quote! {
1974 pub fn #field_name() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1975 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.first())
1976 }
1977 });
1978 }
1979 (WrapperKind::HashMap, Some(inner_ty)) => {
1980 tokens.extend(quote! {
1981 pub fn #field_name() -> key_paths_core::KeyPaths<#name, #ty> {
1982 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
1983 }
1984 });
1985 }
1986 (WrapperKind::BTreeMap, Some(inner_ty)) => {
1987 tokens.extend(quote! {
1988 pub fn #field_name() -> key_paths_core::KeyPaths<#name, #ty> {
1989 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
1990 }
1991 });
1992 }
1993 (WrapperKind::Box, Some(inner_ty)) => {
1994 tokens.extend(quote! {
1995 pub fn #field_name() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1996 key_paths_core::KeyPaths::readable(|s: &#name| &*s.#idx_lit)
1997 }
1998 });
1999 }
2000 (WrapperKind::Rc, Some(inner_ty)) | (WrapperKind::Arc, Some(inner_ty)) => {
2001 tokens.extend(quote! {
2002 pub fn #field_name() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2003 key_paths_core::KeyPaths::readable(|s: &#name| &*s.#idx_lit)
2004 }
2005 });
2006 }
2007 (WrapperKind::HashSet, Some(inner_ty)) => {
2008 tokens.extend(quote! {
2009 pub fn #field_name() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2010 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.iter().next())
2011 }
2012 });
2013 }
2014 (WrapperKind::BTreeSet, Some(inner_ty)) => {
2015 tokens.extend(quote! {
2016 pub fn #field_name() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2017 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.iter().next())
2018 }
2019 });
2020 }
2021 (WrapperKind::VecDeque, Some(inner_ty)) => {
2022 tokens.extend(quote! {
2023 pub fn #field_name() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2024 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.front())
2025 }
2026 });
2027 }
2028 (WrapperKind::LinkedList, Some(inner_ty)) => {
2029 tokens.extend(quote! {
2030 pub fn #field_name() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2031 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.front())
2032 }
2033 });
2034 }
2035 (WrapperKind::BinaryHeap, Some(inner_ty)) => {
2036 tokens.extend(quote! {
2037 pub fn #field_name() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2038 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.peek())
2039 }
2040 });
2041 }
2042 (WrapperKind::None, None) => {
2043 tokens.extend(quote! {
2044 pub fn #field_name() -> key_paths_core::KeyPaths<#name, #ty> {
2045 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
2046 }
2047 });
2048 }
2049 _ => {
2050 tokens.extend(quote! {
2051 pub fn #field_name() -> key_paths_core::KeyPaths<#name, #ty> {
2052 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
2053 }
2054 });
2055 }
2056 }
2057 }
2058 tokens
2059 }
2060 _ => quote! {
2061 compile_error!("Keypath derive supports only structs with named or unnamed fields");
2062 },
2063 },
2064 _ => quote! {
2065 compile_error!("Keypath derive supports only structs");
2066 },
2067 };
2068
2069 let expanded = quote! {
2070 impl #name {
2071 #methods
2072 }
2073 };
2074
2075 TokenStream::from(expanded)
2076}
2077
2078#[proc_macro_derive(ReadableKeypaths)]
2079pub fn derive_readable_keypaths(input: TokenStream) -> TokenStream {
2080 let input = parse_macro_input!(input as DeriveInput);
2081 let name = input.ident;
2082
2083 let methods = match input.data {
2084 Data::Struct(data_struct) => match data_struct.fields {
2085 Fields::Named(fields_named) => {
2086 let mut tokens = proc_macro2::TokenStream::new();
2087 for field in fields_named.named.iter() {
2088 let field_ident = field.ident.as_ref().unwrap();
2089 let ty = &field.ty;
2090
2091 let r_fn = format_ident!("{}_r", field_ident);
2092 let fr_fn = format_ident!("{}_fr", field_ident);
2093 let fr_at_fn = format_ident!("{}_fr_at", field_ident);
2094
2095 let (kind, inner_ty) = extract_wrapper_inner_type(ty);
2096
2097 match (kind, inner_ty) {
2098 (WrapperKind::Option, Some(inner_ty)) => {
2099 tokens.extend(quote! {
2100 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2101 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
2102 }
2103 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2104 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.as_ref())
2105 }
2106 });
2107 }
2108 (WrapperKind::Vec, Some(inner_ty)) => {
2109 tokens.extend(quote! {
2110 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2111 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
2112 }
2113 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2114 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.first())
2115 }
2116 pub fn #fr_at_fn(index: usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
2117 key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.get(index))
2118 }
2119 });
2120 }
2121 (WrapperKind::HashMap, Some(inner_ty)) => {
2122 tokens.extend(quote! {
2123 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2124 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
2125 }
2126 pub fn #fr_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
2127 key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.get(&key))
2128 }
2129 pub fn #fr_at_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
2130 key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.get(&key))
2131 }
2132 });
2133 }
2134 (WrapperKind::Box, Some(inner_ty)) => {
2135 tokens.extend(quote! {
2136 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2137 key_paths_core::KeyPaths::readable(|s: &#name| &*s.#field_ident)
2138 }
2139 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2140 key_paths_core::KeyPaths::failable_readable(|s: &#name| Some(&*s.#field_ident))
2141 }
2142 });
2143 }
2144 (WrapperKind::Rc, Some(inner_ty)) | (WrapperKind::Arc, Some(inner_ty)) => {
2145 tokens.extend(quote! {
2146 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2147 key_paths_core::KeyPaths::readable(|s: &#name| &*s.#field_ident)
2148 }
2149 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2150 key_paths_core::KeyPaths::failable_readable(|s: &#name| Some(&*s.#field_ident))
2151 }
2152 });
2153 }
2154 (WrapperKind::BTreeMap, Some(inner_ty)) => {
2155 tokens.extend(quote! {
2156 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2157 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
2158 }
2159 pub fn #fr_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
2160 key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.get(&key))
2161 }
2162 pub fn #fr_at_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
2163 key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.get(&key))
2164 }
2165 });
2166 }
2167 (WrapperKind::HashSet, Some(inner_ty)) => {
2168 tokens.extend(quote! {
2169 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2170 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
2171 }
2172 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2173 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.iter().next())
2174 }
2175 });
2176 }
2177 (WrapperKind::BTreeSet, Some(inner_ty)) => {
2178 tokens.extend(quote! {
2179 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2180 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
2181 }
2182 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2183 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.iter().next())
2184 }
2185 });
2186 }
2187 (WrapperKind::VecDeque, Some(inner_ty)) => {
2188 tokens.extend(quote! {
2189 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2190 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
2191 }
2192 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2193 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.front())
2194 }
2195 pub fn #fr_at_fn(index: usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
2196 key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.get(index))
2197 }
2198 });
2199 }
2200 (WrapperKind::LinkedList, Some(inner_ty)) => {
2201 tokens.extend(quote! {
2202 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2203 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
2204 }
2205 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2206 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.front())
2207 }
2208 });
2209 }
2210 (WrapperKind::BinaryHeap, Some(inner_ty)) => {
2211 tokens.extend(quote! {
2212 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2213 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
2214 }
2215 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2216 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.peek())
2217 }
2218 });
2219 }
2220 (WrapperKind::None, None) => {
2221 tokens.extend(quote! {
2222 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2223 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
2224 }
2225 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2226 key_paths_core::KeyPaths::failable_readable(|s: &#name| Some(&s.#field_ident))
2227 }
2228 });
2229 }
2230 _ => {
2231 tokens.extend(quote! {
2232 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2233 key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
2234 }
2235 });
2236 }
2237 }
2238 }
2239 tokens
2240 }
2241 Fields::Unnamed(unnamed) => {
2242 let mut tokens = proc_macro2::TokenStream::new();
2243 for (idx, field) in unnamed.unnamed.iter().enumerate() {
2244 let idx_lit = syn::Index::from(idx);
2245 let ty = &field.ty;
2246
2247 let r_fn = format_ident!("f{}_r", idx);
2248 let fr_fn = format_ident!("f{}_fr", idx);
2249 let fr_at_fn = format_ident!("f{}_fr_at", idx);
2250
2251 let (kind, inner_ty) = extract_wrapper_inner_type(ty);
2252
2253 match (kind, inner_ty) {
2254 (WrapperKind::Option, Some(inner_ty)) => {
2255 tokens.extend(quote! {
2256 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2257 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
2258 }
2259 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2260 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.as_ref())
2261 }
2262 });
2263 }
2264 (WrapperKind::Vec, Some(inner_ty)) => {
2265 tokens.extend(quote! {
2266 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2267 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
2268 }
2269 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2270 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.first())
2271 }
2272 pub fn #fr_at_fn(index: &'static usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
2273 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.get(*index))
2274 }
2275 });
2276 }
2277 (WrapperKind::HashMap, Some(inner_ty)) => {
2278 tokens.extend(quote! {
2279 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2280 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
2281 }
2282 pub fn #fr_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
2283 key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#idx_lit.get(&key))
2284 }
2285 pub fn #fr_at_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
2286 key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#idx_lit.get(&key))
2287 }
2288 });
2289 }
2290 (WrapperKind::Box, Some(inner_ty)) => {
2291 tokens.extend(quote! {
2292 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2293 key_paths_core::KeyPaths::readable(|s: &#name| &*s.#idx_lit)
2294 }
2295 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2296 key_paths_core::KeyPaths::failable_readable(|s: &#name| Some(&*s.#idx_lit))
2297 }
2298 });
2299 }
2300 (WrapperKind::Rc, Some(inner_ty)) | (WrapperKind::Arc, Some(inner_ty)) => {
2301 tokens.extend(quote! {
2302 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2303 key_paths_core::KeyPaths::readable(|s: &#name| &*s.#idx_lit)
2304 }
2305 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2306 key_paths_core::KeyPaths::failable_readable(|s: &#name| Some(&*s.#idx_lit))
2307 }
2308 });
2309 }
2310 (WrapperKind::BTreeMap, Some(inner_ty)) => {
2311 tokens.extend(quote! {
2312 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2313 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
2314 }
2315 pub fn #fr_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
2316 key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#idx_lit.get(&key))
2317 }
2318 pub fn #fr_at_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
2319 key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#idx_lit.get(&key))
2320 }
2321 });
2322 }
2323 (WrapperKind::HashSet, Some(inner_ty)) => {
2324 tokens.extend(quote! {
2325 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2326 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
2327 }
2328 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2329 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.iter().next())
2330 }
2331 });
2332 }
2333 (WrapperKind::BTreeSet, Some(inner_ty)) => {
2334 tokens.extend(quote! {
2335 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2336 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
2337 }
2338 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2339 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.iter().next())
2340 }
2341 });
2342 }
2343 (WrapperKind::VecDeque, Some(inner_ty)) => {
2344 tokens.extend(quote! {
2345 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2346 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
2347 }
2348 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2349 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.front())
2350 }
2351 });
2352 }
2353 (WrapperKind::LinkedList, Some(inner_ty)) => {
2354 tokens.extend(quote! {
2355 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2356 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
2357 }
2358 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2359 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.front())
2360 }
2361 });
2362 }
2363 (WrapperKind::BinaryHeap, Some(inner_ty)) => {
2364 tokens.extend(quote! {
2365 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2366 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
2367 }
2368 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2369 key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.peek())
2370 }
2371 });
2372 }
2373 (WrapperKind::None, None) => {
2374 tokens.extend(quote! {
2375 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2376 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
2377 }
2378 pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2379 key_paths_core::KeyPaths::failable_readable(|s: &#name| Some(&s.#idx_lit))
2380 }
2381 });
2382 }
2383 _ => {
2384 tokens.extend(quote! {
2385 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2386 key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
2387 }
2388 });
2389 }
2390 }
2391 }
2392 tokens
2393 }
2394 _ => quote! {
2395 compile_error!("ReadableKeypaths derive supports only structs with named or unnamed fields");
2396 },
2397 },
2398 _ => quote! {
2399 compile_error!("ReadableKeypaths derive supports only structs");
2400 },
2401 };
2402
2403 let expanded = quote! {
2404 impl #name {
2405 #methods
2406 }
2407 };
2408
2409 TokenStream::from(expanded)
2410}
2411
2412#[proc_macro_derive(Casepaths)]
2413pub fn derive_casepaths(input: TokenStream) -> TokenStream {
2414 let input = parse_macro_input!(input as DeriveInput);
2415 let name = input.ident;
2416
2417 let tokens = match input.data {
2418 Data::Enum(data_enum) => {
2419 let mut tokens = proc_macro2::TokenStream::new();
2420 for variant in data_enum.variants.iter() {
2421 let v_ident = &variant.ident;
2422 let snake = format_ident!("{}", to_snake_case(&v_ident.to_string()));
2423 let r_fn = format_ident!("{}_case_r", snake);
2424 let w_fn = format_ident!("{}_case_w", snake);
2425
2426 match &variant.fields {
2427 Fields::Unit => {
2428 tokens.extend(quote! {
2429 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, ()> {
2430 static UNIT: () = ();
2431 key_paths_core::KeyPaths::readable_enum(
2432 |_| #name::#v_ident,
2433 |e: &#name| match e { #name::#v_ident => Some(&UNIT), _ => None }
2434 )
2435 }
2436 });
2437 }
2438 Fields::Unnamed(unnamed) if unnamed.unnamed.len() == 1 => {
2439 let inner_ty = &unnamed.unnamed.first().unwrap().ty;
2440 tokens.extend(quote! {
2441 pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2442 key_paths_core::KeyPaths::readable_enum(
2443 #name::#v_ident,
2444 |e: &#name| match e { #name::#v_ident(v) => Some(v), _ => None }
2445 )
2446 }
2447 pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2448 key_paths_core::KeyPaths::writable_enum(
2449 #name::#v_ident,
2450 |e: &#name| match e { #name::#v_ident(v) => Some(v), _ => None },
2451 |e: &mut #name| match e { #name::#v_ident(v) => Some(v), _ => None },
2452 )
2453 }
2454 });
2455 }
2456 _ => {
2457 tokens.extend(quote! {
2458 compile_error!("Casepaths derive supports only unit and single-field tuple variants");
2459 });
2460 }
2461 }
2462 }
2463 tokens
2464 }
2465 _ => quote! { compile_error!("Casepaths can only be derived for enums"); },
2466 };
2467
2468 let expanded = quote! {
2469 impl #name {
2470 #tokens
2471 }
2472 };
2473
2474 TokenStream::from(expanded)
2475}