Struct mica::TypeBuilder

source ·
pub struct TypeBuilder<T>where
    T: ?Sized,
{ /* private fields */ }
Expand description

A builder that allows for binding APIs with user-defined types.

By default, the Mica VM does not know anything and cannot interact with Rust types. This API, in conjunction with Engine::add_type, serves as an extension point to let Mica programs interact with Rust data.

Opaque user data

Rust values passed into Mica VMs by default are opaque, which means they possess no Mica type information. Opaque values do not have any methods and have unfriendly type names (as returned by std::any::type_name).

Opaque user data do possess Rust’s runtime type information however, so it’s possible to pass them back into arguments of Rust functions available in Mica.

Implementations§

Creates a new TypeBuilder.

The type_name is used for referring to the type inside scripts and should reflect the Rust type name. For generic types, it’s best to define a concrete type alias to make the binding code a little bit more self-documenting.

Examples
use mica::{Engine, TypeBuilder, UserData};

struct Empty;
impl UserData for Empty {}

// A type builder is useless on its own, so we need to create an engine first.
let mut engine = Engine::new();
engine.add_type(TypeBuilder::<Empty>::new("Empty"))?;

Adds a static function to the struct.

The function must follow the “bare” calling convention, in that it doesn’t accept a reference to T as its first parameter.

Examples
use mica::{Engine, TypeBuilder, UserData};

struct Constants;
impl UserData for Constants {}

let mut engine = Engine::new();
engine.add_type(
    TypeBuilder::<Constants>::new("Constants")
        .add_static("the_meaning_of_life_universe_and_everything", || 42_i32),
)?;

let i: i32 = engine
    .start("constant.mi", "Constants.the_meaning_of_life_universe_and_everything")?
    .trampoline()?;
assert_eq!(i, 42);

Adds an instance function to the struct.

The function must follow the “method” calling convention, in that it accepts &T or &mut T as its first parameter.

Examples
use mica::{Engine, TypeBuilder, UserData};

struct Counter {
    value: i32,
}

impl UserData for Counter {}

impl Counter {
    fn increment(&mut self) {
        self.value += 1;
    }

    fn value(&self) -> i32 {
        self.value
    }
}

let mut engine = Engine::new();
engine.add_type(
    TypeBuilder::<Counter>::new("Counter")
        .add_static("new", || Counter { value: 0 })
        .add_function("increment", Counter::increment)
        .add_function("value", Counter::value),
)?;

let i: i32 = engine
    .start(
        "counter.mi",
        r#" count = Counter.new()
            count.increment()
            count.increment()
            count.value "#
    )?
    .trampoline()?;
assert_eq!(i, 2);

Adds a function that’s part of a built-in trait implementation.

The function must have a signature that’s compatible with the built-in trait in question. See the builtin_traits module for more information on each trait, its methods, and their signatures.

Examples
use mica::{builtin_traits::iterator, Engine, TypeBuilder, UserData};

struct Count10 {
    i: i32,
}

impl UserData for Count10 {}

impl Count10 {
    fn has_next(&self) -> bool {
        self.i < 10
    }

    fn next(&mut self) {
        self.i += 1;
    }
}

let mut engine = Engine::new();
engine.add_type(
    TypeBuilder::<Count10>::new("Count10")
        .add_static("new", || Count10 { i: 1 })
        .add_builtin_trait_function(iterator::HasNext, Count10::has_next)
        .add_builtin_trait_function(iterator::Next, Count10::next),
)?;

let i: i32 = engine
    .start(
        "counter.mi",
        r#"
            i = 1
            for _ in Count10.new() do
                i = i * 2
            end
            i
        "#
    )?
    .trampoline()?;
assert_eq!(i, 512);

Adds a raw instance function to the type.

You should generally prefer add_function instead of this.

parameter_count should reflect the parameter count of the function. Method calls resolve differently from function calls, because they match the parameter count exactly - it is impossible to call the method my_method/2 with three parameters. Thus, you can expect the arguments array inside of foreign functions to always have parameter_count elements.

Adds a raw static function to the type.

You should generally prefer add_static instead of this.

parameter_count should reflect the parameter count of the function. Method calls resolve differently from function calls, because they match the parameter count exactly - it is impossible to call the method my_method/2 with three parameters. Thus, you can expect the arguments array inside of foreign functions to always have parameter_count elements.

Trait Implementations§

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.