rhaiscript / rhai

Rhai - An embedded scripting language for Rust.
https://crates.io/crates/rhai
Apache License 2.0
3.73k stars 175 forks source link

Register Array setter #727

Closed assuncaolfi closed 1 year ago

assuncaolfi commented 1 year ago

I would like to register a setter taking an Array as input and casting it to the correct type, like this:

#[derive(Clone, Debug)]
struct Pattern {
    step: Vec<i64>,
}

impl Pattern {
    fn new() -> Self {
        Pattern { step: vec![] }
    }

    fn get_step(&mut self) -> Vec<i64> {
        self.step.clone()
    }

    fn set_step(&mut self, step: Array) {
        self.step = step.into_iter().map(|x| x.try_cast::<i64>().unwrap_or_default()).collect();
    }
}

fn main() {
    let mut engine = Engine::new();
    engine
        .register_type_with_name::<Pattern>("Pattern")
        .register_fn("pattern", Pattern::new)
        .register_get_set("step", Pattern::get_step, Pattern::set_step);
}

However, this produces an error:

error[E0277]: the trait bound `for<'a> fn(&'a mut engine::Pattern, Vec<Dynamic>) {engine::Pattern::set_step}: RegisterNativeFunction<(rhai::func::register::Mut<engine::Pattern>, Vec<i64>), 2, _, (), _>` is not satisfied

It seems there is an alternative through raw functions (https://rhai.rs/book/rust/register-raw.html). Is that correct? If so, is it possible to register a raw getter/setter?

schungx commented 1 year ago

If you use regisyer_get_set, the data type must be the same. Here you have one of them Array and the other Vec... They are different types.

I suggest that get_step returns Array as well.

Or you separate the two calls into register_get and register_set.

assuncaolfi commented 1 year ago

Your first suggestion worked perfectly. Sorry, I had misinterpreted the error. Thank you for your work on Rhai!