Enable termination token.

This commit is contained in:
Stephen Chung 2020-11-02 11:04:45 +08:00
parent b07a2aa79c
commit 6f3ce96d9d
9 changed files with 82 additions and 122 deletions

View File

@ -20,6 +20,8 @@ Breaking changes
* Custom syntax can no longer start with a keyword (even a _reserved_ one), even if it has been disabled. That is to avoid breaking scripts later when the keyword is no longer disabled. * Custom syntax can no longer start with a keyword (even a _reserved_ one), even if it has been disabled. That is to avoid breaking scripts later when the keyword is no longer disabled.
* `EvalAltResult::ErrorAssignmentToUnknownLHS` is moved to `ParseError::AssignmentToInvalidLHS`. `ParseError::AssignmentToCopy` is removed. * `EvalAltResult::ErrorAssignmentToUnknownLHS` is moved to `ParseError::AssignmentToInvalidLHS`. `ParseError::AssignmentToCopy` is removed.
* `EvalAltResult::ErrorDataTooLarge` is simplified.
* `Engine::on_progress` closure signature now returns `Option<Dynamic>` with the termination value passed on to `EvalAltResult::ErrorTerminated`.
New features New features
------------ ------------

View File

@ -17,13 +17,14 @@ engine.on_progress(|&count| { // parameter is '&u64' - number of operations al
if count % 1000 == 0 { if count % 1000 == 0 {
println!("{}", count); // print out a progress log every 1,000 operations println!("{}", count); // print out a progress log every 1,000 operations
} }
true // return 'true' to continue running the script None // return 'None' to continue running the script
// return 'false' to immediately terminate the script // return 'Some(token)' to immediately terminate the script
}); });
``` ```
The closure passed to `Engine::on_progress` will be called once for every operation. The closure passed to `Engine::on_progress` will be called once for every operation.
Return `false` to terminate the script immediately. Return `Some(token)` to terminate the script immediately, with the provided value
(any [`Dynamic`] value) passed to `EvalAltResult::ErrorTerminated` as a termination token.
Operations Count vs. Progress Percentage Operations Count vs. Progress Percentage

View File

@ -576,7 +576,7 @@ pub struct Engine {
/// Callback closure for implementing the `debug` command. /// Callback closure for implementing the `debug` command.
pub(crate) debug: Callback<str, ()>, pub(crate) debug: Callback<str, ()>,
/// Callback closure for progress reporting. /// Callback closure for progress reporting.
pub(crate) progress: Option<Callback<u64, bool>>, pub(crate) progress: Option<Callback<u64, Option<Dynamic>>>,
/// Optimize the AST after compilation. /// Optimize the AST after compilation.
pub(crate) optimization_level: OptimizationLevel, pub(crate) optimization_level: OptimizationLevel,
@ -2300,8 +2300,6 @@ impl Engine {
if s > self.max_string_size() { if s > self.max_string_size() {
return EvalAltResult::ErrorDataTooLarge( return EvalAltResult::ErrorDataTooLarge(
"Length of string".to_string(), "Length of string".to_string(),
self.max_string_size(),
s,
Position::none(), Position::none(),
) )
.into(); .into();
@ -2309,21 +2307,14 @@ impl Engine {
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
if _arr > self.max_array_size() { if _arr > self.max_array_size() {
return EvalAltResult::ErrorDataTooLarge( return EvalAltResult::ErrorDataTooLarge("Size of array".to_string(), Position::none())
"Size of array".to_string(),
self.max_array_size(),
_arr,
Position::none(),
)
.into(); .into();
} }
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
if _map > self.max_map_size() { if _map > self.max_map_size() {
return EvalAltResult::ErrorDataTooLarge( return EvalAltResult::ErrorDataTooLarge(
"Number of properties in object map".to_string(), "Size of object map".to_string(),
self.max_map_size(),
_map,
Position::none(), Position::none(),
) )
.into(); .into();
@ -2345,9 +2336,9 @@ impl Engine {
// Report progress - only in steps // Report progress - only in steps
if let Some(progress) = &self.progress { if let Some(progress) = &self.progress {
if !progress(&state.operations) { if let Some(token) = progress(&state.operations) {
// Terminate script if progress returns false // Terminate script if progress returns a termination token
return EvalAltResult::ErrorTerminated(Position::none()).into(); return EvalAltResult::ErrorTerminated(token, Position::none()).into();
} }
} }

View File

@ -1732,12 +1732,12 @@ impl Engine {
/// ///
/// engine.on_progress(move |&ops| { /// engine.on_progress(move |&ops| {
/// if ops > 10000 { /// if ops > 10000 {
/// false /// Some("Over 10,000 operations!".into())
/// } else if ops % 800 == 0 { /// } else if ops % 800 == 0 {
/// *logger.write().unwrap() = ops; /// *logger.write().unwrap() = ops;
/// true /// None
/// } else { /// } else {
/// true /// None
/// } /// }
/// }); /// });
/// ///
@ -1752,7 +1752,7 @@ impl Engine {
#[inline(always)] #[inline(always)]
pub fn on_progress( pub fn on_progress(
&mut self, &mut self,
callback: impl Fn(&u64) -> bool + SendSync + 'static, callback: impl Fn(&u64) -> Option<Dynamic> + SendSync + 'static,
) -> &mut Self { ) -> &mut Self {
self.progress = Some(Box::new(callback)); self.progress = Some(Box::new(callback));
self self

View File

@ -160,7 +160,7 @@ impl FnPtr {
/// clone them _before_ calling this function. /// clone them _before_ calling this function.
pub fn call_dynamic( pub fn call_dynamic(
&self, &self,
context: NativeCallContext, ctx: NativeCallContext,
this_ptr: Option<&mut Dynamic>, this_ptr: Option<&mut Dynamic>,
mut arg_values: impl AsMut<[Dynamic]>, mut arg_values: impl AsMut<[Dynamic]>,
) -> Result<Dynamic, Box<EvalAltResult>> { ) -> Result<Dynamic, Box<EvalAltResult>> {
@ -182,11 +182,10 @@ impl FnPtr {
args.insert(0, obj); args.insert(0, obj);
} }
context ctx.engine()
.engine()
.exec_fn_call( .exec_fn_call(
&mut Default::default(), &mut Default::default(),
context.lib, ctx.lib,
fn_name, fn_name,
hash_script, hash_script,
args.as_mut(), args.as_mut(),

View File

@ -529,9 +529,8 @@ impl Module {
+ SendSync + SendSync
+ 'static, + 'static,
) -> u64 { ) -> u64 {
let f = move |context: NativeCallContext, args: &mut FnCallArgs| { let f =
func(context, args).map(Dynamic::from) move |ctx: NativeCallContext, args: &mut FnCallArgs| func(ctx, args).map(Dynamic::from);
};
self.set_fn( self.set_fn(
name, name,
FnAccess::Public, FnAccess::Public,

View File

@ -41,12 +41,12 @@ macro_rules! gen_array_functions {
} }
#[rhai_fn(return_raw)] #[rhai_fn(return_raw)]
pub fn pad(_context: NativeCallContext, list: &mut Array, len: INT, item: $arg_type) -> Result<Dynamic, Box<EvalAltResult>> { pub fn pad(_ctx: NativeCallContext, list: &mut Array, len: INT, item: $arg_type) -> Result<Dynamic, Box<EvalAltResult>> {
// Check if array will be over max size limit // Check if array will be over max size limit
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
if _context.engine().max_array_size() > 0 && len > 0 && (len as usize) > _context.engine().max_array_size() { if _ctx.engine().max_array_size() > 0 && len > 0 && (len as usize) > _ctx.engine().max_array_size() {
return EvalAltResult::ErrorDataTooLarge( return EvalAltResult::ErrorDataTooLarge(
"Size of array".to_string(), _context.engine().max_array_size(), len as usize, Position::none(), "Size of array".to_string(), Position::none()
).into(); ).into();
} }
@ -197,7 +197,7 @@ mod array_functions {
} }
#[rhai_fn(return_raw)] #[rhai_fn(return_raw)]
pub fn map( pub fn map(
context: NativeCallContext, ctx: NativeCallContext,
list: &mut Array, list: &mut Array,
mapper: FnPtr, mapper: FnPtr,
) -> Result<Dynamic, Box<EvalAltResult>> { ) -> Result<Dynamic, Box<EvalAltResult>> {
@ -206,12 +206,12 @@ mod array_functions {
for (i, item) in list.iter().enumerate() { for (i, item) in list.iter().enumerate() {
array.push( array.push(
mapper mapper
.call_dynamic(context, None, [item.clone()]) .call_dynamic(ctx, None, [item.clone()])
.or_else(|err| match *err { .or_else(|err| match *err {
EvalAltResult::ErrorFunctionNotFound(fn_sig, _) EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
if fn_sig.starts_with(mapper.fn_name()) => if fn_sig.starts_with(mapper.fn_name()) =>
{ {
mapper.call_dynamic(context, None, [item.clone(), (i as INT).into()]) mapper.call_dynamic(ctx, None, [item.clone(), (i as INT).into()])
} }
_ => Err(err), _ => Err(err),
}) })
@ -229,7 +229,7 @@ mod array_functions {
} }
#[rhai_fn(return_raw)] #[rhai_fn(return_raw)]
pub fn filter( pub fn filter(
context: NativeCallContext, ctx: NativeCallContext,
list: &mut Array, list: &mut Array,
filter: FnPtr, filter: FnPtr,
) -> Result<Dynamic, Box<EvalAltResult>> { ) -> Result<Dynamic, Box<EvalAltResult>> {
@ -237,12 +237,12 @@ mod array_functions {
for (i, item) in list.iter().enumerate() { for (i, item) in list.iter().enumerate() {
if filter if filter
.call_dynamic(context, None, [item.clone()]) .call_dynamic(ctx, None, [item.clone()])
.or_else(|err| match *err { .or_else(|err| match *err {
EvalAltResult::ErrorFunctionNotFound(fn_sig, _) EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
if fn_sig.starts_with(filter.fn_name()) => if fn_sig.starts_with(filter.fn_name()) =>
{ {
filter.call_dynamic(context, None, [item.clone(), (i as INT).into()]) filter.call_dynamic(ctx, None, [item.clone(), (i as INT).into()])
} }
_ => Err(err), _ => Err(err),
}) })
@ -264,18 +264,18 @@ mod array_functions {
} }
#[rhai_fn(return_raw)] #[rhai_fn(return_raw)]
pub fn some( pub fn some(
context: NativeCallContext, ctx: NativeCallContext,
list: &mut Array, list: &mut Array,
filter: FnPtr, filter: FnPtr,
) -> Result<Dynamic, Box<EvalAltResult>> { ) -> Result<Dynamic, Box<EvalAltResult>> {
for (i, item) in list.iter().enumerate() { for (i, item) in list.iter().enumerate() {
if filter if filter
.call_dynamic(context, None, [item.clone()]) .call_dynamic(ctx, None, [item.clone()])
.or_else(|err| match *err { .or_else(|err| match *err {
EvalAltResult::ErrorFunctionNotFound(fn_sig, _) EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
if fn_sig.starts_with(filter.fn_name()) => if fn_sig.starts_with(filter.fn_name()) =>
{ {
filter.call_dynamic(context, None, [item.clone(), (i as INT).into()]) filter.call_dynamic(ctx, None, [item.clone(), (i as INT).into()])
} }
_ => Err(err), _ => Err(err),
}) })
@ -297,18 +297,18 @@ mod array_functions {
} }
#[rhai_fn(return_raw)] #[rhai_fn(return_raw)]
pub fn all( pub fn all(
context: NativeCallContext, ctx: NativeCallContext,
list: &mut Array, list: &mut Array,
filter: FnPtr, filter: FnPtr,
) -> Result<Dynamic, Box<EvalAltResult>> { ) -> Result<Dynamic, Box<EvalAltResult>> {
for (i, item) in list.iter().enumerate() { for (i, item) in list.iter().enumerate() {
if !filter if !filter
.call_dynamic(context, None, [item.clone()]) .call_dynamic(ctx, None, [item.clone()])
.or_else(|err| match *err { .or_else(|err| match *err {
EvalAltResult::ErrorFunctionNotFound(fn_sig, _) EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
if fn_sig.starts_with(filter.fn_name()) => if fn_sig.starts_with(filter.fn_name()) =>
{ {
filter.call_dynamic(context, None, [item.clone(), (i as INT).into()]) filter.call_dynamic(ctx, None, [item.clone(), (i as INT).into()])
} }
_ => Err(err), _ => Err(err),
}) })
@ -330,7 +330,7 @@ mod array_functions {
} }
#[rhai_fn(return_raw)] #[rhai_fn(return_raw)]
pub fn reduce( pub fn reduce(
context: NativeCallContext, ctx: NativeCallContext,
list: &mut Array, list: &mut Array,
reducer: FnPtr, reducer: FnPtr,
) -> Result<Dynamic, Box<EvalAltResult>> { ) -> Result<Dynamic, Box<EvalAltResult>> {
@ -338,16 +338,12 @@ mod array_functions {
for (i, item) in list.iter().enumerate() { for (i, item) in list.iter().enumerate() {
result = reducer result = reducer
.call_dynamic(context, None, [result.clone(), item.clone()]) .call_dynamic(ctx, None, [result.clone(), item.clone()])
.or_else(|err| match *err { .or_else(|err| match *err {
EvalAltResult::ErrorFunctionNotFound(fn_sig, _) EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
if fn_sig.starts_with(reducer.fn_name()) => if fn_sig.starts_with(reducer.fn_name()) =>
{ {
reducer.call_dynamic( reducer.call_dynamic(ctx, None, [result, item.clone(), (i as INT).into()])
context,
None,
[result, item.clone(), (i as INT).into()],
)
} }
_ => Err(err), _ => Err(err),
}) })
@ -364,12 +360,12 @@ mod array_functions {
} }
#[rhai_fn(name = "reduce", return_raw)] #[rhai_fn(name = "reduce", return_raw)]
pub fn reduce_with_initial( pub fn reduce_with_initial(
context: NativeCallContext, ctx: NativeCallContext,
list: &mut Array, list: &mut Array,
reducer: FnPtr, reducer: FnPtr,
initial: FnPtr, initial: FnPtr,
) -> Result<Dynamic, Box<EvalAltResult>> { ) -> Result<Dynamic, Box<EvalAltResult>> {
let mut result = initial.call_dynamic(context, None, []).map_err(|err| { let mut result = initial.call_dynamic(ctx, None, []).map_err(|err| {
Box::new(EvalAltResult::ErrorInFunctionCall( Box::new(EvalAltResult::ErrorInFunctionCall(
"reduce".to_string(), "reduce".to_string(),
err, err,
@ -379,16 +375,12 @@ mod array_functions {
for (i, item) in list.iter().enumerate() { for (i, item) in list.iter().enumerate() {
result = reducer result = reducer
.call_dynamic(context, None, [result.clone(), item.clone()]) .call_dynamic(ctx, None, [result.clone(), item.clone()])
.or_else(|err| match *err { .or_else(|err| match *err {
EvalAltResult::ErrorFunctionNotFound(fn_sig, _) EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
if fn_sig.starts_with(reducer.fn_name()) => if fn_sig.starts_with(reducer.fn_name()) =>
{ {
reducer.call_dynamic( reducer.call_dynamic(ctx, None, [result, item.clone(), (i as INT).into()])
context,
None,
[result, item.clone(), (i as INT).into()],
)
} }
_ => Err(err), _ => Err(err),
}) })
@ -405,7 +397,7 @@ mod array_functions {
} }
#[rhai_fn(return_raw)] #[rhai_fn(return_raw)]
pub fn reduce_rev( pub fn reduce_rev(
context: NativeCallContext, ctx: NativeCallContext,
list: &mut Array, list: &mut Array,
reducer: FnPtr, reducer: FnPtr,
) -> Result<Dynamic, Box<EvalAltResult>> { ) -> Result<Dynamic, Box<EvalAltResult>> {
@ -413,16 +405,12 @@ mod array_functions {
for (i, item) in list.iter().enumerate().rev() { for (i, item) in list.iter().enumerate().rev() {
result = reducer result = reducer
.call_dynamic(context, None, [result.clone(), item.clone()]) .call_dynamic(ctx, None, [result.clone(), item.clone()])
.or_else(|err| match *err { .or_else(|err| match *err {
EvalAltResult::ErrorFunctionNotFound(fn_sig, _) EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
if fn_sig.starts_with(reducer.fn_name()) => if fn_sig.starts_with(reducer.fn_name()) =>
{ {
reducer.call_dynamic( reducer.call_dynamic(ctx, None, [result, item.clone(), (i as INT).into()])
context,
None,
[result, item.clone(), (i as INT).into()],
)
} }
_ => Err(err), _ => Err(err),
}) })
@ -439,12 +427,12 @@ mod array_functions {
} }
#[rhai_fn(name = "reduce_rev", return_raw)] #[rhai_fn(name = "reduce_rev", return_raw)]
pub fn reduce_rev_with_initial( pub fn reduce_rev_with_initial(
context: NativeCallContext, ctx: NativeCallContext,
list: &mut Array, list: &mut Array,
reducer: FnPtr, reducer: FnPtr,
initial: FnPtr, initial: FnPtr,
) -> Result<Dynamic, Box<EvalAltResult>> { ) -> Result<Dynamic, Box<EvalAltResult>> {
let mut result = initial.call_dynamic(context, None, []).map_err(|err| { let mut result = initial.call_dynamic(ctx, None, []).map_err(|err| {
Box::new(EvalAltResult::ErrorInFunctionCall( Box::new(EvalAltResult::ErrorInFunctionCall(
"reduce".to_string(), "reduce".to_string(),
err, err,
@ -454,16 +442,12 @@ mod array_functions {
for (i, item) in list.iter().enumerate().rev() { for (i, item) in list.iter().enumerate().rev() {
result = reducer result = reducer
.call_dynamic(context, None, [result.clone(), item.clone()]) .call_dynamic(ctx, None, [result.clone(), item.clone()])
.or_else(|err| match *err { .or_else(|err| match *err {
EvalAltResult::ErrorFunctionNotFound(fn_sig, _) EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
if fn_sig.starts_with(reducer.fn_name()) => if fn_sig.starts_with(reducer.fn_name()) =>
{ {
reducer.call_dynamic( reducer.call_dynamic(ctx, None, [result, item.clone(), (i as INT).into()])
context,
None,
[result, item.clone(), (i as INT).into()],
)
} }
_ => Err(err), _ => Err(err),
}) })
@ -480,13 +464,13 @@ mod array_functions {
} }
#[rhai_fn(return_raw)] #[rhai_fn(return_raw)]
pub fn sort( pub fn sort(
context: NativeCallContext, ctx: NativeCallContext,
list: &mut Array, list: &mut Array,
comparer: FnPtr, comparer: FnPtr,
) -> Result<Dynamic, Box<EvalAltResult>> { ) -> Result<Dynamic, Box<EvalAltResult>> {
list.sort_by(|x, y| { list.sort_by(|x, y| {
comparer comparer
.call_dynamic(context, None, [x.clone(), y.clone()]) .call_dynamic(ctx, None, [x.clone(), y.clone()])
.ok() .ok()
.and_then(|v| v.as_int().ok()) .and_then(|v| v.as_int().ok())
.map(|v| { .map(|v| {
@ -516,7 +500,7 @@ mod array_functions {
} }
#[rhai_fn(return_raw)] #[rhai_fn(return_raw)]
pub fn drain( pub fn drain(
context: NativeCallContext, ctx: NativeCallContext,
list: &mut Array, list: &mut Array,
filter: FnPtr, filter: FnPtr,
) -> Result<Dynamic, Box<EvalAltResult>> { ) -> Result<Dynamic, Box<EvalAltResult>> {
@ -528,12 +512,12 @@ mod array_functions {
i -= 1; i -= 1;
if filter if filter
.call_dynamic(context, None, [list[i].clone()]) .call_dynamic(ctx, None, [list[i].clone()])
.or_else(|err| match *err { .or_else(|err| match *err {
EvalAltResult::ErrorFunctionNotFound(fn_sig, _) EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
if fn_sig.starts_with(filter.fn_name()) => if fn_sig.starts_with(filter.fn_name()) =>
{ {
filter.call_dynamic(context, None, [list[i].clone(), (i as INT).into()]) filter.call_dynamic(ctx, None, [list[i].clone(), (i as INT).into()])
} }
_ => Err(err), _ => Err(err),
}) })
@ -575,7 +559,7 @@ mod array_functions {
} }
#[rhai_fn(return_raw)] #[rhai_fn(return_raw)]
pub fn retain( pub fn retain(
context: NativeCallContext, ctx: NativeCallContext,
list: &mut Array, list: &mut Array,
filter: FnPtr, filter: FnPtr,
) -> Result<Dynamic, Box<EvalAltResult>> { ) -> Result<Dynamic, Box<EvalAltResult>> {
@ -587,12 +571,12 @@ mod array_functions {
i -= 1; i -= 1;
if !filter if !filter
.call_dynamic(context, None, [list[i].clone()]) .call_dynamic(ctx, None, [list[i].clone()])
.or_else(|err| match *err { .or_else(|err| match *err {
EvalAltResult::ErrorFunctionNotFound(fn_sig, _) EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
if fn_sig.starts_with(filter.fn_name()) => if fn_sig.starts_with(filter.fn_name()) =>
{ {
filter.call_dynamic(context, None, [list[i].clone(), (i as INT).into()]) filter.call_dynamic(ctx, None, [list[i].clone(), (i as INT).into()])
} }
_ => Err(err), _ => Err(err),
}) })

View File

@ -251,20 +251,16 @@ mod string_functions {
#[rhai_fn(return_raw)] #[rhai_fn(return_raw)]
pub fn pad( pub fn pad(
_context: NativeCallContext, _ctx: NativeCallContext,
s: &mut ImmutableString, s: &mut ImmutableString,
len: INT, len: INT,
ch: char, ch: char,
) -> Result<Dynamic, Box<EvalAltResult>> { ) -> Result<Dynamic, Box<EvalAltResult>> {
// Check if string will be over max size limit // Check if string will be over max size limit
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
if _context.engine().max_string_size() > 0 if _ctx.engine().max_string_size() > 0 && len as usize > _ctx.engine().max_string_size() {
&& len as usize > _context.engine().max_string_size()
{
return EvalAltResult::ErrorDataTooLarge( return EvalAltResult::ErrorDataTooLarge(
"Length of string".to_string(), "Length of string".to_string(),
_context.engine().max_string_size(),
len as usize,
Position::none(), Position::none(),
) )
.into(); .into();
@ -281,13 +277,10 @@ mod string_functions {
} }
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
if _context.engine().max_string_size() > 0 if _ctx.engine().max_string_size() > 0 && s.len() > _ctx.engine().max_string_size()
&& s.len() > _context.engine().max_string_size()
{ {
return EvalAltResult::ErrorDataTooLarge( return EvalAltResult::ErrorDataTooLarge(
"Length of string".to_string(), "Length of string".to_string(),
_context.engine().max_string_size(),
s.len(),
Position::none(), Position::none(),
) )
.into(); .into();
@ -299,20 +292,16 @@ mod string_functions {
} }
#[rhai_fn(name = "pad", return_raw)] #[rhai_fn(name = "pad", return_raw)]
pub fn pad_with_string( pub fn pad_with_string(
_context: NativeCallContext, _ctx: NativeCallContext,
s: &mut ImmutableString, s: &mut ImmutableString,
len: INT, len: INT,
padding: &str, padding: &str,
) -> Result<Dynamic, Box<EvalAltResult>> { ) -> Result<Dynamic, Box<EvalAltResult>> {
// Check if string will be over max size limit // Check if string will be over max size limit
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
if _context.engine().max_string_size() > 0 if _ctx.engine().max_string_size() > 0 && len as usize > _ctx.engine().max_string_size() {
&& len as usize > _context.engine().max_string_size()
{
return EvalAltResult::ErrorDataTooLarge( return EvalAltResult::ErrorDataTooLarge(
"Length of string".to_string(), "Length of string".to_string(),
_context.engine().max_string_size(),
len as usize,
Position::none(), Position::none(),
) )
.into(); .into();
@ -336,13 +325,10 @@ mod string_functions {
} }
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
if _context.engine().max_string_size() > 0 if _ctx.engine().max_string_size() > 0 && s.len() > _ctx.engine().max_string_size()
&& s.len() > _context.engine().max_string_size()
{ {
return EvalAltResult::ErrorDataTooLarge( return EvalAltResult::ErrorDataTooLarge(
"Length of string".to_string(), "Length of string".to_string(),
_context.engine().max_string_size(),
s.len(),
Position::none(), Position::none(),
) )
.into(); .into();

View File

@ -83,11 +83,11 @@ pub enum EvalAltResult {
ErrorTooManyModules(Position), ErrorTooManyModules(Position),
/// Call stack over maximum limit. /// Call stack over maximum limit.
ErrorStackOverflow(Position), ErrorStackOverflow(Position),
/// Data value over maximum size limit. Wrapped values are the type name, maximum size and current size. /// Data value over maximum size limit. Wrapped value is the type name.
ErrorDataTooLarge(String, usize, usize, Position), ErrorDataTooLarge(String, Position),
/// The script is prematurely terminated. /// The script is prematurely terminated. Wrapped value is the termination token.
ErrorTerminated(Position), ErrorTerminated(Dynamic, Position),
/// Run-time error encountered. Wrapped value is the error. /// Run-time error encountered. Wrapped value is the error token.
ErrorRuntime(Dynamic, Position), ErrorRuntime(Dynamic, Position),
/// Breaking out of loops - not an error if within a loop. /// Breaking out of loops - not an error if within a loop.
@ -135,8 +135,8 @@ impl EvalAltResult {
Self::ErrorTooManyOperations(_) => "Too many operations", Self::ErrorTooManyOperations(_) => "Too many operations",
Self::ErrorTooManyModules(_) => "Too many modules imported", Self::ErrorTooManyModules(_) => "Too many modules imported",
Self::ErrorStackOverflow(_) => "Stack overflow", Self::ErrorStackOverflow(_) => "Stack overflow",
Self::ErrorDataTooLarge(_, _, _, _) => "Data size exceeds maximum limit", Self::ErrorDataTooLarge(_, _) => "Data size exceeds maximum limit",
Self::ErrorTerminated(_) => "Script terminated.", Self::ErrorTerminated(_,_) => "Script terminated.",
Self::ErrorRuntime(_, _) => "Runtime error", Self::ErrorRuntime(_, _) => "Runtime error",
Self::LoopBreak(true, _) => "Break statement not inside a loop", Self::LoopBreak(true, _) => "Break statement not inside a loop",
Self::LoopBreak(false, _) => "Continue statement not inside a loop", Self::LoopBreak(false, _) => "Continue statement not inside a loop",
@ -185,7 +185,7 @@ impl fmt::Display for EvalAltResult {
| Self::ErrorTooManyOperations(_) | Self::ErrorTooManyOperations(_)
| Self::ErrorTooManyModules(_) | Self::ErrorTooManyModules(_)
| Self::ErrorStackOverflow(_) | Self::ErrorStackOverflow(_)
| Self::ErrorTerminated(_) => f.write_str(desc)?, | Self::ErrorTerminated(_, _) => f.write_str(desc)?,
Self::ErrorRuntime(d, _) if d.is::<ImmutableString>() => { Self::ErrorRuntime(d, _) if d.is::<ImmutableString>() => {
let s = d.as_str().unwrap(); let s = d.as_str().unwrap();
@ -237,9 +237,7 @@ impl fmt::Display for EvalAltResult {
"String index {} is out of bounds: only {} characters in the string", "String index {} is out of bounds: only {} characters in the string",
index, max index, max
)?, )?,
Self::ErrorDataTooLarge(typ, max, size, _) => { Self::ErrorDataTooLarge(typ, _) => write!(f, "{} exceeds maximum limit", typ)?,
write!(f, "{} ({}) exceeds the maximum limit ({})", typ, size, max)?
}
} }
// Do not write any position if None // Do not write any position if None
@ -297,8 +295,8 @@ impl EvalAltResult {
Self::ErrorTooManyOperations(_) Self::ErrorTooManyOperations(_)
| Self::ErrorTooManyModules(_) | Self::ErrorTooManyModules(_)
| Self::ErrorStackOverflow(_) | Self::ErrorStackOverflow(_)
| Self::ErrorDataTooLarge(_, _, _, _) | Self::ErrorDataTooLarge(_, _)
| Self::ErrorTerminated(_) => false, | Self::ErrorTerminated(_, _) => false,
Self::LoopBreak(_, _) | Self::Return(_, _) => unreachable!(), Self::LoopBreak(_, _) | Self::Return(_, _) => unreachable!(),
} }
@ -313,9 +311,9 @@ impl EvalAltResult {
Self::ErrorTooManyOperations(_) Self::ErrorTooManyOperations(_)
| Self::ErrorTooManyModules(_) | Self::ErrorTooManyModules(_)
| Self::ErrorStackOverflow(_) | Self::ErrorStackOverflow(_)
| Self::ErrorDataTooLarge(_, _, _, _) => true, | Self::ErrorDataTooLarge(_, _) => true,
Self::ErrorTerminated(_) => true, Self::ErrorTerminated(_, _) => true,
Self::LoopBreak(_, _) | Self::Return(_, _) => unreachable!(), Self::LoopBreak(_, _) | Self::Return(_, _) => unreachable!(),
@ -349,8 +347,8 @@ impl EvalAltResult {
| Self::ErrorTooManyOperations(pos) | Self::ErrorTooManyOperations(pos)
| Self::ErrorTooManyModules(pos) | Self::ErrorTooManyModules(pos)
| Self::ErrorStackOverflow(pos) | Self::ErrorStackOverflow(pos)
| Self::ErrorDataTooLarge(_, _, _, pos) | Self::ErrorDataTooLarge(_, pos)
| Self::ErrorTerminated(pos) | Self::ErrorTerminated(_, pos)
| Self::ErrorRuntime(_, pos) | Self::ErrorRuntime(_, pos)
| Self::LoopBreak(_, pos) | Self::LoopBreak(_, pos)
| Self::Return(_, pos) => *pos, | Self::Return(_, pos) => *pos,
@ -383,8 +381,8 @@ impl EvalAltResult {
| Self::ErrorTooManyOperations(pos) | Self::ErrorTooManyOperations(pos)
| Self::ErrorTooManyModules(pos) | Self::ErrorTooManyModules(pos)
| Self::ErrorStackOverflow(pos) | Self::ErrorStackOverflow(pos)
| Self::ErrorDataTooLarge(_, _, _, pos) | Self::ErrorDataTooLarge(_, pos)
| Self::ErrorTerminated(pos) | Self::ErrorTerminated(_, pos)
| Self::ErrorRuntime(_, pos) | Self::ErrorRuntime(_, pos)
| Self::LoopBreak(_, pos) | Self::LoopBreak(_, pos)
| Self::Return(_, pos) => *pos = new_position, | Self::Return(_, pos) => *pos = new_position,