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, SingularSeq, Str};
28//! use async_codegen::{Output, Writable};
29//!
30//! use async_codegen::rust::{CfgAttr, Deprecated, Function, FunctionDef, FunctionParam, ModPub, MustUse, NoMangle, Parameterized};
31//!
32//! async fn write_function<O>(output: &mut O) -> Result<(), O::Error> where O: Output {
33//!   // For more advanced usage, you can replace Str("") by other Writable implementations
34//!   let function_def = FunctionDef {
35//!     attr: SingularSeq(Deprecated::with_message(Str("because we all love deprecation"))),
36//!     mods: SingularSeq(ModPub),
37//!     decl: Function {
38//!       name: Str("my_func"),
39//!       args: CombinedSeq(
40//!         SingularSeq(FunctionParam(Str("var1"), Str("Type"))),
41//!         SingularSeq(FunctionParam(Str("var2"), Parameterized::new(Str("Option"), SingularSeq(Str("bool")))))
42//!       )
43//!     },
44//!     return_type: Parameterized::new(Str("Box"), SingularSeq(Str("str"))),
45//!     body: Str("\ntodo!()\n")
46//!   };
47//!   function_def.write_to(output).await
48//!   // Will render as:
49//!   /*
50//!   #[deprecated = "because we all love deprecation"]
51//!   pub fn my_func(var1: Type, var2: Option<bool>) -> Box<str> {
52//!     todo!()
53//!   }
54//!    */
55//! }
56//! ```
57//!
58
59use crate::common::NoOp;
60
61mod syntax;
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#[cfg(test)]
77mod test_edition {
78    use crate::rust::Edition;
79
80    #[test]
81    fn edition_order() {
82        assert!(Edition::Rust2018 < Edition::Rust2021);
83        assert!(Edition::Rust2018 < Edition::Rust2024);
84    }
85}
86
87/// An attribute enabled conditionally, i.e. `#[cfg_attr(Cond, Attr)]`
88pub struct CfgAttr<Cond, Attr>(pub Cond, pub Attr);
89
90/// The no mangle attribute.
91///
92/// Requires that the context satisfies [ContextProvides] for [Edition], because in Rust 2024 and
93/// beyond, the no-mangle attribute is an "unsafe attribute.
94pub struct NoMangle;
95
96/// The attribute content for `allow(...)`. The tuple value must be a sequence.
97pub struct AllowLints<Lints>(pub Lints);
98
99/// The deprecated attribute. The three variants of this enum correspond to the deprecated
100/// attribute's multiple ways of being specified. See:
101/// https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-deprecated-attribute
102pub enum Deprecated<Msg, Since = NoOp> {
103    Basic,
104    Message(Msg),
105    Full { since: Since, note: Msg },
106}
107
108impl Default for Deprecated<NoOp, NoOp> {
109    fn default() -> Self {
110        Self::Basic
111    }
112}
113
114impl Deprecated<NoOp, NoOp> {
115    pub fn basic() -> Self {
116        Self::Basic
117    }
118}
119
120impl<Msg> Deprecated<Msg> {
121    pub fn with_message(msg: Msg) -> Self {
122        Self::Message(msg)
123    }
124}
125
126/// The must_use attribute
127pub struct MustUse;
128
129/// The public modifier
130pub struct ModPub;
131
132/// The extern modifier, with the ABI selected as the tuple value
133pub struct ModExtern<Abi>(pub Abi);
134
135/// A let statement. This statement includes the semicolon and a new line.
136pub struct LetStmt<Variable, Expr>(pub Variable, pub Expr);
137
138/// An item attached to an associated container, via "::".
139/// The output will look like `Cont::Item`.
140pub struct AssociatedItem<Cont, Item>(pub Cont, pub Item);
141
142/// A question mark following another expression.
143pub struct QuestionMarkAfter<Expr>(pub Expr);
144
145/// Wraps an expression in `Ok(EXPR)`.
146pub struct OkResultOf<Expr>(pub Expr);
147
148/// Uses the `as` expression to perform a qualified trait cast (ready for a method call).
149/// I.e., this will render as `<Type as Trait>`.
150pub struct TypeAsTrait<Type, Trait>(pub Type, pub Trait);
151
152/// Declaration of an extern block, i.e. for FFI.
153pub struct ExternBlock<Attr, Abi, Body> {
154    /// The attributes. Must be a sequence, and each value will be placed inside `#[]`.
155    pub attr: Attr,
156    /// The ABI chosen. Must be writable
157    pub abi: Abi,
158    /// The body of the extern block. Must be writable
159    pub body: Body,
160}
161
162/// Places the expression inside an unsafe block.
163/// Adds new lines inside the brackets, wrapping the inner expression.
164pub struct UnsafeBlock<Expr>(pub Expr);
165
166/// Writes a closure.
167/// Adds new lines inside the brackets, wrapping the inner expression.
168pub struct Closure<InputVars, Expr> {
169    /// The input variables.
170    /// Should be a sequence. They will be comma separated and placed within the pipes.
171    /// To use no input variables, use [crate::common::NoOpSeq].
172    pub input_vars: InputVars,
173    /// The expression inside the closure block.
174    pub inside_block: Expr,
175}
176
177/// Performs a call to a function inside code.
178pub struct FunctionCall<Recv, FuncName, Args> {
179    /// The function receiver
180    pub receiver: Recv,
181    /// Whether the function is associated, false if it's a method
182    pub is_assoc: bool,
183    /// The function being called
184    pub function: Function<FuncName, Args>,
185}
186
187/// The base struct for a function. Includes name and arguments.
188/// This function is re-used in other places and is likely not helpful by itself.
189pub struct Function<Name, Args> {
190    /// The function name. Must be writable.
191    pub name: Name,
192    /// The function arguments. Must be a sequence.
193    pub args: Args,
194}
195
196/// A function declaration
197pub struct FunctionDef<Attr, Mods, Name, Args, Return, Body> {
198    /// The attributes. Must be a sequence, and each value will be placed inside `#[]`.
199    pub attr: Attr,
200    /// The modifiers. Must be a sequence.
201    pub mods: Mods,
202    /// The function itself
203    pub decl: Function<Name, Args>,
204    /// The return type, i.e. after the `->` arrow
205    pub return_type: Return,
206    /// The function body. At the minimum, this must be `;` (see [`FunctionBodyDeclare`])
207    pub body: Body,
208}
209
210/// Declares a function body. This is equivalent to just a semicolon.
211pub struct FunctionBodyDeclare;
212
213/// Renders as `Type=Value`. Intended to be used as a type argument, to specify associated types.
214pub struct AssociatedTypeEquals<Type, Value>(pub Type, pub Value);
215
216/// Adds a "dyn " before a type expression.
217pub struct DynOf<Type>(pub Type);
218
219/// Adds a "&" before a type expression
220pub struct RefOf<Type>(pub Type);
221
222/// Adds a "impl " before a type expression
223pub struct ImplOf<Type>(pub Type);
224
225/// Adds a reference with a lifetime before a type expression, i.e. `&'<lifetime> <type>`
226pub struct LifetimedRefOf<'l, Type>(pub &'l str, pub Type);
227
228/// Declares an associated type, rendering as `type VarName = Value;`.
229/// Adds new lines before and after.
230pub struct AssociatedTypeDef<VarName, Value>(pub VarName, pub Value);
231
232/// The declaration of a trait
233pub struct TraitDef<Attr, Mods, Name, TypeVars, SuperTraits, Body> {
234    /// The trait attributes. Must be a sequence, and each value will be placed inside `#[]`.
235    pub attr: Attr,
236    /// The trait modifiers, e.g. visibility. Must be a sequence.
237    pub mods: Mods,
238    /// The name of the trait
239    pub name: Name,
240    /// The type variables. Must be a sequence
241    pub type_variables: TypeVars,
242    /// The super traits. Must be a sequence
243    pub super_traits: SuperTraits,
244    /// The trait definition's body. Use [crate::common::NoOp] if none exists.
245    pub body: Body,
246}
247
248/// The implementation declaration for a trait, applying to a certain receiver.
249pub struct TraitImpl<TypeVars, Trait, Recv, Body> {
250    /// The type variables to use for the impl block itself. All type variables that appear later
251    /// on the trait or the receiver must be declared here, per Rust language rules.
252    ///
253    /// This field must be a sequence.
254    pub type_variables: TypeVars,
255    /// The trait being implemented
256    pub the_trait: Trait,
257    /// The receiver for which it is implemented
258    pub receiver: Recv,
259    /// The body. Use [crate::common::NoOp] if none exists.
260    pub body: Body,
261}
262
263/// A type argument-parameterized expression. Used in relation to parameterized names and their
264/// arguments. Examples: `function_name<args>`, `TypeName<'lifetime, args>`, `MyType<Assoc=Value>`.
265///
266/// If no type args exist, [`crate::common::NoOpSeq`] should be used.
267pub struct Parameterized<Name, TypeArgs> {
268    name: Name,
269    type_args: TypeArgs,
270}
271
272impl<Name, TypeArgs> Parameterized<Name, TypeArgs> {
273    /// Initializes an instance
274    pub fn new(name: Name, type_args: TypeArgs) -> Self {
275        Self { name, type_args }
276    }
277}
278
279/// A type variable with a sequence of bounds.
280/// Will render as `TypeVar: B1 + B2 + ...`
281pub struct BoundedTypeVar<TypeVar, Bounds>(pub TypeVar, pub Bounds);
282
283/// A standalone lifetime, intended to be used as a type argument or variable
284pub struct Lifetime<'l>(pub &'l str);
285
286/// Renders an individual function parameter, `Name: Type`
287pub struct FunctionParam<Name, Type>(pub Name, pub Type);
288
289/// A sequence acceptor that writes attributes
290pub struct AttributesAccept<'o, O>(pub &'o mut O);