formualizer_eval/engine/arena/
value_ref.rs1use std::fmt;
7
8#[repr(u8)]
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum ValueType {
12 Empty = 0,
13 SmallInt = 1, LargeInt = 2, Number = 3, String = 4, Boolean = 5, Error = 6, Array = 7, DateTime = 8, Duration = 9, Pending = 10, FormulaAst = 11, }
26
27impl ValueType {
28 fn from_bits(bits: u8) -> Option<Self> {
29 match bits {
30 0 => Some(ValueType::Empty),
31 1 => Some(ValueType::SmallInt),
32 2 => Some(ValueType::LargeInt),
33 3 => Some(ValueType::Number),
34 4 => Some(ValueType::String),
35 5 => Some(ValueType::Boolean),
36 6 => Some(ValueType::Error),
37 7 => Some(ValueType::Array),
38 8 => Some(ValueType::DateTime),
39 9 => Some(ValueType::Duration),
40 10 => Some(ValueType::Pending),
41 11 => Some(ValueType::FormulaAst),
42 _ => None,
43 }
44 }
45}
46
47#[derive(Copy, Clone, Eq, PartialEq, Hash)]
49pub struct ValueRef {
50 raw: u32,
51}
52
53impl ValueRef {
54 const TYPE_SHIFT: u32 = 28;
56 const TYPE_MASK: u32 = 0xF0000000;
57 const PAYLOAD_MASK: u32 = 0x0FFFFFFF;
58
59 const SMALL_INT_MAX: i32 = (1 << 27) - 1; const SMALL_INT_MIN: i32 = -(1 << 27); const SMALL_INT_SIGN_BIT: u32 = 1 << 27; pub const fn empty() -> Self {
66 Self { raw: 0 }
67 }
68
69 #[cfg(test)]
71 pub const fn from_raw(raw: u32) -> Self {
72 Self { raw }
73 }
74
75 pub const fn as_raw(self) -> u32 {
77 self.raw
78 }
79
80 pub fn value_type(self) -> ValueType {
82 let type_bits = ((self.raw & Self::TYPE_MASK) >> Self::TYPE_SHIFT) as u8;
83 ValueType::from_bits(type_bits).unwrap_or(ValueType::Empty)
84 }
85
86 fn payload(self) -> u32 {
88 self.raw & Self::PAYLOAD_MASK
89 }
90
91 pub fn is_empty(self) -> bool {
93 self.raw == 0
94 }
95
96 pub fn small_int(value: i32) -> Option<Self> {
98 if (Self::SMALL_INT_MIN..=Self::SMALL_INT_MAX).contains(&value) {
99 let payload = (value as u32) & Self::PAYLOAD_MASK;
101 Some(Self {
102 raw: (ValueType::SmallInt as u32) << Self::TYPE_SHIFT | payload,
103 })
104 } else {
105 None
106 }
107 }
108
109 pub fn as_small_int(self) -> Option<i32> {
111 if self.value_type() == ValueType::SmallInt {
112 let payload = self.payload();
113 if payload & Self::SMALL_INT_SIGN_BIT != 0 {
115 Some((payload | !Self::PAYLOAD_MASK) as i32)
117 } else {
118 Some(payload as i32)
120 }
121 } else {
122 None
123 }
124 }
125
126 pub fn boolean(value: bool) -> Self {
128 Self {
129 raw: (ValueType::Boolean as u32) << Self::TYPE_SHIFT | (value as u32),
130 }
131 }
132
133 pub fn as_boolean(self) -> Option<bool> {
135 if self.value_type() == ValueType::Boolean {
136 Some(self.payload() & 1 != 0)
137 } else {
138 None
139 }
140 }
141
142 pub fn error(error_ref: u32) -> Self {
144 assert!(
145 error_ref <= Self::PAYLOAD_MASK,
146 "ErrorRef must fit in 28 bits"
147 );
148 Self {
149 raw: (ValueType::Error as u32) << Self::TYPE_SHIFT | error_ref,
150 }
151 }
152
153 pub fn as_error_ref(self) -> Option<u32> {
155 if self.value_type() == ValueType::Error {
156 Some(self.payload())
157 } else {
158 None
159 }
160 }
161
162 pub fn pending() -> Self {
164 Self {
165 raw: (ValueType::Pending as u32) << Self::TYPE_SHIFT,
166 }
167 }
168
169 pub fn large_int(index: u32) -> Self {
171 assert!(index <= Self::PAYLOAD_MASK, "Large int index overflow");
172 Self {
173 raw: (ValueType::LargeInt as u32) << Self::TYPE_SHIFT | index,
174 }
175 }
176
177 pub fn number(index: u32) -> Self {
179 assert!(index <= Self::PAYLOAD_MASK, "Number index overflow");
180 Self {
181 raw: (ValueType::Number as u32) << Self::TYPE_SHIFT | index,
182 }
183 }
184
185 pub fn string(index: u32) -> Self {
187 assert!(index <= Self::PAYLOAD_MASK, "String index overflow");
188 Self {
189 raw: (ValueType::String as u32) << Self::TYPE_SHIFT | index,
190 }
191 }
192
193 pub fn array(index: u32) -> Self {
195 assert!(index <= Self::PAYLOAD_MASK, "Array index overflow");
196 Self {
197 raw: (ValueType::Array as u32) << Self::TYPE_SHIFT | index,
198 }
199 }
200
201 pub fn date_time(index: u32) -> Self {
203 assert!(index <= Self::PAYLOAD_MASK, "DateTime index overflow");
204 Self {
205 raw: (ValueType::DateTime as u32) << Self::TYPE_SHIFT | index,
206 }
207 }
208
209 pub fn duration(index: u32) -> Self {
211 assert!(index <= Self::PAYLOAD_MASK, "Duration index overflow");
212 Self {
213 raw: (ValueType::Duration as u32) << Self::TYPE_SHIFT | index,
214 }
215 }
216
217 pub fn formula_ast(index: u32) -> Self {
219 assert!(index <= Self::PAYLOAD_MASK, "AST index overflow");
220 Self {
221 raw: (ValueType::FormulaAst as u32) << Self::TYPE_SHIFT | index,
222 }
223 }
224
225 pub fn arena_index(self) -> Option<u32> {
227 match self.value_type() {
228 ValueType::LargeInt
229 | ValueType::Number
230 | ValueType::String
231 | ValueType::Array
232 | ValueType::DateTime
233 | ValueType::Duration
234 | ValueType::FormulaAst => Some(self.payload()),
235 _ => None,
236 }
237 }
238}
239
240impl fmt::Debug for ValueRef {
241 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
242 match self.value_type() {
243 ValueType::Empty => write!(f, "Empty"),
244 ValueType::SmallInt => {
245 if let Some(v) = self.as_small_int() {
246 write!(f, "SmallInt({v})")
247 } else {
248 write!(f, "SmallInt(?)")
249 }
250 }
251 ValueType::Boolean => {
252 if let Some(v) = self.as_boolean() {
253 write!(f, "Boolean({v})")
254 } else {
255 write!(f, "Boolean(?)")
256 }
257 }
258 ValueType::Error => {
259 if let Some(code) = self.as_error_ref() {
260 write!(f, "Error(code={code})")
261 } else {
262 write!(f, "Error(?)")
263 }
264 }
265 ValueType::Pending => write!(f, "Pending"),
266 vt => write!(f, "{:?}(idx={})", vt, self.payload()),
267 }
268 }
269}
270
271impl Default for ValueRef {
272 fn default() -> Self {
273 Self::empty()
274 }
275}
276
277#[cfg(test)]
278mod tests {
279 use super::*;
280
281 #[test]
282 fn test_value_ref_empty() {
283 let vref = ValueRef::empty();
284 assert!(vref.is_empty());
285 assert_eq!(vref.value_type(), ValueType::Empty);
286 assert_eq!(vref.as_raw(), 0);
287 }
288
289 #[test]
290 fn test_value_ref_small_int() {
291 let vref = ValueRef::small_int(42).unwrap();
293 assert_eq!(vref.value_type(), ValueType::SmallInt);
294 assert_eq!(vref.as_small_int(), Some(42));
295
296 let vref = ValueRef::small_int(-100).unwrap();
298 assert_eq!(vref.as_small_int(), Some(-100));
299
300 let vref = ValueRef::small_int(ValueRef::SMALL_INT_MAX).unwrap();
302 assert_eq!(vref.as_small_int(), Some(ValueRef::SMALL_INT_MAX));
303
304 let vref = ValueRef::small_int(ValueRef::SMALL_INT_MIN).unwrap();
305 assert_eq!(vref.as_small_int(), Some(ValueRef::SMALL_INT_MIN));
306
307 assert!(ValueRef::small_int(ValueRef::SMALL_INT_MAX + 1).is_none());
309 assert!(ValueRef::small_int(ValueRef::SMALL_INT_MIN - 1).is_none());
310 }
311
312 #[test]
313 fn test_value_ref_boolean() {
314 let true_ref = ValueRef::boolean(true);
315 assert_eq!(true_ref.value_type(), ValueType::Boolean);
316 assert_eq!(true_ref.as_boolean(), Some(true));
317
318 let false_ref = ValueRef::boolean(false);
319 assert_eq!(false_ref.value_type(), ValueType::Boolean);
320 assert_eq!(false_ref.as_boolean(), Some(false));
321 }
322
323 #[test]
324 fn test_value_ref_error() {
325 let error_ref = ValueRef::error(5);
326 assert_eq!(error_ref.value_type(), ValueType::Error);
327 assert_eq!(error_ref.as_error_ref(), Some(5));
328
329 let error_ref = ValueRef::error(1000);
331 assert_eq!(error_ref.as_error_ref(), Some(1000));
332 }
333
334 #[test]
335 fn test_value_ref_pending() {
336 let pending = ValueRef::pending();
337 assert_eq!(pending.value_type(), ValueType::Pending);
338 assert!(!pending.is_empty());
339 }
340
341 #[test]
342 fn test_value_ref_arena_types() {
343 let large_int = ValueRef::large_int(100);
344 assert_eq!(large_int.value_type(), ValueType::LargeInt);
345 assert_eq!(large_int.arena_index(), Some(100));
346
347 let number = ValueRef::number(200);
348 assert_eq!(number.value_type(), ValueType::Number);
349 assert_eq!(number.arena_index(), Some(200));
350
351 let string = ValueRef::string(300);
352 assert_eq!(string.value_type(), ValueType::String);
353 assert_eq!(string.arena_index(), Some(300));
354
355 let array = ValueRef::array(400);
356 assert_eq!(array.value_type(), ValueType::Array);
357 assert_eq!(array.arena_index(), Some(400));
358
359 let ast = ValueRef::formula_ast(500);
360 assert_eq!(ast.value_type(), ValueType::FormulaAst);
361 assert_eq!(ast.arena_index(), Some(500));
362 }
363
364 #[test]
365 fn test_value_ref_type_checking() {
366 let int_ref = ValueRef::small_int(42).unwrap();
367 assert!(int_ref.as_boolean().is_none());
368 assert!(int_ref.as_error_ref().is_none());
369
370 let bool_ref = ValueRef::boolean(true);
371 assert!(bool_ref.as_small_int().is_none());
372 assert!(bool_ref.as_error_ref().is_none());
373 }
374
375 #[test]
376 fn test_value_ref_debug() {
377 assert_eq!(format!("{:?}", ValueRef::empty()), "Empty");
378 assert_eq!(
379 format!("{:?}", ValueRef::small_int(42).unwrap()),
380 "SmallInt(42)"
381 );
382 assert_eq!(format!("{:?}", ValueRef::boolean(true)), "Boolean(true)");
383 assert_eq!(format!("{:?}", ValueRef::error(5)), "Error(code=5)");
384 assert_eq!(format!("{:?}", ValueRef::pending()), "Pending");
385 assert_eq!(format!("{:?}", ValueRef::number(100)), "Number(idx=100)");
386 }
387
388 #[test]
389 fn test_value_ref_sign_extension() {
390 let neg_one = ValueRef::small_int(-1).unwrap();
392 assert_eq!(neg_one.as_small_int(), Some(-1));
393
394 let large_neg = ValueRef::small_int(-1000000).unwrap();
395 assert_eq!(large_neg.as_small_int(), Some(-1000000));
396
397 let near_boundary = ValueRef::small_int((1 << 26) - 1).unwrap();
399 assert_eq!(near_boundary.as_small_int(), Some((1 << 26) - 1));
400 }
401
402 #[test]
403 #[should_panic(expected = "Array index overflow")]
404 fn test_value_ref_index_overflow() {
405 ValueRef::array(0x10000000); }
407}