facet_derive_parse/
lib.rs

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