Disallow registering indexers for arrays, maps and strings.

This commit is contained in:
Stephen Chung
2020-09-22 17:57:56 +08:00
parent 870ff81203
commit 594dcc3a06
7 changed files with 156 additions and 21 deletions

View File

@@ -12,7 +12,10 @@ use crate::scope::Scope;
use crate::token::{lex, Position};
#[cfg(not(feature = "no_index"))]
use crate::engine::{FN_IDX_GET, FN_IDX_SET};
use crate::{
engine::{Array, FN_IDX_GET, FN_IDX_SET},
utils::ImmutableString,
};
#[cfg(not(feature = "no_object"))]
use crate::{
@@ -433,6 +436,11 @@ impl Engine {
///
/// The function signature must start with `&mut self` and not `&self`.
///
/// # Panics
///
/// Panics if the type is `Array` or `Map`.
/// Indexers for arrays, object maps and strings cannot be registered.
///
/// # Example
///
/// ```
@@ -475,6 +483,20 @@ impl Engine {
U: Variant + Clone,
X: Variant + Clone,
{
if TypeId::of::<T>() == TypeId::of::<Array>() {
panic!("Cannot register indexer for arrays.");
}
#[cfg(not(feature = "no_object"))]
if TypeId::of::<T>() == TypeId::of::<Map>() {
panic!("Cannot register indexer for object maps.");
}
if TypeId::of::<T>() == TypeId::of::<String>()
|| TypeId::of::<T>() == TypeId::of::<&str>()
|| TypeId::of::<T>() == TypeId::of::<ImmutableString>()
{
panic!("Cannot register indexer for strings.");
}
self.register_fn(FN_IDX_GET, callback)
}
@@ -483,6 +505,11 @@ impl Engine {
///
/// The function signature must start with `&mut self` and not `&self`.
///
/// # Panics
///
/// Panics if the type is `Array` or `Map`.
/// Indexers for arrays, object maps and strings cannot be registered.
///
/// # Example
///
/// ```
@@ -526,11 +553,30 @@ impl Engine {
T: Variant + Clone,
X: Variant + Clone,
{
if TypeId::of::<T>() == TypeId::of::<Array>() {
panic!("Cannot register indexer for arrays.");
}
#[cfg(not(feature = "no_object"))]
if TypeId::of::<T>() == TypeId::of::<Map>() {
panic!("Cannot register indexer for object maps.");
}
if TypeId::of::<T>() == TypeId::of::<String>()
|| TypeId::of::<T>() == TypeId::of::<&str>()
|| TypeId::of::<T>() == TypeId::of::<ImmutableString>()
{
panic!("Cannot register indexer for strings.");
}
self.register_result_fn(FN_IDX_GET, callback)
}
/// Register an index setter for a custom type with the `Engine`.
///
/// # Panics
///
/// Panics if the type is `Array` or `Map`.
/// Indexers for arrays, object maps and strings cannot be registered.
///
/// # Example
///
/// ```
@@ -575,12 +621,31 @@ impl Engine {
U: Variant + Clone,
X: Variant + Clone,
{
if TypeId::of::<T>() == TypeId::of::<Array>() {
panic!("Cannot register indexer for arrays.");
}
#[cfg(not(feature = "no_object"))]
if TypeId::of::<T>() == TypeId::of::<Map>() {
panic!("Cannot register indexer for object maps.");
}
if TypeId::of::<T>() == TypeId::of::<String>()
|| TypeId::of::<T>() == TypeId::of::<&str>()
|| TypeId::of::<T>() == TypeId::of::<ImmutableString>()
{
panic!("Cannot register indexer for strings.");
}
self.register_fn(FN_IDX_SET, callback)
}
/// Register an index setter for a custom type with the `Engine`.
/// Returns `Result<(), Box<EvalAltResult>>`.
///
/// # Panics
///
/// Panics if the type is `Array` or `Map`.
/// Indexers for arrays, object maps and strings cannot be registered.
///
/// # Example
///
/// ```
@@ -628,6 +693,20 @@ impl Engine {
U: Variant + Clone,
X: Variant + Clone,
{
if TypeId::of::<T>() == TypeId::of::<Array>() {
panic!("Cannot register indexer for arrays.");
}
#[cfg(not(feature = "no_object"))]
if TypeId::of::<T>() == TypeId::of::<Map>() {
panic!("Cannot register indexer for object maps.");
}
if TypeId::of::<T>() == TypeId::of::<String>()
|| TypeId::of::<T>() == TypeId::of::<&str>()
|| TypeId::of::<T>() == TypeId::of::<ImmutableString>()
{
panic!("Cannot register indexer for strings.");
}
self.register_result_fn(FN_IDX_SET, move |obj: &mut T, index: X, value: U| {
callback(obj, index, value)?;
Ok(().into())
@@ -636,6 +715,11 @@ impl Engine {
/// Short-hand for register both index getter and setter functions for a custom type with the `Engine`.
///
/// # Panics
///
/// Panics if the type is `Array` or `Map`.
/// Indexers for arrays, object maps and strings cannot be registered.
///
/// # Example
///
/// ```

View File

@@ -756,10 +756,7 @@ impl Engine {
Err(err) => match *err {
// No index getter - try to call an index setter
#[cfg(not(feature = "no_index"))]
EvalAltResult::ErrorIndexingType(_, _) => {
// Raise error if there is no index getter nor setter
Some(new_val.unwrap())
}
EvalAltResult::ErrorIndexingType(_, _) => Some(new_val.unwrap()),
// Any other error - return
err => return Err(Box::new(err)),
},

View File

@@ -21,11 +21,10 @@ use crate::{
};
#[cfg(not(feature = "no_index"))]
#[cfg(not(feature = "no_object"))]
use crate::engine::{FN_IDX_GET, FN_IDX_SET};
use crate::engine::{Array, FN_IDX_GET, FN_IDX_SET};
#[cfg(not(feature = "no_object"))]
use crate::engine::{make_getter, make_setter};
use crate::engine::{make_getter, make_setter, Map};
use crate::stdlib::{
any::TypeId,
@@ -675,6 +674,11 @@ impl Module {
///
/// If there is a similar existing setter Rust function, it is replaced.
///
/// # Panics
///
/// Panics if the type is `Array` or `Map`.
/// Indexers for arrays, object maps and strings cannot be registered.
///
/// # Examples
///
/// ```
@@ -686,12 +690,25 @@ impl Module {
/// });
/// assert!(module.contains_fn(hash, true));
/// ```
#[cfg(not(feature = "no_object"))]
#[cfg(not(feature = "no_index"))]
pub fn set_indexer_get_fn<A: Variant + Clone, B: Variant + Clone, T: Variant + Clone>(
&mut self,
func: impl Fn(&mut A, B) -> FuncReturn<T> + SendSync + 'static,
) -> u64 {
if TypeId::of::<A>() == TypeId::of::<Array>() {
panic!("Cannot register indexer for arrays.");
}
#[cfg(not(feature = "no_object"))]
if TypeId::of::<A>() == TypeId::of::<Map>() {
panic!("Cannot register indexer for object maps.");
}
if TypeId::of::<A>() == TypeId::of::<String>()
|| TypeId::of::<A>() == TypeId::of::<&str>()
|| TypeId::of::<A>() == TypeId::of::<ImmutableString>()
{
panic!("Cannot register indexer for strings.");
}
self.set_fn_2_mut(FN_IDX_GET, func)
}
@@ -773,6 +790,11 @@ impl Module {
///
/// If there is a similar existing Rust function, it is replaced.
///
/// # Panics
///
/// Panics if the type is `Array` or `Map`.
/// Indexers for arrays, object maps and strings cannot be registered.
///
/// # Examples
///
/// ```
@@ -785,12 +807,25 @@ impl Module {
/// });
/// assert!(module.contains_fn(hash, true));
/// ```
#[cfg(not(feature = "no_object"))]
#[cfg(not(feature = "no_index"))]
pub fn set_indexer_set_fn<A: Variant + Clone, B: Variant + Clone, C: Variant + Clone>(
&mut self,
func: impl Fn(&mut A, B, C) -> FuncReturn<()> + SendSync + 'static,
) -> u64 {
if TypeId::of::<A>() == TypeId::of::<Array>() {
panic!("Cannot register indexer for arrays.");
}
#[cfg(not(feature = "no_object"))]
if TypeId::of::<A>() == TypeId::of::<Map>() {
panic!("Cannot register indexer for object maps.");
}
if TypeId::of::<A>() == TypeId::of::<String>()
|| TypeId::of::<A>() == TypeId::of::<&str>()
|| TypeId::of::<A>() == TypeId::of::<ImmutableString>()
{
panic!("Cannot register indexer for strings.");
}
let f = move |_: &Engine, _: &Module, args: &mut FnCallArgs| {
let b = cast_arg::<B>(&mut args[1]);
let c = cast_arg::<C>(&mut args[2]);
@@ -812,6 +847,11 @@ impl Module {
///
/// If there are similar existing Rust functions, they are replaced.
///
/// # Panics
///
/// Panics if the type is `Array` or `Map`.
/// Indexers for arrays, object maps and strings cannot be registered.
///
/// # Examples
///
/// ```
@@ -830,7 +870,6 @@ impl Module {
/// assert!(module.contains_fn(hash_get, true));
/// assert!(module.contains_fn(hash_set, true));
/// ```
#[cfg(not(feature = "no_object"))]
#[cfg(not(feature = "no_index"))]
pub fn set_indexer_get_set_fn<A: Variant + Clone, B: Variant + Clone, T: Variant + Clone>(
&mut self,

View File

@@ -18,7 +18,6 @@ mod map_functions {
pub fn has(map: &mut Map, prop: ImmutableString) -> bool {
map.contains_key(&prop)
}
#[rhai_fn(name = "len", get = "len")]
#[inline(always)]
pub fn len(map: &mut Map) -> INT {
map.len() as INT