mlua_manual/
manual.rs

1use tealr::{
2    mlu::{
3        mlua::{FromLua, Lua, Result, UserData, UserDataMethods},
4        TealData, TealDataMethods, UserDataWrapper,
5    },
6    ToTypename, TypeBody, TypeWalker,
7};
8//This example shows how to manually implement UserData using TealData
9//As you can see the amount of code is small and easy copy/paste able.
10//Because of this it may make sense to do the implementation yourself
11//instead of paying the compile time cost of the macro
12
13//First, create the struct you want to export to lua.
14#[derive(Clone, Copy)]
15struct Example(u32);
16impl FromLua for Example {
17    fn from_lua(value: mlua::prelude::LuaValue, _: &Lua) -> Result<Self> {
18        value
19            .as_userdata()
20            .map(|x| x.take())
21            .unwrap_or(Err(mlua::Error::FromLuaConversionError {
22                from: value.type_name(),
23                to: "Example".to_string(),
24                message: None,
25            }))
26    }
27}
28
29//now, implement TealData. This tells mlua what methods are available and tealr what the types are
30impl TealData for Example {
31    //implement your methods/functions
32    fn add_methods<T: TealDataMethods<Self>>(methods: &mut T) {
33        //methods.add_method("example_method", |_, _, x: i8| Ok(x));
34        methods.add_method(
35            "example_method",
36            |_, _, x: tealr::mlu::TypedFunction<i32, i64>| Ok(x),
37        );
38        methods.add_method_mut("example_method_mut", |_, _, x: (i8, String)| Ok(x.1));
39        methods.add_function("example_function", |_, x: Vec<String>| Ok((x, 8)));
40        methods.add_function_mut("example_function_mut", |_, x: (bool, Option<Example>)| {
41            Ok(x)
42        })
43    }
44    fn add_fields<F: tealr::mlu::TealDataFields<Self>>(fields: &mut F) {
45        fields.add_field_method_get("example_field", |_, this| Ok(this.0));
46        fields.add_field_method_set("example_field", |_, this, value| {
47            this.0 = value;
48            Ok(())
49        });
50    }
51}
52
53impl ToTypename for Example {
54    //how the type should be called in lua.
55    fn to_typename() -> tealr::Type {
56        tealr::Type::new_single("Example", tealr::KindOfType::External)
57    }
58}
59
60impl UserData for Example {
61    fn add_fields<F: mlua::UserDataFields<Self>>(fields: &mut F) {
62        let mut wrapper = UserDataWrapper::from_user_data_fields(fields);
63        <Self as TealData>::add_fields(&mut wrapper)
64    }
65    fn add_methods<T: UserDataMethods<Self>>(methods: &mut T) {
66        let mut wrapper = UserDataWrapper::from_user_data_methods(methods);
67        <Self as TealData>::add_methods(&mut wrapper)
68    }
69}
70
71impl TypeBody for Example {
72    fn get_type_body() -> tealr::TypeGenerator {
73        let mut gen = tealr::RecordGenerator::new::<Self>(false);
74        gen.is_user_data = true;
75        <Self as TealData>::add_fields(&mut gen);
76        <Self as TealData>::add_methods(&mut gen);
77        gen.into()
78    }
79}
80fn main() {
81    let file_contents = TypeWalker::new()
82        //tells it that you want to include the Example type
83        //chain extra calls to include more types
84        .process_type::<Example>()
85        //generate the file
86        .to_json()
87        .expect("serde_json failed to serialize our data");
88    //normally you would now save the file somewhere.
89    //however for this example we just print it.
90    println!("{}\n ", file_contents);
91    //how you pass this type to lua hasn't changed:
92    let lua = Lua::new();
93
94    let globals = lua.globals();
95    globals.set("test", Example(1)).unwrap();
96    let code = "
97print(test:example_method(function()return 1 end))
98print(test:example_method_mut(2,\"test\"))
99print(test.example_function({}))
100print(test.example_function_mut(true))
101print(\"Example field\", test.example_field)
102test.example_field = 2
103print(\"After modifying\",test.example_field)
104        ";
105    lua.load(code).set_name("test?").eval::<()>().unwrap();
106}