1#![cfg_attr(nightly, feature(doc_cfg))]
2
3use std::borrow::Cow;
6use std::collections::HashMap;
7
8pub use unsynn;
9use unsynn::*;
10
11mod functions;
12#[cfg(test)]
13mod tests;
14mod vis;
15
16pub use self::functions::Function;
17pub use self::vis::Visibility;
18
19pub fn sanitize_for_tokenizer(content: &str) -> String {
28 let regex = raw_ident_regex();
29 let mut lines = content.lines().map(|line| {
30 if !line.trim_start().starts_with("//") {
32 regex.replace(line, "$1")
33 } else {
34 Cow::Borrowed(line)
35 }
36 });
37 lines.next().map_or_else(String::new, |line| {
38 let mut sanitized = String::with_capacity(content.len());
39 sanitized.push_str(&line);
40 for line in lines {
41 sanitized.push('\n');
42 sanitized.push_str(&line);
43 }
44 sanitized
45 })
46}
47
48fn raw_ident_regex() -> regex::Regex {
49 regex::Regex::new("`([[:alnum:]_]+)`").expect("Valid regex")
50}
51
52pub mod kw {
53 use unsynn::*;
55
56 unsynn! {
57 pub keyword Struct = "struct";
58 pub keyword Phantom = "phantom";
59 pub keyword Public = "public";
60 pub keyword Has = "has";
61 pub keyword Copy = "copy";
62 pub keyword Drop = "drop";
63 pub keyword Key = "key";
64 pub keyword Store = "store";
65 pub keyword Module = "module";
66 pub keyword Package = "package";
67 pub keyword Friend = "friend";
68 pub keyword Use = "use";
69 pub keyword Fun = "fun";
70 pub keyword As = "as";
71 pub keyword Const = "const";
72 pub keyword Mut = "mut";
73 pub keyword Entry = "entry";
74 pub keyword Native = "native";
75 pub keyword Macro = "macro";
76 pub keyword Vector = "vector";
77 pub keyword Enum = "enum";
78 }
79}
80
81unsynn! {
82 pub enum File {
83 ModuleLabel(LabeledModule),
85 Legacy(Vec<Module>),
87 }
88
89 pub struct LabeledModule {
93 attrs: Vec<Attribute>,
94 keyword: kw::Module,
95 named_address: Ident,
96 path_sep: PathSep,
97 ident: Ident,
98 semicolon: Semicolon,
99 contents: Vec<Item>,
100 }
101
102 pub struct Module {
104 pub attrs: Vec<Attribute>,
105 keyword: kw::Module,
106 pub named_address: Ident,
107 path_sep: PathSep,
108 pub ident: Ident,
109 contents: BraceGroupContaining<Vec<Item>>,
110 }
111
112 pub struct Item {
114 pub attrs: Vec<Attribute>,
115 vis: Option<Vis>,
116 pub kind: ItemKind,
117 }
118
119 #[derive(Clone)]
123 pub struct Attribute {
124 pound: Pound,
125 contents: BracketGroupContaining<DelimitedVec<Meta, Comma, TrailingDelimiter::Optional>>,
126 }
127
128 #[derive(Clone)]
137 enum Meta {
138 Doc(Cons<DocKw, Assign, LiteralString>),
140 For(ForKw),
141 Other {
142 ident: Ident,
143 sub: Option<SubMeta>,
144 }
145 }
146
147 keyword DocKw = "doc";
148 keyword ForKw = "for";
149
150 #[derive(Clone)]
151 enum SubMeta {
152 Eq(Cons<Assign, AttributeValue>),
153 List(ParenthesisGroupContaining<DelimitedVec<Box<Meta>, Comma, TrailingDelimiter::Optional>>),
154 }
155
156 #[derive(Clone)]
163 enum AttributeValue {
164 Lit(Literal),
165 NameAccessChain {
169 leading_name_access: Either<SyntaxIdent, Ident>,
172 path: DelimitedVec<PathSep, Ident, TrailingDelimiter::Forbidden>,
175 },
176 }
177
178 #[derive(Clone)]
184 struct Vis {
185 public: kw::Public,
186 modifier: Option<ParenthesisGroupContaining<VisibilityModifier>>,
187 }
188
189 #[derive(Clone)]
195 enum VisibilityModifier {
196 Package(kw::Package),
197 Friend(kw::Friend)
198 }
199
200 #[non_exhaustive]
204 pub enum ItemKind {
205 Struct(Struct),
206 Enum(Enum),
207 Import(Import),
208 UseFun(UseFun),
209 Const(Const),
210 Function(Function),
211 MacroFun(MacroFun),
212 NativeFun(NativeFun)
213 }
214
215 pub struct UseFun {
217 keyword: kw::Use,
218 fun_kw: kw::Fun,
219 path_prefix: Option<Cons<Ident, PathSep, Ident, PathSep>>,
220 fun: Ident,
221 as_kw: kw::As,
222 ty: Ident,
223 dot: Dot,
224 method: Ident,
225 semicolon: Semicolon,
226 }
227
228 pub struct Const {
231 const_kw: kw::Const,
232 ident: Ident,
233 colon: Colon,
234 ty: Type,
235 assign: Assign,
236 expr: ConstVal,
237 semicolon: Semicolon,
238 }
239
240 enum ConstVal {
241 Literal(Literal),
242 Vector(Cons<kw::Vector, BracketGroup>),
243 NamedAddress(Cons<At, Literal>),
244 Expr(Vec<Cons<Except<Semicolon>, TokenTree>>),
246 }
247
248 pub struct Import {
251 keyword: kw::Use,
252 named_address: Ident,
253 path_sep: PathSep,
254 module: ImportModule,
255 semicolon: Semicolon,
256 }
257
258 enum ImportModule {
260 One(ModuleOrItems),
261 Many(BraceGroupContaining<CommaDelimitedVec<ModuleOrItems>>),
262 }
263
264 #[derive(Clone)]
265 struct ModuleOrItems {
266 ident: Ident,
267 next: Option<AliasOrItems>,
268 }
269
270 #[derive(Clone)]
271 enum AliasOrItems {
272 Alias {
273 as_kw: kw::As,
274 alias: Ident,
275 },
276 Items {
277 sep: PathSep,
278 item: ImportItem,
279 }
280 }
281
282 #[derive(Clone)]
283 enum ImportItem {
284 One(MaybeAliased),
285 Many(BraceGroupContaining<CommaDelimitedVec<MaybeAliased>>)
286 }
287
288 #[derive(Clone)]
289 struct MaybeAliased {
290 ident: Ident,
291 alias: Option<Cons<kw::As, Ident>>,
292 }
293
294 #[derive(Clone)]
298 pub struct Struct {
299 keyword: kw::Struct,
300 pub ident: Ident,
301 pub generics: Option<Generics>,
302 pub kind: StructKind,
303 }
304
305 #[derive(Clone)]
307 pub enum StructKind {
308 Braced(BracedStruct),
309 Tuple(TupleStruct),
310 }
311
312 #[derive(Clone)]
314 pub struct BracedStruct {
315 abilities: Option<Abilities>,
316 pub fields: NamedFields,
317 }
318
319 #[derive(Clone)]
322 pub struct TupleStruct {
323 pub fields: PositionalFields,
324 abilities: Option<Cons<Abilities, Semicolon>>
325 }
326
327 #[derive(Clone)]
330 pub struct Enum {
331 keyword: kw::Enum,
332 pub ident: Ident,
333 pub generics: Option<Generics>,
334 abilities: Option<Abilities>,
335 content: BraceGroupContaining<CommaDelimitedVec<EnumVariant>>,
336 }
337
338 #[derive(Clone)]
339 pub struct EnumVariant {
340 pub attrs: Vec<Attribute>,
341 pub ident: Ident,
342 pub fields: Option<FieldsKind>
344 }
345
346 #[derive(Clone)]
348 pub enum FieldsKind {
349 Positional(PositionalFields),
350 Named(NamedFields),
351 }
352
353 #[derive(Clone)]
357 pub struct PositionalFields(ParenthesisGroupContaining<DelimitedVec<UnnamedField, Comma>>);
358
359 #[derive(Clone)]
361 pub struct NamedFields(BraceGroupContaining<DelimitedVec<NamedField, Comma>>);
362
363 #[derive(Clone)]
365 pub struct NamedField {
366 pub attrs: Vec<Attribute>,
367 pub ident: Ident,
368 colon: Colon,
369 pub ty: Type,
370 }
371
372 #[derive(Clone)]
374 pub struct UnnamedField {
375 pub attrs: Vec<Attribute>,
376 pub ty: Type,
377 }
378
379 #[derive(Clone)]
386 pub struct Generics {
387 lt_token: Lt,
388 type_args: DelimitedVec<Generic, Comma>,
389 gt_token: Gt,
390 }
391
392 #[derive(Clone)]
400 pub struct Generic {
401 pub phantom: Option<kw::Phantom>,
402 pub ident: Ident,
403 bounds: Option<GenericBounds>
404 }
405
406 #[derive(Clone)]
410 struct GenericBounds {
411 colon: Colon,
412 abilities: Many<Ability, Plus, TrailingDelimiter::Forbidden>,
413 }
414
415 #[derive(Clone)]
421 struct Abilities {
422 has: kw::Has,
423 keywords: Many<Ability, Comma, TrailingDelimiter::Forbidden>,
424 }
425
426 #[derive(Clone)]
428 pub enum Ability {
429 Copy(kw::Copy),
430 Drop(kw::Drop),
431 Key(kw::Key),
432 Store(kw::Store),
433 }
434
435 pub struct NativeFun {
438 native_kw: kw::Native,
439 fun_kw: kw::Fun,
440 ident: Ident,
441 generics: Option<Generics>,
442 args: ParenthesisGroup,
443 ret: Option<Cons<Colon, Either<MaybeRefType, ParenthesisGroup>>>,
444 semicolon: Semicolon
445 }
446
447 pub struct MacroFun {
450 macro_kw: kw::Macro,
451 fun_kw: kw::Fun,
452 ident: Ident,
453 generics: Option<MacroGenerics>,
454 args: ParenthesisGroup,
455 ret: Option<Cons<Colon, Either<MacroReturn, ParenthesisGroup>>>,
456 body: BraceGroup,
457 }
458
459 struct MacroGenerics {
460 lt_token: Lt,
461 type_args: DelimitedVec<MacroTypeArg, Comma>,
462 gt_token: Gt,
463 }
464
465 struct MacroTypeArg{
467 name: SyntaxIdent,
468 bounds: Option<GenericBounds>,
469 }
470
471 enum MacroReturn {
473 Underscore(Underscore),
474 Concrete(Cons<Option<Ref>, MacroReturnType>),
475 }
476
477 enum MacroReturnType {
484 MacroTypeName(SyntaxIdent),
485 Hybrid(HybridMacroType)
486 }
487
488 struct HybridMacroType {
489 ident: Ident,
490 type_args: Option<Cons<Lt, Many<Either<Type, SyntaxIdent, Box<HybridMacroType>>, Comma>, Gt>>
491 }
492
493 #[derive(Clone)]
498 struct SyntaxIdent {
499 dollar: Dollar,
500 ident: Ident,
501 }
502
503 struct MaybeRefType {
507 r#ref: Option<Ref>,
508 r#type: Type,
509 }
510
511 struct Ref {
513 and: And,
514 r#mut: Option<kw::Mut>,
515 }
516
517 #[derive(Clone)]
519 pub struct Type {
520 pub path: TypePath,
521 pub type_args: Option<TypeArgs>
522 }
523
524 #[derive(Clone)]
526 pub enum TypePath {
527 Full {
529 named_address: Ident,
530 sep0: PathSep,
531 module: Ident,
532 sep1: PathSep,
533 r#type: Ident,
534 },
535 Module {
537 module: Ident,
538 sep: PathSep,
539 r#type: Ident,
540 },
541 Ident(Ident),
543 }
544
545 #[derive(Clone)]
547 pub struct TypeArgs {
548 lt: Lt,
549 args: Many<Box<Type>, Comma>,
550 gt: Gt,
551 }
552}
553
554impl File {
555 pub fn into_modules(self) -> impl Iterator<Item = Module> {
556 match self {
557 Self::ModuleLabel(labeled) => std::iter::once(labeled.into_module()).boxed(),
558 Self::Legacy(modules) => modules.into_iter().boxed(),
559 }
560 }
561}
562
563impl LabeledModule {
564 pub fn into_module(self) -> Module {
565 Module {
566 attrs: self.attrs,
567 keyword: self.keyword,
568 named_address: self.named_address,
569 path_sep: self.path_sep,
570 ident: self.ident,
571 contents: BraceGroupContaining {
572 content: self.contents,
573 },
574 }
575 }
576}
577
578impl Module {
579 pub fn with_implicit_sui_imports(&mut self) -> &mut Self {
583 let implicit_imports: HashMap<_, _> = [
585 "use sui::object;",
586 "use sui::object::ID;",
587 "use sui::object::UID;",
588 "use sui::tx_context;",
589 "use sui::tx_context::TxContext;",
590 "use sui::transfer;",
591 ]
592 .into_iter()
593 .map(|text| {
594 text.to_token_iter()
595 .parse_all::<Import>()
596 .expect("Valid imports")
597 })
598 .map(|import| {
599 let ident = import
600 .imported_idents()
601 .next()
602 .expect("Each import exposes exactly one ident");
603 (ident.clone(), import)
604 })
605 .collect();
606
607 self.add_implicit_imports(implicit_imports)
608 }
609
610 pub fn with_implicit_iota_imports(&mut self) -> &mut Self {
614 let implicit_imports: HashMap<_, _> = [
616 "use iota::object;",
617 "use iota::object::ID;",
618 "use iota::object::UID;",
619 "use iota::tx_context;",
620 "use iota::tx_context::TxContext;",
621 "use iota::transfer;",
622 ]
623 .into_iter()
624 .map(|text| {
625 text.to_token_iter()
626 .parse_all::<Import>()
627 .expect("Valid imports")
628 })
629 .map(|import| {
630 let ident = import
631 .imported_idents()
632 .next()
633 .expect("Each import exposes exactly one ident");
634 (ident.clone(), import)
635 })
636 .collect();
637
638 self.add_implicit_imports(implicit_imports)
639 }
640
641 pub fn fully_qualify_datatype_field_types(&mut self) -> &mut Self {
643 let imports: HashMap<_, _> = self
645 .items()
646 .filter_map(|item| match &item.kind {
647 ItemKind::Import(import) => Some(import),
648 _ => None,
649 })
650 .flat_map(|import| import.flatten())
651 .collect();
652
653 for item in &mut self.contents.content {
655 match &mut item.kind {
656 ItemKind::Enum(e) => {
657 let generics = &e.generics();
658 e.map_types(|ty| ty.resolve(&imports, generics));
659 }
660 ItemKind::Struct(s) => {
661 let generics = &s.generics();
662 s.map_types(|ty| ty.resolve(&imports, generics));
663 }
664 _ => (),
665 }
666 }
667
668 self
669 }
670
671 pub fn items(&self) -> impl Iterator<Item = &Item> {
672 self.contents.content.iter()
673 }
674
675 #[cfg(test)]
676 pub fn into_items(self) -> impl Iterator<Item = Item> {
677 self.contents.content.into_iter()
678 }
679
680 fn add_implicit_imports(&mut self, mut implicit_imports: HashMap<Ident, Import>) -> &mut Self {
681 for item in self.items() {
683 let ItemKind::Import(import) = &item.kind else {
684 continue;
685 };
686 for ident in import.imported_idents() {
687 implicit_imports.remove(ident);
688 }
689 }
690
691 for (_, import) in implicit_imports {
693 self.contents.content.push(Item {
694 attrs: vec![],
695 vis: None,
696 kind: ItemKind::Import(import),
697 })
698 }
699 self
700 }
701}
702
703impl Import {
704 fn flatten(&self) -> impl Iterator<Item = (Ident, FlatImport)> + '_ {
707 let named_address = self.named_address.clone();
708 match &self.module {
709 ImportModule::One(module_or_items) => module_or_items.flatten(named_address),
711 ImportModule::Many(BraceGroupContaining { content: ms }) => ms
713 .iter()
714 .flat_map(move |Delimited { value, .. }| value.flatten(named_address.clone()))
715 .boxed(),
716 }
717 }
718
719 fn imported_idents(&self) -> impl Iterator<Item = &Ident> {
721 match &self.module {
722 ImportModule::One(module_or_items) => module_or_items.available_idents(),
723 ImportModule::Many(BraceGroupContaining { content: ms }) => ms
724 .iter()
725 .flat_map(|delimited| delimited.value.available_idents())
726 .boxed(),
727 }
728 }
729}
730
731impl ModuleOrItems {
732 fn flatten(&self, named_address: Ident) -> Box<dyn Iterator<Item = (Ident, FlatImport)> + '_> {
734 let module = self.ident.clone();
735
736 let Some(next) = &self.next else {
737 return std::iter::once((
739 module.clone(),
740 FlatImport::Module {
741 named_address,
742 module,
743 },
744 ))
745 .boxed();
746 };
747
748 match next {
749 AliasOrItems::Alias { alias, .. } => std::iter::once((
751 alias.clone(),
752 FlatImport::Module {
753 named_address,
754 module,
755 },
756 ))
757 .boxed(),
758
759 AliasOrItems::Items {
761 item: ImportItem::One(maybe_aliased),
762 ..
763 } => std::iter::once(maybe_aliased.flat_import(named_address, module)).boxed(),
764
765 AliasOrItems::Items {
767 item: ImportItem::Many(BraceGroupContaining { content: items }),
768 ..
769 } => items
770 .iter()
771 .map(move |Delimited { value, .. }| {
772 value.flat_import(named_address.clone(), module.clone())
773 })
774 .boxed(),
775 }
776 }
777
778 fn available_idents(&self) -> Box<dyn Iterator<Item = &Ident> + '_> {
780 let Some(next) = &self.next else {
781 return std::iter::once(&self.ident).boxed();
782 };
783
784 match next {
785 AliasOrItems::Alias { alias, .. } => std::iter::once(alias).boxed(),
786
787 AliasOrItems::Items {
788 item: ImportItem::One(item),
789 ..
790 } => std::iter::once(item.available_ident(&self.ident)).boxed(),
791
792 AliasOrItems::Items {
793 item: ImportItem::Many(BraceGroupContaining { content: items }),
794 ..
795 } => items
796 .iter()
797 .map(|delimited| delimited.value.available_ident(&self.ident))
798 .boxed(),
799 }
800 }
801}
802
803impl MaybeAliased {
804 fn flat_import(&self, named_address: Ident, module: Ident) -> (Ident, FlatImport) {
806 if self.ident == "Self" {
807 (
808 self.alias().unwrap_or(&module).clone(),
809 FlatImport::Module {
810 named_address,
811 module,
812 },
813 )
814 } else {
815 (
816 self.alias().unwrap_or(&self.ident).clone(),
817 FlatImport::Item {
818 named_address,
819 module,
820 r#type: self.ident.clone(),
821 },
822 )
823 }
824 }
825
826 fn available_ident<'a>(&'a self, module: &'a Ident) -> &'a Ident {
827 if self.ident == "Self" {
828 self.alias().unwrap_or(module)
829 } else {
830 self.alias().unwrap_or(&self.ident)
831 }
832 }
833
834 fn alias(&self) -> Option<&Ident> {
836 self.alias.as_ref().map(|cons| &cons.second)
837 }
838}
839
840impl Attribute {
841 pub fn is_doc(&self) -> bool {
843 matches!(
844 &self.contents.content[..],
845 [Delimited {
846 value: Meta::Doc(_),
847 ..
848 }]
849 )
850 }
851
852 pub const fn contents(&self) -> &impl ToTokens {
854 &self.contents.content
855 }
856
857 pub fn metas(&self) -> impl Iterator<Item = &dyn ToTokens> + '_ {
858 self.contents
859 .content
860 .iter()
861 .map(|delimited| &delimited.value as _)
862 }
863
864 pub fn external_attributes(&self) -> impl Iterator<Item = &dyn ToTokens> + '_ {
866 self.contents.content.iter().filter_map(|d| match &d.value {
867 Meta::Other {
868 ident,
869 sub: Some(SubMeta::List(inner)),
870 } if ident == "ext" => Some(&inner.content as _),
871 _ => None,
872 })
873 }
874}
875
876impl ItemKind {
877 pub const fn is_datatype(&self) -> bool {
879 matches!(self, Self::Enum(_) | Self::Struct(_))
880 }
881}
882
883impl Struct {
884 pub fn abilities(&self) -> impl Iterator<Item = &Ability> {
885 use StructKind as K;
886 match &self.kind {
887 K::Braced(braced) => braced
888 .abilities
889 .iter()
890 .flat_map(|a| a.keywords.iter())
891 .map(|d| &d.value)
892 .boxed(),
893 K::Tuple(tuple) => tuple
894 .abilities
895 .iter()
896 .flat_map(|a| a.first.keywords.iter())
897 .map(|d| &d.value)
898 .boxed(),
899 }
900 }
901}
902
903impl BracedStruct {
904 pub fn fields(&self) -> impl Iterator<Item = &NamedField> + Clone + '_ {
905 self.fields.fields()
906 }
907
908 pub fn is_empty(&self) -> bool {
910 self.fields.is_empty()
911 }
912}
913
914impl TupleStruct {
915 pub fn fields(&self) -> impl Iterator<Item = &UnnamedField> + Clone + '_ {
916 self.fields.fields()
917 }
918
919 pub fn is_empty(&self) -> bool {
921 self.fields.is_empty()
922 }
923}
924
925impl Enum {
926 pub fn abilities(&self) -> impl Iterator<Item = &Ability> {
927 self.abilities
928 .iter()
929 .flat_map(|a| a.keywords.iter())
930 .map(|d| &d.value)
931 }
932
933 pub fn variants(&self) -> impl Iterator<Item = &EnumVariant> {
934 self.content
935 .content
936 .iter()
937 .map(|Delimited { value, .. }| value)
938 }
939}
940
941impl NamedFields {
942 pub fn fields(&self) -> impl Iterator<Item = &NamedField> + Clone + '_ {
943 self.0.content.iter().map(|d| &d.value)
944 }
945
946 pub fn is_empty(&self) -> bool {
947 self.0.content.is_empty()
948 }
949}
950
951impl PositionalFields {
952 pub fn new() -> Self {
953 Self(ParenthesisGroupContaining {
954 content: std::iter::empty::<UnnamedField>()
955 .collect::<DelimitedVec<_, _, TrailingDelimiter::Mandatory>>()
956 .into(),
957 })
958 }
959
960 pub fn fields(&self) -> impl Iterator<Item = &UnnamedField> + Clone + '_ {
961 self.0.content.iter().map(|d| &d.value)
962 }
963
964 pub fn is_empty(&self) -> bool {
965 self.0.content.is_empty()
966 }
967}
968
969impl Default for PositionalFields {
970 fn default() -> Self {
971 Self::new()
972 }
973}
974
975impl Type {
976 fn resolve(&mut self, imports: &HashMap<Ident, FlatImport>, generics: &[Ident]) {
978 use TypePath as P;
979 self.map_types(|ty| ty.resolve(imports, generics));
981
982 let resolved = match &self.path {
986 P::Module { module, r#type, .. } => {
987 let Some(FlatImport::Module {
988 named_address,
989 module,
990 }) = imports.get(module)
991 else {
992 return;
993 };
994 P::Full {
995 named_address: named_address.clone(),
996 sep0: PathSep::default(),
997 module: module.clone(),
998 sep1: PathSep::default(),
999 r#type: r#type.clone(),
1000 }
1001 }
1002 P::Ident(ident) if !generics.contains(ident) => {
1003 let Some(FlatImport::Item {
1004 named_address,
1005 module,
1006 r#type,
1007 }) = imports.get(ident)
1008 else {
1009 return;
1010 };
1011 P::Full {
1012 named_address: named_address.clone(),
1013 sep0: PathSep::default(),
1014 module: module.clone(),
1015 sep1: PathSep::default(),
1016 r#type: r#type.clone(),
1017 }
1018 }
1019 _ => return,
1021 };
1022 self.path = resolved;
1023 }
1024}
1025
1026impl TypeArgs {
1027 pub fn types(&self) -> impl Iterator<Item = &Type> {
1029 self.args.iter().map(|args| &*args.value)
1030 }
1031}
1032
1033impl Generics {
1034 pub fn generics(&self) -> impl Iterator<Item = &Generic> + '_ {
1035 self.type_args.iter().map(|d| &d.value)
1036 }
1037}
1038
1039#[cfg_attr(test, derive(derive_more::Display))]
1042enum FlatImport {
1043 #[cfg_attr(test, display("{named_address}::{module}"))]
1044 Module { named_address: Ident, module: Ident },
1045 #[cfg_attr(test, display("{named_address}::{module}::{type}"))]
1046 Item {
1047 named_address: Ident,
1048 module: Ident,
1049 r#type: Ident,
1050 },
1051}
1052
1053trait IteratorBoxed<'a>: Iterator + 'a {
1057 fn boxed(self) -> Box<dyn Iterator<Item = Self::Item> + 'a>
1058 where
1059 Self: Sized,
1060 {
1061 Box::new(self)
1062 }
1063}
1064
1065impl<'a, T> IteratorBoxed<'a> for T where T: Iterator + 'a {}
1066
1067trait Datatype {
1069 fn generics(&self) -> Vec<Ident>;
1070}
1071
1072impl Datatype for Enum {
1073 fn generics(&self) -> Vec<Ident> {
1074 self.generics
1075 .iter()
1076 .flat_map(|generics| generics.generics())
1077 .map(|generic| generic.ident.clone())
1078 .collect()
1079 }
1080}
1081
1082impl Datatype for Struct {
1083 fn generics(&self) -> Vec<Ident> {
1084 self.generics
1085 .iter()
1086 .flat_map(|generics| generics.generics())
1087 .map(|generic| generic.ident.clone())
1088 .collect()
1089 }
1090}
1091
1092trait Typed {
1094 fn map_types(&mut self, f: impl FnMut(&mut Type));
1096}
1097
1098impl Typed for Enum {
1099 fn map_types(&mut self, mut f: impl FnMut(&mut Type)) {
1100 mutate_delimited_vec(&mut self.content.content, |variant| {
1101 variant.map_types(&mut f)
1102 });
1103 }
1104}
1105
1106impl Typed for EnumVariant {
1107 fn map_types(&mut self, f: impl FnMut(&mut Type)) {
1108 let Some(fields) = &mut self.fields else {
1109 return;
1110 };
1111 fields.map_types(f);
1112 }
1113}
1114
1115impl Typed for Struct {
1116 fn map_types(&mut self, f: impl FnMut(&mut Type)) {
1117 match &mut self.kind {
1118 StructKind::Braced(braced_struct) => braced_struct.fields.map_types(f),
1119 StructKind::Tuple(tuple_struct) => tuple_struct.fields.map_types(f),
1120 }
1121 }
1122}
1123
1124impl Typed for FieldsKind {
1125 fn map_types(&mut self, f: impl FnMut(&mut Type)) {
1126 match self {
1127 Self::Named(named) => named.map_types(f),
1128 Self::Positional(positional) => positional.map_types(f),
1129 }
1130 }
1131}
1132
1133impl Typed for NamedFields {
1134 fn map_types(&mut self, mut f: impl FnMut(&mut Type)) {
1135 mutate_delimited_vec(&mut self.0.content, |field| f(&mut field.ty));
1136 }
1137}
1138
1139impl Typed for PositionalFields {
1140 fn map_types(&mut self, mut f: impl FnMut(&mut Type)) {
1141 mutate_delimited_vec(&mut self.0.content, |field| f(&mut field.ty));
1142 }
1143}
1144
1145impl Typed for Type {
1146 fn map_types(&mut self, mut f: impl FnMut(&mut Self)) {
1147 if let Some(args) = &mut self.type_args {
1148 mutate_delimited_vec(&mut args.args, |t| f(&mut *t))
1149 }
1150 }
1151}
1152
1153fn mutate_delimited_vec<T, D: Default, const MIN: usize, const MAX: usize>(
1156 dvec: &mut DelimitedVec<T, D, TrailingDelimiter::Optional, MIN, MAX>,
1157 mut f: impl FnMut(&mut T),
1158) {
1159 type ForbiddenDelimited<T, D, const MIN: usize, const MAX: usize> =
1160 DelimitedVec<T, D, TrailingDelimiter::Forbidden, MIN, MAX>;
1161
1162 let temp: ForbiddenDelimited<T, D, MIN, MAX> = std::iter::empty::<T>().collect();
1163 let mut swapped = std::mem::replace(dvec, temp.into());
1164 swapped = swapped
1165 .into_iter()
1166 .map(|mut d| {
1167 f(&mut d.value);
1168 d.value
1169 })
1170 .collect::<ForbiddenDelimited<T, D, MIN, MAX>>()
1171 .into();
1172 *dvec = swapped;
1173}