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::new(Str("Option"), SingularSeq(Str("bool")))))
39//!     ),
40//!     return_type: Parameterized::new(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 [crate::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", 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 extern modifier, with the ABI selected as the tuple value.
167///
168/// This struct includes `unsafe`. Since Rust 2024, the unsafe keyword is required for extern
169/// functions, and before Rust 2024 it is optional. To make it easy to generate code targeting
170/// multiple editions, we unconditionally emit the "unsafe" keyword alongside "extern".
171#[derive(Clone, Debug)]
172pub struct ModUnsafeExtern<Abi>(pub Abi);
173
174/// A standalone statement. Renders the expression and adds a semicolon and a new line.
175#[derive(Clone, Debug)]
176pub struct Stmt<Expr>(pub Expr);
177
178/// A let statement. This statement includes the semicolon and a new line.
179#[derive(Clone, Debug)]
180pub struct LetStmt<Variable, Expr>(pub Variable, pub Expr);
181
182/// An assignation. This statement includes the semicolon and a new line.
183#[derive(Clone, Debug)]
184pub struct AssignStmt<Variable, Expr>(pub Variable, pub Expr);
185
186/// A return statement. Renders as `return Expr;` with a new line at the end.
187#[derive(Clone, Debug)]
188pub struct ReturnStmt<Expr>(pub Expr);
189
190/// A let expression.
191/// This can be used, for example, as the condition of [IfBlock] in order to create an "if-let" block.
192#[derive(Clone, Debug)]
193pub struct LetExpr<Pattern, Expr>(pub Pattern, pub Expr);
194
195/// An array literal with predefined elements written out.
196/// Renders as `[E1, E2, E3, ...]` where EX is in the element sequence.
197#[derive(Clone, Debug)]
198pub struct ArrayFromElements<Elements>(pub Elements);
199
200/// An item attached to an associated container, via "::".
201/// The output will look like `Cont::Item`.
202#[derive(Clone, Debug)]
203pub struct AssociatedItem<Cont, Item>(pub Cont, pub Item);
204
205/// A question mark following another expression.
206#[derive(Clone, Debug)]
207pub struct QuestionMarkAfter<Expr>(pub Expr);
208
209/// Wraps an expression in `Ok(EXPR)`.
210#[derive(Clone, Debug)]
211pub struct OkResultOf<Expr>(pub Expr);
212
213/// Uses the `as` expression to perform a qualified trait cast (ready for a method call).
214/// I.e., this will render as `<Type as Trait>`.
215#[derive(Clone, Debug)]
216pub struct TypeAsTrait<Type, Trait>(pub Type, pub Trait);
217
218/// Declaration of an extern block, i.e. for FFI.
219/// In Rust 2024 and later, the unsafe keyword must be added for extern blocks. Thus, this struct
220/// requires that the context satisfies [ContextProvides] for [Edition].
221#[derive(Clone, Debug)]
222pub struct ExternBlock<Abi, Body> {
223    /// The ABI chosen. Must be writable
224    pub abi: Abi,
225    /// The body of the extern block. Must be writable
226    pub body: Body,
227}
228
229impl<Abi, Body> CanHaveAttributes for ExternBlock<Abi, Body> {
230    fn with_attributes<Attr>(self, attr: Attr) -> WithAttributes<Attr, Self> {
231        WithAttributes {
232            attr,
233            separator: "\n",
234            value: self,
235        }
236    }
237}
238
239/// Declaration of a module block. Renders as `mod Mod {Body}`.
240#[derive(Clone, Debug)]
241pub struct ModBlock<Name, Body> {
242    /// The module name
243    pub name: Name,
244    /// The body. Must be writable
245    pub body: Body,
246}
247
248/// An if block. The condition and body must both be writable.
249#[derive(Clone, Debug)]
250pub struct IfBlock<Cond, Body>(pub Cond, pub Body);
251
252/// Represents "else" syntactically. Renders as `Before else After`.
253///
254/// This struct requires you to specify what comes before and after the else. For example:
255/// ```
256/// # use async_codegen::common::Str;
257/// # use async_codegen::context::EmptyContext;
258/// # use async_codegen::rust::{Block, Else, IfBlock};
259/// # use async_codegen::util::InMemoryOutput;
260///
261/// let if_block = IfBlock(Str("true"), Str("log::info(\"Hello\")"));
262/// let else_block = Block(Str("panic!()"));
263/// let if_else = Else(if_block, else_block);
264///
265/// let string = InMemoryOutput::print_output(EmptyContext, &if_else);
266/// assert_eq!("if true {\nlog::info(\"Hello\")\n} else {\npanic!()\n}", string)
267/// ```
268#[derive(Clone, Debug)]
269pub struct Else<Before, After>(pub Before, pub After);
270
271/// An unlabeled block.
272/// This can be used in many contexts, including merely organizing the code.
273#[derive(Clone, Debug)]
274pub struct Block<Body>(pub Body);
275
276/// Places the expression inside an unsafe block.
277/// Adds new lines inside the brackets, wrapping the inner expression.
278#[derive(Clone, Debug)]
279pub struct UnsafeBlock<Expr>(pub Expr);
280
281/// Writes a closure.
282/// Adds new lines inside the brackets, wrapping the inner expression.
283#[derive(Clone, Debug)]
284pub struct Closure<InputVars, Expr> {
285    /// The input variables.
286    /// Should be a sequence. They will be comma separated and placed within the pipes.
287    /// To use no input variables, use [NoOpSeq].
288    pub input_vars: InputVars,
289    /// The expression inside the closure block.
290    pub inside_block: Expr,
291}
292
293/// Performs a call to a function inside code.
294#[derive(Clone, Debug)]
295pub struct FunctionCall<Recv, Name, Args> {
296    /// The function receiver
297    pub receiver: Recv,
298    /// Whether the function is associated, false if it's a method
299    pub is_assoc: bool,
300    /// The function name
301    pub name: Name,
302    /// The arguments. Must be a sequence
303    pub args: Args,
304}
305
306/// Provides access to the "turbofish" syntax, i.e. `Name::<Args>`.
307/// The first tuple value must be writable, and the second must be a sequence.
308///
309/// Note that if the sequence outputs nothing, this struct will behave as if no args were
310/// specified. I.e. `Turbofish(Name, NoOpSeq)` is equivalent to just `Name`.
311#[derive(Clone, Debug)]
312pub struct Turbofish<Name, Args>(pub Name, pub Args);
313
314/// A function declaration
315#[derive(Clone, Debug)]
316pub struct FunctionDef<Mods, Name, Args, Return, Where, Body> {
317    /// The modifiers. Must be a sequence.
318    pub mods: Mods,
319    /// The function name. Type variables can be declared here via [Parameterized]
320    pub name: Name,
321    /// The arguments. Must be a sequence
322    pub args: Args,
323    /// The return type, i.e. after the `->` arrow
324    pub return_type: Return,
325    /// The "where" conditions. Must be a sequence. Set to [NoOp] to disable.
326    /// Will render as `where C1, C2, C3, ...` where CX is a value in the sequence.
327    pub where_conds: Where,
328    /// The function body.
329    /// To only declare the function, this must be `;` so use [FunctionBodyDeclare]
330    /// To implement the function, use [FunctionBodyImplement]
331    pub body: Body,
332}
333
334impl<Mods, Name, Args, Return, Where, Body> CanHaveAttributes
335    for FunctionDef<Mods, Name, Args, Return, Where, Body>
336{
337    fn with_attributes<Attr>(self, attr: Attr) -> WithAttributes<Attr, Self> {
338        WithAttributes {
339            attr,
340            separator: "\n",
341            value: self,
342        }
343    }
344}
345
346/// Declares a function body. This is equivalent to just a semicolon.
347#[derive(Clone, Debug)]
348pub struct FunctionBodyDeclare;
349
350/// Implements a function body. Places the contents inside brackets
351#[derive(Clone, Debug)]
352pub struct FunctionBodyImplement<Inner>(pub Inner);
353
354/// A function pointer. Can be used for `fn`, `Fn`, `FnMut`, and `FnOnce`.
355///
356/// Example:
357/// ```
358/// # use async_codegen::common::{SingularSeq, Str};
359/// # use async_codegen::context::EmptyContext;
360/// # use async_codegen::rust::{FunctionPtr, FunctionPtrKind};
361/// # use async_codegen::util::InMemoryOutput;
362/// let function_ptr = FunctionPtr {
363///   kind: FunctionPtrKind::FnMut,
364///   args: SingularSeq(Str("String")),
365///   return_type: Str("bool")
366/// };
367/// let string = InMemoryOutput::print_output(EmptyContext, &function_ptr);
368/// assert_eq!("FnMut(String) -> bool", string);
369/// ```
370#[derive(Clone, Debug)]
371pub struct FunctionPtr<Args, Return> {
372    /// The function pointer kind
373    pub kind: FunctionPtrKind,
374    /// The arguments. Must be a sequence
375    pub args: Args,
376    /// The return type, i.e. after the `->` arrow
377    pub return_type: Return,
378}
379
380/// The kind of function type
381#[derive(Clone, Debug)]
382pub enum FunctionPtrKind {
383    /// An `fn` pointer. E.g. `fn(String) -> bool`.
384    FnPtr,
385    /// Represents [Fn]
386    Fn,
387    /// Represents [FnMut]
388    FnMut,
389    /// Represents [FnOnce]
390    FnOnce,
391}
392
393/// Renders as `Type=Value`. Intended to be used as a type argument, to specify associated types.
394#[derive(Clone, Debug)]
395pub struct AssociatedTypeEquals<Type, Value>(pub Type, pub Value);
396
397/// Adds a "dyn " before a type expression.
398#[derive(Clone, Debug)]
399pub struct DynOf<Type>(pub Type);
400
401/// Adds a "&" before a type expression
402#[derive(Clone, Debug)]
403pub struct RefOf<Type>(pub Type);
404
405/// Adds an "impl " before a type expression
406pub struct ImplOf<Type>(pub Type);
407
408/// Adds a reference with a lifetime before a type expression, i.e. `&'<lifetime> <type>`
409#[derive(Clone, Debug)]
410pub struct LifetimedRefOf<'l, Type>(pub &'l str, pub Type);
411
412/// Declares an associated type, rendering as `type VarName = Value;`.
413/// Adds new lines before and after.
414#[derive(Clone, Debug)]
415pub struct AssociatedTypeDef<VarName, Value>(pub VarName, pub Value);
416
417/// The declaration of a trait
418#[derive(Clone, Debug)]
419pub struct TraitDef<Mods, Name, TypeVars, SuperTraits, Body> {
420    /// The trait modifiers, e.g. visibility. Must be a sequence.
421    pub mods: Mods,
422    /// The name of the trait
423    pub name: Name,
424    /// The type variables. Must be a sequence
425    pub type_variables: TypeVars,
426    /// The super traits. Must be a sequence
427    pub super_traits: SuperTraits,
428    /// The trait definition's body. Use [NoOp] if none exists.
429    pub body: Body,
430}
431
432impl<Mods, Name, TypeVars, SuperTraits, Body> CanHaveAttributes
433    for TraitDef<Mods, Name, TypeVars, SuperTraits, Body>
434{
435    fn with_attributes<Attr>(self, attr: Attr) -> WithAttributes<Attr, Self> {
436        WithAttributes {
437            attr,
438            separator: "\n",
439            value: self,
440        }
441    }
442}
443
444/// The implementation declaration for a trait, applying to a certain receiver.
445#[derive(Clone, Debug)]
446pub struct TraitImpl<TypeVars, Trait, Recv, Where, Body> {
447    /// The type variables to use for the impl block itself. All type variables that appear later
448    /// on the trait or the receiver must be declared here, per Rust language rules.
449    ///
450    /// This field must be a sequence.
451    pub type_variables: TypeVars,
452    /// The trait being implemented
453    pub the_trait: Trait,
454    /// The receiver for which it is implemented
455    pub receiver: Recv,
456    /// The "where" conditions. Must be a sequence. Set to [NoOpSeq] to disable.
457    /// Will render as `where C1, C2, C3, ...` where CX is a value in the sequence.
458    pub where_conds: Where,
459    /// The body. Use [NoOp] if none exists.
460    pub body: Body,
461}
462
463impl<TypeVars, Trait, Recv, Where, Body> CanHaveAttributes
464    for TraitImpl<TypeVars, Trait, Recv, Where, Body>
465{
466    fn with_attributes<Attr>(self, attr: Attr) -> WithAttributes<Attr, Self> {
467        WithAttributes {
468            attr,
469            separator: "\n",
470            value: self,
471        }
472    }
473}
474
475/// The declaration of a struct.
476#[derive(Clone, Debug)]
477pub struct StructDef<Mods, Name, Elements> {
478    /// The struct modifiers. Must be a sequence.
479    pub mods: Mods,
480    /// The kind of the struct.
481    ///
482    /// It is suggested to use either a [NamedTuple] or [StructCall]. A semicolon will be
483    /// automatically added afterward, as is needed for tuple structs, and this semicolon will not
484    /// affect structs with named fields.
485    pub kind: StructKind<Name, Elements>,
486}
487
488impl<Mods, Name, Elements> CanHaveAttributes for StructDef<Mods, Name, Elements> {
489    fn with_attributes<Attr>(self, attr: Attr) -> WithAttributes<Attr, Self> {
490        WithAttributes {
491            attr,
492            separator: "\n",
493            value: self,
494        }
495    }
496}
497
498/// Completes the struct definition as either a named tuple or a struct with named fields.
499#[derive(Clone, Debug)]
500pub enum StructKind<Name, Elements> {
501    /// A named tuple. This will function similarly to [NamedTuple], except a semicolon will
502    /// be added afterward.
503    ///
504    /// `Name` must be writable, and `Elements` must be a writable sequence for the tuple arguments.
505    Tuple(Name, Elements),
506    /// A struct with named fields. This will function similarly to [StructCall].
507    ///
508    /// `Name` must be writable, and `Elements` must be writable sequence for the struct fields.
509    NamedFields(Name, Elements),
510}
511
512/// The construction or deconstruction of a struct.
513///
514/// When rendered, will use the format `Name { Body }`. Spaces will be added automatically.
515///
516/// This should **not** be used for tuple structs, for that see [NamedTuple].
517#[derive(Clone, Debug)]
518pub struct StructCall<Name, Body> {
519    /// The struct name. Must be writable.
520    ///
521    /// If you are declaring a struct for the first time, you can use [Parameterized] in order
522    /// to declare type variables.
523    pub name: Name,
524    /// The body. Must be writable.
525    ///
526    /// It is suggested to use [StructFields] for multiple fields, or [DeclareField] for just one.
527    pub body: Body,
528}
529
530/// Named struct fields. This will place every field on a new line with a comma afterward.
531/// It is recommended that the sequence should pass [DeclareField].
532///
533/// If you have a single field, you can skip using a sequence and just use [DeclareField] directly.
534pub struct StructFields<Fields>(pub Fields);
535
536/// Declares a single field within a struct. Renders as `Name: Value`.
537///
538/// Does not add attributes. If you want to use attributes for declaration purposes, you can use
539/// [CanHaveAttributes::with_attributes] on this field.
540pub struct DeclareField<Name, Value>(pub Name, pub Value);
541
542impl<Name, Value> CanHaveAttributes for DeclareField<Name, Value> {
543    fn with_attributes<Attr>(self, attr: Attr) -> WithAttributes<Attr, Self> {
544        WithAttributes {
545            attr,
546            separator: "\n",
547            value: self,
548        }
549    }
550}
551
552/// A named tuple type.
553///
554/// Renders as `Name(A1, A2, A3, ...)` where AX is part of the argument sequence.
555/// If no arguments exist, will render only as `Name` (i.e., a unit struct).
556pub struct NamedTuple<Name, Args> {
557    pub name: Name,
558    pub args: Args,
559}
560
561/// An anonymous tuple type. This struct's tuple value must be a sequence.
562///
563/// Renders as `(A1, A2, A3, ...)` where AX is part of the argument sequence.
564#[derive(Clone, Debug)]
565pub struct AnonTuple<Args>(pub Args);
566
567/// The unit type, i.e. `()`
568pub type UnitType = AnonTuple<NoOpSeq>;
569
570impl AnonTuple<NoOpSeq> {
571    /// Creates
572    pub fn unit() -> Self {
573        Self(NoOpSeq)
574    }
575}
576
577/// Adds attributes to ANY item.
578///
579/// The first tuple value must be a sequence. The second must be a writable value. This struct
580/// is typically constructed via [CanHaveAttributes::with_attributes].
581///
582/// Rust attributes can be put in many places, so this enables you to add attributes to any
583/// writable item. For example, adding attributes to function parameters can be done like so:
584///
585/// ```rust
586/// # use async_codegen::common::{SingularSeq, Str};
587/// # use async_codegen::context::EmptyContext;
588/// # use async_codegen::rust::{Cfg, FunctionParam, MustUse, Target, WithAttributes, CanHaveAttributes};
589/// # use async_codegen::util::InMemoryOutput;
590///
591/// let function_param = FunctionParam(Str("conditional_param"), Str("Fd")).with_attributes(
592///   SingularSeq(Cfg(Target::Os(Str("linux"))))
593/// );
594/// let string = InMemoryOutput::print_output(EmptyContext, &function_param);
595/// assert_eq!("#[cfg(target_os = \"linux\")] conditional_param: Fd", string);
596/// ```
597#[derive(Clone, Debug)]
598pub struct WithAttributes<Attr, Value> {
599    pub attr: Attr,
600    /// The separator. Usually a space or a new line, depending on what the target value is
601    pub separator: &'static str,
602    /// The value
603    pub value: Value,
604}
605
606/// A writable that can have attributes attached to it
607pub trait CanHaveAttributes: Sized {
608    /// Adds attributes to this writable
609    fn with_attributes<Attr>(self, attr: Attr) -> WithAttributes<Attr, Self>;
610}
611
612/// Defines an enum.
613///
614/// In order to use or refer to an enum, you can use [AssociatedItem] together with [NamedTuple]
615/// or [StructCall].
616pub struct EnumDef<Mods, Name, Entries> {
617    /// The modifiers on the type. Must be a sequence.
618    pub mods: Mods,
619    /// The name of the enum
620    pub name: Name,
621    /// The enum entries. Must be a sequence, each entry will be written on a new line with a comma
622    ///
623    /// As for the entries themselves, it is suggested to use [NamedTuple] or [StructCall]
624    /// depending on which kind of enum entry you want to create.
625    pub entries: Entries,
626}
627
628impl<Mods, Name, Entries> CanHaveAttributes for EnumDef<Mods, Name, Entries> {
629    fn with_attributes<Attr>(self, attr: Attr) -> WithAttributes<Attr, Self> {
630        WithAttributes {
631            attr,
632            separator: "\n",
633            value: self,
634        }
635    }
636}
637
638/// A type argument-parameterized expression. Used in relation to parameterized names and their
639/// arguments. Examples: `function_name<args>`, `TypeName<'lifetime, args>`, `MyType<Assoc=Value>`.
640///
641/// If no type args exist, [NoOpSeq] should be used.
642#[derive(Clone, Debug)]
643pub struct Parameterized<Name, TypeArgs> {
644    name: Name,
645    type_args: TypeArgs,
646}
647
648impl<Name, TypeArgs> Parameterized<Name, TypeArgs> {
649    /// Initializes an instance
650    pub fn new(name: Name, type_args: TypeArgs) -> Self {
651        Self { name, type_args }
652    }
653}
654
655/// A type variable with a sequence of bounds.
656/// Will render as `TypeVar: B1 + B2 + ...`
657#[derive(Clone, Debug)]
658pub struct BoundedTypeVar<TypeVar, Bounds>(pub TypeVar, pub Bounds);
659
660/// A standalone lifetime, intended to be used as a type argument or variable
661#[derive(Clone, Debug)]
662pub struct Lifetime<'l>(pub &'l str);
663
664/// Renders an individual function parameter, `Name: Type`
665#[derive(Clone, Debug)]
666pub struct FunctionParam<Name, Type>(pub Name, pub Type);
667
668impl<Name, Type> CanHaveAttributes for FunctionParam<Name, Type> {
669    fn with_attributes<Attr>(self, attr: Attr) -> WithAttributes<Attr, Self> {
670        WithAttributes {
671            attr,
672            separator: " ",
673            value: self,
674        }
675    }
676}
677
678/// A sequence acceptor that writes attributes. Every attribute will be surrounded with "#[]"
679#[derive(Debug)]
680pub struct AttributesAccept<'o, O, Sep> {
681    inner: SurroundingSeqAccept<'o, O, Str<&'static str>, Combined<Str<&'static str>, Sep>>,
682}
683
684impl<'o, O> AttributesAccept<'o, O, Str<&'static str>> {
685    pub fn multiline(output: &'o mut O) -> Self {
686        Self::with_separator(output, "\n")
687    }
688}
689
690impl<'o, O> AttributesAccept<'o, O, Str<&'static str>> {
691    pub fn with_separator(output: &'o mut O, separator: &'static str) -> Self {
692        Self {
693            inner: SurroundingSeqAccept::new(output, Str("#["), Combined(Str("]"), Str(separator))),
694        }
695    }
696}
697
698impl<'o, O, Sep> SequenceAccept<O> for AttributesAccept<'o, O, Sep>
699where
700    O: Output,
701    Sep: Writable<O>,
702{
703    async fn accept<W: Writable<O>>(&mut self, writable: &W) -> Result<(), O::Error> {
704        self.inner.accept(writable).await
705    }
706}