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