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}