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
sourceimpl<T> TypeBuilder<T>where
T: ?Sized,
impl<T> TypeBuilder<T>where
T: ?Sized,
sourcepub fn new(type_name: impl Into<Rc<str>>) -> Selfwhere
T: Any,
pub fn new(type_name: impl Into<Rc<str>>) -> Selfwhere
T: Any,
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"))?;
sourcepub fn add_static<F, V>(self, name: &str, f: F) -> Selfwhere
V: BareExactArgs,
F: ForeignFunction<V, ParameterCount = FunctionParameterCount>,
pub fn add_static<F, V>(self, name: &str, f: F) -> Selfwhere
V: BareExactArgs,
F: ForeignFunction<V, ParameterCount = FunctionParameterCount>,
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);
sourcepub fn add_function<F, V>(self, name: &str, f: F) -> Selfwhere
V: Method<T>,
F: ForeignFunction<V, ParameterCount = MethodParameterCount>,
pub fn add_function<F, V>(self, name: &str, f: F) -> Selfwhere
V: Method<T>,
F: ForeignFunction<V, ParameterCount = MethodParameterCount>,
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);
sourcepub fn add_builtin_trait_function<S, B, F>(self, which: B, f: F) -> Selfwhere
B: BuiltinTraitFunction<S>,
F: ForeignFunction<S, ParameterCount = MethodParameterCount>,
pub fn add_builtin_trait_function<S, B, F>(self, which: B, f: F) -> Selfwhere
B: BuiltinTraitFunction<S>,
F: ForeignFunction<S, ParameterCount = MethodParameterCount>,
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);
sourcepub fn add_raw_function(
self,
name: &str,
parameter_count: MethodParameterCount,
f: FunctionKind
) -> Self
pub fn add_raw_function(
self,
name: &str,
parameter_count: MethodParameterCount,
f: FunctionKind
) -> Self
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.
sourcepub fn add_raw_static(
self,
name: &str,
parameter_count: MethodParameterCount,
f: FunctionKind
) -> Self
pub fn add_raw_static(
self,
name: &str,
parameter_count: MethodParameterCount,
f: FunctionKind
) -> Self
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.