1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{parse_macro_input, DeriveInput, Data, Fields};
4use syn::{Attribute, Ident};
5use std::collections::BTreeSet;
6
7#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
8enum PolyZipperTrait {
9 Zipper,
10 ZipperValues,
11 ZipperReadOnlyValues,
12 ZipperReadOnlyConditionalValues,
13 ZipperReadOnlyConditionalIteration,
14 ZipperReadOnlyIteration,
15 ZipperMoving,
16 ZipperIteration,
17 ZipperConcrete,
18 ZipperAbsolutePath,
19 ZipperPathBuffer,
20 ZipperSubtries,
21 ZipperInfallibleSubtries,
22}
23
24impl PolyZipperTrait {
25 fn from_ident(ident: &Ident) -> Option<Self> {
26 match ident.to_string().as_str() {
27 "Zipper" => Some(Self::Zipper),
28 "ZipperValues" => Some(Self::ZipperValues),
29 "ZipperReadOnlyValues" => Some(Self::ZipperReadOnlyValues),
30 "ZipperReadOnlyConditionalValues" => Some(Self::ZipperReadOnlyConditionalValues),
31 "ZipperReadOnlyConditionalIteration" => Some(Self::ZipperReadOnlyConditionalIteration),
32 "ZipperReadOnlyIteration" => Some(Self::ZipperReadOnlyIteration),
33 "ZipperMoving" => Some(Self::ZipperMoving),
34 "ZipperIteration" => Some(Self::ZipperIteration),
35 "ZipperConcrete" => Some(Self::ZipperConcrete),
36 "ZipperAbsolutePath" => Some(Self::ZipperAbsolutePath),
37 "ZipperPathBuffer" => Some(Self::ZipperPathBuffer),
38 "ZipperSubtries" => Some(Self::ZipperSubtries),
39 "ZipperInfallibleSubtries" => Some(Self::ZipperInfallibleSubtries),
40 _ => None,
41 }
42 }
43}
44
45fn all_poly_zipper_traits() -> BTreeSet<PolyZipperTrait> {
46 use PolyZipperTrait::*;
47 BTreeSet::from([
48 Zipper,
49 ZipperValues,
50 ZipperReadOnlyValues,
51 ZipperReadOnlyConditionalValues,
52 ZipperReadOnlyConditionalIteration,
53 ZipperReadOnlyIteration,
54 ZipperMoving,
55 ZipperIteration,
56 ZipperConcrete,
57 ZipperAbsolutePath,
58 ZipperPathBuffer,
59 ZipperSubtries,
60 ZipperInfallibleSubtries,
61 ])
62}
63
64fn add_trait_dependencies(traits: &mut BTreeSet<PolyZipperTrait>) {
65 use PolyZipperTrait::*;
66 let mut changed = true;
67 while changed {
68 changed = false;
69 if traits.contains(&ZipperReadOnlyIteration) {
70 if traits.insert(ZipperReadOnlyValues) {
71 changed = true;
72 }
73 if traits.insert(ZipperIteration) {
74 changed = true;
75 }
76 }
77 if traits.contains(&ZipperReadOnlyConditionalIteration) {
78 if traits.insert(ZipperReadOnlyConditionalValues) {
79 changed = true;
80 }
81 if traits.insert(ZipperIteration) {
82 changed = true;
83 }
84 }
85 if traits.contains(&ZipperReadOnlyValues) {
86 if traits.insert(ZipperValues) {
87 changed = true;
88 }
89 }
90 if traits.contains(&ZipperReadOnlyConditionalValues) {
91 if traits.insert(ZipperValues) {
92 changed = true;
93 }
94 }
95 if traits.contains(&ZipperIteration) {
96 if traits.insert(ZipperMoving) {
97 changed = true;
98 }
99 }
100 if traits.contains(&ZipperAbsolutePath) {
101 if traits.insert(ZipperMoving) {
102 changed = true;
103 }
104 }
105 if traits.contains(&ZipperPathBuffer) {
106 if traits.insert(ZipperMoving) {
107 changed = true;
108 }
109 }
110 if traits.contains(&ZipperMoving) {
111 if traits.insert(Zipper) {
112 changed = true;
113 }
114 }
115 if traits.contains(&ZipperSubtries) {
116 if traits.insert(ZipperValues) {
117 changed = true;
118 }
119 }
120 if traits.contains(&ZipperInfallibleSubtries) {
121 if traits.insert(ZipperValues) {
122 changed = true;
123 }
124 }
125 }
126}
127
128fn parse_explicit_traits(attrs: &[Attribute]) -> Result<Option<BTreeSet<PolyZipperTrait>>, syn::Error> {
129 let mut explicit: Option<BTreeSet<PolyZipperTrait>> = None;
130 for attr in attrs {
131 if !attr.path().is_ident("poly_zipper_explicit") {
132 continue;
133 }
134 if explicit.is_some() {
135 return Err(syn::Error::new_spanned(attr, "duplicate `poly_zipper_explicit` attribute"));
136 }
137 let mut trait_set = BTreeSet::new();
138 let mut saw_traits = false;
139 attr.parse_nested_meta(|meta| {
140 if meta.path.is_ident("traits") {
141 saw_traits = true;
142 meta.parse_nested_meta(|meta| {
143 let ident = meta.path.get_ident().ok_or_else(|| {
144 meta.error("expected trait name identifier")
145 })?;
146 let trait_kind = PolyZipperTrait::from_ident(ident).ok_or_else(|| {
147 meta.error("unknown trait name in poly_zipper_explicit traits list")
148 })?;
149 trait_set.insert(trait_kind);
150 Ok(())
151 })
152 } else {
153 Err(meta.error("expected `traits(...)`"))
154 }
155 })?;
156 if !saw_traits {
157 return Err(syn::Error::new_spanned(attr, "expected `traits(...)`"));
158 }
159 if trait_set.is_empty() {
160 return Err(syn::Error::new_spanned(attr, "traits list must not be empty"));
161 }
162 explicit = Some(trait_set);
163 }
164 Ok(explicit)
165}
166
167#[proc_macro_derive(PolyZipper)]
169pub fn derive_poly_zipper(input: TokenStream) -> TokenStream {
170 let input = parse_macro_input!(input as DeriveInput);
171 derive_poly_zipper_with_traits(input, all_poly_zipper_traits(), true)
172}
173
174#[proc_macro_derive(PolyZipperExplicit, attributes(poly_zipper_explicit))]
176pub fn derive_poly_zipper_explicit(input: TokenStream) -> TokenStream {
177 let input = parse_macro_input!(input as DeriveInput);
178 let explicit_traits = match parse_explicit_traits(&input.attrs) {
179 Ok(value) => value,
180 Err(err) => return TokenStream::from(err.to_compile_error()),
181 };
182 let mut traits = explicit_traits.unwrap_or_else(all_poly_zipper_traits);
183 add_trait_dependencies(&mut traits);
184 derive_poly_zipper_with_traits(input, traits, false)
185}
186
187fn derive_poly_zipper_with_traits(
188 input: DeriveInput,
189 traits: BTreeSet<PolyZipperTrait>,
190 include_where_clause: bool,
191) -> TokenStream {
192
193 let enum_name = &input.ident;
194 let generics = &input.generics;
195 let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
196
197 let variants = match &input.data {
199 Data::Enum(data_enum) => &data_enum.variants,
200 _ => panic!("PolyZipper can only be derived for enums"),
201 };
202
203 let from_impls = variants.iter().map(|variant| {
205 let variant_name = &variant.ident;
206
207 let inner_type = match &variant.fields {
209 Fields::Unnamed(fields) if fields.unnamed.len() == 1 => {
210 &fields.unnamed[0].ty
211 }
212 _ => panic!("Each variant must have exactly one unnamed field"),
213 };
214
215 quote! {
216 impl #impl_generics From<#inner_type> for #enum_name #ty_generics #where_clause {
217 fn from(value: #inner_type) -> Self {
218 #enum_name::#variant_name(value)
219 }
220 }
221
222 impl #impl_generics core::convert::TryFrom<#enum_name #ty_generics> for #inner_type #where_clause {
223 type Error = ();
224
225 fn try_from(value: #enum_name #ty_generics) -> Result<Self, Self::Error> {
226 match value {
227 #enum_name::#variant_name(inner) => Ok(inner),
228 _ => Err(()),
229 }
230 }
231 }
232 }
233 });
234
235 let variant_arms: Vec<_> = variants.iter().map(|variant| {
236 let variant_name = &variant.ident;
237 quote! { Self::#variant_name(inner) }
238 }).collect();
239
240 let inner_types: Vec<_> = variants.iter().map(|variant| {
241 match &variant.fields {
242 Fields::Unnamed(fields) if fields.unnamed.len() == 1 => {
243 &fields.unnamed[0].ty
244 }
245 _ => panic!("Each variant must have exactly one unnamed field"),
246 }
247 }).collect();
248
249 let zipper_impl = if traits.contains(&PolyZipperTrait::Zipper) {
251 let variant_arms = &variant_arms;
252 let zipper_where = if include_where_clause {
253 quote! {
254 where
255 #(#inner_types: pathmap::zipper::Zipper,)*
256 #where_clause
257 }
258 } else {
259 quote! {}
260 };
261 Some(quote! {
262 impl #impl_generics pathmap::zipper::Zipper for #enum_name #ty_generics
263 #zipper_where
264 {
265 fn path_exists(&self) -> bool {
266 match self {
267 #(#variant_arms => inner.path_exists(),)*
268 }
269 }
270
271 fn is_val(&self) -> bool {
272 match self {
273 #(#variant_arms => inner.is_val(),)*
274 }
275 }
276
277 fn child_count(&self) -> usize {
278 match self {
279 #(#variant_arms => inner.child_count(),)*
280 }
281 }
282
283 fn child_mask(&self) -> pathmap::utils::ByteMask {
284 match self {
285 #(#variant_arms => inner.child_mask(),)*
286 }
287 }
288 }
289 })
290 } else {
291 None
292 };
293
294 let zipper_values_impl = if traits.contains(&PolyZipperTrait::ZipperValues) {
296 let variant_arms = &variant_arms;
297 let zipper_values_where = if include_where_clause {
298 quote! {
299 where
300 #(#inner_types: pathmap::zipper::ZipperValues<V>,)*
301 #where_clause
302 }
303 } else {
304 quote! {}
305 };
306 Some(quote! {
307 impl #impl_generics pathmap::zipper::ZipperValues<V> for #enum_name #ty_generics
308 #zipper_values_where
309 {
310 fn val(&self) -> Option<&V> {
311 match self {
312 #(#variant_arms => inner.val(),)*
313 }
314 }
315
316 fn val_at<K: AsRef<[u8]>>(&self, path: K) -> Option<&V> {
317 match self {
318 #(#variant_arms => inner.val_at(path),)*
319 }
320 }
321 }
322 })
323 } else {
324 None
325 };
326
327 let zipper_read_only_values_impl = if traits.contains(&PolyZipperTrait::ZipperReadOnlyValues) {
329 let variant_arms = &variant_arms;
330 let zipper_read_only_values_where = if include_where_clause {
331 quote! {
332 where
333 #(#inner_types: pathmap::zipper::ZipperReadOnlyValues<'trie, V>,)*
334 #where_clause
335 }
336 } else {
337 quote! {}
338 };
339 Some(quote! {
340 impl #impl_generics pathmap::zipper::ZipperReadOnlyValues<'trie, V> for #enum_name #ty_generics
341 #zipper_read_only_values_where
342 {
343 fn get_val(&self) -> Option<&'trie V> {
344 match self {
345 #(#variant_arms => inner.get_val(),)*
346 }
347 }
348
349 fn get_val_at<K: AsRef<[u8]>>(&self, path: K) -> Option<&'trie V> {
350 match self {
351 #(#variant_arms => inner.get_val_at(path),)*
352 }
353 }
354 }
355 })
356 } else {
357 None
358 };
359
360 let witness_enum_name = syn::Ident::new(&format!("{}Witness", enum_name), enum_name.span());
362 let variant_names: Vec<_> = variants.iter().map(|variant| &variant.ident).collect();
363
364 let zipper_read_only_conditional_values_impl = if traits.contains(&PolyZipperTrait::ZipperReadOnlyConditionalValues) {
366 let zipper_read_only_conditional_values_where = if include_where_clause {
367 quote! {
368 where
369 #(#inner_types: pathmap::zipper::ZipperReadOnlyConditionalValues<'trie, V>,)*
370 #where_clause
371 }
372 } else {
373 quote! {}
374 };
375 Some(quote! {
376 pub enum #witness_enum_name #impl_generics
379 #zipper_read_only_conditional_values_where
380 {
381 #(#variant_names(<#inner_types as pathmap::zipper::ZipperReadOnlyConditionalValues<'trie, V>>::WitnessT),)*
382 }
383
384 impl #impl_generics pathmap::zipper::ZipperReadOnlyConditionalValues<'trie, V> for #enum_name #ty_generics
385 #zipper_read_only_conditional_values_where
386 {
387 type WitnessT = #witness_enum_name #ty_generics;
388
389 fn witness<'w>(&self) -> Self::WitnessT {
390 match self {
391 #(Self::#variant_names(inner) => #witness_enum_name::#variant_names(inner.witness()),)*
392 }
393 }
394
395 fn get_val_with_witness<'w>(&self, witness: &'w Self::WitnessT) -> Option<&'w V> where 'trie: 'w {
396 match (self, witness) {
397 #((Self::#variant_names(inner), #witness_enum_name::#variant_names(w)) => inner.get_val_with_witness(w),)*
398 _ => {
399 debug_assert!(false, "Witness variant must match zipper + variant");
400 None
401 },
402 }
403 }
404 }
405 })
406 } else {
407 None
408 };
409
410 let zipper_moving_impl = if traits.contains(&PolyZipperTrait::ZipperMoving) {
451 let variant_arms = &variant_arms;
452 let zipper_moving_where = if include_where_clause {
453 quote! {
454 where
455 #(#inner_types: pathmap::zipper::ZipperMoving,)*
456 #where_clause
457 }
458 } else {
459 quote! {}
460 };
461 Some(quote! {
462 impl #impl_generics pathmap::zipper::ZipperMoving for #enum_name #ty_generics
463 #zipper_moving_where
464 {
465 fn path(&self) -> &[u8] {
466 match self {
467 #(#variant_arms => inner.path(),)*
468 }
469 }
470
471 fn val_count(&self) -> usize {
472 match self {
473 #(#variant_arms => inner.val_count(),)*
474 }
475 }
476
477 fn descend_to<K: AsRef<[u8]>>(&mut self, k: K) {
478 match self {
479 #(#variant_arms => inner.descend_to(k),)*
480 }
481 }
482
483 fn descend_to_check<K: AsRef<[u8]>>(&mut self, k: K) -> bool {
484 match self {
485 #(#variant_arms => inner.descend_to_check(k),)*
486 }
487 }
488
489 #[inline]
490 fn descend_to_byte(&mut self, k: u8) {
491 match self {
492 #(#variant_arms => inner.descend_to_byte(k),)*
493 }
494 }
495
496 #[inline]
497 fn descend_to_existing_byte(&mut self, k: u8) -> bool {
498 match self {
499 #(#variant_arms => inner.descend_to_existing_byte(k),)*
500 }
501 }
502
503 fn ascend(&mut self, steps: usize) -> bool {
504 match self {
505 #(#variant_arms => inner.ascend(steps),)*
506 }
507 }
508
509 fn ascend_until(&mut self) -> bool {
510 match self {
511 #(#variant_arms => inner.ascend_until(),)*
512 }
513 }
514
515 fn ascend_until_branch(&mut self) -> bool {
516 match self {
517 #(#variant_arms => inner.ascend_until_branch(),)*
518 }
519 }
520 }
521 })
522 } else {
523 None
524 };
525
526 let zipper_concrete_impl = if traits.contains(&PolyZipperTrait::ZipperConcrete) {
528 let variant_arms = &variant_arms;
529 let zipper_concrete_where = if include_where_clause {
530 quote! {
531 where
532 #(#inner_types: pathmap::zipper::ZipperConcrete,)*
533 #where_clause
534 }
535 } else {
536 quote! {}
537 };
538 Some(quote! {
539 impl #impl_generics pathmap::zipper::ZipperConcrete for #enum_name #ty_generics
540 #zipper_concrete_where
541 {
542 fn shared_node_id(&self) -> Option<u64> {
543 match self {
544 #(#variant_arms => inner.shared_node_id(),)*
545 }
546 }
547 fn is_shared(&self) -> bool {
548 match self {
549 #(#variant_arms => inner.is_shared(),)*
550 }
551 }
552 }
553 })
554 } else {
555 None
556 };
557
558 let zipper_absolute_path_impl = if traits.contains(&PolyZipperTrait::ZipperAbsolutePath) {
560 let variant_arms = &variant_arms;
561 let zipper_absolute_path_where = if include_where_clause {
562 quote! {
563 where
564 #(#inner_types: pathmap::zipper::ZipperAbsolutePath,)*
565 #where_clause
566 }
567 } else {
568 quote! {}
569 };
570 Some(quote! {
571 impl #impl_generics pathmap::zipper::ZipperAbsolutePath for #enum_name #ty_generics
572 #zipper_absolute_path_where
573 {
574 fn origin_path(&self) -> &[u8] {
575 match self {
576 #(#variant_arms => inner.origin_path(),)*
577 }
578 }
579
580 fn root_prefix_path(&self) -> &[u8] {
581 match self {
582 #(#variant_arms => inner.root_prefix_path(),)*
583 }
584 }
585 }
586 })
587 } else {
588 None
589 };
590
591 let zipper_path_buffer_impl = if traits.contains(&PolyZipperTrait::ZipperPathBuffer) {
593 let variant_arms = &variant_arms;
594 let zipper_path_buffer_where = if include_where_clause {
595 quote! {
596 where
597 #(#inner_types: pathmap::zipper::ZipperPathBuffer,)*
598 #where_clause
599 }
600 } else {
601 quote! {}
602 };
603 Some(quote! {
604 impl #impl_generics pathmap::zipper::ZipperPathBuffer for #enum_name #ty_generics
605 #zipper_path_buffer_where
606 {
607 unsafe fn origin_path_assert_len(&self, len: usize) -> &[u8] {
608 match self {
609 #(#variant_arms => unsafe { inner.origin_path_assert_len(len) },)*
610 }
611 }
612
613 fn prepare_buffers(&mut self) {
614 match self {
615 #(#variant_arms => inner.prepare_buffers(),)*
616 }
617 }
618
619 fn reserve_buffers(&mut self, path_len: usize, stack_depth: usize) {
620 match self {
621 #(#variant_arms => inner.reserve_buffers(path_len, stack_depth),)*
622 }
623 }
624 }
625 })
626 } else {
627 None
628 };
629
630 let zipper_iteration_impl = if traits.contains(&PolyZipperTrait::ZipperIteration) {
632 let variant_arms = &variant_arms;
633 let zipper_iteration_where = if include_where_clause {
634 quote! {
635 where
636 #(#inner_types: pathmap::zipper::ZipperIteration,)*
637 #where_clause
638 }
639 } else {
640 quote! {}
641 };
642 Some(quote! {
643 impl #impl_generics pathmap::zipper::ZipperIteration for #enum_name #ty_generics
644 #zipper_iteration_where
645 {
646 fn to_next_val(&mut self) -> bool {
647 match self {
648 #(#variant_arms => inner.to_next_val(),)*
649 }
650 }
651
652 fn descend_last_path(&mut self) -> bool {
653 match self {
654 #(#variant_arms => inner.descend_last_path(),)*
655 }
656 }
657
658 fn descend_first_k_path(&mut self, k: usize) -> bool {
659 match self {
660 #(#variant_arms => inner.descend_first_k_path(k),)*
661 }
662 }
663
664 fn to_next_k_path(&mut self, k: usize) -> bool {
665 match self {
666 #(#variant_arms => inner.to_next_k_path(k),)*
667 }
668 }
669 }
670 })
671 } else {
672 None
673 };
674
675 let zipper_read_only_iteration_impl = if traits.contains(&PolyZipperTrait::ZipperReadOnlyIteration) {
677 let variant_arms = &variant_arms;
678 let zipper_read_only_iteration_where = if include_where_clause {
679 quote! {
680 where
681 #(#inner_types: pathmap::zipper::ZipperReadOnlyIteration<'trie, V>,)*
682 #where_clause
683 }
684 } else {
685 quote! {}
686 };
687 Some(quote! {
688 impl #impl_generics pathmap::zipper::ZipperReadOnlyIteration<'trie, V> for #enum_name #ty_generics
689 #zipper_read_only_iteration_where
690 {
691 fn to_next_get_val(&mut self) -> Option<&'trie V> {
692 match self {
693 #(#variant_arms => inner.to_next_get_val(),)*
694 }
695 }
696 }
697 })
698 } else {
699 None
700 };
701
702 let zipper_read_only_conditional_iteration_impl = if traits.contains(&PolyZipperTrait::ZipperReadOnlyConditionalIteration) {
704 let zipper_read_only_conditional_iteration_where = if include_where_clause {
705 quote! {
706 where
707 #(#inner_types: pathmap::zipper::ZipperReadOnlyConditionalIteration<'trie, V>,)*
708 #where_clause
709 }
710 } else {
711 quote! {}
712 };
713 Some(quote! {
714 impl #impl_generics pathmap::zipper::ZipperReadOnlyConditionalIteration<'trie, V> for #enum_name #ty_generics
715 #zipper_read_only_conditional_iteration_where
716 {
717 fn to_next_get_val_with_witness<'w>(&mut self, witness: &'w Self::WitnessT) -> Option<&'w V> where 'trie: 'w {
718 match (self, witness) {
719 #((Self::#variant_names(inner), #witness_enum_name::#variant_names(w)) => inner.to_next_get_val_with_witness(w),)*
720 _ => {
721 debug_assert!(false, "Witness variant must match zipper variant");
722 None
723 },
724 }
725 }
726 }
727 })
728 } else {
729 None
730 };
731
732 let zipper_subtries_impl = if traits.contains(&PolyZipperTrait::ZipperSubtries) {
736 let zipper_subtries_where = if include_where_clause {
737 quote! {
738 where
739 #(#inner_types: pathmap::zipper::ZipperSubtries<V>,)*
740 #where_clause
741 }
742 } else {
743 quote! {}
744 };
745 Some(quote! {
746 impl #impl_generics pathmap::zipper::ZipperSubtries<V> for #enum_name #ty_generics
747 #zipper_subtries_where
748 {
749 fn native_subtries(&self) -> bool {
750 match self {
751 #(#variant_arms => inner.native_subtries(),)*
752 }
753 }
754 fn try_make_map(&self) -> Option<pathmap::PathMap<V>> {
755 match self {
756 #(#variant_arms => inner.try_make_map(),)*
757 }
758 }
759 fn trie_ref(&self) -> Option<pathmap::zipper::TrieRef<'_, V>> {
760 match self {
761 #(#variant_arms => inner.trie_ref(),)*
762 }
763 }
764 fn alloc(&self) -> pathmap::alloc::GlobalAlloc {
765 pathmap::alloc::global_alloc()
766 }
767 }
768 })
769 } else {
770 None
771 };
772
773 let zipper_infallible_subtries_impl = if traits.contains(&PolyZipperTrait::ZipperInfallibleSubtries) {
776 let zipper_infallible_subtries_where = if include_where_clause {
777 quote! {
778 where
779 #(#inner_types: pathmap::zipper::ZipperInfallibleSubtries<V>,)*
780 #where_clause
781 }
782 } else {
783 quote! {}
784 };
785 Some(quote! {
786 impl #impl_generics pathmap::zipper::ZipperInfallibleSubtries<V> for #enum_name #ty_generics
787 #zipper_infallible_subtries_where
788 {
789 fn make_map(&self) -> pathmap::PathMap<V> {
790 match self {
791 #(#variant_arms => inner.make_map(),)*
792 }
793 }
794
795 fn get_trie_ref(&self) -> pathmap::zipper::TrieRef<'_, V> {
796 match self {
797 #(#variant_arms => inner.get_trie_ref(),)*
798 }
799 }
800
801 fn get_focus(&self) -> pathmap::zipper::OpaqueAbstractNodeRef<'_, V, pathmap::alloc::GlobalAlloc> {
802 match self {
803 #(#variant_arms => inner.get_focus(),)*
804 }
805 }
806
807 fn get_focus_at<K: AsRef<[u8]>>(&self, path: K) -> pathmap::zipper::OpaqueAbstractNodeRef<'_, V, pathmap::alloc::GlobalAlloc> {
808 match self {
809 #(#variant_arms => inner.get_focus_at(path),)*
810 }
811 }
812
813 fn try_borrow_focus(&self) -> Option<pathmap::zipper::OpaqueTrieNodeRef<'_, V, pathmap::alloc::GlobalAlloc>> {
814 match self {
815 #(#variant_arms => inner.try_borrow_focus(),)*
816 }
817 }
818 }
819 })
820 } else {
821 None
822 };
823
824 let expanded = quote! {
825 #(#from_impls)*
826 #zipper_impl
827 #zipper_values_impl
828 #zipper_read_only_values_impl
829 #zipper_read_only_conditional_values_impl
830 #zipper_moving_impl
832 #zipper_concrete_impl
833 #zipper_absolute_path_impl
834 #zipper_path_buffer_impl
835 #zipper_iteration_impl
836 #zipper_read_only_iteration_impl
837 #zipper_read_only_conditional_iteration_impl
838 #zipper_subtries_impl
839 #zipper_infallible_subtries_impl
840 };
841
842 TokenStream::from(expanded)
843}