1use mlua::{
2 AnyUserData, FromLua, FromLuaMulti, IntoLua, IntoLuaMulti, Lua, UserData,
3 UserDataFields, UserDataMethods,
4};
5#[cfg(feature = "async")]
6use mlua::{UserDataRef, UserDataRefMut};
7use crate::{MaybeSend, typed::IntoDocComment};
8
9use super::{Type, Typed, TypedDataFields, TypedDataMethods, TypedMultiValue};
10
11pub struct WrappedBuilder<'ctx, U>(&'ctx mut U);
15impl<'ctx, U> WrappedBuilder<'ctx, U> {
16 pub fn new(u: &'ctx mut U) -> Self {
17 WrappedBuilder(u)
18 }
19}
20
21impl<'ctx, T: UserData, U: UserDataFields<T>> TypedDataFields<T> for WrappedBuilder<'ctx, U> {
22 fn document(&mut self, _doc: impl IntoDocComment) -> &mut Self {
23 self
24 }
25
26 fn coerce(&mut self, _ty: impl Into<Type>) -> &mut Self {
27 self
28 }
29
30 fn add_field<V>(&mut self, name: impl Into<String>, value: V)
31 where
32 V: IntoLua + Clone + 'static + Typed,
33 {
34 self.0.add_field(name, value)
35 }
36
37 fn add_field_function_set<S, A, F>(&mut self, name: S, function: F)
38 where
39 S: Into<String>,
40 A: FromLua + Typed,
41 F: FnMut(&Lua, AnyUserData, A) -> mlua::Result<()> + MaybeSend + 'static,
42 {
43 self.0.add_field_function_set(name, function)
44 }
45
46 fn add_field_function_get<S, R, F>(&mut self, name: S, function: F)
47 where
48 S: Into<String>,
49 R: IntoLua + Typed,
50 F: Fn(&Lua, AnyUserData) -> mlua::Result<R> + MaybeSend + 'static,
51 {
52 self.0.add_field_function_get(name, function)
53 }
54
55 fn add_field_function_get_set<S, R, A, GET, SET>(&mut self, name: S, get: GET, set: SET)
56 where
57 S: Into<String>,
58 R: IntoLua + Typed,
59 A: FromLua + Typed,
60 GET: Fn(&Lua, AnyUserData) -> mlua::Result<R> + MaybeSend + 'static,
61 SET: Fn(&Lua, AnyUserData, A) -> mlua::Result<()> + MaybeSend + 'static,
62 {
63 let name: String = name.into();
64 self.0.add_field_function_get(&name, get);
65 self.0.add_field_function_set(name, set);
66 }
67
68 fn add_field_method_set<S, A, M>(&mut self, name: S, method: M)
69 where
70 S: Into<String>,
71 A: FromLua + Typed,
72 M: FnMut(&Lua, &mut T, A) -> mlua::Result<()> + MaybeSend + 'static,
73 {
74 self.0.add_field_method_set(name, method)
75 }
76
77 fn add_field_method_get<S, R, M>(&mut self, name: S, method: M)
78 where
79 S: Into<String>,
80 R: IntoLua + Typed,
81 M: Fn(&Lua, &T) -> mlua::Result<R> + MaybeSend + 'static,
82 {
83 self.0.add_field_method_get(name, method)
84 }
85
86 fn add_field_method_get_set<S, R, A, GET, SET>(&mut self, name: S, get: GET, set: SET)
87 where
88 S: Into<String>,
89 R: IntoLua + Typed,
90 A: FromLua + Typed,
91 GET: Fn(&Lua, &T) -> mlua::Result<R> + MaybeSend + 'static,
92 SET: Fn(&Lua, &mut T, A) -> mlua::Result<()> + MaybeSend + 'static,
93 {
94 let name: String = name.into();
95 self.0.add_field_method_get(&name, get);
96 self.0.add_field_method_set(name, set);
97 }
98
99 fn add_meta_field<V>(&mut self, meta: impl Into<String>, value: V)
100 where
101 V: IntoLua + 'static,
102 {
103 self.0.add_meta_field(meta, value)
104 }
105
106 fn add_meta_field_with<R, F>(&mut self, name: impl Into<String>, f: F)
107 where
108 F: 'static + MaybeSend + Fn(&Lua) -> mlua::Result<R>,
109 R: IntoLua + 'static {
110 self.0.add_meta_field_with(name, f);
111 }
112}
113
114impl<'ctx, T: UserData, U: UserDataMethods<T>> TypedDataMethods<T> for WrappedBuilder<'ctx, U> {
115 fn document(&mut self, _documentation: impl IntoDocComment) -> &mut Self {
116 self
117 }
118
119 fn param(
120 &mut self,
121 _name: impl std::fmt::Display,
122 _doc: impl IntoDocComment,
123 ) -> &mut Self {
124 self
125 }
126
127 fn param_as(
128 &mut self,
129 _ty: impl Into<Type>,
130 _name: impl std::fmt::Display,
131 _doc: impl IntoDocComment,
132 ) -> &mut Self {
133 self
134 }
135
136
137 fn ret(&mut self, _: impl IntoDocComment) -> &mut Self {
138 self
139 }
140
141 fn ret_as(&mut self, _: impl Into<Type>, _: impl IntoDocComment) -> &mut Self {
142 self
143 }
144
145 fn index<I: Typed>(&mut self, _idx: isize, _doc: impl IntoDocComment) -> &mut Self {
146 self
147 }
148
149 fn index_as(&mut self, _idx: isize, _ty: impl Into<Type>, _doc: impl IntoDocComment) -> &mut Self {
150 self
151 }
152
153 fn add_method<S, A, R, M>(&mut self, name: S, method: M)
154 where
155 S: Into<String>,
156 A: FromLuaMulti + TypedMultiValue,
157 R: IntoLuaMulti + TypedMultiValue,
158 M: Fn(&Lua, &T, A) -> mlua::Result<R> + MaybeSend + 'static,
159 {
160 self.0.add_method(name, method)
161 }
162
163 fn add_function<S, A, R, F>(&mut self, name: S, function: F)
164 where
165 S: Into<String>,
166 A: FromLuaMulti + TypedMultiValue,
167 R: IntoLuaMulti + TypedMultiValue,
168 F: Fn(&Lua, A) -> mlua::Result<R> + MaybeSend + 'static,
169 {
170 self.0.add_function(name, function)
171 }
172
173 fn add_method_mut<S, A, R, M>(&mut self, name: S, method: M)
174 where
175 S: Into<String>,
176 A: FromLuaMulti + TypedMultiValue,
177 R: IntoLuaMulti + TypedMultiValue,
178 M: FnMut(&Lua, &mut T, A) -> mlua::Result<R> + MaybeSend + 'static,
179 {
180 self.0.add_method_mut(name, method)
181 }
182
183 fn add_meta_method<A, R, M>(&mut self, meta: impl Into<String>, method: M)
184 where
185 A: FromLuaMulti + TypedMultiValue,
186 R: IntoLuaMulti + TypedMultiValue,
187 M: 'static + MaybeSend + Fn(&Lua, &T, A) -> mlua::Result<R>,
188 {
189 self.0.add_meta_method(meta, method)
190 }
191
192 #[cfg(feature = "async")]
193 fn add_async_method<S: Into<String>, A, R, M, MR>(&mut self, name: S, method: M)
194 where
195 T: 'static,
196 M: Fn(Lua, UserDataRef<T>, A) -> MR + MaybeSend + 'static,
197 A: FromLuaMulti + TypedMultiValue,
198 MR: std::future::Future<Output = mlua::Result<R>> + MaybeSend + 'static,
199 R: IntoLuaMulti + TypedMultiValue,
200 {
201 self.0.add_async_method(name, method)
202 }
203
204 #[cfg(feature = "async")]
205 fn add_async_method_mut<S: Into<String>, A, R, M, MR>(&mut self, name: S, method: M)
206 where
207 T: 'static,
208 M: Fn(Lua, UserDataRefMut<T>, A) -> MR + MaybeSend + 'static,
209 A: FromLuaMulti + TypedMultiValue,
210 MR: std::future::Future<Output = mlua::Result<R>> + MaybeSend + 'static,
211 R: IntoLuaMulti + TypedMultiValue,
212 {
213 self.0.add_async_method_mut(name, method)
214 }
215
216 fn add_function_mut<S, A, R, F>(&mut self, name: S, function: F)
217 where
218 S: Into<String>,
219 A: FromLuaMulti + TypedMultiValue,
220 R: IntoLuaMulti + TypedMultiValue,
221 F: FnMut(&Lua, A) -> mlua::Result<R> + MaybeSend + 'static,
222 {
223 self.0.add_function_mut(name, function)
224 }
225
226 fn add_meta_function<A, R, F>(&mut self, meta: impl Into<String>, function: F)
227 where
228 A: FromLuaMulti + TypedMultiValue,
229 R: IntoLuaMulti + TypedMultiValue,
230 F: Fn(&Lua, A) -> mlua::Result<R> + MaybeSend + 'static,
231 {
232 self.0.add_meta_function(meta, function)
233 }
234
235 #[cfg(feature = "async")]
236 fn add_async_function<S, A, R, F, FR>(&mut self, name: S, function: F)
237 where
238 S: Into<String>,
239 A: FromLuaMulti + TypedMultiValue,
240 R: IntoLuaMulti + TypedMultiValue,
241 F: 'static + MaybeSend + Fn(Lua, A) -> FR,
242 FR: 'static + MaybeSend + std::future::Future<Output = mlua::Result<R>>,
243 {
244 self.0.add_async_function(name, function)
245 }
246
247 fn add_meta_method_mut<A, R, M>(&mut self, meta: impl Into<String>, method: M)
248 where
249 A: FromLuaMulti + TypedMultiValue,
250 R: IntoLuaMulti + TypedMultiValue,
251 M: 'static + MaybeSend + FnMut(&Lua, &mut T, A) -> mlua::Result<R>,
252 {
253 self.0.add_meta_method_mut(meta, method)
254 }
255
256 fn add_meta_function_mut<A, R, F>(&mut self, meta: impl Into<String>, function: F)
257 where
258 A: FromLuaMulti + TypedMultiValue,
259 R: IntoLuaMulti + TypedMultiValue,
260 F: FnMut(&Lua, A) -> mlua::Result<R> + MaybeSend + 'static,
261 {
262 self.0.add_meta_function_mut(meta, function)
263 }
264}
265
266#[cfg(test)]
267#[cfg(all(feature = "async", feature = "macros"))]
268mod tests {
269 use super::*;
270 use crate as mlua_extras;
271 use crate::typed::TypedUserData;
272 use crate::{Typed, UserData};
273
274 #[derive(Clone, Typed, UserData)]
275 struct Counter {
276 value: i64,
277 }
278
279 impl TypedUserData for Counter {
280 fn add_methods<T: TypedDataMethods<Self>>(methods: &mut T) {
281 methods.add_async_method("get_value", |_lua, this, _: ()| async move {
282 Ok(this.value)
283 });
284 }
285 }
286
287 #[test]
288 fn test_add_async_method_compiles() {
289 let lua = Lua::new();
290 lua.globals()
291 .set("counter", Counter { value: 42 })
292 .unwrap();
293 }
294}