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