summaryrefslogtreecommitdiff
path: root/ecs/src/util.rs
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2024-11-29 15:55:36 +0100
committerHampusM <hampus@hampusmat.com>2024-11-29 17:18:10 +0100
commit97dde76198a94073ec3c5fcf1326c114890d96b2 (patch)
tree5da03547606e1a07abf2638ac3a820db0b7bbb76 /ecs/src/util.rs
parent9d59f8b283e8a4d84c1909a750d0e789de866c6a (diff)
refactor(ecs): set & get UID parts using bit masks
Diffstat (limited to 'ecs/src/util.rs')
-rw-r--r--ecs/src/util.rs88
1 files changed, 88 insertions, 0 deletions
diff --git a/ecs/src/util.rs b/ecs/src/util.rs
index 4480fc8..0344e89 100644
--- a/ecs/src/util.rs
+++ b/ecs/src/util.rs
@@ -1,3 +1,5 @@
+use std::ops::BitAnd;
+
pub trait Sortable
{
type Item;
@@ -46,3 +48,89 @@ impl<Item> Sortable for Vec<Item>
self.sort_by_key(func);
}
}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct BitMask<Value>
+{
+ mask: Value,
+}
+
+impl BitMask<u64>
+{
+ #[must_use]
+ pub const fn new(mask: u64) -> Self
+ {
+ Self { mask }
+ }
+
+ pub const fn value(self) -> u64
+ {
+ self.mask
+ }
+
+ /// Prepares a bitfield value in the range of bits specified by this `BitMask`.
+ #[must_use]
+ pub const fn field_prep(self, field_value: u64) -> u64
+ {
+ ((field_value) << self.mask.trailing_zeros()) & (self.mask)
+ }
+}
+
+impl BitAnd<u64> for BitMask<u64>
+{
+ type Output = u64;
+
+ fn bitand(self, rhs: u64) -> Self::Output
+ {
+ self.mask & rhs
+ }
+}
+
+pub trait NumberExt: Sized
+{
+ /// Returns a range of bits (field) specified by the provided [`BitMask`].
+ fn field_get(self, field_mask: BitMask<Self>) -> Self;
+}
+
+impl NumberExt for u64
+{
+ fn field_get(self, field_mask: BitMask<Self>) -> Self
+ {
+ (field_mask & self) >> field_mask.value().trailing_zeros()
+ }
+}
+
+macro_rules! gen_mask_64 {
+ ($low: literal..=$high: literal) => {
+ const {
+ if $high <= $low {
+ panic!("High bit index cannot be less than or equal to low bit index");
+ }
+
+ (((!0u64) - (1u64 << ($low)) + 1)
+ & (!0u64 >> (u64::BITS as u64 - 1 - ($high))))
+ }
+ };
+}
+
+pub(crate) use gen_mask_64;
+
+#[cfg(test)]
+mod tests
+{
+
+ use super::BitMask;
+ use crate::util::NumberExt;
+
+ #[test]
+ fn field_get_works()
+ {
+ assert_eq!(0b11011u64.field_get(BitMask::new(0b11100)), 0b00110);
+ }
+
+ #[test]
+ fn bitmask_field_prep_works()
+ {
+ assert_eq!(BitMask::new(0b11000).field_prep(3), 0b11000);
+ }
+}