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        }
31    }
32
33    fn successor_bytes(&self) -> Option<Vec<u8>> {
34        match self {
35            Value::String(s) => {
36                let mut bytes = s.as_bytes().to_vec();
37                bytes.push(0);
38                Some(bytes)
39            }
40            Value::I16(x) => {
41                if *x == i16::MAX {
42                    None
43                } else {
44                    Some(((*x as i64) + 1).to_be_bytes().to_vec())
45                }
46            }
47            Value::I32(x) => {
48                if *x == i32::MAX {
49                    None
50                } else {
51                    Some(((*x as i64) + 1).to_be_bytes().to_vec())
52                }
53            }
54            Value::I64(x) => {
55                if *x == i64::MAX {
56                    None
57                } else {
58                    Some((x + 1).to_be_bytes().to_vec())
59                }
60            }
61            Value::F64(f) => {
62                if f.is_nan() || (f.is_infinite() && *f > 0.0) {
63                    None
64                } else {
65                    let bits = if *f >= 0.0 { f.to_bits() ^ (1 << 63) } else { !f.to_bits() };
66                    let next_bits = bits + 1;
67                    Some(next_bits.to_be_bytes().to_vec())
68                }
69            }
70            Value::Bool(b) => {
71                if *b {
72                    None
73                } else {
74                    Some(vec![1])
75                }
76            }
77            Value::EntityId(entity_id) => {
78                let mut bytes = entity_id.to_bytes();
79                // Increment the byte array (big-endian arithmetic)
80                for i in (0..16).rev() {
81                    if bytes[i] == 0xFF {
82                        bytes[i] = 0;
83                    } else {
84                        bytes[i] += 1;
85                        return Some(bytes.to_vec());
86                    }
87                }
88                None // Overflow - already at maximum
89            }
90            Value::Object(_) | Value::Binary(_) => None,
91        }
92    }
93
94    fn predecessor_bytes(&self) -> Option<Vec<u8>> {
95        match self {
96            Value::String(s) => {
97                let bytes = s.as_bytes();
98                if bytes.is_empty() {
99                    None
100                } else {
101                    Some(bytes[..bytes.len() - 1].to_vec())
102                }
103            }
104            Value::I16(x) => {
105                if *x == i16::MIN {
106                    None
107                } else {
108                    Some(((*x as i64) - 1).to_be_bytes().to_vec())
109                }
110            }
111            Value::I32(x) => {
112                if *x == i32::MIN {
113                    None
114                } else {
115                    Some(((*x as i64) - 1).to_be_bytes().to_vec())
116                }
117            }
118            Value::I64(x) => {
119                if *x == i64::MIN {
120                    None
121                } else {
122                    Some((x - 1).to_be_bytes().to_vec())
123                }
124            }
125            Value::F64(f) => {
126                if f.is_nan() || (f.is_infinite() && *f < 0.0) {
127                    None
128                } else {
129                    let bits = if *f >= 0.0 { f.to_bits() ^ (1 << 63) } else { !f.to_bits() };
130                    let prev_bits = bits - 1;
131                    Some(prev_bits.to_be_bytes().to_vec())
132                }
133            }
134            Value::Bool(b) => {
135                if *b {
136                    Some(vec![0])
137                } else {
138                    None
139                }
140            }
141            Value::EntityId(entity_id) => {
142                let mut bytes = entity_id.to_bytes();
143                if bytes == [0u8; 16] {
144                    None // Already at minimum
145                } else {
146                    // Decrement the byte array (big-endian arithmetic)
147                    for i in (0..16).rev() {
148                        if bytes[i] == 0 {
149                            bytes[i] = 0xFF;
150                        } else {
151                            bytes[i] -= 1;
152                            return Some(bytes.to_vec());
153                        }
154                    }
155                    None // Should never reach here since we checked for zero above
156                }
157            }
158            Value::Object(_) | Value::Binary(_) => None,
159        }
160    }
161
162    fn is_minimum(&self) -> bool {
163        match self {
164            Value::String(s) => s.is_empty(),
165            Value::I16(x) => *x == i16::MIN,
166            Value::I32(x) => *x == i32::MIN,
167            Value::I64(x) => *x == i64::MIN,
168            Value::F64(f) => *f == f64::NEG_INFINITY,
169            Value::Bool(b) => !b,
170            Value::EntityId(entity_id) => entity_id.to_bytes() == [0u8; 16],
171            Value::Object(_) | Value::Binary(_) => false,
172        }
173    }
174
175    fn is_maximum(&self) -> bool {
176        match self {
177            Value::String(_) => false, // Strings have no theoretical maximum
178            Value::I16(x) => *x == i16::MAX,
179            Value::I32(x) => *x == i32::MAX,
180            Value::I64(x) => *x == i64::MAX,
181            Value::F64(f) => *f == f64::INFINITY,
182            Value::Bool(b) => *b,
183            Value::EntityId(entity_id) => entity_id.to_bytes() == [0xFFu8; 16],
184            Value::Object(_) | Value::Binary(_) => false,
185        }
186    }
187}