Add Scope::set_or_push.

This commit is contained in:
Stephen Chung 2021-08-14 14:56:15 +08:00
parent 0354f154ce
commit 9c6cea3c9f
2 changed files with 46 additions and 0 deletions

View File

@ -23,6 +23,7 @@ Enhancements
* `ln` for `Decimal` is now checked and won't panic. * `ln` for `Decimal` is now checked and won't panic.
* `Scope::set_value` now takes anything that implements `Into<Cow<str>>`. * `Scope::set_value` now takes anything that implements `Into<Cow<str>>`.
* Added `Scope::is_constant` to check if a variable is constant. * Added `Scope::is_constant` to check if a variable is constant.
* Added `Scope::set_or_push` to add a new variable only if one doesn't already exist.
Version 1.0.2 Version 1.0.2

View File

@ -363,6 +363,51 @@ impl<'a> Scope<'a> {
AccessMode::ReadOnly => Some(true), AccessMode::ReadOnly => Some(true),
}) })
} }
/// Update the value of the named entry in the [`Scope`] if it already exists and is not constant.
/// Push a new entry with the value into the [`Scope`] if the name doesn't exist or if the
/// existing entry is constant.
///
/// Search starts backwards from the last, and only the first entry matching the specified name is updated.
///
/// # Example
///
/// ```
/// use rhai::Scope;
///
/// let mut my_scope = Scope::new();
///
/// my_scope.set_or_push("x", 42_i64);
/// assert_eq!(my_scope.get_value::<i64>("x").unwrap(), 42);
/// assert_eq!(my_scope.len(), 1);
///
/// my_scope.set_or_push("x", 0_i64);
/// assert_eq!(my_scope.get_value::<i64>("x").unwrap(), 0);
/// assert_eq!(my_scope.len(), 1);
///
/// my_scope.set_or_push("y", 123_i64);
/// assert_eq!(my_scope.get_value::<i64>("y").unwrap(), 123);
/// assert_eq!(my_scope.len(), 2);
/// ```
#[inline]
pub fn set_or_push(
&mut self,
name: impl AsRef<str> + Into<Cow<'a, str>>,
value: impl Variant + Clone,
) -> &mut Self {
match self.get_index(name.as_ref()) {
None | Some((_, AccessMode::ReadOnly)) => {
self.push(name, value);
}
Some((index, AccessMode::ReadWrite)) => {
let value_ref = self
.values
.get_mut(index)
.expect("never fails because the index is returned by `get_index`");
*value_ref = Dynamic::from(value);
}
}
self
}
/// Update the value of the named entry in the [`Scope`]. /// Update the value of the named entry in the [`Scope`].
/// ///
/// Search starts backwards from the last, and only the first entry matching the specified name is updated. /// Search starts backwards from the last, and only the first entry matching the specified name is updated.