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