mlua-extras 11.6.1

Extra helpers and functionality built on top of mlua for embedded lua development
use std::io::stdout;

use mlua::{MetaMethod, Value, Variadic};
use mlua_extras::typed::{generator::{Definition, DefinitionFileGenerator, Definitions}, Type, TypedModule};

struct NestedModule;
impl TypedModule for NestedModule {
    fn documentation() -> Option<String> {
        Some("Nested module".into())
    }
}

struct TestModule;
impl TypedModule for TestModule {
    fn documentation() -> Option<String> {
        Some("Test module documentation".into())
    }

    fn add_fields<F: mlua_extras::typed::TypedModuleFields>(fields: &mut F) -> mlua::Result<()> {
        fields
            .document("Some test data")
            .add_field("data", "Some data")?;

        fields
            .document("Meta field")
            .add_meta_field("__count", 0u32)?;

        fields
            .document("Nested module")
            .add_module::<NestedModule>("nested")?;

        Ok(())
    }

    fn add_methods<M: mlua_extras::typed::TypedModuleMethods>(methods: &mut M) -> mlua::Result<()> {
        methods
            .document("Greetings")
            .add_function_with("greet", |_, _name: String| { Ok(()) }, |func| {
                func.param(0).unwrap().doc("Name of the person to greet").name("name");
            })?;

        methods
            .document("Logs errors")
            .add_function_with("LogError", |_, _args: (String, Variadic<Value>)| { Ok(()) }, |func| {
                func.param(0)
                    .unwrap()
                    .name("format")
                    .doc("String to pass to the formatter.");
                func.param(1)
                    .unwrap()
                    .name("...")
                    .doc("Arguments to pass to the formatter.");
            })?;

        methods
            .document("Convert the test module to a string")
            .add_meta_method(MetaMethod::ToString, |_, _this, ()| {
                Ok(String::new())
            })?;

        Ok(())
    }
}

fn main() {
    let defs = Definitions::start()
        .define("init", Definition::start()
            .module::<TestModule>("test")
            .function::<String, ()>("greet", ())
            .function_with::<String, String, _>("greet", (), |func| {
                func.document("Greet the name that was passed in");
                func.param(0).unwrap().name("name").doc("Name of the person to greet");
                func.ret(0).unwrap().doc("Formatted greeting using the given name");
            })
        )
        .finish();

    for (name, writer) in DefinitionFileGenerator::new(defs).iter() {
        println!("==== {name} ====");
        writer.write(stdout()).unwrap();
    }

    println!("{:#?}", Type::string() | "literal" | true | 0 | [Type::string(), Type::nil(), Type::literal(3)]);
}