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}