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