Move bit-fields into new package.
This commit is contained in:
parent
bccdf70521
commit
8961f36e8e
@ -12,6 +12,12 @@ Script-breaking changes
|
||||
|
||||
* `is` is (pun intended) now a reserved keyword to prepare for possible future type checking expressions (e.g. `x is "string"`).
|
||||
|
||||
Breaking changes
|
||||
----------------
|
||||
|
||||
* `LogicPackage` is removed from `CorePackage`.
|
||||
* Bit-field functions are moved into a new `BitFieldPackage` (used to be in `LogicPackage`) which makes more sense.
|
||||
|
||||
New features
|
||||
------------
|
||||
|
||||
|
198
src/packages/bit_field.rs
Normal file
198
src/packages/bit_field.rs
Normal file
@ -0,0 +1,198 @@
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use crate::plugin::*;
|
||||
use crate::{def_package, ExclusiveRange, InclusiveRange, Position, RhaiResultOf, ERR, INT};
|
||||
#[cfg(feature = "no_std")]
|
||||
use std::prelude::v1::*;
|
||||
|
||||
def_package! {
|
||||
/// Package of basic bit-field utilities.
|
||||
crate::BitFieldPackage => |lib| {
|
||||
lib.standard = true;
|
||||
|
||||
combine_with_exported_module!(lib, "bit_field", bit_field_functions);
|
||||
}
|
||||
}
|
||||
|
||||
#[export_module]
|
||||
mod bit_field_functions {
|
||||
const BITS: usize = std::mem::size_of::<INT>() * 8;
|
||||
|
||||
#[rhai_fn(return_raw)]
|
||||
pub fn get_bit(value: INT, index: INT) -> RhaiResultOf<bool> {
|
||||
if index >= 0 {
|
||||
let offset = index as usize;
|
||||
|
||||
if offset >= BITS {
|
||||
Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into())
|
||||
} else {
|
||||
Ok((value & (1 << offset)) != 0)
|
||||
}
|
||||
} else if let Some(abs_index) = index.checked_abs() {
|
||||
let offset = abs_index as usize;
|
||||
|
||||
// Count from end if negative
|
||||
if offset > BITS {
|
||||
Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into())
|
||||
} else {
|
||||
Ok((value & (1 << (BITS - offset))) != 0)
|
||||
}
|
||||
} else {
|
||||
Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into())
|
||||
}
|
||||
}
|
||||
#[rhai_fn(return_raw)]
|
||||
pub fn set_bit(value: &mut INT, index: INT, new_value: bool) -> RhaiResultOf<()> {
|
||||
if index >= 0 {
|
||||
let offset = index as usize;
|
||||
|
||||
if offset >= BITS {
|
||||
Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into())
|
||||
} else {
|
||||
let mask = 1 << offset;
|
||||
if new_value {
|
||||
*value |= mask;
|
||||
} else {
|
||||
*value &= !mask;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
} else if let Some(abs_index) = index.checked_abs() {
|
||||
let offset = abs_index as usize;
|
||||
|
||||
// Count from end if negative
|
||||
if offset > BITS {
|
||||
Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into())
|
||||
} else {
|
||||
let mask = 1 << offset;
|
||||
if new_value {
|
||||
*value |= mask;
|
||||
} else {
|
||||
*value &= !mask;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
} else {
|
||||
Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into())
|
||||
}
|
||||
}
|
||||
#[rhai_fn(name = "get_bits", return_raw)]
|
||||
pub fn get_bits_range(value: INT, range: ExclusiveRange) -> RhaiResultOf<INT> {
|
||||
let from = INT::max(range.start, 0);
|
||||
let to = INT::max(range.end, from);
|
||||
get_bits(value, from, to - from)
|
||||
}
|
||||
#[rhai_fn(name = "get_bits", return_raw)]
|
||||
pub fn get_bits_range_inclusive(value: INT, range: InclusiveRange) -> RhaiResultOf<INT> {
|
||||
let from = INT::max(*range.start(), 0);
|
||||
let to = INT::max(*range.end(), from - 1);
|
||||
get_bits(value, from, to - from + 1)
|
||||
}
|
||||
#[rhai_fn(return_raw)]
|
||||
pub fn get_bits(value: INT, index: INT, bits: INT) -> RhaiResultOf<INT> {
|
||||
if bits < 1 {
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
let offset = if index >= 0 {
|
||||
let offset = index as usize;
|
||||
|
||||
if offset >= BITS {
|
||||
return Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into());
|
||||
}
|
||||
|
||||
offset
|
||||
} else if let Some(abs_index) = index.checked_abs() {
|
||||
let offset = abs_index as usize;
|
||||
|
||||
// Count from end if negative
|
||||
if offset > BITS {
|
||||
return Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into());
|
||||
}
|
||||
BITS - offset
|
||||
} else {
|
||||
return Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into());
|
||||
};
|
||||
|
||||
let bits = if offset + bits as usize > BITS {
|
||||
BITS - offset
|
||||
} else {
|
||||
bits as usize
|
||||
};
|
||||
|
||||
let mut base = 1;
|
||||
let mut mask = 0;
|
||||
|
||||
for _ in 0..bits {
|
||||
mask |= base;
|
||||
base <<= 1;
|
||||
}
|
||||
|
||||
Ok(((value & (mask << index)) >> index) & mask)
|
||||
}
|
||||
#[rhai_fn(name = "set_bits", return_raw)]
|
||||
pub fn set_bits_range(
|
||||
value: &mut INT,
|
||||
range: ExclusiveRange,
|
||||
new_value: INT,
|
||||
) -> RhaiResultOf<()> {
|
||||
let from = INT::max(range.start, 0);
|
||||
let to = INT::max(range.end, from);
|
||||
set_bits(value, from, to - from, new_value)
|
||||
}
|
||||
#[rhai_fn(name = "set_bits", return_raw)]
|
||||
pub fn set_bits_range_inclusive(
|
||||
value: &mut INT,
|
||||
range: InclusiveRange,
|
||||
new_value: INT,
|
||||
) -> RhaiResultOf<()> {
|
||||
let from = INT::max(*range.start(), 0);
|
||||
let to = INT::max(*range.end(), from - 1);
|
||||
set_bits(value, from, to - from + 1, new_value)
|
||||
}
|
||||
#[rhai_fn(return_raw)]
|
||||
pub fn set_bits(value: &mut INT, index: INT, bits: INT, new_value: INT) -> RhaiResultOf<()> {
|
||||
if bits < 1 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let offset = if index >= 0 {
|
||||
let offset = index as usize;
|
||||
|
||||
if offset >= BITS {
|
||||
return Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into());
|
||||
}
|
||||
|
||||
offset
|
||||
} else if let Some(abs_index) = index.checked_abs() {
|
||||
let offset = abs_index as usize;
|
||||
|
||||
// Count from end if negative
|
||||
if offset > BITS {
|
||||
return Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into());
|
||||
}
|
||||
BITS - offset
|
||||
} else {
|
||||
return Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into());
|
||||
};
|
||||
|
||||
let bits = if offset + bits as usize > BITS {
|
||||
BITS - offset
|
||||
} else {
|
||||
bits as usize
|
||||
};
|
||||
|
||||
let mut base = 1;
|
||||
let mut mask = 0;
|
||||
|
||||
for _ in 0..bits {
|
||||
mask |= base;
|
||||
base <<= 1;
|
||||
}
|
||||
|
||||
*value &= !(mask << index);
|
||||
*value |= (new_value & mask) << index;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -16,6 +16,10 @@ def_package! {
|
||||
|
||||
#[export_module]
|
||||
mod core_functions {
|
||||
#[rhai_fn(name = "!")]
|
||||
pub fn not(x: bool) -> bool {
|
||||
!x
|
||||
}
|
||||
#[rhai_fn(name = "tag", get = "tag", pure)]
|
||||
pub fn get_tag(value: &mut Dynamic) -> INT {
|
||||
value.tag() as INT
|
||||
|
@ -1,7 +1,7 @@
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use crate::plugin::*;
|
||||
use crate::{def_package, ExclusiveRange, InclusiveRange, RhaiResultOf, ERR, INT};
|
||||
use crate::{def_package, INT};
|
||||
#[cfg(feature = "no_std")]
|
||||
use std::prelude::v1::*;
|
||||
|
||||
@ -61,19 +61,9 @@ def_package! {
|
||||
reg_functions!(lib += float; f64);
|
||||
combine_with_exported_module!(lib, "f64", f64_functions);
|
||||
}
|
||||
|
||||
set_exported_fn!(lib, "!", not);
|
||||
|
||||
combine_with_exported_module!(lib, "bit_field", bit_field_functions);
|
||||
}
|
||||
}
|
||||
|
||||
// Logic operators
|
||||
#[export_fn]
|
||||
fn not(x: bool) -> bool {
|
||||
!x
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "only_i32"))]
|
||||
#[cfg(not(feature = "only_i64"))]
|
||||
gen_cmp_functions!(numbers => i8, u8, i16, u16, i32, u32, u64);
|
||||
@ -196,186 +186,3 @@ mod f64_functions {
|
||||
(x as f64) <= (y as f64)
|
||||
}
|
||||
}
|
||||
|
||||
#[export_module]
|
||||
mod bit_field_functions {
|
||||
const BITS: usize = std::mem::size_of::<INT>() * 8;
|
||||
|
||||
#[rhai_fn(return_raw)]
|
||||
pub fn get_bit(value: INT, index: INT) -> RhaiResultOf<bool> {
|
||||
if index >= 0 {
|
||||
let offset = index as usize;
|
||||
|
||||
if offset >= BITS {
|
||||
Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into())
|
||||
} else {
|
||||
Ok((value & (1 << offset)) != 0)
|
||||
}
|
||||
} else if let Some(abs_index) = index.checked_abs() {
|
||||
let offset = abs_index as usize;
|
||||
|
||||
// Count from end if negative
|
||||
if offset > BITS {
|
||||
Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into())
|
||||
} else {
|
||||
Ok((value & (1 << (BITS - offset))) != 0)
|
||||
}
|
||||
} else {
|
||||
Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into())
|
||||
}
|
||||
}
|
||||
#[rhai_fn(return_raw)]
|
||||
pub fn set_bit(value: &mut INT, index: INT, new_value: bool) -> RhaiResultOf<()> {
|
||||
if index >= 0 {
|
||||
let offset = index as usize;
|
||||
|
||||
if offset >= BITS {
|
||||
Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into())
|
||||
} else {
|
||||
let mask = 1 << offset;
|
||||
if new_value {
|
||||
*value |= mask;
|
||||
} else {
|
||||
*value &= !mask;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
} else if let Some(abs_index) = index.checked_abs() {
|
||||
let offset = abs_index as usize;
|
||||
|
||||
// Count from end if negative
|
||||
if offset > BITS {
|
||||
Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into())
|
||||
} else {
|
||||
let mask = 1 << offset;
|
||||
if new_value {
|
||||
*value |= mask;
|
||||
} else {
|
||||
*value &= !mask;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
} else {
|
||||
Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into())
|
||||
}
|
||||
}
|
||||
#[rhai_fn(name = "get_bits", return_raw)]
|
||||
pub fn get_bits_range(value: INT, range: ExclusiveRange) -> RhaiResultOf<INT> {
|
||||
let from = INT::max(range.start, 0);
|
||||
let to = INT::max(range.end, from);
|
||||
get_bits(value, from, to - from)
|
||||
}
|
||||
#[rhai_fn(name = "get_bits", return_raw)]
|
||||
pub fn get_bits_range_inclusive(value: INT, range: InclusiveRange) -> RhaiResultOf<INT> {
|
||||
let from = INT::max(*range.start(), 0);
|
||||
let to = INT::max(*range.end(), from - 1);
|
||||
get_bits(value, from, to - from + 1)
|
||||
}
|
||||
#[rhai_fn(return_raw)]
|
||||
pub fn get_bits(value: INT, index: INT, bits: INT) -> RhaiResultOf<INT> {
|
||||
if bits < 1 {
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
let offset = if index >= 0 {
|
||||
let offset = index as usize;
|
||||
|
||||
if offset >= BITS {
|
||||
return Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into());
|
||||
}
|
||||
|
||||
offset
|
||||
} else if let Some(abs_index) = index.checked_abs() {
|
||||
let offset = abs_index as usize;
|
||||
|
||||
// Count from end if negative
|
||||
if offset > BITS {
|
||||
return Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into());
|
||||
}
|
||||
BITS - offset
|
||||
} else {
|
||||
return Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into());
|
||||
};
|
||||
|
||||
let bits = if offset + bits as usize > BITS {
|
||||
BITS - offset
|
||||
} else {
|
||||
bits as usize
|
||||
};
|
||||
|
||||
let mut base = 1;
|
||||
let mut mask = 0;
|
||||
|
||||
for _ in 0..bits {
|
||||
mask |= base;
|
||||
base <<= 1;
|
||||
}
|
||||
|
||||
Ok(((value & (mask << index)) >> index) & mask)
|
||||
}
|
||||
#[rhai_fn(name = "set_bits", return_raw)]
|
||||
pub fn set_bits_range(
|
||||
value: &mut INT,
|
||||
range: ExclusiveRange,
|
||||
new_value: INT,
|
||||
) -> RhaiResultOf<()> {
|
||||
let from = INT::max(range.start, 0);
|
||||
let to = INT::max(range.end, from);
|
||||
set_bits(value, from, to - from, new_value)
|
||||
}
|
||||
#[rhai_fn(name = "set_bits", return_raw)]
|
||||
pub fn set_bits_range_inclusive(
|
||||
value: &mut INT,
|
||||
range: InclusiveRange,
|
||||
new_value: INT,
|
||||
) -> RhaiResultOf<()> {
|
||||
let from = INT::max(*range.start(), 0);
|
||||
let to = INT::max(*range.end(), from - 1);
|
||||
set_bits(value, from, to - from + 1, new_value)
|
||||
}
|
||||
#[rhai_fn(return_raw)]
|
||||
pub fn set_bits(value: &mut INT, index: INT, bits: INT, new_value: INT) -> RhaiResultOf<()> {
|
||||
if bits < 1 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let offset = if index >= 0 {
|
||||
let offset = index as usize;
|
||||
|
||||
if offset >= BITS {
|
||||
return Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into());
|
||||
}
|
||||
|
||||
offset
|
||||
} else if let Some(abs_index) = index.checked_abs() {
|
||||
let offset = abs_index as usize;
|
||||
|
||||
// Count from end if negative
|
||||
if offset > BITS {
|
||||
return Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into());
|
||||
}
|
||||
BITS - offset
|
||||
} else {
|
||||
return Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into());
|
||||
};
|
||||
|
||||
let bits = if offset + bits as usize > BITS {
|
||||
BITS - offset
|
||||
} else {
|
||||
bits as usize
|
||||
};
|
||||
|
||||
let mut base = 1;
|
||||
let mut mask = 0;
|
||||
|
||||
for _ in 0..bits {
|
||||
mask |= base;
|
||||
base <<= 1;
|
||||
}
|
||||
|
||||
*value &= !(mask << index);
|
||||
*value |= (new_value & mask) << index;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ use crate::{Module, Shared};
|
||||
|
||||
pub(crate) mod arithmetic;
|
||||
pub(crate) mod array_basic;
|
||||
mod bit_field;
|
||||
pub(crate) mod blob_basic;
|
||||
mod fn_basic;
|
||||
mod iter_basic;
|
||||
@ -20,6 +21,7 @@ mod time_basic;
|
||||
pub use arithmetic::ArithmeticPackage;
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
pub use array_basic::BasicArrayPackage;
|
||||
pub use bit_field::BitFieldPackage;
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
pub use blob_basic::BasicBlobPackage;
|
||||
pub use fn_basic::BasicFnPackage;
|
||||
|
@ -10,7 +10,6 @@ def_package! {
|
||||
///
|
||||
/// * [`LanguageCorePackage`][super::LanguageCorePackage]
|
||||
/// * [`ArithmeticPackage`][super::ArithmeticPackage]
|
||||
/// * [`LogicPackage`][super::LogicPackage]
|
||||
/// * [`BasicStringPackage`][super::BasicStringPackage]
|
||||
/// * [`BasicIteratorPackage`][super::BasicIteratorPackage]
|
||||
/// * [`BasicFnPackage`][super::BasicFnPackage]
|
||||
@ -19,7 +18,6 @@ def_package! {
|
||||
|
||||
super::LanguageCorePackage::init(lib);
|
||||
super::ArithmeticPackage::init(lib);
|
||||
super::LogicPackage::init(lib);
|
||||
super::BasicStringPackage::init(lib);
|
||||
super::BasicIteratorPackage::init(lib);
|
||||
super::BasicFnPackage::init(lib);
|
||||
|
@ -9,6 +9,8 @@ def_package! {
|
||||
/// # Contents
|
||||
///
|
||||
/// * [`CorePackage`][super::CorePackage]
|
||||
/// * [`BitFieldPackage`][super::BitFieldPackage]
|
||||
/// * [`LogicPackage`][super::LogicPackage]
|
||||
/// * [`BasicMathPackage`][super::BasicMathPackage]
|
||||
/// * [`BasicArrayPackage`][super::BasicArrayPackage]
|
||||
/// * [`BasicBlobPackage`][super::BasicBlobPackage]
|
||||
@ -19,6 +21,8 @@ def_package! {
|
||||
lib.standard = true;
|
||||
|
||||
super::CorePackage::init(lib);
|
||||
super::BitFieldPackage::init(lib);
|
||||
super::LogicPackage::init(lib);
|
||||
super::BasicMathPackage::init(lib);
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
super::BasicArrayPackage::init(lib);
|
||||
|
Loading…
Reference in New Issue
Block a user