Skip to main content

ankurah_core/value/
collatable.rs

1use crate::collation::Collatable;
2use crate::value::Value;
3
4// Collation for Value (single value). Tuple framing (type tags/lengths) is handled by higher-level encoders.
5impl Collatable for Value {
6    fn to_bytes(&self) -> Vec<u8> {
7        match self {
8            Value::String(s) => s.as_bytes().to_vec(),
9            // Use fixed-width big-endian encoding to preserve numeric order across widths
10            Value::I16(x) => (*x as i64).to_be_bytes().to_vec(),
11            Value::I32(x) => (*x as i64).to_be_bytes().to_vec(),
12            Value::I64(x) => x.to_be_bytes().to_vec(),
13            Value::F64(f) => {
14                let bits = if f.is_nan() {
15                    u64::MAX // NaN sorts last
16                } else {
17                    let bits = f.to_bits();
18                    if *f >= 0.0 {
19                        bits ^ (1 << 63) // Flip sign bit for positive numbers
20                    } else {
21                        !bits // Flip all bits for negative numbers
22                    }
23                };
24                bits.to_be_bytes().to_vec()
25            }
26            Value::Bool(b) => vec![*b as u8],
27            Value::EntityId(entity_id) => entity_id.to_bytes().to_vec(),
28            // For binary/object, return raw bytes; tuple framing will add type-tag/len for cross-type ordering
29            Value::Object(bytes) | Value::Binary(bytes) => bytes.clone(),
30            // For JSON, serialize to bytes
31            Value::Json(json) => serde_json::to_vec(json).unwrap_or_default(),
32        }
33    }
34
35    fn successor_bytes(&self) -> Option<Vec<u8>> {
36        match self {
37            Value::String(s) => {
38                let mut bytes = s.as_bytes().to_vec();
39                bytes.push(0);
40                Some(bytes)
41            }
42            Value::I16(x) => {
43                if *x == i16::MAX {
44                    None
45                } else {
46                    Some(((*x as i64) + 1).to_be_bytes().to_vec())
47                }
48            }
49            Value::I32(x) => {
50                if *x == i32::MAX {
51                    None
52                } else {
53                    Some(((*x as i64) + 1).to_be_bytes().to_vec())
54                }
55            }
56            Value::I64(x) => {
57                if *x == i64::MAX {
58                    None
59                } else {
60                    Some((x + 1).to_be_bytes().to_vec())
61                }
62            }
63            Value::F64(f) => {
64                if f.is_nan() || (f.is_infinite() && *f > 0.0) {
65                    None
66                } else {
67                    let bits = if *f >= 0.0 { f.to_bits() ^ (1 << 63) } else { !f.to_bits() };
68                    let next_bits = bits + 1;
69                    Some(next_bits.to_be_bytes().to_vec())
70                }
71            }
72            Value::Bool(b) => {
73                if *b {
74                    None
75                } else {
76                    Some(vec![1])
77                }
78            }
79            Value::EntityId(entity_id) => {
80                let mut bytes = entity_id.to_bytes();
81                // Increment the byte array (big-endian arithmetic)
82                for i in (0..16).rev() {
83                    if bytes[i] == 0xFF {
84                        bytes[i] = 0;
85                    } else {
86                        bytes[i] += 1;
87                        return Some(bytes.to_vec());
88                    }
89                }
90                None // Overflow - already at maximum
91            }
92            Value::Object(_) | Value::Binary(_) | Value::Json(_) => None,
93        }
94    }
95
96    fn predecessor_bytes(&self) -> Option<Vec<u8>> {
97        match self {
98            Value::String(s) => {
99                let bytes = s.as_bytes();
100                if bytes.is_empty() {
101                    None
102                } else {
103                    Some(bytes[..bytes.len() - 1].to_vec())
104                }
105            }
106            Value::I16(x) => {
107                if *x == i16::MIN {
108                    None
109                } else {
110                    Some(((*x as i64) - 1).to_be_bytes().to_vec())
111                }
112            }
113            Value::I32(x) => {
114                if *x == i32::MIN {
115                    None
116                } else {
117                    Some(((*x as i64) - 1).to_be_bytes().to_vec())
118                }
119            }
120            Value::I64(x) => {
121                if *x == i64::MIN {
122                    None
123                } else {
124                    Some((x - 1).to_be_bytes().to_vec())
125                }
126            }
127            Value::F64(f) => {
128                if f.is_nan() || (f.is_infinite() && *f < 0.0) {
129                    None
130                } else {
131                    let bits = if *f >= 0.0 { f.to_bits() ^ (1 << 63) } else { !f.to_bits() };
132                    let prev_bits = bits - 1;
133                    Some(prev_bits.to_be_bytes().to_vec())
134                }
135            }
136            Value::Bool(b) => {
137                if *b {
138                    Some(vec![0])
139                } else {
140                    None
141                }
142            }
143            Value::EntityId(entity_id) => {
144                let mut bytes = entity_id.to_bytes();
145                if bytes == [0u8; 16] {
146                    None // Already at minimum
147                } else {
148                    // Decrement the byte array (big-endian arithmetic)
149                    for i in (0..16).rev() {
150                        if bytes[i] == 0 {
151                            bytes[i] = 0xFF;
152                        } else {
153                            bytes[i] -= 1;
154                            return Some(bytes.to_vec());
155                        }
156                    }
157                    None // Should never reach here since we checked for zero above
158                }
159            }
160            Value::Object(_) | Value::Binary(_) | Value::Json(_) => None,
161        }
162    }
163
164    fn is_minimum(&self) -> bool {
165        match self {
166            Value::String(s) => s.is_empty(),
167            Value::I16(x) => *x == i16::MIN,
168            Value::I32(x) => *x == i32::MIN,
169            Value::I64(x) => *x == i64::MIN,
170            Value::F64(f) => *f == f64::NEG_INFINITY,
171            Value::Bool(b) => !b,
172            Value::EntityId(entity_id) => entity_id.to_bytes() == [0u8; 16],
173            Value::Object(_) | Value::Binary(_) | Value::Json(_) => false,
174        }
175    }
176
177    fn is_maximum(&self) -> bool {
178        match self {
179            Value::String(_) => false, // Strings have no theoretical maximum
180            Value::I16(x) => *x == i16::MAX,
181            Value::I32(x) => *x == i32::MAX,
182            Value::I64(x) => *x == i64::MAX,
183            Value::F64(f) => *f == f64::INFINITY,
184            Value::Bool(b) => *b,
185            Value::EntityId(entity_id) => entity_id.to_bytes() == [0xFFu8; 16],
186            Value::Object(_) | Value::Binary(_) | Value::Json(_) => false,
187        }
188    }
189}