diff --git a/src/packages/blob_basic.rs b/src/packages/blob_basic.rs index 2adf04f8..8e70d94f 100644 --- a/src/packages/blob_basic.rs +++ b/src/packages/blob_basic.rs @@ -24,7 +24,7 @@ def_package!(crate:BasicBlobPackage:"Basic BLOB utilities.", lib, { #[export_module] mod blob_functions { - pub fn blob() -> Blob { + pub const fn blob() -> Blob { Blob::new() } #[rhai_fn(name = "blob", return_raw)] @@ -54,7 +54,7 @@ mod blob_functions { } let mut blob = Blob::new(); - blob.resize(len, (value & 0x00ff) as u8); + blob.resize(len, (value & 0x000000ff) as u8); Ok(blob) } #[rhai_fn(name = "len", get = "len", pure)] @@ -63,7 +63,7 @@ mod blob_functions { } #[rhai_fn(name = "push")] pub fn push(blob: &mut Blob, item: INT) { - let item = (item & 0x00ff) as u8; + let item = (item & 0x000000ff) as u8; blob.push(item); } #[rhai_fn(name = "append")] @@ -77,7 +77,7 @@ mod blob_functions { } } pub fn insert(blob: &mut Blob, position: INT, item: INT) { - let item = (item & 0x00ff) as u8; + let item = (item & 0x000000ff) as u8; if blob.is_empty() { blob.push(item); @@ -108,7 +108,7 @@ mod blob_functions { return Ok(()); } - let item = (item & 0x00ff) as u8; + let item = (item & 0x000000ff) as u8; let _ctx = ctx; // Check if blob will be over max size limit @@ -452,13 +452,11 @@ mod blob_functions { let len = usize::min(len, INT_BYTES); - let mut buf = [0_u8; INT_BYTES]; - - buf.copy_from_slice(&if is_le { + let buf = if is_le { value.to_le_bytes() } else { value.to_be_bytes() - }); + }; blob[start..][..len].copy_from_slice(&buf[..len]); } @@ -598,14 +596,11 @@ mod blob_functions { const FLOAT_BYTES: usize = mem::size_of::(); let len = usize::min(len, FLOAT_BYTES); - - let mut buf = [0_u8; FLOAT_BYTES]; - - buf.copy_from_slice(&if is_le { + let buf = if is_le { value.to_le_bytes() } else { value.to_be_bytes() - }); + }; blob[start..][..len].copy_from_slice(&buf[..len]); } @@ -647,4 +642,43 @@ mod blob_functions { pub fn write_be_float(blob: &mut Blob, start: INT, len: INT, value: FLOAT) { write_float(blob, start, len, value, false) } + #[rhai_fn(name = "write")] + pub fn write_string(blob: &mut Blob, start: INT, len: INT, string: &str) { + if len <= 0 || blob.is_empty() || string.is_empty() { + 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 + }; + + let len = usize::min(len, string.len()); + + blob[start..][..len].copy_from_slice(string[..len].as_bytes()); + } + #[rhai_fn(name = "write")] + pub fn write_string_range(blob: &mut Blob, range: ExclusiveRange, string: &str) { + let start = INT::max(range.start, 0); + let end = INT::max(range.end, start); + write_string(blob, start, end - start, string) + } + #[rhai_fn(name = "write")] + pub fn write_string_range_inclusive(blob: &mut Blob, range: InclusiveRange, string: &str) { + let start = INT::max(*range.start(), 0); + let end = INT::max(*range.end(), start); + write_string(blob, start, end - start + 1, string) + } } diff --git a/tests/blobs.rs b/tests/blobs.rs index f53958b1..dcca26d3 100644 --- a/tests/blobs.rs +++ b/tests/blobs.rs @@ -169,6 +169,16 @@ fn test_blobs_parse() -> Result<(), Box> { vec![0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x90] ); + assert_eq!( + engine.eval::(r#"let x = blob(16, 0); write(x, 0, 14, "hello, world!"); x"#)?, + "hello, world!\0\0\0".as_bytes() + ); + + assert_eq!( + engine.eval::(r#"let x = blob(10, 0); write(x, 3, 5, "hello, world!"); x"#)?, + "\0\0\0hello\0\0".as_bytes() + ); + Ok(()) } @@ -238,5 +248,15 @@ fn test_blobs_parse() -> Result<(), Box> { 0x1cf588 ); + assert_eq!( + engine.eval::(r#"let x = blob(16, 0); write(x, 0, 14, "hello, world!"); x"#)?, + "hello, world!\0\0\0".as_bytes() + ); + + assert_eq!( + engine.eval::(r#"let x = blob(10, 0); write(x, 3, 5, "hello, world!"); x"#)?, + "\0\0\0hello\0\0".as_bytes() + ); + Ok(()) }