Remove unnecessary unchecked gates.
This commit is contained in:
parent
80f95b6f2a
commit
42c0eeed57
@ -1,12 +1,31 @@
|
||||
//! Settings for [`Engine`]'s limitations.
|
||||
#![cfg(not(feature = "unchecked"))]
|
||||
|
||||
use super::default_limits;
|
||||
use crate::Engine;
|
||||
use std::num::{NonZeroU64, NonZeroUsize};
|
||||
#[cfg(feature = "no_std")]
|
||||
use std::prelude::v1::*;
|
||||
|
||||
pub mod default_limits {
|
||||
#[cfg(debug_assertions)]
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
pub const MAX_CALL_STACK_DEPTH: usize = 8;
|
||||
#[cfg(debug_assertions)]
|
||||
pub const MAX_EXPR_DEPTH: usize = 32;
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
#[cfg(debug_assertions)]
|
||||
pub const MAX_FUNCTION_EXPR_DEPTH: usize = 16;
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
pub const MAX_CALL_STACK_DEPTH: usize = 64;
|
||||
#[cfg(not(debug_assertions))]
|
||||
pub const MAX_EXPR_DEPTH: usize = 64;
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
#[cfg(not(debug_assertions))]
|
||||
pub const MAX_FUNCTION_EXPR_DEPTH: usize = 32;
|
||||
}
|
||||
|
||||
/// A type containing all the limits imposed by the [`Engine`].
|
||||
///
|
||||
/// Not available under `unchecked`.
|
||||
|
@ -43,28 +43,7 @@ use std::prelude::v1::*;
|
||||
|
||||
pub mod default_limits {
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
#[cfg(debug_assertions)]
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
pub const MAX_CALL_STACK_DEPTH: usize = 8;
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
#[cfg(debug_assertions)]
|
||||
pub const MAX_EXPR_DEPTH: usize = 32;
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
#[cfg(debug_assertions)]
|
||||
pub const MAX_FUNCTION_EXPR_DEPTH: usize = 16;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
#[cfg(not(debug_assertions))]
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
pub const MAX_CALL_STACK_DEPTH: usize = 64;
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
#[cfg(not(debug_assertions))]
|
||||
pub const MAX_EXPR_DEPTH: usize = 64;
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
#[cfg(not(debug_assertions))]
|
||||
pub const MAX_FUNCTION_EXPR_DEPTH: usize = 32;
|
||||
pub use super::limits::default_limits::*;
|
||||
|
||||
pub const MAX_DYNAMIC_PARAMETERS: usize = 16;
|
||||
}
|
||||
@ -236,55 +215,3 @@ impl Engine {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "unchecked")]
|
||||
impl Engine {
|
||||
/// The maximum levels of function calls allowed for a script.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn max_call_levels(&self) -> usize {
|
||||
usize::MAX
|
||||
}
|
||||
/// The maximum number of operations allowed for a script to run (0 for unlimited).
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub const fn max_operations(&self) -> u64 {
|
||||
0
|
||||
}
|
||||
/// The maximum number of imported [modules][crate::Module] allowed for a script.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn max_modules(&self) -> usize {
|
||||
usize::MAX
|
||||
}
|
||||
/// The depth limit for expressions (0 for unlimited).
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn max_expr_depth(&self) -> usize {
|
||||
0
|
||||
}
|
||||
/// The depth limit for expressions in functions (0 for unlimited).
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn max_function_expr_depth(&self) -> usize {
|
||||
0
|
||||
}
|
||||
/// The maximum length of [strings][crate::ImmutableString] (0 for unlimited).
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn max_string_size(&self) -> usize {
|
||||
0
|
||||
}
|
||||
/// The maximum length of [arrays][crate::Array] (0 for unlimited).
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn max_array_size(&self) -> usize {
|
||||
0
|
||||
}
|
||||
/// The maximum size of [object maps][crate::Map] (0 for unlimited).
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn max_map_size(&self) -> usize {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
@ -347,9 +347,9 @@ impl Engine {
|
||||
}
|
||||
|
||||
/// Check a result to ensure that it is valid.
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
#[inline]
|
||||
pub(crate) fn check_return_value(&self, result: RhaiResult, _pos: Position) -> RhaiResult {
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
if let Ok(ref r) = result {
|
||||
self.check_data_size(r, _pos)?;
|
||||
}
|
||||
@ -357,3 +357,81 @@ impl Engine {
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "unchecked")]
|
||||
impl Engine {
|
||||
/// The maximum levels of function calls allowed for a script.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn max_call_levels(&self) -> usize {
|
||||
usize::MAX
|
||||
}
|
||||
/// The maximum number of operations allowed for a script to run (0 for unlimited).
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn max_operations(&self) -> u64 {
|
||||
0
|
||||
}
|
||||
/// The maximum number of imported [modules][crate::Module] allowed for a script.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn max_modules(&self) -> usize {
|
||||
usize::MAX
|
||||
}
|
||||
/// The depth limit for expressions (0 for unlimited).
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn max_expr_depth(&self) -> usize {
|
||||
0
|
||||
}
|
||||
/// The depth limit for expressions in functions (0 for unlimited).
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn max_function_expr_depth(&self) -> usize {
|
||||
0
|
||||
}
|
||||
/// The maximum length of [strings][crate::ImmutableString] (0 for unlimited).
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn max_string_size(&self) -> usize {
|
||||
0
|
||||
}
|
||||
/// The maximum length of [arrays][crate::Array] (0 for unlimited).
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn max_array_size(&self) -> usize {
|
||||
0
|
||||
}
|
||||
/// The maximum size of [object maps][crate::Map] (0 for unlimited).
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub const fn max_map_size(&self) -> usize {
|
||||
0
|
||||
}
|
||||
|
||||
/// Check if the number of operations stay within limit.
|
||||
#[inline(always)]
|
||||
pub(crate) const fn track_operation(
|
||||
&self,
|
||||
_: &crate::GlobalRuntimeState,
|
||||
_: Position,
|
||||
) -> crate::RhaiResultOf<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Check whether the size of a [`Dynamic`] is within limits.
|
||||
#[inline(always)]
|
||||
pub(crate) const fn check_data_size(
|
||||
&self,
|
||||
_: &Dynamic,
|
||||
_: Position,
|
||||
) -> crate::RhaiResultOf<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Check a result to ensure that it is valid.
|
||||
#[inline(always)]
|
||||
pub(crate) const fn check_return_value(&self, result: RhaiResult, _: Position) -> RhaiResult {
|
||||
result
|
||||
}
|
||||
}
|
||||
|
@ -131,7 +131,6 @@ impl Engine {
|
||||
self.eval_op_assignment(
|
||||
global, caches, lib, op_info, obj_ptr, root, new_val, level,
|
||||
)?;
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
self.check_data_size(obj_ptr, op_info.pos)?;
|
||||
None
|
||||
}
|
||||
@ -159,7 +158,6 @@ impl Engine {
|
||||
)?;
|
||||
// Replace new value
|
||||
new_val = val.take_or_clone();
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
self.check_data_size(&new_val, op_info.pos)?;
|
||||
}
|
||||
}
|
||||
@ -246,7 +244,6 @@ impl Engine {
|
||||
global, caches, lib, op_info, val_target, root, new_val, level,
|
||||
)?;
|
||||
}
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
self.check_data_size(target.source(), op_info.pos)?;
|
||||
Ok((Dynamic::UNIT, true))
|
||||
}
|
||||
@ -606,9 +603,7 @@ impl Engine {
|
||||
Expr::Variable(x, .., var_pos) => {
|
||||
#[cfg(feature = "debugging")]
|
||||
self.run_debugger(scope, global, lib, this_ptr, lhs, level)?;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
self.inc_operations(&mut global.num_operations, *var_pos)?;
|
||||
self.track_operation(global, *var_pos)?;
|
||||
|
||||
let (mut target, ..) =
|
||||
self.search_namespace(scope, global, lib, this_ptr, lhs, level)?;
|
||||
@ -655,8 +650,7 @@ impl Engine {
|
||||
idx_values: &mut FnArgsVec<Dynamic>,
|
||||
level: usize,
|
||||
) -> RhaiResultOf<()> {
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
self.inc_operations(&mut global.num_operations, expr.position())?;
|
||||
self.track_operation(global, expr.position())?;
|
||||
|
||||
match expr {
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
@ -814,8 +808,7 @@ impl Engine {
|
||||
use_indexers: bool,
|
||||
level: usize,
|
||||
) -> RhaiResultOf<Target<'t>> {
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
self.inc_operations(&mut global.num_operations, Position::NONE)?;
|
||||
self.track_operation(global, Position::NONE)?;
|
||||
|
||||
match target {
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
|
@ -1,6 +1,7 @@
|
||||
//! Data size checks during evaluation.
|
||||
#![cfg(not(feature = "unchecked"))]
|
||||
|
||||
use super::GlobalRuntimeState;
|
||||
use crate::types::dynamic::Union;
|
||||
use crate::{Dynamic, Engine, Position, RhaiResultOf, ERR};
|
||||
use std::num::NonZeroUsize;
|
||||
@ -15,7 +16,6 @@ impl Engine {
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if any interior data is shared (should never happen).
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
pub(crate) fn calc_data_sizes(value: &Dynamic, _top: bool) -> (usize, usize, usize) {
|
||||
match value.0 {
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
@ -71,24 +71,11 @@ impl Engine {
|
||||
}
|
||||
|
||||
/// Is there a data size limit set?
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
pub(crate) const fn has_data_size_limit(&self) -> bool {
|
||||
let mut _limited = self.limits.max_string_size.is_some();
|
||||
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
{
|
||||
_limited = _limited || self.limits.max_array_size.is_some();
|
||||
}
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
{
|
||||
_limited = _limited || self.limits.max_map_size.is_some();
|
||||
}
|
||||
|
||||
_limited
|
||||
self.max_string_size() > 0 || self.max_array_size() > 0 || self.max_map_size() > 0
|
||||
}
|
||||
|
||||
/// Raise an error if any data size exceeds limit.
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
pub(crate) fn raise_err_if_over_data_size_limit(
|
||||
&self,
|
||||
sizes: (usize, usize, usize),
|
||||
@ -128,7 +115,6 @@ impl Engine {
|
||||
}
|
||||
|
||||
/// Check whether the size of a [`Dynamic`] is within limits.
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
pub(crate) fn check_data_size(&self, value: &Dynamic, pos: Position) -> RhaiResultOf<()> {
|
||||
// If no data size limits, just return
|
||||
if !self.has_data_size_limit() {
|
||||
@ -143,29 +129,30 @@ impl Engine {
|
||||
/// Raise an error if the size of a [`Dynamic`] is out of limits (if any).
|
||||
///
|
||||
/// Not available under `unchecked`.
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
#[inline(always)]
|
||||
pub fn ensure_data_size_within_limits(&self, value: &Dynamic) -> RhaiResultOf<()> {
|
||||
self.check_data_size(value, Position::NONE)
|
||||
}
|
||||
|
||||
/// Check if the number of operations stay within limit.
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
pub(crate) fn inc_operations(
|
||||
pub(crate) fn track_operation(
|
||||
&self,
|
||||
num_operations: &mut u64,
|
||||
global: &mut GlobalRuntimeState,
|
||||
pos: Position,
|
||||
) -> RhaiResultOf<()> {
|
||||
*num_operations += 1;
|
||||
global.num_operations += 1;
|
||||
|
||||
// Guard against too many operations
|
||||
if self.max_operations() > 0 && *num_operations > self.max_operations() {
|
||||
let max = self.max_operations();
|
||||
let num_operations = global.num_operations;
|
||||
|
||||
if max > 0 && num_operations > max {
|
||||
return Err(ERR::ErrorTooManyOperations(pos).into());
|
||||
}
|
||||
|
||||
// Report progress - only in steps
|
||||
if let Some(ref progress) = self.progress {
|
||||
if let Some(token) = progress(*num_operations) {
|
||||
if let Some(token) = progress(num_operations) {
|
||||
// Terminate script if progress returns a termination token
|
||||
return Err(ERR::ErrorTerminated(token, pos).into());
|
||||
}
|
||||
|
@ -318,8 +318,7 @@ impl Engine {
|
||||
let reset_debugger =
|
||||
self.run_debugger_with_reset(scope, global, lib, this_ptr, expr, level)?;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
self.inc_operations(&mut global.num_operations, expr.position())?;
|
||||
self.track_operation(global, expr.position())?;
|
||||
|
||||
let result =
|
||||
self.eval_fn_call_expr(scope, global, caches, lib, this_ptr, x, x.pos, level);
|
||||
@ -337,8 +336,7 @@ impl Engine {
|
||||
#[cfg(feature = "debugging")]
|
||||
self.run_debugger(scope, global, lib, this_ptr, expr, level)?;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
self.inc_operations(&mut global.num_operations, expr.position())?;
|
||||
self.track_operation(global, expr.position())?;
|
||||
|
||||
return if index.is_none() && x.0.is_none() && x.3 == KEYWORD_THIS {
|
||||
this_ptr
|
||||
@ -355,8 +353,7 @@ impl Engine {
|
||||
let reset_debugger =
|
||||
self.run_debugger_with_reset(scope, global, lib, this_ptr, expr, level)?;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
self.inc_operations(&mut global.num_operations, expr.position())?;
|
||||
self.track_operation(global, expr.position())?;
|
||||
|
||||
let result = match expr {
|
||||
// Constants
|
||||
@ -410,7 +407,7 @@ impl Engine {
|
||||
let mut result = Ok(Dynamic::UNIT);
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
let mut sizes = (0, 0, 0);
|
||||
let mut total_data_sizes = (0, 0, 0);
|
||||
|
||||
for item_expr in &**x {
|
||||
let value = match self
|
||||
@ -424,19 +421,21 @@ impl Engine {
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
let val_sizes = Self::calc_data_sizes(&value, true);
|
||||
if self.has_data_size_limit() {
|
||||
let val_sizes = Self::calc_data_sizes(&value, true);
|
||||
|
||||
total_data_sizes = (
|
||||
total_data_sizes.0 + val_sizes.0,
|
||||
total_data_sizes.1 + val_sizes.1,
|
||||
total_data_sizes.2 + val_sizes.2,
|
||||
);
|
||||
self.raise_err_if_over_data_size_limit(
|
||||
total_data_sizes,
|
||||
item_expr.position(),
|
||||
)?;
|
||||
}
|
||||
|
||||
array.push(value);
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
if self.has_data_size_limit() {
|
||||
sizes = (
|
||||
sizes.0 + val_sizes.0,
|
||||
sizes.1 + val_sizes.1,
|
||||
sizes.2 + val_sizes.2,
|
||||
);
|
||||
self.raise_err_if_over_data_size_limit(sizes, item_expr.position())?;
|
||||
}
|
||||
}
|
||||
|
||||
result.map(|_| array.into())
|
||||
@ -448,7 +447,7 @@ impl Engine {
|
||||
let mut result = Ok(Dynamic::UNIT);
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
let mut sizes = (0, 0, 0);
|
||||
let mut total_data_sizes = (0, 0, 0);
|
||||
|
||||
for (key, value_expr) in &x.0 {
|
||||
let value = match self
|
||||
@ -462,15 +461,20 @@ impl Engine {
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
let delta = Self::calc_data_sizes(&value, true);
|
||||
if self.has_data_size_limit() {
|
||||
let delta = Self::calc_data_sizes(&value, true);
|
||||
total_data_sizes = (
|
||||
total_data_sizes.0 + delta.0,
|
||||
total_data_sizes.1 + delta.1,
|
||||
total_data_sizes.2 + delta.2,
|
||||
);
|
||||
self.raise_err_if_over_data_size_limit(
|
||||
total_data_sizes,
|
||||
value_expr.position(),
|
||||
)?;
|
||||
}
|
||||
|
||||
*map.get_mut(key.as_str()).unwrap() = value;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
if self.has_data_size_limit() {
|
||||
sizes = (sizes.0 + delta.0, sizes.1 + delta.1, sizes.2 + delta.2);
|
||||
self.raise_err_if_over_data_size_limit(sizes, value_expr.position())?;
|
||||
}
|
||||
}
|
||||
|
||||
result.map(|_| map.into())
|
||||
|
@ -152,7 +152,6 @@ impl Engine {
|
||||
let context = (self, op, None, &*global, lib, *op_pos, level).into();
|
||||
let result = func(context, args).map(|_| ());
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
self.check_data_size(args[0], root.1)?;
|
||||
|
||||
return result;
|
||||
@ -165,10 +164,7 @@ impl Engine {
|
||||
match self.call_native_fn(
|
||||
global, caches, lib, op_assign, hash, args, true, true, *op_pos, level,
|
||||
) {
|
||||
Ok(_) => {
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
self.check_data_size(args[0], root.1)?;
|
||||
}
|
||||
Ok(_) => self.check_data_size(args[0], root.1)?,
|
||||
Err(err) if matches!(*err, ERR::ErrorFunctionNotFound(ref f, ..) if f.starts_with(op_assign)) =>
|
||||
{
|
||||
// Expand to `var = var op rhs`
|
||||
@ -218,8 +214,7 @@ impl Engine {
|
||||
|
||||
// Function calls should account for a relatively larger portion of statements.
|
||||
if let Stmt::FnCall(x, ..) = stmt {
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
self.inc_operations(&mut global.num_operations, stmt.position())?;
|
||||
self.track_operation(global, stmt.position())?;
|
||||
|
||||
let result =
|
||||
self.eval_fn_call_expr(scope, global, caches, lib, this_ptr, x, x.pos, level);
|
||||
@ -236,8 +231,7 @@ impl Engine {
|
||||
if let Stmt::Assignment(x, ..) = stmt {
|
||||
let (op_info, BinaryExpr { lhs, rhs }) = &**x;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
self.inc_operations(&mut global.num_operations, stmt.position())?;
|
||||
self.track_operation(global, stmt.position())?;
|
||||
|
||||
let result = if let Expr::Variable(x, ..) = lhs {
|
||||
let rhs_result = self
|
||||
@ -267,8 +261,7 @@ impl Engine {
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
self.inc_operations(&mut global.num_operations, pos)?;
|
||||
self.track_operation(global, pos)?;
|
||||
|
||||
let root = (var_name, pos);
|
||||
let lhs_ptr = &mut lhs_ptr;
|
||||
@ -339,8 +332,7 @@ impl Engine {
|
||||
return result;
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
self.inc_operations(&mut global.num_operations, stmt.position())?;
|
||||
self.track_operation(global, stmt.position())?;
|
||||
|
||||
let result = match stmt {
|
||||
// No-op
|
||||
@ -512,8 +504,7 @@ impl Engine {
|
||||
let (.., body) = &**x;
|
||||
|
||||
if body.is_empty() {
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
self.inc_operations(&mut global.num_operations, body.position())?;
|
||||
self.track_operation(global, body.position())?;
|
||||
} else {
|
||||
match self
|
||||
.eval_stmt_block(scope, global, caches, lib, this_ptr, body, true, level)
|
||||
@ -668,10 +659,7 @@ impl Engine {
|
||||
|
||||
*scope.get_mut_by_index(index).write_lock().unwrap() = value;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
if let Err(err) = self
|
||||
.inc_operations(&mut global.num_operations, statements.position())
|
||||
{
|
||||
if let Err(err) = self.track_operation(global, statements.position()) {
|
||||
loop_result = Err(err);
|
||||
break;
|
||||
}
|
||||
|
@ -298,7 +298,7 @@ pub fn get_builtin_binary_op_fn(op: &Token, x: &Dynamic, y: &Dynamic) -> Option<
|
||||
($x:ty, $xx:ident, $y:ty, $yy:ident) => {
|
||||
if (type1, type2) == (TypeId::of::<$x>(), TypeId::of::<$y>()) {
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
use crate::packages::arithmetic::decimal_functions::*;
|
||||
use crate::packages::arithmetic::decimal_functions::builtin::*;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
match op {
|
||||
@ -697,7 +697,7 @@ pub fn get_builtin_op_assignment_fn(op: &Token, x: &Dynamic, y: &Dynamic) -> Opt
|
||||
($x:ident, $xx:ident, $y:ty, $yy:ident) => {
|
||||
if (type1, type2) == (TypeId::of::<$x>(), TypeId::of::<$y>()) {
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
use crate::packages::arithmetic::decimal_functions::*;
|
||||
use crate::packages::arithmetic::decimal_functions::builtin::*;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
return match op {
|
||||
|
@ -358,8 +358,7 @@ impl Engine {
|
||||
pos: Position,
|
||||
level: usize,
|
||||
) -> RhaiResultOf<(Dynamic, bool)> {
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
self.inc_operations(&mut global.num_operations, pos)?;
|
||||
self.track_operation(global, pos)?;
|
||||
|
||||
let parent_source = global.source.clone();
|
||||
let op_assign = if is_op_assign {
|
||||
@ -1232,8 +1231,7 @@ impl Engine {
|
||||
target = target.into_owned();
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
self.inc_operations(&mut global.num_operations, _pos)?;
|
||||
self.track_operation(global, _pos)?;
|
||||
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
let target_is_shared = target.is_shared();
|
||||
@ -1312,8 +1310,7 @@ impl Engine {
|
||||
let (target, _pos) =
|
||||
self.search_scope_only(scope, global, lib, this_ptr, first_arg, level)?;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
self.inc_operations(&mut global.num_operations, _pos)?;
|
||||
self.track_operation(global, _pos)?;
|
||||
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
let target_is_shared = target.is_shared();
|
||||
@ -1350,9 +1347,7 @@ impl Engine {
|
||||
let mut func = match module.get_qualified_fn(hash) {
|
||||
// Then search native Rust functions
|
||||
None => {
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
self.inc_operations(&mut global.num_operations, pos)?;
|
||||
|
||||
self.track_operation(global, pos)?;
|
||||
let hash_params = calc_fn_params_hash(args.iter().map(|a| a.type_id()));
|
||||
let hash_qualified_fn = combine_hashes(hash, hash_params);
|
||||
|
||||
@ -1384,8 +1379,7 @@ impl Engine {
|
||||
}));
|
||||
let hash_qualified_fn = combine_hashes(hash, hash_params);
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
self.inc_operations(&mut global.num_operations, pos)?;
|
||||
self.track_operation(global, pos)?;
|
||||
|
||||
if let Some(f) = module.get_qualified_fn(hash_qualified_fn) {
|
||||
func = Some(f);
|
||||
@ -1461,8 +1455,7 @@ impl Engine {
|
||||
_pos: Position,
|
||||
level: usize,
|
||||
) -> RhaiResult {
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
self.inc_operations(&mut global.num_operations, _pos)?;
|
||||
self.track_operation(global, _pos)?;
|
||||
|
||||
let script = script.trim();
|
||||
|
||||
|
@ -63,8 +63,7 @@ impl Engine {
|
||||
|
||||
assert!(fn_def.params.len() == args.len());
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
self.inc_operations(&mut global.num_operations, pos)?;
|
||||
self.track_operation(global, pos)?;
|
||||
|
||||
// Check for stack overflow
|
||||
if level > self.max_call_levels() {
|
||||
|
@ -488,39 +488,29 @@ mod f64_functions {
|
||||
#[cfg(feature = "decimal")]
|
||||
#[export_module]
|
||||
pub mod decimal_functions {
|
||||
use num_traits::Pow;
|
||||
use rust_decimal::{prelude::Zero, Decimal, MathematicalOps};
|
||||
use rust_decimal::{prelude::Zero, Decimal};
|
||||
|
||||
#[rhai_fn(skip, return_raw)]
|
||||
pub fn add(x: Decimal, y: Decimal) -> RhaiResultOf<Decimal> {
|
||||
if cfg!(not(feature = "unchecked")) {
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
pub mod builtin {
|
||||
use rust_decimal::MathematicalOps;
|
||||
|
||||
#[rhai_fn(return_raw)]
|
||||
pub fn add(x: Decimal, y: Decimal) -> RhaiResultOf<Decimal> {
|
||||
x.checked_add(y)
|
||||
.ok_or_else(|| make_err(format!("Addition overflow: {x} + {y}")))
|
||||
} else {
|
||||
Ok(x + y)
|
||||
}
|
||||
}
|
||||
#[rhai_fn(skip, return_raw)]
|
||||
pub fn subtract(x: Decimal, y: Decimal) -> RhaiResultOf<Decimal> {
|
||||
if cfg!(not(feature = "unchecked")) {
|
||||
#[rhai_fn(return_raw)]
|
||||
pub fn subtract(x: Decimal, y: Decimal) -> RhaiResultOf<Decimal> {
|
||||
x.checked_sub(y)
|
||||
.ok_or_else(|| make_err(format!("Subtraction overflow: {x} - {y}")))
|
||||
} else {
|
||||
Ok(x - y)
|
||||
}
|
||||
}
|
||||
#[rhai_fn(skip, return_raw)]
|
||||
pub fn multiply(x: Decimal, y: Decimal) -> RhaiResultOf<Decimal> {
|
||||
if cfg!(not(feature = "unchecked")) {
|
||||
#[rhai_fn(return_raw)]
|
||||
pub fn multiply(x: Decimal, y: Decimal) -> RhaiResultOf<Decimal> {
|
||||
x.checked_mul(y)
|
||||
.ok_or_else(|| make_err(format!("Multiplication overflow: {x} * {y}")))
|
||||
} else {
|
||||
Ok(x * y)
|
||||
}
|
||||
}
|
||||
#[rhai_fn(skip, return_raw)]
|
||||
pub fn divide(x: Decimal, y: Decimal) -> RhaiResultOf<Decimal> {
|
||||
if cfg!(not(feature = "unchecked")) {
|
||||
#[rhai_fn(return_raw)]
|
||||
pub fn divide(x: Decimal, y: Decimal) -> RhaiResultOf<Decimal> {
|
||||
// Detect division by zero
|
||||
if y == Decimal::zero() {
|
||||
Err(make_err(format!("Division by zero: {x} / {y}")))
|
||||
@ -528,26 +518,16 @@ pub mod decimal_functions {
|
||||
x.checked_div(y)
|
||||
.ok_or_else(|| make_err(format!("Division overflow: {x} / {y}")))
|
||||
}
|
||||
} else {
|
||||
Ok(x / y)
|
||||
}
|
||||
}
|
||||
#[rhai_fn(skip, return_raw)]
|
||||
pub fn modulo(x: Decimal, y: Decimal) -> RhaiResultOf<Decimal> {
|
||||
if cfg!(not(feature = "unchecked")) {
|
||||
#[rhai_fn(return_raw)]
|
||||
pub fn modulo(x: Decimal, y: Decimal) -> RhaiResultOf<Decimal> {
|
||||
x.checked_rem(y)
|
||||
.ok_or_else(|| make_err(format!("Modulo division by zero or overflow: {x} % {y}")))
|
||||
} else {
|
||||
Ok(x % y)
|
||||
}
|
||||
}
|
||||
#[rhai_fn(skip, return_raw)]
|
||||
pub fn power(x: Decimal, y: Decimal) -> RhaiResultOf<Decimal> {
|
||||
if cfg!(not(feature = "unchecked")) {
|
||||
#[rhai_fn(return_raw)]
|
||||
pub fn power(x: Decimal, y: Decimal) -> RhaiResultOf<Decimal> {
|
||||
x.checked_powd(y)
|
||||
.ok_or_else(|| make_err(format!("Exponential overflow: {x} ** {y}")))
|
||||
} else {
|
||||
Ok(x.pow(y))
|
||||
}
|
||||
}
|
||||
#[rhai_fn(name = "-")]
|
||||
|
@ -236,9 +236,8 @@ pub mod array_functions {
|
||||
}
|
||||
|
||||
let check_sizes = match item.0 {
|
||||
crate::types::dynamic::Union::Array(..) | crate::types::dynamic::Union::Str(..) => {
|
||||
true
|
||||
}
|
||||
crate::types::dynamic::Union::Str(..) => true,
|
||||
crate::types::dynamic::Union::Array(..) => true,
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
crate::types::dynamic::Union::Map(..) => true,
|
||||
_ => false,
|
||||
|
Loading…
Reference in New Issue
Block a user