2021-11-23 07:58:54 +01:00
|
|
|
#![cfg(not(feature = "no_index"))]
|
|
|
|
#![allow(non_snake_case)]
|
|
|
|
|
|
|
|
use crate::plugin::*;
|
2021-12-15 05:06:17 +01:00
|
|
|
use crate::{
|
|
|
|
def_package, Blob, Dynamic, EvalAltResult, ExclusiveRange, InclusiveRange, NativeCallContext,
|
|
|
|
Position, INT,
|
|
|
|
};
|
2021-11-23 07:58:54 +01:00
|
|
|
#[cfg(feature = "no_std")]
|
|
|
|
use std::prelude::v1::*;
|
|
|
|
use std::{any::TypeId, mem};
|
|
|
|
|
2021-12-12 09:29:54 +01:00
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
use crate::FLOAT;
|
|
|
|
|
2021-11-23 07:58:54 +01:00
|
|
|
def_package!(crate:BasicBlobPackage:"Basic BLOB utilities.", lib, {
|
|
|
|
lib.standard = true;
|
|
|
|
|
|
|
|
combine_with_exported_module!(lib, "blob", blob_functions);
|
|
|
|
|
|
|
|
// Register blob iterator
|
|
|
|
lib.set_iterable::<Blob>();
|
|
|
|
});
|
|
|
|
|
|
|
|
#[export_module]
|
|
|
|
mod blob_functions {
|
|
|
|
pub fn blob() -> Blob {
|
|
|
|
Blob::new()
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "blob", return_raw)]
|
|
|
|
pub fn blob_with_capacity(
|
|
|
|
ctx: NativeCallContext,
|
|
|
|
len: INT,
|
|
|
|
) -> Result<Blob, Box<EvalAltResult>> {
|
|
|
|
blob_with_capacity_and_value(ctx, len, 0)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "blob", return_raw)]
|
|
|
|
pub fn blob_with_capacity_and_value(
|
2021-11-23 11:10:01 +01:00
|
|
|
ctx: NativeCallContext,
|
2021-11-23 07:58:54 +01:00
|
|
|
len: INT,
|
|
|
|
value: INT,
|
|
|
|
) -> Result<Blob, Box<EvalAltResult>> {
|
|
|
|
let len = if len < 0 { 0 } else { len as usize };
|
2021-11-23 11:10:01 +01:00
|
|
|
let _ctx = ctx;
|
2021-11-23 07:58:54 +01:00
|
|
|
|
|
|
|
// Check if blob will be over max size limit
|
|
|
|
#[cfg(not(feature = "unchecked"))]
|
|
|
|
if _ctx.engine().max_array_size() > 0 && len > _ctx.engine().max_array_size() {
|
|
|
|
return Err(EvalAltResult::ErrorDataTooLarge(
|
|
|
|
"Size of BLOB".to_string(),
|
|
|
|
Position::NONE,
|
|
|
|
)
|
|
|
|
.into());
|
|
|
|
}
|
|
|
|
|
2021-11-23 11:10:01 +01:00
|
|
|
let mut blob = Blob::new();
|
2021-12-07 12:03:04 +01:00
|
|
|
blob.resize(len, (value & 0x00ff) as u8);
|
2021-11-23 07:58:54 +01:00
|
|
|
Ok(blob)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "len", get = "len", pure)]
|
|
|
|
pub fn len(blob: &mut Blob) -> INT {
|
|
|
|
blob.len() as INT
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "push", name = "+=")]
|
|
|
|
pub fn push(blob: &mut Blob, item: INT) {
|
2021-12-07 12:03:04 +01:00
|
|
|
let item = (item & 0x00ff) as u8;
|
2021-11-23 07:58:54 +01:00
|
|
|
blob.push(item);
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "append", name = "+=")]
|
|
|
|
pub fn append(blob: &mut Blob, y: Blob) {
|
|
|
|
if !y.is_empty() {
|
|
|
|
if blob.is_empty() {
|
|
|
|
*blob = y;
|
|
|
|
} else {
|
|
|
|
blob.extend(y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "+")]
|
|
|
|
pub fn concat(mut blob: Blob, y: Blob) -> Blob {
|
|
|
|
if !y.is_empty() {
|
|
|
|
if blob.is_empty() {
|
|
|
|
blob = y;
|
|
|
|
} else {
|
|
|
|
blob.extend(y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
blob
|
|
|
|
}
|
|
|
|
pub fn insert(blob: &mut Blob, position: INT, item: INT) {
|
2021-12-07 12:03:04 +01:00
|
|
|
let item = (item & 0x00ff) as u8;
|
2021-11-23 07:58:54 +01:00
|
|
|
|
|
|
|
if blob.is_empty() {
|
|
|
|
blob.push(item);
|
|
|
|
} else if position < 0 {
|
|
|
|
if let Some(n) = position.checked_abs() {
|
|
|
|
if n as usize > blob.len() {
|
|
|
|
blob.insert(0, item);
|
|
|
|
} else {
|
|
|
|
blob.insert(blob.len() - n as usize, item);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
blob.insert(0, item);
|
|
|
|
}
|
|
|
|
} else if (position as usize) >= blob.len() {
|
|
|
|
blob.push(item);
|
|
|
|
} else {
|
|
|
|
blob.insert(position as usize, item);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#[rhai_fn(return_raw)]
|
|
|
|
pub fn pad(
|
2021-11-23 11:10:01 +01:00
|
|
|
ctx: NativeCallContext,
|
2021-11-23 07:58:54 +01:00
|
|
|
blob: &mut Blob,
|
|
|
|
len: INT,
|
|
|
|
item: INT,
|
|
|
|
) -> Result<(), Box<EvalAltResult>> {
|
|
|
|
if len <= 0 {
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
|
2021-12-07 12:03:04 +01:00
|
|
|
let item = (item & 0x00ff) as u8;
|
2021-11-23 11:10:01 +01:00
|
|
|
let _ctx = ctx;
|
2021-11-23 07:58:54 +01:00
|
|
|
|
|
|
|
// Check if blob will be over max size limit
|
|
|
|
#[cfg(not(feature = "unchecked"))]
|
|
|
|
if _ctx.engine().max_array_size() > 0 && (len as usize) > _ctx.engine().max_array_size() {
|
|
|
|
return Err(EvalAltResult::ErrorDataTooLarge(
|
|
|
|
"Size of BLOB".to_string(),
|
|
|
|
Position::NONE,
|
|
|
|
)
|
|
|
|
.into());
|
|
|
|
}
|
|
|
|
|
|
|
|
if len as usize > blob.len() {
|
|
|
|
blob.resize(len as usize, item);
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
pub fn pop(blob: &mut Blob) -> INT {
|
|
|
|
if blob.is_empty() {
|
|
|
|
0
|
|
|
|
} else {
|
|
|
|
blob.pop().map_or_else(|| 0, |v| v as INT)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pub fn shift(blob: &mut Blob) -> INT {
|
|
|
|
if blob.is_empty() {
|
|
|
|
0
|
|
|
|
} else {
|
|
|
|
blob.remove(0) as INT
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pub fn remove(blob: &mut Blob, len: INT) -> INT {
|
|
|
|
if len < 0 || (len as usize) >= blob.len() {
|
|
|
|
0
|
|
|
|
} else {
|
|
|
|
blob.remove(len as usize) as INT
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pub fn clear(blob: &mut Blob) {
|
|
|
|
if !blob.is_empty() {
|
|
|
|
blob.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pub fn truncate(blob: &mut Blob, len: INT) {
|
|
|
|
if !blob.is_empty() {
|
|
|
|
if len >= 0 {
|
|
|
|
blob.truncate(len as usize);
|
|
|
|
} else {
|
|
|
|
blob.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pub fn chop(blob: &mut Blob, len: INT) {
|
|
|
|
if !blob.is_empty() && len as usize >= blob.len() {
|
|
|
|
if len >= 0 {
|
|
|
|
blob.drain(0..blob.len() - len as usize);
|
|
|
|
} else {
|
|
|
|
blob.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pub fn reverse(blob: &mut Blob) {
|
|
|
|
if !blob.is_empty() {
|
|
|
|
blob.reverse();
|
|
|
|
}
|
|
|
|
}
|
2021-12-15 05:06:17 +01:00
|
|
|
#[rhai_fn(name = "splice")]
|
|
|
|
pub fn splice_range(blob: &mut Blob, range: ExclusiveRange, replace: Blob) {
|
|
|
|
let start = INT::max(range.start, 0);
|
|
|
|
let end = INT::max(range.end, start);
|
|
|
|
splice(blob, start, end - start, replace)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "splice")]
|
|
|
|
pub fn splice_range_inclusive(blob: &mut Blob, range: InclusiveRange, replace: Blob) {
|
|
|
|
let start = INT::max(*range.start(), 0);
|
|
|
|
let end = INT::max(*range.end(), start);
|
|
|
|
splice(blob, start, end - start + 1, replace)
|
|
|
|
}
|
2021-11-23 07:58:54 +01:00
|
|
|
pub fn splice(blob: &mut Blob, start: INT, len: INT, replace: Blob) {
|
|
|
|
if blob.is_empty() {
|
|
|
|
*blob = replace;
|
|
|
|
return;
|
|
|
|
}
|
2021-12-12 10:26:15 +01:00
|
|
|
let blob_len = blob.len();
|
2021-11-23 07:58:54 +01:00
|
|
|
|
|
|
|
let start = if start < 0 {
|
|
|
|
start
|
|
|
|
.checked_abs()
|
2021-12-12 09:29:54 +01:00
|
|
|
.map_or(0, |n| blob_len - (n as usize).min(blob_len))
|
2021-12-12 10:26:15 +01:00
|
|
|
} else if start as usize >= blob_len {
|
2021-11-23 07:58:54 +01:00
|
|
|
blob.extend(replace.into_iter());
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
start as usize
|
|
|
|
};
|
|
|
|
|
|
|
|
let len = if len < 0 {
|
|
|
|
0
|
2021-12-12 10:26:15 +01:00
|
|
|
} else if len as usize > blob_len - start {
|
|
|
|
blob_len - start
|
2021-11-23 07:58:54 +01:00
|
|
|
} else {
|
|
|
|
len as usize
|
|
|
|
};
|
|
|
|
|
|
|
|
blob.splice(start..start + len, replace.into_iter());
|
|
|
|
}
|
2021-12-15 05:06:17 +01:00
|
|
|
#[rhai_fn(name = "extract")]
|
|
|
|
pub fn extract_range(blob: &mut Blob, range: ExclusiveRange) -> Blob {
|
|
|
|
let start = INT::max(range.start, 0);
|
|
|
|
let end = INT::max(range.end, start);
|
|
|
|
extract(blob, start, end - start)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "extract")]
|
|
|
|
pub fn extract_range_inclusive(blob: &mut Blob, range: InclusiveRange) -> Blob {
|
|
|
|
let start = INT::max(*range.start(), 0);
|
|
|
|
let end = INT::max(*range.end(), start);
|
|
|
|
extract(blob, start, end - start + 1)
|
|
|
|
}
|
2021-11-23 07:58:54 +01:00
|
|
|
pub fn extract(blob: &mut Blob, start: INT, len: INT) -> Blob {
|
|
|
|
if blob.is_empty() || len <= 0 {
|
|
|
|
return Blob::new();
|
|
|
|
}
|
2021-12-12 10:26:15 +01:00
|
|
|
let blob_len = blob.len();
|
2021-11-23 07:58:54 +01:00
|
|
|
|
|
|
|
let start = if start < 0 {
|
|
|
|
start
|
|
|
|
.checked_abs()
|
2021-12-12 09:29:54 +01:00
|
|
|
.map_or(0, |n| blob_len - (n as usize).min(blob_len))
|
2021-12-12 10:26:15 +01:00
|
|
|
} else if start as usize >= blob_len {
|
2021-11-23 07:58:54 +01:00
|
|
|
return Blob::new();
|
|
|
|
} else {
|
|
|
|
start as usize
|
|
|
|
};
|
|
|
|
|
2021-12-12 10:26:15 +01:00
|
|
|
let len = if len as usize > blob_len - start {
|
|
|
|
blob_len - start
|
2021-11-23 07:58:54 +01:00
|
|
|
} else {
|
|
|
|
len as usize
|
|
|
|
};
|
|
|
|
|
2021-12-12 10:26:15 +01:00
|
|
|
blob[start..start + len].to_vec()
|
2021-11-23 07:58:54 +01:00
|
|
|
}
|
|
|
|
#[rhai_fn(name = "extract")]
|
|
|
|
pub fn extract_tail(blob: &mut Blob, start: INT) -> Blob {
|
2021-12-12 10:26:15 +01:00
|
|
|
extract(blob, start, INT::MAX)
|
2021-11-23 07:58:54 +01:00
|
|
|
}
|
|
|
|
#[rhai_fn(name = "split")]
|
|
|
|
pub fn split_at(blob: &mut Blob, start: INT) -> Blob {
|
|
|
|
if blob.is_empty() {
|
|
|
|
Blob::new()
|
|
|
|
} else if start < 0 {
|
|
|
|
if let Some(n) = start.checked_abs() {
|
|
|
|
if n as usize > blob.len() {
|
|
|
|
mem::take(blob)
|
|
|
|
} else {
|
|
|
|
let mut result = Blob::new();
|
|
|
|
result.extend(blob.drain(blob.len() - n as usize..));
|
|
|
|
result
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
mem::take(blob)
|
|
|
|
}
|
|
|
|
} else if start as usize >= blob.len() {
|
|
|
|
Blob::new()
|
|
|
|
} else {
|
|
|
|
let mut result = Blob::new();
|
|
|
|
result.extend(blob.drain(start as usize..));
|
|
|
|
result
|
|
|
|
}
|
|
|
|
}
|
2021-12-15 05:06:17 +01:00
|
|
|
#[rhai_fn(name = "drain")]
|
|
|
|
pub fn drain_range(blob: &mut Blob, range: ExclusiveRange) -> Blob {
|
|
|
|
let start = INT::max(range.start, 0);
|
|
|
|
let end = INT::max(range.end, start);
|
|
|
|
drain(blob, start, end - start)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "drain")]
|
|
|
|
pub fn drain_range_inclusive(blob: &mut Blob, range: InclusiveRange) -> Blob {
|
|
|
|
let start = INT::max(*range.start(), 0);
|
|
|
|
let end = INT::max(*range.end(), start);
|
|
|
|
drain(blob, start, end - start + 1)
|
|
|
|
}
|
2021-11-23 16:01:14 +01:00
|
|
|
pub fn drain(blob: &mut Blob, start: INT, len: INT) -> Blob {
|
2021-11-23 07:58:54 +01:00
|
|
|
if blob.is_empty() || len <= 0 {
|
|
|
|
return Blob::new();
|
|
|
|
}
|
2021-12-12 10:26:15 +01:00
|
|
|
let blob_len = blob.len();
|
2021-11-23 07:58:54 +01:00
|
|
|
|
|
|
|
let start = if start < 0 {
|
|
|
|
start
|
|
|
|
.checked_abs()
|
2021-12-12 09:29:54 +01:00
|
|
|
.map_or(0, |n| blob_len - (n as usize).min(blob_len))
|
2021-12-12 10:26:15 +01:00
|
|
|
} else if start as usize >= blob_len {
|
2021-11-23 07:58:54 +01:00
|
|
|
return Blob::new();
|
|
|
|
} else {
|
|
|
|
start as usize
|
|
|
|
};
|
|
|
|
|
2021-12-12 10:26:15 +01:00
|
|
|
let len = if len as usize > blob_len - start {
|
|
|
|
blob_len - start
|
2021-11-23 07:58:54 +01:00
|
|
|
} else {
|
|
|
|
len as usize
|
|
|
|
};
|
|
|
|
|
|
|
|
blob.drain(start..start + len).collect()
|
|
|
|
}
|
2021-12-15 05:06:17 +01:00
|
|
|
#[rhai_fn(name = "retain")]
|
|
|
|
pub fn retain_range(blob: &mut Blob, range: ExclusiveRange) -> Blob {
|
|
|
|
let start = INT::max(range.start, 0);
|
|
|
|
let end = INT::max(range.end, start);
|
|
|
|
retain(blob, start, end - start)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "retain")]
|
|
|
|
pub fn retain_range_inclusive(blob: &mut Blob, range: InclusiveRange) -> Blob {
|
|
|
|
let start = INT::max(*range.start(), 0);
|
|
|
|
let end = INT::max(*range.end(), start);
|
|
|
|
retain(blob, start, end - start + 1)
|
|
|
|
}
|
2021-11-23 16:01:14 +01:00
|
|
|
pub fn retain(blob: &mut Blob, start: INT, len: INT) -> Blob {
|
2021-11-23 07:58:54 +01:00
|
|
|
if blob.is_empty() || len <= 0 {
|
|
|
|
return Blob::new();
|
|
|
|
}
|
2021-12-12 10:26:15 +01:00
|
|
|
let blob_len = blob.len();
|
2021-11-23 07:58:54 +01:00
|
|
|
|
|
|
|
let start = if start < 0 {
|
|
|
|
start
|
|
|
|
.checked_abs()
|
2021-12-12 09:29:54 +01:00
|
|
|
.map_or(0, |n| blob_len - (n as usize).min(blob_len))
|
2021-12-12 10:26:15 +01:00
|
|
|
} else if start as usize >= blob_len {
|
2021-11-23 07:58:54 +01:00
|
|
|
return mem::take(blob);
|
|
|
|
} else {
|
|
|
|
start as usize
|
|
|
|
};
|
|
|
|
|
2021-12-12 10:26:15 +01:00
|
|
|
let len = if len as usize > blob_len - start {
|
|
|
|
blob_len - start
|
2021-11-23 07:58:54 +01:00
|
|
|
} else {
|
|
|
|
len as usize
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut drained: Blob = blob.drain(..start).collect();
|
|
|
|
drained.extend(blob.drain(len..));
|
|
|
|
|
|
|
|
drained
|
|
|
|
}
|
2021-12-12 09:29:54 +01:00
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn parse_int(blob: &mut Blob, start: INT, len: INT, is_le: bool) -> INT {
|
|
|
|
if blob.is_empty() || len <= 0 {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
let blob_len = blob.len();
|
|
|
|
|
|
|
|
let start = if start < 0 {
|
|
|
|
start
|
|
|
|
.checked_abs()
|
|
|
|
.map_or(0, |n| blob_len - (n as usize).min(blob_len))
|
|
|
|
} else if start as usize >= blob_len {
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
start as usize
|
|
|
|
};
|
|
|
|
|
|
|
|
let len = if len as usize > blob_len - start {
|
|
|
|
blob_len - start
|
|
|
|
} else {
|
|
|
|
len as usize
|
|
|
|
};
|
|
|
|
|
|
|
|
const INT_BYTES: usize = mem::size_of::<INT>();
|
|
|
|
|
|
|
|
let len = usize::min(len, INT_BYTES);
|
|
|
|
|
|
|
|
let mut buf = [0_u8; INT_BYTES];
|
|
|
|
|
|
|
|
buf[..len].copy_from_slice(&blob[start..][..len]);
|
|
|
|
|
|
|
|
if is_le {
|
|
|
|
INT::from_le_bytes(buf)
|
|
|
|
} else {
|
|
|
|
INT::from_be_bytes(buf)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-15 05:06:17 +01:00
|
|
|
#[rhai_fn(name = "parse_le_int")]
|
|
|
|
pub fn parse_le_int_range(blob: &mut Blob, range: ExclusiveRange) -> INT {
|
|
|
|
let start = INT::max(range.start, 0);
|
|
|
|
let end = INT::max(range.end, start);
|
|
|
|
parse_le_int(blob, start, end - start)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "parse_le_int")]
|
|
|
|
pub fn parse_le_int_range_inclusive(blob: &mut Blob, range: InclusiveRange) -> INT {
|
|
|
|
let start = INT::max(*range.start(), 0);
|
|
|
|
let end = INT::max(*range.end(), start);
|
|
|
|
parse_le_int(blob, start, end - start + 1)
|
|
|
|
}
|
2021-12-12 09:29:54 +01:00
|
|
|
pub fn parse_le_int(blob: &mut Blob, start: INT, len: INT) -> INT {
|
|
|
|
parse_int(blob, start, len, true)
|
|
|
|
}
|
2021-12-15 05:06:17 +01:00
|
|
|
#[rhai_fn(name = "parse_be_int")]
|
|
|
|
pub fn parse_be_int_range(blob: &mut Blob, range: ExclusiveRange) -> INT {
|
|
|
|
let start = INT::max(range.start, 0);
|
|
|
|
let end = INT::max(range.end, start);
|
|
|
|
parse_be_int(blob, start, end - start)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "parse_be_int")]
|
|
|
|
pub fn parse_be_int_range_inclusive(blob: &mut Blob, range: InclusiveRange) -> INT {
|
|
|
|
let start = INT::max(*range.start(), 0);
|
|
|
|
let end = INT::max(*range.end(), start);
|
|
|
|
parse_be_int(blob, start, end - start + 1)
|
|
|
|
}
|
2021-12-12 09:29:54 +01:00
|
|
|
pub fn parse_be_int(blob: &mut Blob, start: INT, len: INT) -> INT {
|
|
|
|
parse_int(blob, start, len, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn write_int(blob: &mut Blob, start: INT, len: INT, value: INT, is_le: bool) {
|
|
|
|
if blob.is_empty() || len <= 0 {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
let blob_len = blob.len();
|
|
|
|
|
|
|
|
let start = if start < 0 {
|
|
|
|
start
|
|
|
|
.checked_abs()
|
|
|
|
.map_or(0, |n| blob_len - (n as usize).min(blob_len))
|
|
|
|
} else if start as usize >= blob_len {
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
start as usize
|
|
|
|
};
|
|
|
|
|
|
|
|
let len = if len as usize > blob_len - start {
|
|
|
|
blob_len - start
|
|
|
|
} else {
|
|
|
|
len as usize
|
|
|
|
};
|
|
|
|
|
|
|
|
const INT_BYTES: usize = mem::size_of::<INT>();
|
|
|
|
|
|
|
|
let len = usize::min(len, INT_BYTES);
|
|
|
|
|
|
|
|
let mut buf = [0_u8; INT_BYTES];
|
|
|
|
|
|
|
|
buf.copy_from_slice(&if is_le {
|
|
|
|
value.to_le_bytes()
|
|
|
|
} else {
|
|
|
|
value.to_be_bytes()
|
|
|
|
});
|
|
|
|
|
|
|
|
blob[start..][..len].copy_from_slice(&buf[..len]);
|
|
|
|
}
|
2021-12-15 05:06:17 +01:00
|
|
|
#[rhai_fn(name = "write_le_int")]
|
|
|
|
pub fn write_le_int_range(blob: &mut Blob, range: ExclusiveRange, value: INT) {
|
|
|
|
let start = INT::max(range.start, 0);
|
|
|
|
let end = INT::max(range.end, start);
|
|
|
|
write_le_int(blob, start, end - start, value)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "write_le_int")]
|
|
|
|
pub fn write_le_int_range_inclusive(blob: &mut Blob, range: InclusiveRange, value: INT) {
|
|
|
|
let start = INT::max(*range.start(), 0);
|
|
|
|
let end = INT::max(*range.end(), start);
|
|
|
|
write_le_int(blob, start, end - start + 1, value)
|
|
|
|
}
|
2021-12-12 09:29:54 +01:00
|
|
|
#[rhai_fn(name = "write_le")]
|
|
|
|
pub fn write_le_int(blob: &mut Blob, start: INT, len: INT, value: INT) {
|
|
|
|
write_int(blob, start, len, value, true)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "write_be")]
|
2021-12-15 05:06:17 +01:00
|
|
|
pub fn write_be_int_range(blob: &mut Blob, range: ExclusiveRange, value: INT) {
|
|
|
|
let start = INT::max(range.start, 0);
|
|
|
|
let end = INT::max(range.end, start);
|
|
|
|
write_be_int(blob, start, end - start, value)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "write_be")]
|
|
|
|
pub fn write_be_int_range_inclusive(blob: &mut Blob, range: InclusiveRange, value: INT) {
|
|
|
|
let start = INT::max(*range.start(), 0);
|
|
|
|
let end = INT::max(*range.end(), start);
|
|
|
|
write_be_int(blob, start, end - start + 1, value)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "write_be")]
|
2021-12-12 09:29:54 +01:00
|
|
|
pub fn write_be_int(blob: &mut Blob, start: INT, len: INT, value: INT) {
|
|
|
|
write_int(blob, start, len, value, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
#[inline]
|
|
|
|
fn parse_float(blob: &mut Blob, start: INT, len: INT, is_le: bool) -> FLOAT {
|
|
|
|
if blob.is_empty() || len <= 0 {
|
|
|
|
return 0.0;
|
|
|
|
}
|
|
|
|
let blob_len = blob.len();
|
|
|
|
|
|
|
|
let start = if start < 0 {
|
|
|
|
start
|
|
|
|
.checked_abs()
|
|
|
|
.map_or(0, |n| blob_len - (n as usize).min(blob_len))
|
|
|
|
} else if start as usize >= blob_len {
|
|
|
|
return 0.0;
|
|
|
|
} else {
|
|
|
|
start as usize
|
|
|
|
};
|
|
|
|
|
|
|
|
let len = if len as usize > blob_len - start {
|
|
|
|
blob_len - start
|
|
|
|
} else {
|
|
|
|
len as usize
|
|
|
|
};
|
|
|
|
|
|
|
|
const FLOAT_BYTES: usize = mem::size_of::<FLOAT>();
|
|
|
|
|
|
|
|
let len = usize::min(len, FLOAT_BYTES);
|
|
|
|
|
|
|
|
let mut buf = [0_u8; FLOAT_BYTES];
|
|
|
|
|
|
|
|
buf[..len].copy_from_slice(&blob[start..][..len]);
|
|
|
|
|
|
|
|
if is_le {
|
|
|
|
FLOAT::from_le_bytes(buf)
|
|
|
|
} else {
|
|
|
|
FLOAT::from_be_bytes(buf)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-15 05:06:17 +01:00
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
#[rhai_fn(name = "parse_le_float")]
|
|
|
|
pub fn parse_le_float_range(blob: &mut Blob, range: ExclusiveRange) -> FLOAT {
|
|
|
|
let start = INT::max(range.start, 0);
|
|
|
|
let end = INT::max(range.end, start);
|
|
|
|
parse_le_float(blob, start, end - start)
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
#[rhai_fn(name = "parse_le_float")]
|
|
|
|
pub fn parse_le_float_range_inclusive(blob: &mut Blob, range: InclusiveRange) -> FLOAT {
|
|
|
|
let start = INT::max(*range.start(), 0);
|
|
|
|
let end = INT::max(*range.end(), start);
|
|
|
|
parse_le_float(blob, start, end - start + 1)
|
|
|
|
}
|
2021-12-12 09:29:54 +01:00
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
pub fn parse_le_float(blob: &mut Blob, start: INT, len: INT) -> FLOAT {
|
|
|
|
parse_float(blob, start, len, true)
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
2021-12-15 05:06:17 +01:00
|
|
|
#[rhai_fn(name = "parse_be_float")]
|
|
|
|
pub fn parse_be_float_range(blob: &mut Blob, range: ExclusiveRange) -> FLOAT {
|
|
|
|
let start = INT::max(range.start, 0);
|
|
|
|
let end = INT::max(range.end, start);
|
|
|
|
parse_be_float(blob, start, end - start)
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
#[rhai_fn(name = "parse_be_float")]
|
|
|
|
pub fn parse_be_float_range_inclusive(blob: &mut Blob, range: InclusiveRange) -> FLOAT {
|
|
|
|
let start = INT::max(*range.start(), 0);
|
|
|
|
let end = INT::max(*range.end(), start);
|
|
|
|
parse_be_float(blob, start, end - start + 1)
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
2021-12-12 09:29:54 +01:00
|
|
|
pub fn parse_be_float(blob: &mut Blob, start: INT, len: INT) -> FLOAT {
|
|
|
|
parse_float(blob, start, len, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
#[inline]
|
|
|
|
fn write_float(blob: &mut Blob, start: INT, len: INT, value: FLOAT, is_le: bool) {
|
|
|
|
if blob.is_empty() || len <= 0 {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
let blob_len = blob.len();
|
|
|
|
|
|
|
|
let start = if start < 0 {
|
|
|
|
start
|
|
|
|
.checked_abs()
|
|
|
|
.map_or(0, |n| blob_len - (n as usize).min(blob_len))
|
|
|
|
} else if start as usize >= blob_len {
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
start as usize
|
|
|
|
};
|
|
|
|
|
|
|
|
let len = if len as usize > blob_len - start {
|
|
|
|
blob_len - start
|
|
|
|
} else {
|
|
|
|
len as usize
|
|
|
|
};
|
|
|
|
|
|
|
|
const FLOAT_BYTES: usize = mem::size_of::<FLOAT>();
|
|
|
|
|
|
|
|
let len = usize::min(len, FLOAT_BYTES);
|
|
|
|
|
|
|
|
let mut buf = [0_u8; FLOAT_BYTES];
|
|
|
|
|
|
|
|
buf.copy_from_slice(&if is_le {
|
|
|
|
value.to_le_bytes()
|
|
|
|
} else {
|
|
|
|
value.to_be_bytes()
|
|
|
|
});
|
|
|
|
|
|
|
|
blob[start..][..len].copy_from_slice(&buf[..len]);
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
2021-12-15 05:06:17 +01:00
|
|
|
#[rhai_fn(name = "write_le_float")]
|
|
|
|
pub fn write_le_float_range(blob: &mut Blob, range: ExclusiveRange, value: FLOAT) {
|
|
|
|
let start = INT::max(range.start, 0);
|
|
|
|
let end = INT::max(range.end, start);
|
|
|
|
write_le_float(blob, start, end - start, value)
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
#[rhai_fn(name = "write_le_float")]
|
|
|
|
pub fn write_le_float_range_inclusive(blob: &mut Blob, range: InclusiveRange, value: FLOAT) {
|
|
|
|
let start = INT::max(*range.start(), 0);
|
|
|
|
let end = INT::max(*range.end(), start);
|
|
|
|
write_le_float(blob, start, end - start + 1, value)
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
2021-12-12 09:29:54 +01:00
|
|
|
#[rhai_fn(name = "write_le")]
|
|
|
|
pub fn write_le_float(blob: &mut Blob, start: INT, len: INT, value: FLOAT) {
|
|
|
|
write_float(blob, start, len, value, true)
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
#[rhai_fn(name = "write_be")]
|
2021-12-15 05:06:17 +01:00
|
|
|
pub fn write_be_float_range(blob: &mut Blob, range: ExclusiveRange, value: FLOAT) {
|
|
|
|
let start = INT::max(range.start, 0);
|
|
|
|
let end = INT::max(range.end, start);
|
|
|
|
write_be_float(blob, start, end - start, value)
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
#[rhai_fn(name = "write_be")]
|
|
|
|
pub fn write_be_float_range_inclusive(blob: &mut Blob, range: InclusiveRange, value: FLOAT) {
|
|
|
|
let start = INT::max(*range.start(), 0);
|
|
|
|
let end = INT::max(*range.end(), start);
|
|
|
|
write_be_float(blob, start, end - start + 1, value)
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
#[rhai_fn(name = "write_be")]
|
2021-12-12 09:29:54 +01:00
|
|
|
pub fn write_be_float(blob: &mut Blob, start: INT, len: INT, value: FLOAT) {
|
|
|
|
write_float(blob, start, len, value, false)
|
|
|
|
}
|
2021-11-23 07:58:54 +01:00
|
|
|
}
|