1use std::sync::atomic::{AtomicU64, Ordering};
57
58#[repr(u8)]
60#[derive(Clone, Copy, Debug, PartialEq, Eq)]
61pub enum ValueTag {
62 Null = 0,
64 Bool = 1,
66 SmallInt = 2,
68 InlineString = 3,
70 HeapString = 4,
72 InlineBytes = 5,
74 HeapBytes = 6,
76 Float = 7,
78}
79
80impl ValueTag {
81 fn from_u8(v: u8) -> Option<Self> {
82 match v {
83 0 => Some(Self::Null),
84 1 => Some(Self::Bool),
85 2 => Some(Self::SmallInt),
86 3 => Some(Self::InlineString),
87 4 => Some(Self::HeapString),
88 5 => Some(Self::InlineBytes),
89 6 => Some(Self::HeapBytes),
90 7 => Some(Self::Float),
91 _ => None,
92 }
93 }
94}
95
96const MAX_INLINE_SIZE: usize = 7;
98
99const TAG_SHIFT: u32 = 61;
101
102const INLINE_LEN_SHIFT: u32 = 56;
104const INLINE_LEN_MASK: u64 = 0x0F; const INLINE_DATA_MASK: u64 = 0x00FF_FFFF_FFFF_FFFF; #[derive(Clone)]
119pub struct PolymorphicValue {
120 bits: u64,
122 heap: Option<Box<[u8]>>,
124}
125
126impl PolymorphicValue {
127 #[inline]
129 pub fn null() -> Self {
130 Self {
131 bits: (ValueTag::Null as u64) << TAG_SHIFT,
132 heap: None,
133 }
134 }
135
136 #[inline]
138 pub fn bool(v: bool) -> Self {
139 let bits = ((ValueTag::Bool as u64) << TAG_SHIFT) | (v as u64);
140 Self { bits, heap: None }
141 }
142
143 #[inline]
147 pub fn int(v: i64) -> Self {
148 if v >= -(1i64 << 55) && v < (1i64 << 55) {
150 let bits = ((ValueTag::SmallInt as u64) << TAG_SHIFT)
151 | ((v as u64) & INLINE_DATA_MASK);
152 Self { bits, heap: None }
153 } else {
154 let bytes = v.to_le_bytes();
156 Self::heap_bytes(&bytes, ValueTag::HeapBytes)
157 }
158 }
159
160 pub fn string(s: &str) -> Self {
164 let bytes = s.as_bytes();
165 if bytes.len() <= MAX_INLINE_SIZE {
166 Self::inline_bytes(bytes, ValueTag::InlineString)
167 } else {
168 Self::heap_bytes(bytes, ValueTag::HeapString)
169 }
170 }
171
172 pub fn bytes(b: &[u8]) -> Self {
176 if b.len() <= MAX_INLINE_SIZE {
177 Self::inline_bytes(b, ValueTag::InlineBytes)
178 } else {
179 Self::heap_bytes(b, ValueTag::HeapBytes)
180 }
181 }
182
183 #[inline]
185 pub fn float(v: f64) -> Self {
186 let bits = v.to_bits();
188 let packed = ((ValueTag::Float as u64) << TAG_SHIFT) | (bits & INLINE_DATA_MASK);
189 Self { bits: packed, heap: Some(Box::new(bits.to_le_bytes())) }
190 }
191
192 fn inline_bytes(data: &[u8], tag: ValueTag) -> Self {
194 debug_assert!(data.len() <= MAX_INLINE_SIZE);
195
196 let mut packed = 0u64;
197 for (i, &byte) in data.iter().enumerate() {
198 packed |= (byte as u64) << (i * 8);
199 }
200
201 let bits = ((tag as u64) << TAG_SHIFT)
202 | ((data.len() as u64) << INLINE_LEN_SHIFT)
203 | packed;
204
205 Self { bits, heap: None }
206 }
207
208 fn heap_bytes(data: &[u8], tag: ValueTag) -> Self {
210 let heap = data.to_vec().into_boxed_slice();
211 let bits = ((tag as u64) << TAG_SHIFT) | (data.len() as u64 & 0x1FFF_FFFF);
212 Self { bits, heap: Some(heap) }
213 }
214
215 #[inline]
217 pub fn tag(&self) -> ValueTag {
218 ValueTag::from_u8((self.bits >> TAG_SHIFT) as u8 & 0x07).unwrap_or(ValueTag::Null)
219 }
220
221 #[inline]
223 pub fn is_null(&self) -> bool {
224 self.tag() == ValueTag::Null
225 }
226
227 #[inline]
229 pub fn is_inline(&self) -> bool {
230 matches!(
231 self.tag(),
232 ValueTag::Null | ValueTag::Bool | ValueTag::SmallInt
233 | ValueTag::InlineString | ValueTag::InlineBytes
234 )
235 }
236
237 #[inline]
239 pub fn as_bool(&self) -> Option<bool> {
240 if self.tag() == ValueTag::Bool {
241 Some((self.bits & 1) != 0)
242 } else {
243 None
244 }
245 }
246
247 #[inline]
249 pub fn as_int(&self) -> Option<i64> {
250 if self.tag() == ValueTag::SmallInt {
251 let raw = (self.bits & INLINE_DATA_MASK) as i64;
253 let sign_bit = 1i64 << 55;
254 Some(if raw & sign_bit != 0 {
255 raw | !INLINE_DATA_MASK as i64
256 } else {
257 raw
258 })
259 } else {
260 None
261 }
262 }
263
264 pub fn as_float(&self) -> Option<f64> {
266 if self.tag() == ValueTag::Float {
267 self.heap.as_ref().map(|h| {
268 let bytes: [u8; 8] = h.as_ref().try_into().unwrap_or([0; 8]);
269 f64::from_le_bytes(bytes)
270 })
271 } else {
272 None
273 }
274 }
275
276 #[inline]
278 fn inline_len(&self) -> usize {
279 ((self.bits >> INLINE_LEN_SHIFT) & INLINE_LEN_MASK) as usize
280 }
281
282 pub fn as_str(&self) -> Option<String> {
286 match self.tag() {
287 ValueTag::InlineString => {
288 self.inline_bytes_copy()
289 .and_then(|bytes| String::from_utf8(bytes).ok())
290 }
291 ValueTag::HeapString => {
292 self.heap.as_ref().and_then(|h| std::str::from_utf8(h).ok().map(|s| s.to_owned()))
293 }
294 _ => None,
295 }
296 }
297
298 pub fn as_heap_str(&self) -> Option<&str> {
300 match self.tag() {
301 ValueTag::HeapString => {
302 self.heap.as_ref().and_then(|h| std::str::from_utf8(h).ok())
303 }
304 _ => None,
305 }
306 }
307
308 pub fn as_bytes(&self) -> Option<&[u8]> {
310 match self.tag() {
311 ValueTag::InlineBytes => {
312 None
314 }
315 ValueTag::HeapBytes => {
316 self.heap.as_ref().map(|h| h.as_ref())
317 }
318 _ => None,
319 }
320 }
321
322 pub fn inline_bytes_copy(&self) -> Option<Vec<u8>> {
324 match self.tag() {
325 ValueTag::InlineBytes | ValueTag::InlineString => {
326 let len = self.inline_len();
327 let bytes = (self.bits & INLINE_DATA_MASK).to_le_bytes();
328 Some(bytes[..len].to_vec())
329 }
330 _ => None,
331 }
332 }
333
334 pub fn encoded_size(&self) -> usize {
336 8 + self.heap.as_ref().map(|h| h.len()).unwrap_or(0)
337 }
338
339 pub fn to_bytes(&self) -> Vec<u8> {
341 let mut buf = Vec::with_capacity(self.encoded_size());
342 buf.extend_from_slice(&self.bits.to_le_bytes());
343 if let Some(ref heap) = self.heap {
344 buf.extend_from_slice(heap);
345 }
346 buf
347 }
348
349 pub fn from_bytes(data: &[u8]) -> Option<Self> {
351 if data.len() < 8 {
352 return None;
353 }
354
355 let bits = u64::from_le_bytes(data[..8].try_into().ok()?);
356 let tag = ValueTag::from_u8((bits >> TAG_SHIFT) as u8 & 0x07)?;
357
358 let heap = match tag {
359 ValueTag::HeapString | ValueTag::HeapBytes => {
360 let len = (bits & 0x1FFF_FFFF) as usize;
361 if data.len() < 8 + len {
362 return None;
363 }
364 Some(data[8..8 + len].to_vec().into_boxed_slice())
365 }
366 ValueTag::Float => {
367 if data.len() >= 16 {
368 Some(data[8..16].to_vec().into_boxed_slice())
369 } else {
370 None
371 }
372 }
373 _ => None,
374 };
375
376 Some(Self { bits, heap })
377 }
378}
379
380impl Default for PolymorphicValue {
381 fn default() -> Self {
382 Self::null()
383 }
384}
385
386impl std::fmt::Debug for PolymorphicValue {
387 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
388 match self.tag() {
389 ValueTag::Null => write!(f, "Null"),
390 ValueTag::Bool => write!(f, "Bool({})", self.as_bool().unwrap_or(false)),
391 ValueTag::SmallInt => write!(f, "Int({})", self.as_int().unwrap_or(0)),
392 ValueTag::InlineString | ValueTag::HeapString => {
393 if let Some(s) = self.as_str() {
394 write!(f, "String({:?})", s)
395 } else if let Some(b) = self.inline_bytes_copy() {
396 write!(f, "String({:?})", String::from_utf8_lossy(&b))
397 } else {
398 write!(f, "String(<invalid>)")
399 }
400 }
401 ValueTag::InlineBytes | ValueTag::HeapBytes => {
402 write!(f, "Bytes({} bytes)", self.inline_len())
403 }
404 ValueTag::Float => write!(f, "Float({:?})", self.as_float()),
405 }
406 }
407}
408
409pub struct AtomicPolymorphicValue {
418 bits: AtomicU64,
419}
420
421impl AtomicPolymorphicValue {
422 pub fn null() -> Self {
424 Self {
425 bits: AtomicU64::new((ValueTag::Null as u64) << TAG_SHIFT),
426 }
427 }
428
429 pub fn from_inline(v: &PolymorphicValue) -> Option<Self> {
431 if v.is_inline() {
432 Some(Self {
433 bits: AtomicU64::new(v.bits),
434 })
435 } else {
436 None
437 }
438 }
439
440 #[inline]
442 pub fn load(&self, order: Ordering) -> u64 {
443 self.bits.load(order)
444 }
445
446 #[inline]
448 pub fn store(&self, value: &PolymorphicValue, order: Ordering) {
449 debug_assert!(value.is_inline(), "AtomicPolymorphicValue only supports inline values");
450 self.bits.store(value.bits, order);
451 }
452
453 #[inline]
455 pub fn compare_exchange(
456 &self,
457 current: &PolymorphicValue,
458 new: &PolymorphicValue,
459 success: Ordering,
460 failure: Ordering,
461 ) -> Result<u64, u64> {
462 debug_assert!(new.is_inline(), "AtomicPolymorphicValue only supports inline values");
463 self.bits.compare_exchange(current.bits, new.bits, success, failure)
464 }
465
466 #[inline]
468 pub fn tag(&self) -> ValueTag {
469 let bits = self.bits.load(Ordering::Relaxed);
470 ValueTag::from_u8((bits >> TAG_SHIFT) as u8 & 0x07).unwrap_or(ValueTag::Null)
471 }
472
473 #[inline]
475 pub fn try_as_int(&self, order: Ordering) -> Option<i64> {
476 let bits = self.bits.load(order);
477 let tag = ValueTag::from_u8((bits >> TAG_SHIFT) as u8 & 0x07)?;
478
479 if tag == ValueTag::SmallInt {
480 let raw = (bits & INLINE_DATA_MASK) as i64;
481 let sign_bit = 1i64 << 55;
482 Some(if raw & sign_bit != 0 {
483 raw | !INLINE_DATA_MASK as i64
484 } else {
485 raw
486 })
487 } else {
488 None
489 }
490 }
491
492 pub fn fetch_add(&self, delta: i64, order: Ordering) -> Option<i64> {
494 loop {
495 let bits = self.bits.load(Ordering::Acquire);
496 let tag = ValueTag::from_u8((bits >> TAG_SHIFT) as u8 & 0x07)?;
497
498 if tag != ValueTag::SmallInt {
499 return None;
500 }
501
502 let current = {
503 let raw = (bits & INLINE_DATA_MASK) as i64;
504 let sign_bit = 1i64 << 55;
505 if raw & sign_bit != 0 {
506 raw | !INLINE_DATA_MASK as i64
507 } else {
508 raw
509 }
510 };
511
512 let new_value = current.wrapping_add(delta);
513 let new_bits = ((ValueTag::SmallInt as u64) << TAG_SHIFT)
514 | ((new_value as u64) & INLINE_DATA_MASK);
515
516 if self.bits.compare_exchange_weak(bits, new_bits, order, Ordering::Relaxed).is_ok() {
517 return Some(current);
518 }
519 }
520 }
521}
522
523pub struct CompressedValueArray {
531 data: Vec<u8>,
533 len: usize,
535}
536
537impl CompressedValueArray {
538 pub fn from_values(values: &[PolymorphicValue]) -> Self {
540 let mut data = Vec::new();
541 let mut i = 0;
542
543 while i < values.len() {
544 let value = &values[i];
545
546 let mut run_len = 1usize;
548 while i + run_len < values.len() && run_len < 255 {
549 if Self::values_equal(&values[i + run_len], value) {
550 run_len += 1;
551 } else {
552 break;
553 }
554 }
555
556 if run_len > 1 {
558 data.push(0xFF); data.push(run_len as u8);
560 } else {
561 data.push(0xFE); }
563 data.extend_from_slice(&value.to_bytes());
564
565 i += run_len;
566 }
567
568 Self {
569 data,
570 len: values.len(),
571 }
572 }
573
574 fn values_equal(a: &PolymorphicValue, b: &PolymorphicValue) -> bool {
576 if a.tag() != b.tag() || a.bits != b.bits {
577 return false;
578 }
579 match (&a.heap, &b.heap) {
580 (Some(ha), Some(hb)) => ha == hb,
581 (None, None) => true,
582 _ => false,
583 }
584 }
585
586 pub fn len(&self) -> usize {
588 self.len
589 }
590
591 pub fn is_empty(&self) -> bool {
593 self.len == 0
594 }
595
596 pub fn compressed_size(&self) -> usize {
598 self.data.len()
599 }
600
601 pub fn decompress(&self) -> Vec<PolymorphicValue> {
603 let mut values = Vec::with_capacity(self.len);
604 let mut i = 0;
605
606 while i < self.data.len() {
607 let marker = self.data[i];
608 i += 1;
609
610 let (run_len, value) = if marker == 0xFF {
611 let run_len = self.data[i] as usize;
613 i += 1;
614 let value = PolymorphicValue::from_bytes(&self.data[i..]);
615 if let Some(v) = value {
616 i += v.encoded_size();
617 (run_len, v)
618 } else {
619 break;
620 }
621 } else if marker == 0xFE {
622 let value = PolymorphicValue::from_bytes(&self.data[i..]);
624 if let Some(v) = value {
625 i += v.encoded_size();
626 (1, v)
627 } else {
628 break;
629 }
630 } else {
631 break;
632 };
633
634 for _ in 0..run_len {
635 values.push(value.clone());
636 }
637 }
638
639 values
640 }
641}
642
643#[cfg(test)]
644mod tests {
645 use super::*;
646
647 #[test]
648 fn test_null_value() {
649 let v = PolymorphicValue::null();
650 assert!(v.is_null());
651 assert!(v.is_inline());
652 assert_eq!(v.encoded_size(), 8);
653 }
654
655 #[test]
656 fn test_bool_value() {
657 let t = PolymorphicValue::bool(true);
658 let f = PolymorphicValue::bool(false);
659
660 assert_eq!(t.as_bool(), Some(true));
661 assert_eq!(f.as_bool(), Some(false));
662 assert!(t.is_inline());
663 assert!(f.is_inline());
664 }
665
666 #[test]
667 fn test_int_value() {
668 let v1 = PolymorphicValue::int(42);
669 let v2 = PolymorphicValue::int(-100);
670 let v3 = PolymorphicValue::int(0);
671 let v4 = PolymorphicValue::int(i64::MAX >> 8); assert_eq!(v1.as_int(), Some(42));
674 assert_eq!(v2.as_int(), Some(-100));
675 assert_eq!(v3.as_int(), Some(0));
676 assert_eq!(v4.as_int(), Some(i64::MAX >> 8));
677
678 assert!(v1.is_inline());
679 assert!(v2.is_inline());
680 }
681
682 #[test]
683 fn test_inline_string() {
684 let v = PolymorphicValue::string("hello");
685 assert!(v.is_inline());
686 assert_eq!(v.tag(), ValueTag::InlineString);
687
688 let bytes = v.inline_bytes_copy().unwrap();
689 assert_eq!(&bytes, b"hello");
690 }
691
692 #[test]
693 fn test_heap_string() {
694 let long_str = "This is a string that is longer than 7 bytes";
695 let v = PolymorphicValue::string(long_str);
696
697 assert!(!v.is_inline());
698 assert_eq!(v.tag(), ValueTag::HeapString);
699 assert_eq!(v.as_str(), Some(long_str.to_string()));
700 }
701
702 #[test]
703 fn test_float_value() {
704 let v = PolymorphicValue::float(3.14159);
705 assert_eq!(v.tag(), ValueTag::Float);
706
707 let f = v.as_float().unwrap();
708 assert!((f - 3.14159).abs() < 1e-10);
709 }
710
711 #[test]
712 fn test_serialization() {
713 let values = vec![
714 PolymorphicValue::null(),
715 PolymorphicValue::bool(true),
716 PolymorphicValue::int(42),
717 PolymorphicValue::string("hi"),
718 PolymorphicValue::string("This is a longer string"),
719 ];
720
721 for v in values {
722 let bytes = v.to_bytes();
723 let restored = PolymorphicValue::from_bytes(&bytes).unwrap();
724
725 assert_eq!(v.tag(), restored.tag());
726 assert_eq!(v.bits, restored.bits);
727 }
728 }
729
730 #[test]
731 fn test_atomic_value() {
732 let atomic = AtomicPolymorphicValue::from_inline(&PolymorphicValue::int(0)).unwrap();
733
734 let old = atomic.fetch_add(5, Ordering::SeqCst);
736 assert_eq!(old, Some(0));
737
738 let current = atomic.try_as_int(Ordering::Acquire);
739 assert_eq!(current, Some(5));
740 }
741
742 #[test]
743 fn test_compressed_array() {
744 let values: Vec<_> = (0..100)
746 .map(|i| {
747 if i < 50 {
748 PolymorphicValue::int(42)
749 } else {
750 PolymorphicValue::int(i as i64)
751 }
752 })
753 .collect();
754
755 let compressed = CompressedValueArray::from_values(&values);
756 assert_eq!(compressed.len(), 100);
757
758 let uncompressed_size = 100 * 8; assert!(compressed.compressed_size() < uncompressed_size);
761
762 let restored = compressed.decompress();
764 assert_eq!(restored.len(), 100);
765
766 for (i, v) in restored.iter().enumerate() {
767 let expected = if i < 50 { 42 } else { i as i64 };
768 assert_eq!(v.as_int(), Some(expected));
769 }
770 }
771
772 #[test]
773 fn test_int_edge_cases() {
774 let max_inline = (1i64 << 55) - 1;
776 let min_inline = -(1i64 << 55);
777
778 let v1 = PolymorphicValue::int(max_inline);
779 let v2 = PolymorphicValue::int(min_inline);
780
781 assert_eq!(v1.as_int(), Some(max_inline));
782 assert_eq!(v2.as_int(), Some(min_inline));
783 }
784}