Refine calc_index API.
This commit is contained in:
parent
a8ec984b0f
commit
2a8a8c00f5
@ -790,8 +790,9 @@ impl Engine {
|
|||||||
.as_int()
|
.as_int()
|
||||||
.map_err(|typ| self.make_type_mismatch_err::<crate::INT>(typ, pos))?;
|
.map_err(|typ| self.make_type_mismatch_err::<crate::INT>(typ, pos))?;
|
||||||
let len = arr.len();
|
let len = arr.len();
|
||||||
let arr_idx =
|
let arr_idx = calc_index(len, index, true, || {
|
||||||
calc_index(len, index, true, || ERR::ErrorArrayBounds(len, index, pos))?;
|
ERR::ErrorArrayBounds(len, index, pos).into()
|
||||||
|
})?;
|
||||||
|
|
||||||
Ok(arr.get_mut(arr_idx).map(Target::from).unwrap())
|
Ok(arr.get_mut(arr_idx).map(Target::from).unwrap())
|
||||||
}
|
}
|
||||||
@ -803,8 +804,9 @@ impl Engine {
|
|||||||
.as_int()
|
.as_int()
|
||||||
.map_err(|typ| self.make_type_mismatch_err::<crate::INT>(typ, pos))?;
|
.map_err(|typ| self.make_type_mismatch_err::<crate::INT>(typ, pos))?;
|
||||||
let len = arr.len();
|
let len = arr.len();
|
||||||
let arr_idx =
|
let arr_idx = calc_index(len, index, true, || {
|
||||||
calc_index(len, index, true, || ERR::ErrorArrayBounds(len, index, pos))?;
|
ERR::ErrorArrayBounds(len, index, pos).into()
|
||||||
|
})?;
|
||||||
|
|
||||||
let value = arr.get(arr_idx).map(|&v| (v as crate::INT).into()).unwrap();
|
let value = arr.get(arr_idx).map(|&v| (v as crate::INT).into()).unwrap();
|
||||||
|
|
||||||
@ -844,10 +846,10 @@ impl Engine {
|
|||||||
let end = range.end;
|
let end = range.end;
|
||||||
|
|
||||||
let start = calc_index(BITS, start, false, || {
|
let start = calc_index(BITS, start, false, || {
|
||||||
ERR::ErrorBitFieldBounds(BITS, start, pos)
|
ERR::ErrorBitFieldBounds(BITS, start, pos).into()
|
||||||
})?;
|
})?;
|
||||||
let end = calc_index(BITS, end, false, || {
|
let end = calc_index(BITS, end, false, || {
|
||||||
ERR::ErrorBitFieldBounds(BITS, end, pos)
|
ERR::ErrorBitFieldBounds(BITS, end, pos).into()
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if end <= start {
|
if end <= start {
|
||||||
@ -869,10 +871,10 @@ impl Engine {
|
|||||||
let end = *range.end();
|
let end = *range.end();
|
||||||
|
|
||||||
let start = calc_index(BITS, start, false, || {
|
let start = calc_index(BITS, start, false, || {
|
||||||
ERR::ErrorBitFieldBounds(BITS, start, pos)
|
ERR::ErrorBitFieldBounds(BITS, start, pos).into()
|
||||||
})?;
|
})?;
|
||||||
let end = calc_index(BITS, end, false, || {
|
let end = calc_index(BITS, end, false, || {
|
||||||
ERR::ErrorBitFieldBounds(BITS, end, pos)
|
ERR::ErrorBitFieldBounds(BITS, end, pos).into()
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if end < start {
|
if end < start {
|
||||||
@ -913,7 +915,7 @@ impl Engine {
|
|||||||
const BITS: usize = std::mem::size_of::<crate::INT>() * 8;
|
const BITS: usize = std::mem::size_of::<crate::INT>() * 8;
|
||||||
|
|
||||||
let bit = calc_index(BITS, index, true, || {
|
let bit = calc_index(BITS, index, true, || {
|
||||||
ERR::ErrorBitFieldBounds(BITS, index, pos)
|
ERR::ErrorBitFieldBounds(BITS, index, pos).into()
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let bit_value = (*value & (1 << bit)) != 0;
|
let bit_value = (*value & (1 << bit)) != 0;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Type to hold a mutable reference to the target of an evaluation.
|
//! Type to hold a mutable reference to the target of an evaluation.
|
||||||
|
|
||||||
use crate::types::dynamic::Variant;
|
use crate::types::dynamic::Variant;
|
||||||
use crate::{Dynamic, EvalAltResult, RhaiResultOf, INT};
|
use crate::{Dynamic, RhaiResultOf, INT};
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
@ -38,35 +38,35 @@ pub fn calc_offset_len(length: usize, start: INT, len: INT) -> (usize, usize) {
|
|||||||
//
|
//
|
||||||
// Negative starting positions count from the end.
|
// Negative starting positions count from the end.
|
||||||
//
|
//
|
||||||
// Values going over bounds call the provided closure to create an error.
|
// Values going over bounds call the provided closure to return a default value or an error.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn calc_index(
|
pub fn calc_index<E>(
|
||||||
length: usize,
|
length: usize,
|
||||||
start: INT,
|
start: INT,
|
||||||
negative_count_from_end: bool,
|
negative_count_from_end: bool,
|
||||||
err: impl Fn() -> EvalAltResult,
|
err: impl Fn() -> Result<usize, E>,
|
||||||
) -> RhaiResultOf<usize> {
|
) -> Result<usize, E> {
|
||||||
if start < 0 {
|
if start < 0 {
|
||||||
if negative_count_from_end {
|
if negative_count_from_end {
|
||||||
// Count from end if negative
|
// Count from end if negative
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
return start
|
return match start.checked_abs() {
|
||||||
.checked_abs()
|
Some(positive_start) => {
|
||||||
.ok_or_else(|| err().into())
|
|
||||||
.and_then(|positive_start| {
|
|
||||||
if (positive_start as usize) > length {
|
if (positive_start as usize) > length {
|
||||||
Err(err().into())
|
err()
|
||||||
} else {
|
} else {
|
||||||
Ok(length - (positive_start as usize))
|
Ok(length - (positive_start as usize))
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
None => err(),
|
||||||
|
};
|
||||||
#[cfg(feature = "unchecked")]
|
#[cfg(feature = "unchecked")]
|
||||||
return Ok(length - (start.abs() as usize));
|
return Ok(length - (start.abs() as usize));
|
||||||
} else {
|
} else {
|
||||||
Err(err().into())
|
err()
|
||||||
}
|
}
|
||||||
} else if start as usize >= length {
|
} else if start as usize >= length {
|
||||||
Err(err().into())
|
err()
|
||||||
} else {
|
} else {
|
||||||
Ok(start as usize)
|
Ok(start as usize)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user