mlua_manual_documentation/
manual_documentation.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.document_type("This is just an example type");
34        methods.document_type("This part of the documentation is for the type itself");
35        methods.document_type(
36            "That means it gets placed before the `record {name}` part in the .d.tl file",
37        );
38        methods.document_type(
39            "And is also visible when calling instance.help() without any parameters",
40        );
41
42        methods.document("This documentation is for the next registered method.");
43        methods.document("In this case that will be example_method");
44        methods.document("This means that it gets placed before this method in the .d.tl file");
45        methods.document("You can access it by calling instance.help(\"example_method\")");
46        methods.add_method("example_method", |_, _, x: i8| Ok(x));
47        methods.add_method_mut("example_method_mut", |_, _, x: (i8, String)| Ok(x.1));
48        methods.add_function("example_function", |_, x: Vec<String>| Ok((x, 8)));
49        methods.add_function_mut("example_function_mut", |_, x: (bool, Option<Example>)| {
50            Ok(x)
51        });
52        methods.generate_help();
53    }
54    fn add_fields<F: tealr::mlu::TealDataFields<Self>>(fields: &mut F) {
55        fields.document("This is an example field");
56        fields.add_field_method_get("example", |_, this| Ok(this.0));
57        fields.document("Documentation for fields with the same name get merged");
58        fields.add_field_method_set("example", |_, this, value| {
59            this.0 = value;
60            Ok(())
61        })
62    }
63}
64
65impl ToTypename for Example {
66    //how the type should be called in lua.
67    fn to_typename() -> tealr::Type {
68        tealr::Type::new_single("Example", tealr::KindOfType::External)
69    }
70}
71
72impl UserData for Example {
73    fn add_fields<F: mlua::UserDataFields<Self>>(fields: &mut F) {
74        let mut wrapper = UserDataWrapper::from_user_data_fields(fields);
75        <Self as TealData>::add_fields(&mut wrapper);
76    }
77    fn add_methods<T: UserDataMethods<Self>>(methods: &mut T) {
78        let mut wrapper = UserDataWrapper::from_user_data_methods(methods);
79        <Self as TealData>::add_methods(&mut wrapper);
80    }
81}
82
83impl TypeBody for Example {
84    fn get_type_body() -> tealr::TypeGenerator {
85        let mut gen = tealr::RecordGenerator::new::<Self>(false);
86        gen.is_user_data = true;
87        <Self as TealData>::add_fields(&mut gen);
88        <Self as TealData>::add_methods(&mut gen);
89        gen.into()
90    }
91}
92fn main() {
93    let file_contents = TypeWalker::new()
94        //tells it that you want to include the Example type
95        //chain extra calls to include more types
96        .process_type::<Example>()
97        //generate the file
98        .to_json()
99        .expect("serde_json failed to serialize our data");
100    //normally you would now save the file somewhere.
101    //however for this example we just print it.
102    println!("{}\n ", file_contents);
103
104    //how you pass this type to lua hasn't changed:
105    let lua = Lua::new();
106
107    let globals = lua.globals();
108    globals.set("test", Example(1)).unwrap();
109    let code = "
110print(test.help())
111print(\"----\")
112print(test.help(\"example_method\"))
113print(test:example_method(1))
114print(test:example_method_mut(2,\"test\"))
115print(test.example_function({}))
116print(test.example_function_mut(true))
117        ";
118
119    lua.load(code).set_name("test?").eval::<()>().unwrap();
120}