async_codegen/rust/
mod.rs

1/*
2 * Copyright © 2025 Anand Beh
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//!
18//! Rust syntax elements.
19//!
20//! Note that no checking exists to make sure the elements are used correctly, i.e. the correct
21//! combination of structs. Instead, the library user is expected to have basic knowledge of how
22//! Rust syntax is composed, and to combine the structs in this module likewise.
23//!
24//! Example:
25//!
26//! ```
27//! # use async_codegen::common::{CombinedSeq, NoOpSeq, SingularSeq, Str};
28//! # use async_codegen::{Output, Writable};
29//! # use async_codegen::rust::{CanHaveAttributes, CfgAttr, Deprecated, FunctionBodyImplement, FunctionDef, FunctionParam, ModPub, MustUse, NoMangle, Parameterized};
30//!
31//! async fn write_function<O>(output: &mut O) -> Result<(), O::Error> where O: Output {
32//!   // For more advanced usage, you can replace Str("") by other Writable implementations
33//!   let function_def = FunctionDef {
34//!     mods: SingularSeq(ModPub),
35//!     name: Str("my_func"),
36//!     args: CombinedSeq(
37//!      SingularSeq(FunctionParam(Str("var1"), Str("Type"))),
38//!      SingularSeq(FunctionParam(Str("var2"), Parameterized(Str("Option"), SingularSeq(Str("bool")))))
39//!     ),
40//!     return_type: Parameterized(Str("Box"), SingularSeq(Str("str"))),
41//!     where_conds: NoOpSeq,
42//!     body: FunctionBodyImplement(Str("todo!()"))
43//!   };
44//!   function_def.write_to(output).await
45//!   // Will render as:
46//!   /*
47//!   pub fn my_func(var1: Type, var2: Option<bool>) -> Box<str> {
48//!     todo!()
49//!   }
50//!    */
51//! }
52//! ```
53//!
54
55use crate::common::{Combined, NoOp, NoOpSeq, Str, SurroundingSeqAccept};
56use crate::{Output, SequenceAccept, Writable};
57use std::fmt::Debug;
58
59mod syntax;
60#[cfg(test)]
61mod tests;
62
63/// All possible Rust editions.
64/// This is the only type in this module meant to be used as context, and not as a writable itself.
65#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
66#[non_exhaustive]
67pub enum Edition {
68    /// This Rust edition is declared for usability purposes. However, not all [Writable]
69    /// implementations are guaranteed to work with it.
70    Rust2015,
71    Rust2018,
72    Rust2021,
73    Rust2024,
74}
75
76/// Imports a single type so that it can be used later.
77/// Renders as `use Type;`. Adds a new line after the semicolon.
78#[derive(Clone, Debug)]
79pub struct UseType<Type>(pub Type);
80
81/// An attribute enabled conditionally, i.e. `#[cfg_attr(Cond, Attr)]`
82#[derive(Clone, Debug)]
83pub struct CfgAttr<Cond, Attr>(pub Cond, pub Attr);
84
85/// A cfg attribute. Renders as `cfg(Cond)`.
86#[derive(Clone, Debug)]
87pub struct Cfg<Cond>(pub Cond);
88
89/// A cfg condition for targeting an OS, OS family, or architecture. For example:
90/// ```
91/// # use async_codegen::common::{NoOpSeq, SingularSeq, Str};
92/// # use async_codegen::context::EmptyContext;
93/// # use async_codegen::rust::{FunctionBodyDeclare, Cfg, FunctionDef, Target, CanHaveAttributes};
94/// # use async_codegen::util::InMemoryOutput;
95/// let function = FunctionDef {
96///   mods: NoOpSeq,
97///   name: Str("conditional_func"),
98///   args: NoOpSeq,
99///   return_type: Str("()"),
100///   where_conds: NoOpSeq,
101///   body: FunctionBodyDeclare
102/// }.with_attributes(
103///   SingularSeq(Cfg(Target::Os(Str("linux"))))
104/// );
105/// let string = InMemoryOutput::print_output(EmptyContext, &function);
106/// assert_eq!("#[cfg(target_os = \"linux\")]\nfn conditional_func() -> ();\n\n", string);
107/// ```
108#[derive(Clone, Debug)]
109pub enum Target<Value> {
110    Os(Value),
111    Family(Value),
112    Arch(Value),
113}
114
115/// The link attribute.
116#[derive(Clone, Debug)]
117pub struct Link<Arg>(pub Arg);
118
119/// The no mangle attribute.
120///
121/// Requires that the context satisfies [ContextProvides] for [Edition], because in Rust 2024 and
122/// beyond, the no-mangle attribute is an unsafe attribute.
123#[derive(Clone, Debug)]
124pub struct NoMangle;
125
126/// The attribute content for `allow(...)`. The tuple value must be a sequence.
127#[derive(Clone, Debug)]
128pub struct AllowLints<Lints>(pub Lints);
129
130/// The deprecated attribute. The three variants of this enum correspond to the deprecated
131/// attribute's multiple ways of being specified. See:
132/// https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-deprecated-attribute
133#[derive(Clone, Debug)]
134pub enum Deprecated<Msg, Since = NoOp> {
135    Basic,
136    Message(Msg),
137    Full { since: Since, note: Msg },
138}
139
140impl Default for Deprecated<NoOp, NoOp> {
141    fn default() -> Self {
142        Self::Basic
143    }
144}
145
146impl Deprecated<NoOp, NoOp> {
147    pub fn basic() -> Self {
148        Self::Basic
149    }
150}
151
152impl<Msg> Deprecated<Msg> {
153    pub fn with_message(msg: Msg) -> Self {
154        Self::Message(msg)
155    }
156}
157
158/// The must_use attribute
159#[derive(Clone, Debug)]
160pub struct MustUse;
161
162/// The public modifier
163#[derive(Clone, Debug)]
164pub struct ModPub;
165
166/// The unsafe modifier
167#[derive(Clone, Debug)]
168pub struct ModUnsafe;
169
170/// The extern modifier, with the ABI selected as the tuple value.
171///
172/// This struct includes `unsafe`. Since Rust 2024, the unsafe keyword is required for extern
173/// functions, and before Rust 2024 it is optional. To make it easy to generate code targeting
174/// multiple editions, we unconditionally emit the "unsafe" keyword alongside "extern".
175#[derive(Clone, Debug)]
176pub struct ModUnsafeExtern<Abi>(pub Abi);
177
178/// A standalone statement. Renders the expression and adds a semicolon and a new line.
179#[derive(Clone, Debug)]
180pub struct Stmt<Expr>(pub Expr);
181
182/// A let statement. This statement includes the semicolon and a new line.
183#[derive(Clone, Debug)]
184pub struct LetStmt<Variable, Expr>(pub Variable, pub Expr);
185
186/// An assignation. This statement includes the semicolon and a new line.
187#[derive(Clone, Debug)]
188pub struct AssignStmt<Variable, Expr>(pub Variable, pub Expr);
189
190/// A return statement. Renders as `return Expr;` with a new line at the end.
191#[derive(Clone, Debug)]
192pub struct ReturnStmt<Expr>(pub Expr);
193
194/// A let expression.
195/// This can be used, for example, as the condition of [IfBlock] in order to create an "if-let" block.
196#[derive(Clone, Debug)]
197pub struct LetExpr<Pattern, Expr>(pub Pattern, pub Expr);
198
199/// A raw string literal expression, i.e. r#"Content"#. Example:
200/// ```
201/// # use async_codegen::common::Str;
202/// # use async_codegen::context::EmptyContext;
203/// # use async_codegen::rust::RawStringLiteral;
204/// # use async_codegen::util::InMemoryOutput;
205/// let string_lit = RawStringLiteral(Str("hello_world"));
206///
207/// assert_eq!("r#\"hello_world\"#", InMemoryOutput::print_output(EmptyContext, &string_lit));
208/// ```
209#[derive(Clone, Debug)]
210pub struct RawStringLiteral<Content>(pub Content);
211
212/// An array literal with predefined elements written out.
213/// Renders as `[E1, E2, E3, ...]` where EX is in the element sequence.
214#[derive(Clone, Debug)]
215pub struct ArrayFromElements<Elements>(pub Elements);
216
217/// An item attached to an associated container, via "::".
218/// The output will look like `Cont::Item`.
219#[derive(Clone, Debug)]
220pub struct AssociatedItem<Cont, Item>(pub Cont, pub Item);
221
222/// A question mark following another expression.
223#[derive(Clone, Debug)]
224pub struct QuestionMarkAfter<Expr>(pub Expr);
225
226/// Uses the `as` expression to perform a qualified trait cast (e.g. ready for a method call).
227/// This will render as `<Type as Trait>`.
228#[derive(Clone, Debug)]
229pub struct TypeAsTrait<Type, Trait>(pub Type, pub Trait);
230
231/// Uses the `as` expression to coerce one type to another.
232/// This will render as `<Type1 as Type2>`.
233#[derive(Clone, Debug)]
234pub struct TypeAsType<Type1, Type2>(pub Type1, pub Type2);
235
236/// Declaration of an extern block, i.e. for FFI.
237/// In Rust 2024 and later, the unsafe keyword must be added for extern blocks. Thus, this struct
238/// requires that the context satisfies [ContextProvides] for [Edition].
239#[derive(Clone, Debug)]
240pub struct ExternBlock<Abi, Body> {
241    /// The ABI chosen. Must be writable
242    pub abi: Abi,
243    /// The body of the extern block. Must be writable
244    pub body: Body,
245}
246
247impl<Abi, Body> CanHaveAttributes for ExternBlock<Abi, Body> {
248    fn with_attributes<Attr>(self, attr: Attr) -> WithAttributes<Attr, Self> {
249        WithAttributes {
250            attr,
251            separator: AttributeSeparator::NewLine,
252            value: self,
253        }
254    }
255}
256
257/// Declaration of a module block. Renders as `mod Name {Body}`.
258#[derive(Clone, Debug)]
259pub struct ModBlock<Name, Body> {
260    /// The module name
261    pub name: Name,
262    /// The body. Must be writable
263    pub body: Body,
264}
265
266/// An if block. The condition and body must both be writable.
267#[derive(Clone, Debug)]
268pub struct IfBlock<Cond, Body>(pub Cond, pub Body);
269
270/// Represents "else" syntactically. Renders as `Before else After`.
271///
272/// This struct requires you to specify what comes before and after the else. For example:
273/// ```
274/// # use async_codegen::common::Str;
275/// # use async_codegen::context::EmptyContext;
276/// # use async_codegen::rust::{Block, Else, IfBlock};
277/// # use async_codegen::util::InMemoryOutput;
278///
279/// let if_block = IfBlock(Str("true"), Str("log::info(\"Hello\")"));
280/// let else_block = Block(Str("panic!()"));
281/// let if_else = Else(if_block, else_block);
282///
283/// let string = InMemoryOutput::print_output(EmptyContext, &if_else);
284/// assert_eq!("if true {\nlog::info(\"Hello\")\n} else {\npanic!()\n}", string)
285/// ```
286#[derive(Clone, Debug)]
287pub struct Else<Before, After>(pub Before, pub After);
288
289/// An unlabeled block.
290/// This can be used in many contexts, including merely organizing the code.
291#[derive(Clone, Debug)]
292pub struct Block<Body>(pub Body);
293
294/// Places the expression inside an unsafe block.
295/// Adds new lines inside the brackets, wrapping the inner expression.
296#[derive(Clone, Debug)]
297pub struct UnsafeBlock<Expr>(pub Expr);
298
299/// Writes a closure.
300/// Adds new lines inside the brackets, wrapping the inner expression.
301#[derive(Clone, Debug)]
302pub struct Closure<InputVars, Expr> {
303    /// The input variables.
304    /// Should be a sequence. They will be comma separated and placed within the pipes.
305    /// To use no input variables, use [NoOpSeq].
306    pub input_vars: InputVars,
307    /// The expression inside the closure block.
308    pub inside_block: Expr,
309}
310
311/// Performs a call to a function inside code.
312#[derive(Clone, Debug)]
313pub struct FunctionCall<Recv, Name, Args> {
314    /// The function receiver
315    pub receiver: Recv,
316    /// Whether the function is associated, false if it's a method
317    pub is_assoc: bool,
318    /// The function name
319    pub name: Name,
320    /// The arguments. Must be a sequence
321    pub args: Args,
322}
323
324/// Provides access to the "turbofish" syntax, i.e. `Name::<Args>`.
325/// The first tuple value must be writable, and the second must be a sequence.
326///
327/// Note that if the sequence outputs nothing, this struct will behave as if no args were
328/// specified. I.e. `Turbofish(Name, NoOpSeq)` is equivalent to just `Name`.
329#[derive(Clone, Debug)]
330pub struct Turbofish<Name, Args>(pub Name, pub Args);
331
332/// Accesses a struct field by name. Can be used for named fields or tuple fields.
333/// Renders as `Owner.Field`. For example:
334/// ```
335/// # use async_codegen::common::Str;
336/// # use async_codegen::context::EmptyContext;
337/// # use async_codegen::rust::{FieldAccess, LetStmt, RefOf};
338/// # use async_codegen::util::InMemoryOutput;
339/// let string = InMemoryOutput::print_output(EmptyContext, &LetStmt(
340///   Str("borrowed_field"), RefOf(FieldAccess(Str("my_var"), Str("my_field")))
341/// ));
342/// assert_eq!(string, "let borrowed_field = &my_var.my_field;\n");
343/// ```
344#[derive(Clone, Debug)]
345pub struct FieldAccess<Owner, Field>(pub Owner, pub Field);
346
347/// A function declaration
348#[derive(Clone, Debug)]
349pub struct FunctionDef<Mods, Name, Args, Return, Where, Body> {
350    /// The modifiers. Must be a sequence.
351    pub mods: Mods,
352    /// The function name. Type variables can be declared here via [Parameterized]
353    pub name: Name,
354    /// The arguments. Must be a sequence
355    pub args: Args,
356    /// The return type, i.e. after the `->` arrow
357    pub return_type: Return,
358    /// The "where" conditions. Must be a sequence. Set to [NoOp] to disable.
359    /// Will render as `where C1, C2, C3, ...` where CX is a value in the sequence.
360    pub where_conds: Where,
361    /// The function body.
362    /// To only declare the function, this must be `;` so use [FunctionBodyDeclare]
363    /// To implement the function, use [FunctionBodyImplement]
364    pub body: Body,
365}
366
367impl<Mods, Name, Args, Return, Where, Body> CanHaveAttributes
368    for FunctionDef<Mods, Name, Args, Return, Where, Body>
369{
370    fn with_attributes<Attr>(self, attr: Attr) -> WithAttributes<Attr, Self> {
371        WithAttributes {
372            attr,
373            separator: AttributeSeparator::NewLine,
374            value: self,
375        }
376    }
377}
378
379/// Declares a function body. This is equivalent to just a semicolon.
380#[derive(Clone, Debug)]
381pub struct FunctionBodyDeclare;
382
383/// Implements a function body. Places the contents inside brackets
384#[derive(Clone, Debug)]
385pub struct FunctionBodyImplement<Inner>(pub Inner);
386
387/// A function pointer. Can be used for `fn`, `Fn`, `FnMut`, and `FnOnce`.
388///
389/// Example:
390/// ```
391/// # use async_codegen::common::{SingularSeq, Str};
392/// # use async_codegen::context::EmptyContext;
393/// # use async_codegen::rust::{FunctionPtr, FunctionPtrKind};
394/// # use async_codegen::util::InMemoryOutput;
395/// let function_ptr = FunctionPtr {
396///   kind: FunctionPtrKind::FnMut,
397///   args: SingularSeq(Str("String")),
398///   return_type: Str("bool")
399/// };
400/// let string = InMemoryOutput::print_output(EmptyContext, &function_ptr);
401/// assert_eq!("FnMut(String) -> bool", string);
402/// ```
403#[derive(Clone, Debug)]
404pub struct FunctionPtr<Args, Return> {
405    /// The function pointer kind
406    pub kind: FunctionPtrKind,
407    /// The arguments. Must be a sequence
408    pub args: Args,
409    /// The return type, i.e. after the `->` arrow
410    pub return_type: Return,
411}
412
413/// The kind of function type
414#[derive(Clone, Debug)]
415pub enum FunctionPtrKind {
416    /// An `fn` pointer. E.g. `fn(String) -> bool`.
417    FnPtr,
418    /// Represents [Fn]
419    Fn,
420    /// Represents [FnMut]
421    FnMut,
422    /// Represents [FnOnce]
423    FnOnce,
424}
425
426/// Renders as `Type=Value`. Intended to be used as a type argument, to specify associated types.
427#[derive(Clone, Debug)]
428pub struct AssociatedTypeEquals<Type, Value>(pub Type, pub Value);
429
430/// Adds a "dyn " before a type expression.
431#[derive(Clone, Debug)]
432pub struct DynOf<Type>(pub Type);
433
434/// Adds a "&" before a type expression
435#[derive(Clone, Debug)]
436pub struct RefOf<Expr>(pub Expr);
437
438/// Dereferences an expression using `*`
439#[derive(Clone, Debug)]
440pub struct Dereference<Expr>(pub Expr);
441
442/// Surrounds an expression with parentheses, rendering as `(Expr)`.
443/// Even if the expression is empty, the parentheses will still be rendered.
444#[derive(Clone, Debug)]
445pub struct ParenthesesAround<Expr>(pub Expr);
446
447/// Adds an "impl " before a type expression
448pub struct ImplOf<Type>(pub Type);
449
450/// Adds a reference with a lifetime before a type expression, i.e. `&'<lifetime> <type>`
451#[derive(Clone, Debug)]
452pub struct LifetimedRefOf<'l, Type>(pub &'l str, pub Type);
453
454/// Uses the `&raw const` syntax to get a pointer from another pointer. For example:
455/// ```
456/// # use async_codegen::common::Str;
457/// # use async_codegen::context::EmptyContext;
458/// # use async_codegen::rust::{FieldAccess, LetStmt, RawConstOf};
459/// # use async_codegen::util::InMemoryOutput;
460/// let pointer_var = Str("ptr");
461/// let let_stmt = LetStmt(pointer_var, RawConstOf(FieldAccess(Str("packed"), Str("field1"))));
462/// let string = InMemoryOutput::print_output(EmptyContext, &let_stmt);
463/// assert_eq!("let ptr = &raw const packed.field1;\n", string);
464/// ```
465#[derive(Clone, Debug)]
466pub struct RawConstOf<Expr>(pub Expr);
467
468/// Uses the `&raw must` syntax to get a pointer from another pointer. For example:
469/// ```
470/// # use async_codegen::common::Str;
471/// # use async_codegen::context::EmptyContext;
472/// # use async_codegen::rust::{FieldAccess, LetStmt, RawMutOf};
473/// # use async_codegen::util::InMemoryOutput;
474/// let pointer_var = Str("ptr");
475/// let let_stmt = LetStmt(pointer_var, RawMutOf(FieldAccess(Str("packed"), Str("field1"))));
476/// let string = InMemoryOutput::print_output(EmptyContext, &let_stmt);
477/// assert_eq!("let ptr = &raw mut packed.field1;\n", string);
478/// ```
479#[derive(Clone, Debug)]
480pub struct RawMutOf<Expr>(pub Expr);
481
482/// A `*const Type` for some arbitrary type
483#[derive(Clone, Debug)]
484pub struct ConstPtr<Type>(pub Type);
485
486/// A `*mut Type` for some arbitrary type.
487#[derive(Clone, Debug)]
488pub struct MutPtr<Type>(pub Type);
489
490/// Declares an associated type, rendering as `type VarName = Value;`.
491/// Adds new lines before and after.
492#[derive(Clone, Debug)]
493pub struct AssociatedTypeDef<VarName, Value>(pub VarName, pub Value);
494
495/// The declaration of a trait
496#[derive(Clone, Debug)]
497pub struct TraitDef<Mods, Name, TypeVars, SuperTraits, Body> {
498    /// The trait modifiers, e.g. visibility. Must be a sequence.
499    pub mods: Mods,
500    /// The name of the trait
501    pub name: Name,
502    /// The type variables. Must be a sequence
503    pub type_variables: TypeVars,
504    /// The super traits. Must be a sequence
505    pub super_traits: SuperTraits,
506    /// The trait definition's body. Use [NoOp] if none exists.
507    pub body: Body,
508}
509
510impl<Mods, Name, TypeVars, SuperTraits, Body> CanHaveAttributes
511    for TraitDef<Mods, Name, TypeVars, SuperTraits, Body>
512{
513    fn with_attributes<Attr>(self, attr: Attr) -> WithAttributes<Attr, Self> {
514        WithAttributes {
515            attr,
516            separator: AttributeSeparator::NewLine,
517            value: self,
518        }
519    }
520}
521
522/// The implementation declaration for a trait, applying to a certain receiver.
523#[derive(Clone, Debug)]
524pub struct TraitImpl<Mods, TypeVars, Trait, Recv, Where, Body> {
525    /// The modifiers on the `impl` block.
526    /// Set to [NoOpSeq] for none, or use `SingularSeq(ModUnsafe)` to generate an `unsafe impl`.
527    pub mods: Mods,
528    /// The type variables to use for the impl block itself. All type variables that appear later
529    /// on the trait or the receiver must be declared here, per Rust language rules.
530    ///
531    /// This field must be a sequence.
532    pub type_variables: TypeVars,
533    /// The trait being implemented
534    pub the_trait: Trait,
535    /// The receiver for which it is implemented
536    pub receiver: Recv,
537    /// The "where" conditions. Must be a sequence. Set to [NoOpSeq] to disable.
538    /// Will render as `where C1, C2, C3, ...` where CX is a value in the sequence.
539    pub where_conds: Where,
540    /// The body. Use [NoOp] if none exists.
541    pub body: Body,
542}
543
544impl<Mods, TypeVars, Trait, Recv, Where, Body> CanHaveAttributes
545    for TraitImpl<Mods, TypeVars, Trait, Recv, Where, Body>
546{
547    fn with_attributes<Attr>(self, attr: Attr) -> WithAttributes<Attr, Self> {
548        WithAttributes {
549            attr,
550            separator: AttributeSeparator::NewLine,
551            value: self,
552        }
553    }
554}
555
556/// The declaration of a struct.
557#[derive(Clone, Debug)]
558pub struct StructDef<Mods, Name, Elements> {
559    /// The struct modifiers. Must be a sequence.
560    pub mods: Mods,
561    /// The kind of the struct.
562    ///
563    /// It is suggested to use either a [NamedTuple] or [StructCall]. A semicolon will be
564    /// automatically added afterward, as is needed for tuple structs, and this semicolon will not
565    /// affect structs with named fields.
566    pub kind: StructKind<Name, Elements>,
567}
568
569impl<Mods, Name, Elements> CanHaveAttributes for StructDef<Mods, Name, Elements> {
570    fn with_attributes<Attr>(self, attr: Attr) -> WithAttributes<Attr, Self> {
571        WithAttributes {
572            attr,
573            separator: AttributeSeparator::NewLine,
574            value: self,
575        }
576    }
577}
578
579/// Completes the struct definition as either a named tuple or a struct with named fields.
580#[derive(Clone, Debug)]
581pub enum StructKind<Name, Elements> {
582    /// A named tuple. This will function similarly to [NamedTuple], except a semicolon will
583    /// be added afterward.
584    ///
585    /// `Name` must be writable, and `Elements` must be a writable sequence for the tuple arguments.
586    Tuple(Name, Elements),
587    /// A struct with named fields. This will function similarly to [StructCall].
588    ///
589    /// `Name` must be writable, and `Elements` must be writable sequence for the struct fields.
590    NamedFields(Name, Elements),
591}
592
593/// The construction or deconstruction of a struct.
594///
595/// When rendered, will use the format `Name { Body }`. Spaces will be added automatically.
596///
597/// This should **not** be used for tuple structs, for that see [NamedTuple].
598#[derive(Clone, Debug)]
599pub struct StructCall<Name, Body> {
600    /// The struct name. Must be writable.
601    ///
602    /// If you are declaring a struct for the first time, you can use [Parameterized] in order
603    /// to declare type variables.
604    pub name: Name,
605    /// The body. Must be writable.
606    ///
607    /// It is suggested to use [StructFields] for multiple fields, or [DeclareField] for just one.
608    pub body: Body,
609}
610
611/// Named struct fields. This will place every field on a new line with a comma afterward.
612/// It is recommended that the sequence should pass [DeclareField].
613///
614/// If you have a single field, you can skip using a sequence and just use [DeclareField] directly.
615pub struct StructFields<Fields>(pub Fields);
616
617/// Declares a single field within a struct. Renders as `Name: Value`.
618///
619/// Does not add attributes. If you want to use attributes for declaration purposes, you can use
620/// [CanHaveAttributes::with_attributes] on this field.
621pub struct DeclareField<Name, Value>(pub Name, pub Value);
622
623impl<Name, Value> CanHaveAttributes for DeclareField<Name, Value> {
624    fn with_attributes<Attr>(self, attr: Attr) -> WithAttributes<Attr, Self> {
625        WithAttributes {
626            attr,
627            separator: AttributeSeparator::NewLine,
628            value: self,
629        }
630    }
631}
632
633/// A named tuple type.
634///
635/// Renders as `Name(A1, A2, A3, ...)` where AX is part of the argument sequence.
636/// If no arguments exist, will render only as `Name` (i.e., a unit struct).
637pub struct NamedTuple<Name, Args> {
638    pub name: Name,
639    pub args: Args,
640}
641
642/// An anonymous tuple type. This struct's tuple value must be a sequence.
643///
644/// Renders as `(A1, A2, A3, ...)` where AX is part of the argument sequence.
645#[derive(Clone, Debug)]
646pub struct AnonTuple<Args>(pub Args);
647
648/// The unit type, i.e. `()`
649pub type UnitType = AnonTuple<NoOpSeq>;
650
651impl AnonTuple<NoOpSeq> {
652    /// Creates
653    pub fn unit() -> Self {
654        Self(NoOpSeq)
655    }
656}
657
658/// Adds attributes to ANY item.
659///
660/// The first tuple value must be a sequence. The second must be a writable value. This struct
661/// is typically constructed via [CanHaveAttributes::with_attributes].
662///
663/// Rust attributes can be put in many places, so this enables you to add attributes to any
664/// writable item. For example, adding attributes to function parameters can be done like so:
665///
666/// ```rust
667/// # use async_codegen::common::{SingularSeq, Str};
668/// # use async_codegen::context::EmptyContext;
669/// # use async_codegen::rust::{Cfg, FunctionParam, MustUse, Target, WithAttributes, CanHaveAttributes};
670/// # use async_codegen::util::InMemoryOutput;
671///
672/// let function_param = FunctionParam(Str("conditional_param"), Str("Fd")).with_attributes(
673///   SingularSeq(Cfg(Target::Os(Str("linux"))))
674/// );
675/// let string = InMemoryOutput::print_output(EmptyContext, &function_param);
676/// assert_eq!("#[cfg(target_os = \"linux\")] conditional_param: Fd", string);
677/// ```
678#[derive(Clone, Debug)]
679pub struct WithAttributes<Attr, Value> {
680    /// The attributes. Must be a sequence.
681    pub attr: Attr,
682    /// The separator between each attribute
683    pub separator: AttributeSeparator,
684    /// The value
685    pub value: Value,
686}
687
688#[derive(Copy, Clone, Debug)]
689pub enum AttributeSeparator {
690    Space,
691    NewLine,
692}
693
694/// A writable that can have attributes attached to it
695pub trait CanHaveAttributes: Sized {
696    /// Adds attributes to this writable
697    fn with_attributes<Attr>(self, attr: Attr) -> WithAttributes<Attr, Self>;
698}
699
700/// Defines an enum.
701///
702/// In order to use or refer to an enum, you can use [AssociatedItem] together with [NamedTuple]
703/// or [StructCall].
704pub struct EnumDef<Mods, Name, Entries> {
705    /// The modifiers on the type. Must be a sequence.
706    pub mods: Mods,
707    /// The name of the enum
708    pub name: Name,
709    /// The enum entries. Must be a sequence, each entry will be written on a new line with a comma
710    ///
711    /// As for the entries themselves, it is suggested to use [NamedTuple] or [StructCall]
712    /// depending on which kind of enum entry you want to create.
713    pub entries: Entries,
714}
715
716impl<Mods, Name, Entries> CanHaveAttributes for EnumDef<Mods, Name, Entries> {
717    fn with_attributes<Attr>(self, attr: Attr) -> WithAttributes<Attr, Self> {
718        WithAttributes {
719            attr,
720            separator: AttributeSeparator::NewLine,
721            value: self,
722        }
723    }
724}
725
726/// A type argument-parameterized expression. Used in relation to parameterized names and their
727/// arguments. Examples: `function_name<args>`, `TypeName<'lifetime, args>`, `MyType<Assoc=Value>`.
728///
729/// If no type args exist, [NoOpSeq] should be used. In any case, the second tuple value of this
730/// struct must be a sequence.
731#[derive(Clone, Debug)]
732pub struct Parameterized<Name, TypeArgs>(pub Name, pub TypeArgs);
733
734/// A type variable with a sequence of bounds.
735/// Will render as `TypeVar: B1 + B2 + ...`
736#[derive(Clone, Debug)]
737pub struct BoundedTypeVar<TypeVar, Bounds>(pub TypeVar, pub Bounds);
738
739/// A standalone lifetime, intended to be used as a type argument or variable
740#[derive(Clone, Debug)]
741pub struct Lifetime<'l>(pub &'l str);
742
743/// Renders an individual function parameter, `Name: Type`
744#[derive(Clone, Debug)]
745pub struct FunctionParam<Name, Type>(pub Name, pub Type);
746
747impl<Name, Type> CanHaveAttributes for FunctionParam<Name, Type> {
748    fn with_attributes<Attr>(self, attr: Attr) -> WithAttributes<Attr, Self> {
749        WithAttributes {
750            attr,
751            separator: AttributeSeparator::Space,
752            value: self,
753        }
754    }
755}
756
757/// A sequence acceptor that writes attributes. Every attribute will be surrounded with "#[]"
758#[derive(Debug)]
759pub struct AttributesAccept<'o, O, Sep> {
760    inner: SurroundingSeqAccept<'o, O, Str<&'static str>, Combined<Str<&'static str>, Sep>>,
761}
762
763impl<'o, O, Sep> AttributesAccept<'o, O, Sep> {
764    pub fn with_separator(output: &'o mut O, separator: Sep) -> Self {
765        Self {
766            inner: SurroundingSeqAccept::new(output, Str("#["), Combined(Str("]"), separator)),
767        }
768    }
769}
770
771impl<'o, O, Sep> SequenceAccept<O> for AttributesAccept<'o, O, Sep>
772where
773    O: Output,
774    Sep: Writable<O>,
775{
776    async fn accept<W: Writable<O>>(&mut self, writable: &W) -> Result<(), O::Error> {
777        self.inner.accept(writable).await
778    }
779}