diff --git a/doc/src/language/constants.md b/doc/src/language/constants.md index da2a13be..52124d21 100644 --- a/doc/src/language/constants.md +++ b/doc/src/language/constants.md @@ -34,23 +34,28 @@ It is very useful to have a constant value hold a [custom type], which essential as a [_singleton_](../patterns/singleton.md). ```rust -use rhai::{Engine, Scope}; +use rhai::{Engine, Scope, RegisterFn}; +#[derive(Debug, Clone)] struct TestStruct(i64); // custom type -let engine = Engine::new() +let mut engine = Engine::new(); + +engine .register_type_with_name::("TestStruct") // register custom type - .register_get_set("value", - |obj: &mut TestStruct| obj.0, // property getter - |obj: &mut TestStruct, value: i64| obj.0 = value // property setter + .register_get("value", |obj: &mut TestStruct| obj.0), // property getter + .register_fn("update_value", + |obj: &mut TestStruct, value: i64| obj.0 = value // mutating method ); let mut scope = Scope::new(); // create custom scope scope.push_constant("MY_NUMBER", TestStruct(123_i64)); // add constant variable -engine.consume_with_scope(&mut scope, r" - MY_NUMBER.value = 42; // constant objects can be modified +// Beware: constant objects can still be modified via a method call! +engine.consume_with_scope(&mut scope, +r" + MY_NUMBER.update_value(42); print(MY_NUMBER.value); // prints 42 ")?; ``` diff --git a/tests/constants.rs b/tests/constants.rs index 2f516a1b..090abfaa 100644 --- a/tests/constants.rs +++ b/tests/constants.rs @@ -1,4 +1,4 @@ -use rhai::{Engine, EvalAltResult, ParseErrorType, Scope, INT}; +use rhai::{Engine, EvalAltResult, ParseErrorType, RegisterFn, Scope, INT}; #[test] fn test_constant() -> Result<(), Box> { @@ -62,3 +62,36 @@ fn test_var_is_def() -> Result<(), Box> { Ok(()) } + +#[cfg(not(feature = "no_object"))] +#[test] +fn test_constant_mut() -> Result<(), Box> { + #[derive(Debug, Clone)] + struct TestStruct(INT); // custom type + + let mut engine = Engine::new(); + + engine + .register_type_with_name::("TestStruct") + .register_get("value", |obj: &mut TestStruct| obj.0) + .register_fn("update_value", |obj: &mut TestStruct, value: INT| { + obj.0 = value + }); + + let mut scope = Scope::new(); + + scope.push_constant("MY_NUMBER", TestStruct(123)); + + assert_eq!( + engine.eval_with_scope::( + &mut scope, + r" + MY_NUMBER.update_value(42); + MY_NUMBER.value + ", + )?, + 42 + ); + + Ok(()) +}