facet_macros_parse/
lib.rs

1#![warn(missing_docs)]
2#![doc = include_str!("../README.md")]
3
4/// Parse function signature shape
5#[cfg(feature = "function")]
6pub mod function;
7#[cfg(feature = "function")]
8pub use function::*;
9
10pub use unsynn::*;
11
12keyword! {
13    /// The "pub" keyword.
14    pub KPub = "pub";
15    /// The "struct" keyword.
16    pub KStruct = "struct";
17    /// The "enum" keyword.
18    pub KEnum = "enum";
19    /// The "doc" keyword.
20    pub KDoc = "doc";
21    /// The "repr" keyword.
22    pub KRepr = "repr";
23    /// The "crate" keyword.
24    pub KCrate = "crate";
25    /// The "in" keyword.
26    pub KIn = "in";
27    /// The "const" keyword.
28    pub KConst = "const";
29    /// The "where" keyword.
30    pub KWhere = "where";
31    /// The "mut" keyword.
32    pub KMut = "mut";
33    /// The "facet" keyword.
34    pub KFacet = "facet";
35    /// The "sensitive" keyword.
36    pub KSensitive = "sensitive";
37    /// The "invariants" keyword.
38    pub KInvariants = "invariants";
39    /// The "opaque" keyword.
40    pub KOpaque = "opaque";
41    /// The "deny_unknown_fields" keyword.
42    pub KDenyUnknownFields = "deny_unknown_fields";
43    /// The "default" keyword.
44    pub KDefault = "default";
45    /// The "transparent" keyword.
46    pub KTransparent = "transparent";
47    /// The "rename" keyword.
48    pub KRename = "rename";
49    /// The "rename_all" keyword.
50    pub KRenameAll = "rename_all";
51    /// The "flatten" keyword
52    pub KFlatten = "flatten";
53    /// The "child" keyword
54    pub KChild = "child";
55    /// The "skip_serializing" keyword.
56    pub KSkipSerializing = "skip_serializing";
57    /// The "skip_serializing_if" keyword.
58    pub KSkipSerializingIf = "skip_serializing_if";
59    /// The "type_tag" keyword.
60    pub KTypeTag = "type_tag";
61}
62
63operator! {
64    /// Represents the '=' operator.
65    pub Eq = "=";
66    /// Represents the ';' operator.
67    pub Semi = ";";
68    /// Represents the apostrophe '\'' operator.
69    pub Apostrophe = "'";
70    /// Represents the double semicolon '::' operator.
71    pub DoubleSemicolon = "::";
72}
73
74/// Parses tokens and groups until `C` is found on the current token tree level.
75pub type VerbatimUntil<C> = Many<Cons<Except<C>, AngleTokenTree>>;
76
77/// Represents a module path, consisting of an optional path separator followed by
78/// a path-separator-delimited sequence of identifiers.
79pub type ModPath = Cons<Option<PathSep>, PathSepDelimited<Ident>>;
80
81/// Represents type bounds, consisting of a colon followed by tokens until
82/// a comma, equals sign, or closing angle bracket is encountered.
83pub type Bounds = Cons<Colon, VerbatimUntil<Either<Comma, Eq, Gt>>>;
84
85unsynn! {
86    /// Parses either a `TokenTree` or `<...>` grouping (which is not a [`Group`] as far as proc-macros
87    /// are concerned).
88    #[derive(Clone)]
89    pub struct AngleTokenTree(
90        #[allow(clippy::type_complexity)] // look,
91        pub Either<Cons<Lt, Vec<Cons<Except<Gt>, AngleTokenTree>>, Gt>, TokenTree>,
92    );
93
94    /// Represents an algebraic data type (ADT) declaration, which can be either a struct or enum.
95    pub enum AdtDecl {
96        /// A struct ADT variant.
97        Struct(Struct),
98        /// An enum ADT variant.
99        Enum(Enum),
100    }
101
102    /// Represents visibility modifiers for items.
103    pub enum Vis {
104        /// `pub(in? crate::foo::bar)`/`pub(in? ::foo::bar)`
105        PubIn(Cons<KPub, ParenthesisGroupContaining<Cons<Option<KIn>, ModPath>>>),
106        /// Public visibility, indicated by the "pub" keyword.
107        Pub(KPub),
108    }
109
110    /// Represents an attribute annotation on a field, typically in the form `#[attr]`.
111    pub struct Attribute {
112        /// The pound sign preceding the attribute.
113        pub _pound: Pound,
114        /// The content of the attribute enclosed in square brackets.
115        pub body: BracketGroupContaining<AttributeInner>,
116    }
117
118    /// Represents the inner content of an attribute annotation.
119    pub enum AttributeInner {
120        /// A facet attribute that can contain specialized metadata.
121        Facet(FacetAttr),
122        /// A documentation attribute typically used for generating documentation.
123        Doc(DocInner),
124        /// A representation attribute that specifies how data should be laid out.
125        Repr(ReprInner),
126        /// Any other attribute represented as a sequence of token trees.
127        Any(Vec<TokenTree>),
128    }
129
130    /// Represents a facet attribute that can contain specialized metadata.
131    pub struct FacetAttr {
132        /// The keyword for the facet attribute.
133        pub _facet: KFacet,
134        /// The inner content of the facet attribute.
135        pub inner: ParenthesisGroupContaining<CommaDelimitedVec<FacetInner>>,
136    }
137
138    /// Represents the inner content of a facet attribute.
139    pub enum FacetInner {
140        /// A sensitive attribute that specifies sensitivity information.
141        Sensitive(KSensitive),
142        /// An invariants attribute that specifies invariants for the type.
143        Invariants(InvariantInner),
144        /// An opaque attribute that specifies opaque information.
145        Opaque(KOpaque),
146        /// A deny_unknown_fields attribute that specifies whether unknown fields are allowed.
147        DenyUnknownFields(KDenyUnknownFields),
148        /// A default attribute with an explicit value (#[facet(default = "myfunc")])
149        DefaultEquals(DefaultEqualsInner),
150        /// A default attribute with no explicit value (#[facet(default)])
151        Default(KDefault),
152        /// A transparent attribute for containers
153        Transparent(KTransparent),
154        /// A rename_all attribute that specifies a case conversion for all fields/variants (#[facet(rename_all = "camelCase")])
155        RenameAll(RenameAllInner),
156        /// A rename attribute that specifies a custom name for a field/variant (#[facet(rename = "custom_name")])
157        Rename(RenameInner),
158        /// A flatten attribute that marks a field to be flattened into the parent structure
159        Flatten(FlattenInner),
160        /// A child attribute that marks a field as a child node
161        Child(ChildInner),
162        /// A skip_serializing attribute that specifies whether a field should be skipped during serialization.
163        SkipSerializing(SkipSerializingInner),
164        /// A skip_serializing_if attribute that specifies a condition for skipping serialization.
165        SkipSerializingIf(SkipSerializingIfInner),
166        /// A type_tag attribute that specifies the identifying tag for self describing formats
167        TypeTag(TypeTagInner),
168        /// Any other attribute represented as a sequence of token trees.
169        Arbitrary(VerbatimUntil<Comma>),
170    }
171
172    /// Inner value for #[facet(flatten)]
173    pub struct FlattenInner {
174        /// The "flatten" keyword.
175        pub _kw_flatten: KFlatten,
176    }
177
178    /// Inner value for #[facet(child)]
179    pub struct ChildInner {
180        /// The "child" keyword.
181        pub _kw_child: KChild,
182    }
183
184    /// Inner value for #[facet(skip_serializing)]
185    pub struct SkipSerializingInner {
186        /// The "skip_serializing" keyword.
187        pub _kw_skip_serializing: KSkipSerializing,
188    }
189
190    /// Inner value for #[facet(skip_serializing_if = ...)]
191    pub struct SkipSerializingIfInner {
192        /// The "skip_serializing_if" keyword.
193        pub _kw_skip_serializing_if: KSkipSerializingIf,
194        /// The equals sign '='.
195        pub _eq: Eq,
196        /// The conditional expression as verbatim until comma.
197        pub expr: VerbatimUntil<Comma>,
198    }
199
200    /// Inner value for #[facet(type_tag = ...)]
201    pub struct TypeTagInner {
202        /// The "type_tag" keyword.
203        pub _kw_type_tag: KTypeTag,
204        /// The equals sign '='.
205        pub _eq: Eq,
206        /// The value assigned, as a literal string.
207        pub expr: LiteralString,
208    }
209
210    /// Inner value for #[facet(default = ...)]
211    pub struct DefaultEqualsInner {
212        /// The "default" keyword.
213        pub _kw_default: KDefault,
214        /// The equals sign '='.
215        pub _eq: Eq,
216        /// The value assigned, as verbatim until comma.
217        pub expr: VerbatimUntil<Comma>,
218    }
219
220    /// Inner value for #[facet(rename = ...)]
221    pub struct RenameInner {
222        /// The "rename" keyword.
223        pub _kw_rename: KRename,
224        /// The equals sign '='.
225        pub _eq: Eq,
226        /// The value assigned, as a literal string.
227        pub value: LiteralString,
228    }
229
230    /// Inner value for #[facet(rename_all = ...)]
231    pub struct RenameAllInner {
232        /// The "rename_all" keyword.
233        pub _kw_rename_all: KRenameAll,
234        /// The equals sign '='.
235        pub _eq: Eq,
236        /// The value assigned, as a literal string.
237        pub value: LiteralString,
238    }
239
240    /// Represents invariants for a type.
241    pub struct InvariantInner {
242        /// The "invariants" keyword.
243        pub _kw_invariants: KInvariants,
244        /// The equality operator.
245        pub _eq: Eq,
246        /// The invariant value
247        pub expr: VerbatimUntil<Comma>,
248    }
249
250    /// Represents documentation for an item.
251    pub struct DocInner {
252        /// The "doc" keyword.
253        pub _kw_doc: KDoc,
254        /// The equality operator.
255        pub _eq: Eq,
256        /// The documentation content as a literal string.
257        pub value: LiteralString,
258    }
259
260    /// Represents the inner content of a `repr` attribute, typically used for specifying
261    /// memory layout or representation hints.
262    pub struct ReprInner {
263        /// The "repr" keyword.
264        pub _kw_repr: KRepr,
265        /// The representation attributes enclosed in parentheses.
266        pub attr: ParenthesisGroupContaining<CommaDelimitedVec<Ident>>,
267    }
268
269    /// Represents a struct definition.
270    pub struct Struct {
271        /// Attributes applied to the struct.
272        pub attributes: Vec<Attribute>,
273        /// The visibility modifier of the struct (e.g., `pub`).
274        pub _vis: Option<Vis>,
275        /// The "struct" keyword.
276        pub _kw_struct: KStruct,
277        /// The name of the struct.
278        pub name: Ident,
279        /// Generic parameters for the struct, if any.
280        pub generics: Option<GenericParams>,
281        /// The variant of struct (unit, tuple, or regular struct with named fields).
282        pub kind: StructKind,
283    }
284
285    /// Represents the generic parameters of a struct or enum definition, enclosed in angle brackets.
286    /// e.g., `<'a, T: Trait, const N: usize>`.
287    pub struct GenericParams {
288        /// The opening angle bracket `<`.
289        pub _lt: Lt,
290        /// The comma-delimited list of generic parameters.
291        pub params: CommaDelimitedVec<GenericParam>,
292        /// The closing angle bracket `>`.
293        pub _gt: Gt,
294    }
295
296    /// Represents a single generic parameter within a `GenericParams` list.
297    pub enum GenericParam {
298        /// A lifetime parameter, e.g., `'a` or `'a: 'b + 'c`.
299        Lifetime {
300            /// The lifetime identifier (e.g., `'a`).
301            name: Lifetime,
302            /// Optional lifetime bounds (e.g., `: 'b + 'c`).
303            bounds: Option<Cons<Colon, VerbatimUntil<Either<Comma, Gt>>>>,
304        },
305        /// A const generic parameter, e.g., `const N: usize = 10`.
306        Const {
307            /// The `const` keyword.
308            _const: KConst,
309            /// The name of the const parameter (e.g., `N`).
310            name: Ident,
311            /// The colon separating the name and type.
312            _colon: Colon,
313            /// The type of the const parameter (e.g., `usize`).
314            typ: VerbatimUntil<Either<Comma, Gt, Eq>>,
315            /// An optional default value (e.g., `= 10`).
316            default: Option<Cons<Eq, VerbatimUntil<Either<Comma, Gt>>>>,
317        },
318        /// A type parameter, e.g., `T: Trait = DefaultType`.
319        Type {
320            /// The name of the type parameter (e.g., `T`).
321            name: Ident,
322            /// Optional type bounds (e.g., `: Trait`).
323            bounds: Option<Bounds>,
324            /// An optional default type (e.g., `= DefaultType`).
325            default: Option<Cons<Eq, VerbatimUntil<Either<Comma, Gt>>>>,
326        },
327    }
328
329    /// Represents a `where` clause attached to a definition.
330    /// e.g., `where T: Trait, 'a: 'b`.
331    #[derive(Clone)]
332    pub struct WhereClauses {
333        /// The `where` keyword.
334        pub _kw_where: KWhere,
335        /// The comma-delimited list of where clause predicates.
336        pub clauses: CommaDelimitedVec<WhereClause>,
337    }
338
339    /// Represents a single predicate within a `where` clause.
340    /// e.g., `T: Trait` or `'a: 'b`.
341    #[derive(Clone)]
342    pub struct WhereClause {
343        // FIXME: This likely breaks for absolute `::` paths
344        /// The type or lifetime being constrained (e.g., `T` or `'a`).
345        pub _pred: VerbatimUntil<Colon>,
346        /// The colon separating the constrained item and its bounds.
347        pub _colon: Colon,
348        /// The bounds applied to the type or lifetime (e.g., `Trait` or `'b`).
349        pub bounds: VerbatimUntil<Either<Comma, Semicolon, BraceGroup>>,
350    }
351
352    /// Represents the kind of a struct definition.
353    pub enum StructKind {
354        /// A regular struct with named fields, e.g., `struct Foo { bar: u32 }`.
355        Struct {
356            /// Optional where clauses.
357            clauses: Option<WhereClauses>,
358            /// The fields enclosed in braces `{}`.
359            fields: BraceGroupContaining<CommaDelimitedVec<StructField>>,
360        },
361        /// A tuple struct, e.g., `struct Foo(u32, String);`.
362        TupleStruct {
363            /// The fields enclosed in parentheses `()`.
364            fields: ParenthesisGroupContaining<CommaDelimitedVec<TupleField>>,
365            /// Optional where clauses.
366            clauses: Option<WhereClauses>,
367            /// The trailing semicolon `;`.
368            semi: Semi,
369        },
370        /// A unit struct, e.g., `struct Foo;`.
371        UnitStruct {
372            /// Optional where clauses.
373            clauses: Option<WhereClauses>,
374            /// The trailing semicolon `;`.
375            semi: Semi,
376        },
377    }
378
379    /// Represents a lifetime annotation, like `'a`.
380    pub struct Lifetime {
381        /// The apostrophe `'` starting the lifetime.
382        pub _apostrophe: PunctJoint<'\''>,
383        /// The identifier name of the lifetime (e.g., `a`).
384        pub name: Ident,
385    }
386
387    /// Represents a simple expression, currently only integer literals.
388    /// Used potentially for const generic default values.
389    pub enum Expr {
390        /// An integer literal expression.
391        Integer(LiteralInteger),
392    }
393
394    /// Represents either the `const` or `mut` keyword, often used with pointers.
395    pub enum ConstOrMut {
396        /// The `const` keyword.
397        Const(KConst),
398        /// The `mut` keyword.
399        Mut(KMut),
400    }
401
402    /// Represents a field within a regular struct definition.
403    /// e.g., `pub name: String`.
404    pub struct StructField {
405        /// Attributes applied to the field (e.g., `#[doc = "..."]`).
406        pub attributes: Vec<Attribute>,
407        /// Optional visibility modifier (e.g., `pub`).
408        pub _vis: Option<Vis>,
409        /// The name of the field.
410        pub name: Ident,
411        /// The colon separating the name and type.
412        pub _colon: Colon,
413        /// The type of the field.
414        pub typ: VerbatimUntil<Comma>,
415    }
416
417    /// Represents a field within a tuple struct definition.
418    /// e.g., `pub String`.
419    pub struct TupleField {
420        /// Attributes applied to the field (e.g., `#[doc = "..."]`).
421        pub attributes: Vec<Attribute>,
422        /// Optional visibility modifier (e.g., `pub`).
423        pub vis: Option<Vis>,
424        /// The type of the field.
425        pub typ: VerbatimUntil<Comma>,
426    }
427
428    /// Represents an enum definition.
429    /// e.g., `#[repr(u8)] pub enum MyEnum<T> where T: Clone { Variant1, Variant2(T) }`.
430    pub struct Enum {
431        /// Attributes applied to the enum (e.g., `#[repr(...)]`).
432        pub attributes: Vec<Attribute>,
433        /// Optional visibility modifier (e.g., `pub`, `pub(crate)`, etc.).
434        pub _vis: Option<Vis>,
435        /// The `enum` keyword.
436        pub _kw_enum: KEnum,
437        /// The name of the enum.
438        pub name: Ident,
439        /// Optional generic parameters.
440        pub generics: Option<GenericParams>,
441        /// Optional where clauses.
442        pub clauses: Option<WhereClauses>,
443        /// The enum variants enclosed in braces `{}`.
444        pub body: BraceGroupContaining<CommaDelimitedVec<EnumVariantLike>>,
445    }
446
447    /// Represents a variant of an enum, including the optional discriminant value
448    pub struct EnumVariantLike {
449        /// The actual variant
450        pub variant: EnumVariantData,
451        /// The optional discriminant value
452        pub discriminant: Option<Cons<Eq, VerbatimUntil<Comma>>>
453    }
454
455    /// Represents the different kinds of variants an enum can have.
456    pub enum EnumVariantData {
457        /// A tuple-like variant, e.g., `Variant(u32, String)`.
458        Tuple(TupleVariant),
459        /// A struct-like variant, e.g., `Variant { field1: u32, field2: String }`.
460        Struct(StructEnumVariant),
461        /// A unit-like variant, e.g., `Variant`.
462        Unit(UnitVariant),
463    }
464
465    /// Represents a unit-like enum variant.
466    /// e.g., `MyVariant`.
467    pub struct UnitVariant {
468        /// Attributes applied to the variant.
469        pub attributes: Vec<Attribute>,
470        /// The name of the variant.
471        pub name: Ident,
472    }
473
474    /// Represents a tuple-like enum variant.
475    /// e.g., `MyVariant(u32, String)`.
476    pub struct TupleVariant {
477        /// Attributes applied to the variant.
478        pub attributes: Vec<Attribute>,
479        /// The name of the variant.
480        pub name: Ident,
481        /// The fields enclosed in parentheses `()`.
482        pub fields: ParenthesisGroupContaining<CommaDelimitedVec<TupleField>>,
483    }
484
485    /// Represents a struct-like enum variant.
486    /// e.g., `MyVariant { field1: u32, field2: String }`.
487    pub struct StructEnumVariant {
488        /// Attributes applied to the variant.
489        pub attributes: Vec<Attribute>,
490        /// The name of the variant.
491        pub name: Ident,
492        /// The fields enclosed in braces `{}`.
493        pub fields: BraceGroupContaining<CommaDelimitedVec<StructField>>,
494    }
495
496    /// A lifetime or a tokentree, used to gather lifetimes in type definitions
497    pub enum LifetimeOrTt {
498        /// A lifetime annotation.
499        Lifetime(Lifetime),
500        /// A single token tree.
501        TokenTree(TokenTree),
502    }
503}
504
505impl core::fmt::Display for AngleTokenTree {
506    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
507        match &self.0 {
508            Either::First(it) => {
509                write!(f, "<")?;
510                for it in it.second.iter() {
511                    write!(f, "{}", it.second)?;
512                }
513                write!(f, ">")?;
514            }
515            Either::Second(it) => write!(f, "{}", it)?,
516            Either::Third(Invalid) => unreachable!(),
517            Either::Fourth(Invalid) => unreachable!(),
518        };
519        Ok(())
520    }
521}
522
523/// Display the verbatim tokens until the given token.
524pub struct VerbatimDisplay<'a, C>(pub &'a VerbatimUntil<C>);
525
526impl<C> core::fmt::Display for VerbatimDisplay<'_, C> {
527    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
528        for tt in self.0.0.iter() {
529            write!(f, "{}", tt.value.second)?;
530        }
531        Ok(())
532    }
533}
534
535impl core::fmt::Display for ConstOrMut {
536    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
537        match self {
538            ConstOrMut::Const(_) => write!(f, "const"),
539            ConstOrMut::Mut(_) => write!(f, "mut"),
540        }
541    }
542}
543
544impl core::fmt::Display for Lifetime {
545    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
546        write!(f, "'{}", self.name)
547    }
548}
549
550impl core::fmt::Display for WhereClauses {
551    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
552        write!(f, "where ")?;
553        for clause in self.clauses.0.iter() {
554            write!(f, "{},", clause.value)?;
555        }
556        Ok(())
557    }
558}
559
560impl core::fmt::Display for WhereClause {
561    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
562        write!(
563            f,
564            "{}: {}",
565            VerbatimDisplay(&self._pred),
566            VerbatimDisplay(&self.bounds)
567        )
568    }
569}
570
571impl core::fmt::Display for Expr {
572    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
573        match self {
574            Expr::Integer(int) => write!(f, "{}", int.value()),
575        }
576    }
577}
578
579impl Struct {
580    /// Returns an iterator over the `FacetInner` content of `#[facet(...)]` attributes
581    /// applied to this struct.
582    pub fn facet_attributes(&self) -> impl Iterator<Item = &FacetInner> {
583        self.attributes
584            .iter()
585            .filter_map(|attr| match &attr.body.content {
586                AttributeInner::Facet(f) => Some(&f.inner.content.0),
587                _ => None,
588            })
589            .flatten()
590            .map(|d| &d.value)
591    }
592
593    /// Returns `true` if the struct is marked `#[facet(transparent)]`.
594    pub fn is_transparent(&self) -> bool {
595        self.facet_attributes()
596            .any(|inner| matches!(inner, FacetInner::Transparent(_)))
597    }
598}