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}