#![cfg(not(feature = "no_object"))] use rhai::{CustomType, Engine, EvalAltResult, Position, TypeBuilder, INT}; #[test] fn build_type() -> Result<(), Box> { #[derive(Debug, Clone, PartialEq)] struct Vec3 { x: INT, y: INT, z: INT, } impl Vec3 { fn new(x: INT, y: INT, z: INT) -> Self { Self { x, y, z } } fn get_x(&mut self) -> INT { self.x } fn set_x(&mut self, x: INT) { self.x = x } fn get_y(&mut self) -> INT { self.y } fn set_y(&mut self, y: INT) { self.y = y } fn get_z(&mut self) -> INT { self.z } fn set_z(&mut self, z: INT) { self.z = z } fn get_component(&mut self, idx: INT) -> Result> { match idx { 0 => Ok(self.x), 1 => Ok(self.y), 2 => Ok(self.z), _ => Err(Box::new(EvalAltResult::ErrorIndexNotFound( idx.into(), Position::NONE, ))), } } } impl IntoIterator for Vec3 { type Item = INT; type IntoIter = std::array::IntoIter; fn into_iter(self) -> Self::IntoIter { <[INT; 3] as IntoIterator>::into_iter([self.x, self.y, self.z]) } } impl CustomType for Vec3 { fn build(mut builder: TypeBuilder) { builder .with_name("Vec3") .is_iterable() .with_fn("vec3", Self::new) .with_get_set("x", Self::get_x, Self::set_x) .with_get_set("y", Self::get_y, Self::set_y) .with_get_set("z", Self::get_z, Self::set_z); #[cfg(not(feature = "no_index"))] builder.with_indexer_get_result(Self::get_component); } } let mut engine = Engine::new(); engine.build_type::(); assert_eq!( engine.eval::( " let v = vec3(1, 2, 3); v ", )?, Vec3::new(1, 2, 3), ); assert_eq!( engine.eval::( " let v = vec3(1, 2, 3); v.x ", )?, 1, ); assert_eq!( engine.eval::( " let v = vec3(1, 2, 3); v.y ", )?, 2, ); assert_eq!( engine.eval::( " let v = vec3(1, 2, 3); v.z ", )?, 3, ); #[cfg(not(feature = "no_index"))] assert!(engine.eval::( " let v = vec3(1, 2, 3); v.x == v[0] && v.y == v[1] && v.z == v[2] ", )?); assert_eq!( engine.eval::( " let v = vec3(1, 2, 3); v.x = 5; v.y = 6; v.z = 7; v ", )?, Vec3::new(5, 6, 7), ); assert_eq!( engine.eval::( " let sum = 0; let v = vec3(1, 2, 3); for i in v { sum += i; } sum ", )?, 6, ); Ok(()) }