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, VerbatimUntil<Comma>>>
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 /// A lifetime or a tokentree, used to gather lifetimes in type definitions
477 pub enum LifetimeOrTt {
478 /// A lifetime annotation.
479 Lifetime(Lifetime),
480 /// A single token tree.
481 TokenTree(TokenTree),
482 }
483}
484
485impl core::fmt::Display for AngleTokenTree {
486 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
487 match &self.0 {
488 Either::First(it) => {
489 write!(f, "<")?;
490 for it in it.second.iter() {
491 write!(f, "{}", it.second)?;
492 }
493 write!(f, ">")?;
494 }
495 Either::Second(it) => write!(f, "{}", it)?,
496 Either::Third(Invalid) => unreachable!(),
497 Either::Fourth(Invalid) => unreachable!(),
498 };
499 Ok(())
500 }
501}
502
503/// Display the verbatim tokens until the given token.
504pub struct VerbatimDisplay<'a, C>(pub &'a VerbatimUntil<C>);
505
506impl<C> core::fmt::Display for VerbatimDisplay<'_, C> {
507 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
508 for tt in self.0.0.iter() {
509 write!(f, "{}", tt.value.second)?;
510 }
511 Ok(())
512 }
513}
514
515impl core::fmt::Display for ConstOrMut {
516 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
517 match self {
518 ConstOrMut::Const(_) => write!(f, "const"),
519 ConstOrMut::Mut(_) => write!(f, "mut"),
520 }
521 }
522}
523
524impl core::fmt::Display for Lifetime {
525 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
526 write!(f, "'{}", self.name)
527 }
528}
529
530impl core::fmt::Display for WhereClauses {
531 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
532 write!(f, "where ")?;
533 for clause in self.clauses.0.iter() {
534 write!(f, "{},", clause.value)?;
535 }
536 Ok(())
537 }
538}
539
540impl core::fmt::Display for WhereClause {
541 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
542 write!(
543 f,
544 "{}: {}",
545 VerbatimDisplay(&self._pred),
546 VerbatimDisplay(&self.bounds)
547 )
548 }
549}
550
551impl core::fmt::Display for Expr {
552 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
553 match self {
554 Expr::Integer(int) => write!(f, "{}", int.value()),
555 }
556 }
557}
558
559impl Struct {
560 /// Returns an iterator over the `FacetInner` content of `#[facet(...)]` attributes
561 /// applied to this struct.
562 pub fn facet_attributes(&self) -> impl Iterator<Item = &FacetInner> {
563 self.attributes
564 .iter()
565 .filter_map(|attr| match &attr.body.content {
566 AttributeInner::Facet(f) => Some(&f.inner.content.0),
567 _ => None,
568 })
569 .flatten()
570 .map(|d| &d.value)
571 }
572
573 /// Returns `true` if the struct is marked `#[facet(transparent)]`.
574 pub fn is_transparent(&self) -> bool {
575 self.facet_attributes()
576 .any(|inner| matches!(inner, FacetInner::Transparent(_)))
577 }
578}