egglog_core_relations/base_values/
unboxed.rs1use crate::numeric_id::NumericId;
7
8use crate::Value;
9
10use super::BaseValue;
11
12macro_rules! impl_small_base_value {
14 ($ty:ty) => {
15 impl BaseValue for $ty {
16 const MAY_UNBOX: bool = true;
17 fn try_unbox(val: Value) -> Option<Self> {
18 Some(val.rep() as $ty)
19 }
20 fn try_box(&self) -> Option<Value> {
21 Some(Value::new(*self as u32))
22 }
23 }
24 };
25 ($ty:ty, $($rest:ty),+) => {
26 impl_small_base_value!($ty);
27 impl_small_base_value!($($rest),+);
28 };
29}
30
31impl_small_base_value!(u8, u16, u32, i8, i16, i32);
32
33impl BaseValue for bool {
34 const MAY_UNBOX: bool = true;
35 fn try_unbox(val: Value) -> Option<Self> {
37 Some(val.rep() != 0)
38 }
39 fn try_box(&self) -> Option<Value> {
50 Some(Value::new(if *self { 1 } else { 0 }))
51 }
52}
53
54impl BaseValue for () {
55 const MAY_UNBOX: bool = true;
56 fn try_unbox(_val: Value) -> Option<Self> {
64 Some(())
65 }
66 fn try_box(&self) -> Option<Value> {
67 Some(Value::new(0))
68 }
69}
70
71const VAL_BITS: u32 = std::mem::size_of::<Value>() as u32 * 8;
72const VAL_MASK: u32 = 1 << (VAL_BITS - 1);
73
74macro_rules! impl_medium_base_value {
75 ($ty:ty) => {
76 impl BaseValue for $ty {
77 const MAY_UNBOX: bool = true;
78 fn try_box(&self) -> Option<Value> {
79 if *self & (VAL_MASK-1) as $ty == *self {
80 Some(Value::new(*self as u32))
82 } else {
83 None
85 }
86 }
87 fn try_unbox(val: Value) -> Option<Self> {
88 let top_bit_clear = val.rep() & VAL_MASK == 0;
89 if top_bit_clear {
90 Some(val.rep() as $ty)
91 } else {
92 None
94 }
95 }
96 }
97 };
98
99 ($ty:ty, $($rest:ty),+) => {
100 impl_medium_base_value!($ty);
101 impl_medium_base_value!($($rest),+);
102 };
103}
104
105impl_medium_base_value!(u64, i64, usize, isize);