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