1use crate::types::storage_ids::VertexId;
24use crate::value::date_time::{DateTimeValue, DateValue, TimeValue};
25use crate::value::UuidValue;
26use crate::wal::EntityRef;
27use crate::{NullType, StorageError, Value};
28use compact_str::CompactString;
29
30pub const ORDERED_CODEC_VERSION: u8 = 0x02;
32
33const TAG_EMPTY: u8 = 0x00;
36const TAG_NULL: u8 = 0x01;
37const TAG_BOOL: u8 = 0x02;
38const TAG_SMALL_INT: u8 = 0x03;
39const TAG_INT: u8 = 0x04;
40const TAG_BIG_INT: u8 = 0x05;
41const TAG_FLOAT: u8 = 0x06;
42const TAG_DOUBLE: u8 = 0x07;
43const TAG_DECIMAL: u8 = 0x08;
44const TAG_DATE: u8 = 0x09;
45const TAG_TIME: u8 = 0x0A;
46const TAG_DATE_TIME: u8 = 0x0B;
47const TAG_STRING: u8 = 0x0C;
48const TAG_FIXED_STRING: u8 = 0x0D;
49const TAG_BLOB: u8 = 0x0E;
50const TAG_VERTEX_ID: u8 = 0x0F;
51const TAG_EDGE_REF: u8 = 0x10;
52const TAG_UUID: u8 = 0x1A;
53const TAG_NULL_LAST: u8 = 0xFF;
54const NULL_KIND_EMPTY: u8 = 0xFF;
55
56#[derive(Debug, Clone, Copy)]
60pub struct OrderedCodec {
61 version: u8,
62}
63
64impl OrderedCodec {
65 pub const fn new() -> Self {
66 Self {
67 version: ORDERED_CODEC_VERSION,
68 }
69 }
70
71 pub const fn version(&self) -> u8 {
72 self.version
73 }
74
75 pub fn supports_ordered_key(data_type: &crate::DataType) -> bool {
83 matches!(
84 data_type,
85 crate::DataType::Bool
86 | crate::DataType::SmallInt
87 | crate::DataType::Int
88 | crate::DataType::BigInt
89 | crate::DataType::Float
90 | crate::DataType::Double
91 | crate::DataType::Decimal128
92 | crate::DataType::String
93 | crate::DataType::FixedString(_)
94 | crate::DataType::Blob
95 | crate::DataType::Date
96 | crate::DataType::Time
97 | crate::DataType::DateTime
98 | crate::DataType::Uuid
99 )
100 }
101
102 pub fn encode(&self, value: &Value) -> Result<Vec<u8>, StorageError> {
104 let mut buf = Vec::new();
105 self.encode_value(value, &mut buf, false)?;
106 Ok(buf)
107 }
108
109 pub fn encode_null_last(&self, value: &Value) -> Result<Vec<u8>, StorageError> {
111 let mut buf = Vec::new();
112 self.encode_value(value, &mut buf, true)?;
113 Ok(buf)
114 }
115
116 pub fn decode(&self, bytes: &[u8]) -> Result<Value, StorageError> {
118 let (value, consumed) = self.decode_value_inner(bytes)?;
119 if consumed != bytes.len() {
120 return Err(StorageError::deserialize_error(format!(
121 "OrderedCodec decode: {} bytes trailing data after value",
122 bytes.len() - consumed
123 )));
124 }
125 Ok(value)
126 }
127
128 pub fn decode_value_inner(&self, bytes: &[u8]) -> Result<(Value, usize), StorageError> {
130 if bytes.is_empty() {
131 return Err(StorageError::deserialize_error(
132 "OrderedCodec decode_value: empty input",
133 ));
134 }
135 let tag = bytes[0];
136 match tag {
137 TAG_EMPTY => Ok((Value::Empty, 1)),
138 TAG_NULL | TAG_NULL_LAST => {
139 if bytes.len() < 2 {
140 return Err(StorageError::deserialize_error("truncated null value"));
141 }
142 let kind = bytes[1];
143 if tag == TAG_NULL_LAST && kind == NULL_KIND_EMPTY {
144 Ok((Value::Empty, 2))
145 } else {
146 Ok((Value::Null(decode_null_type(kind)?), 2))
147 }
148 }
149 TAG_BOOL => {
150 if bytes.len() < 2 {
151 return Err(StorageError::deserialize_error("truncated bool"));
152 }
153 Ok((Value::Bool(bytes[1] != 0), 2))
154 }
155 TAG_SMALL_INT => {
156 if bytes.len() < 3 {
157 return Err(StorageError::deserialize_error("truncated smallint"));
158 }
159 let raw = u16::from_be_bytes([bytes[1], bytes[2]]);
160 Ok((Value::SmallInt((raw ^ 0x8000) as i16), 3))
161 }
162 TAG_INT => {
163 if bytes.len() < 5 {
164 return Err(StorageError::deserialize_error("truncated int"));
165 }
166 let raw = u32::from_be_bytes([bytes[1], bytes[2], bytes[3], bytes[4]]);
167 Ok((Value::Int((raw ^ 0x8000_0000) as i32), 5))
168 }
169 TAG_BIG_INT => {
170 if bytes.len() < 9 {
171 return Err(StorageError::deserialize_error("truncated bigint"));
172 }
173 let raw = u64::from_be_bytes([
174 bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], bytes[8],
175 ]);
176 Ok((Value::BigInt((raw ^ 0x8000_0000_0000_0000) as i64), 9))
177 }
178 TAG_FLOAT => {
179 if bytes.len() < 5 {
180 return Err(StorageError::deserialize_error("truncated float"));
181 }
182 let raw = u32::from_be_bytes([bytes[1], bytes[2], bytes[3], bytes[4]]);
183 Ok((Value::Float(decode_f32_ordered(raw)), 5))
184 }
185 TAG_DOUBLE => {
186 if bytes.len() < 9 {
187 return Err(StorageError::deserialize_error("truncated double"));
188 }
189 let raw = u64::from_be_bytes([
190 bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], bytes[8],
191 ]);
192 Ok((Value::Double(decode_f64_ordered(raw)), 9))
193 }
194 TAG_DECIMAL => {
195 let (value, consumed) = decode_decimal(bytes)?;
196 Ok((value, consumed))
197 }
198 TAG_STRING | TAG_FIXED_STRING | TAG_BLOB => {
199 let (data, end) = decode_escaped_bytes(bytes, 1)?;
200 if tag == TAG_STRING {
201 let s = String::from_utf8(data).map_err(|e| {
202 StorageError::deserialize_error(format!("invalid UTF-8: {}", e))
203 })?;
204 Ok((Value::String(CompactString::from(s)), end))
205 } else if tag == TAG_BLOB {
206 Ok((Value::Blob(data), end))
207 } else {
208 let s = String::from_utf8(data).map_err(|e| {
209 StorageError::deserialize_error(format!("invalid UTF-8: {}", e))
210 })?;
211 Ok((Value::FixedString(s), end))
212 }
213 }
214 TAG_DATE => {
215 if bytes.len() < 7 {
216 return Err(StorageError::deserialize_error("truncated date"));
217 }
218 let raw_year = u32::from_be_bytes([bytes[1], bytes[2], bytes[3], bytes[4]]);
219 let year = (raw_year ^ 0x8000_0000) as i32;
220 let month = bytes[5] as u32;
221 let day = bytes[6] as u32;
222 Ok((Value::Date(DateValue { year, month, day }), 7))
223 }
224 TAG_TIME => {
225 if bytes.len() < 9 {
226 return Err(StorageError::deserialize_error("truncated time"));
227 }
228 let total_micros = u64::from_be_bytes([
229 bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], bytes[8],
230 ]);
231 let microsec = (total_micros % 1_000_000) as u32;
232 let total_secs = total_micros / 1_000_000;
233 let hour = (total_secs / 3600) as u32;
234 let minute = ((total_secs % 3600) / 60) as u32;
235 let sec = (total_secs % 60) as u32;
236 Ok((
237 Value::Time(TimeValue {
238 hour,
239 minute,
240 sec,
241 microsec,
242 }),
243 9,
244 ))
245 }
246 TAG_DATE_TIME => {
247 if bytes.len() < 15 {
248 return Err(StorageError::deserialize_error("truncated datetime"));
249 }
250 let raw_year = u32::from_be_bytes([bytes[1], bytes[2], bytes[3], bytes[4]]);
251 let year = (raw_year ^ 0x8000_0000) as i32;
252 let month = bytes[5] as u32;
253 let day = bytes[6] as u32;
254 let total_micros = u64::from_be_bytes([
255 bytes[7], bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13],
256 bytes[14],
257 ]);
258 let microsec = (total_micros % 1_000_000) as u32;
259 let total_secs = total_micros / 1_000_000;
260 let hour = (total_secs / 3600) as u32;
261 let minute = ((total_secs % 3600) / 60) as u32;
262 let sec = (total_secs % 60) as u32;
263 Ok((
264 Value::DateTime(DateTimeValue {
265 year,
266 month,
267 day,
268 hour,
269 minute,
270 sec,
271 microsec,
272 }),
273 15,
274 ))
275 }
276 TAG_UUID => {
277 if bytes.len() < 17 {
278 return Err(StorageError::deserialize_error("truncated uuid"));
279 }
280 let mut uuid_bytes = [0u8; 16];
281 uuid_bytes.copy_from_slice(&bytes[1..17]);
282 Ok((Value::Uuid(UuidValue(uuid_bytes)), 17))
283 }
284 TAG_VERTEX_ID => {
285 let (entity, consumed) = self.decode_entity_bytes(bytes)?;
286 match entity {
287 EntityRef::Vertex(vid) => {
288 let val = Value::VertexId(vid);
289 Ok((val, consumed))
290 }
291 EntityRef::Edge { .. } => Err(StorageError::deserialize_error(
292 "expected vertex tag but found edge ref",
293 )),
294 }
295 }
296 TAG_EDGE_REF => {
297 let (_entity, consumed) = self.decode_entity_bytes(bytes)?;
298 Ok((Value::String(CompactString::new("(edge)")), consumed))
300 }
301 _ => Err(StorageError::deserialize_error(format!(
302 "unknown type tag 0x{:02x}",
303 tag
304 ))),
305 }
306 }
307
308 pub fn encode_composite(
311 &self,
312 values: &[&Value],
313 entity: Option<&EntityRef>,
314 null_last: bool,
315 ) -> Result<Vec<u8>, StorageError> {
316 let mut buf = Vec::new();
317 for v in values {
318 self.encode_value(v, &mut buf, null_last)?;
319 }
320 if let Some(e) = entity {
321 self.encode_entity(e, &mut buf)?;
322 }
323 Ok(buf)
324 }
325
326 pub fn encode_entity(&self, entity: &EntityRef, buf: &mut Vec<u8>) -> Result<(), StorageError> {
328 match entity {
329 EntityRef::Vertex(vid) => {
330 buf.push(TAG_VERTEX_ID);
331 write_vertex_id(vid, buf);
332 Ok(())
333 }
334 EntityRef::Edge {
335 src,
336 dst,
337 edge_type,
338 ranking,
339 } => {
340 buf.push(TAG_EDGE_REF);
341 write_vertex_id(src, buf);
342 write_vertex_id(dst, buf);
343 buf.extend_from_slice(&edge_type.to_be_bytes());
344 buf.extend_from_slice(&ranking.to_be_bytes());
345 Ok(())
346 }
347 }
348 }
349
350 pub fn decode_entity_bytes(&self, bytes: &[u8]) -> Result<(EntityRef, usize), StorageError> {
352 if bytes.is_empty() {
353 return Err(StorageError::deserialize_error("empty entity input"));
354 }
355 let tag = bytes[0];
356 match tag {
357 TAG_VERTEX_ID => {
358 let (vid, consumed) = read_vertex_id(&bytes[1..])?;
359 Ok((EntityRef::Vertex(vid), 1 + consumed))
360 }
361 TAG_EDGE_REF => {
362 let mut pos = 1;
363 let (src, c1) = read_vertex_id(&bytes[pos..])?;
364 pos += c1;
365 let (dst, c2) = read_vertex_id(&bytes[pos..])?;
366 pos += c2;
367 if bytes.len() < pos + 12 {
368 return Err(StorageError::deserialize_error("truncated edge ref"));
369 }
370 let et_bytes: [u8; 4] = bytes[pos..pos + 4]
371 .try_into()
372 .map_err(|_| StorageError::deserialize_error("invalid edge type bytes"))?;
373 let rank_bytes: [u8; 8] = bytes[pos + 4..pos + 12]
374 .try_into()
375 .map_err(|_| StorageError::deserialize_error("invalid edge ranking bytes"))?;
376 pos += 12;
377 Ok((
378 EntityRef::Edge {
379 src,
380 dst,
381 edge_type: u32::from_be_bytes(et_bytes),
382 ranking: i64::from_be_bytes(rank_bytes),
383 },
384 pos,
385 ))
386 }
387 _ => Err(StorageError::deserialize_error(format!(
388 "unknown entity tag 0x{:02x}",
389 tag
390 ))),
391 }
392 }
393
394 pub fn prefix_upper_bound(prefix: &[u8]) -> Vec<u8> {
399 let mut end = prefix.to_vec();
400 for i in (0..end.len()).rev() {
401 if end[i] == 0xFF {
402 end[i] = 0x00;
403 } else {
404 end[i] += 1;
405 break;
406 }
407 }
408 end
409 }
410
411 pub fn prefix_bounds(&self, value: &Value) -> Result<(Vec<u8>, Vec<u8>), StorageError> {
422 match value {
423 Value::Null(_)
425 | Value::Empty
426 | Value::Bool(_)
427 | Value::SmallInt(_)
428 | Value::Int(_)
429 | Value::BigInt(_)
430 | Value::Float(_)
431 | Value::Double(_)
432 | Value::Date(_)
433 | Value::Time(_)
434 | Value::DateTime(_)
435 | Value::Uuid(_) => {
436 let lower = self.encode(value)?;
437 let upper = Self::prefix_upper_bound(&lower);
438 Ok((lower, upper))
439 }
440
441 Value::String(_) | Value::FixedString(_) | Value::Blob(_) => {
448 let lower = self.encode(value)?;
449 let tag = lower[0];
450 let (_, terminator_end) = decode_escaped_bytes(&lower, 1)?;
451 let data = &lower[1..terminator_end - 2];
452 let mut upper = vec![tag];
453 if data.is_empty() {
454 upper = Self::prefix_upper_bound(&upper);
455 } else {
456 upper.extend_from_slice(&Self::prefix_upper_bound(data));
457 }
458 Ok((lower, upper))
459 }
460
461 other => Err(StorageError::db_error(format!(
463 "prefix_bounds not supported for type {:?}",
464 other
465 ))),
466 }
467 }
468
469 fn encode_value(
472 &self,
473 value: &Value,
474 buf: &mut Vec<u8>,
475 null_last: bool,
476 ) -> Result<(), StorageError> {
477 match value {
478 Value::Empty => {
479 if null_last {
480 buf.extend_from_slice(&[TAG_NULL_LAST, NULL_KIND_EMPTY]);
481 } else {
482 buf.push(TAG_EMPTY);
483 }
484 }
485 Value::Null(null_type) => {
486 buf.push(if null_last { TAG_NULL_LAST } else { TAG_NULL });
487 buf.push(encode_null_type(null_type));
488 }
489 Value::Bool(b) => {
490 buf.push(TAG_BOOL);
491 buf.push(u8::from(*b));
492 }
493 Value::SmallInt(n) => {
494 buf.push(TAG_SMALL_INT);
495 buf.extend_from_slice(&((*n as u16) ^ 0x8000).to_be_bytes());
496 }
497 Value::Int(n) => {
498 buf.push(TAG_INT);
499 buf.extend_from_slice(&((*n as u32) ^ 0x8000_0000).to_be_bytes());
500 }
501 Value::BigInt(n) => {
502 buf.push(TAG_BIG_INT);
503 buf.extend_from_slice(&((*n as u64) ^ 0x8000_0000_0000_0000).to_be_bytes());
504 }
505 Value::Float(f) => {
506 buf.push(TAG_FLOAT);
507 buf.extend_from_slice(&encode_f32_ordered(*f).to_be_bytes());
508 }
509 Value::Double(f) => {
510 buf.push(TAG_DOUBLE);
511 buf.extend_from_slice(&encode_f64_ordered(*f).to_be_bytes());
512 }
513 Value::Decimal128(decimal) => {
514 encode_decimal(decimal, buf)?;
515 }
516 Value::String(s) => {
517 buf.push(TAG_STRING);
518 encode_escaped_bytes(s.as_bytes(), buf);
519 }
520 Value::FixedString(data) => {
521 buf.push(TAG_FIXED_STRING);
522 encode_escaped_bytes(data.as_bytes(), buf);
523 }
524 Value::Blob(b) => {
525 buf.push(TAG_BLOB);
526 encode_escaped_bytes(b, buf);
527 }
528 Value::Date(d) => {
529 buf.push(TAG_DATE);
530 buf.extend_from_slice(&((d.year as u32) ^ 0x8000_0000).to_be_bytes());
531 buf.push(d.month as u8);
532 buf.push(d.day as u8);
533 }
534 Value::Time(t) => {
535 buf.push(TAG_TIME);
536 let total_micros = (t.hour as u64) * 3_600_000_000
537 + (t.minute as u64) * 60_000_000
538 + (t.sec as u64) * 1_000_000
539 + t.microsec as u64;
540 buf.extend_from_slice(&total_micros.to_be_bytes());
541 }
542 Value::DateTime(dt) => {
543 buf.push(TAG_DATE_TIME);
544 buf.extend_from_slice(&((dt.year as u32) ^ 0x8000_0000).to_be_bytes());
545 buf.push(dt.month as u8);
546 buf.push(dt.day as u8);
547 let total_micros = (dt.hour as u64) * 3_600_000_000
548 + (dt.minute as u64) * 60_000_000
549 + (dt.sec as u64) * 1_000_000
550 + dt.microsec as u64;
551 buf.extend_from_slice(&total_micros.to_be_bytes());
552 }
553 Value::Uuid(u) => {
554 buf.push(TAG_UUID);
555 buf.extend_from_slice(&u.0);
556 }
557 Value::Vertex(_)
560 | Value::Edge(_)
561 | Value::EdgeHeader(_)
562 | Value::Path(_)
563 | Value::List(_)
564 | Value::Map(_)
565 | Value::Set(_)
566 | Value::Geography(_)
567 | Value::Vector(_)
568 | Value::DataSet(_)
569 | Value::Json(_)
570 | Value::JsonB(_)
571 | Value::Interval(_)
572 | Value::VertexId(_)
573 | Value::EdgeId(_)
574 | Value::Struct(_)
575 | Value::Array(_) => {
576 return Err(StorageError::invalid_input(format!(
577 "Value type {:?} is not supported by OrderedCodec",
578 value.get_type()
579 )));
580 }
581 }
582 Ok(())
583 }
584}
585
586fn encode_escaped_bytes(data: &[u8], buf: &mut Vec<u8>) {
587 for byte in data {
588 if *byte == 0 {
589 buf.extend_from_slice(&[0, 1]);
590 } else {
591 buf.push(*byte);
592 }
593 }
594 buf.extend_from_slice(&[0, 0]);
595}
596
597fn encode_null_type(null_type: &NullType) -> u8 {
598 match null_type {
599 NullType::Null => 0,
600 NullType::NaN => 1,
601 NullType::BadData => 2,
602 NullType::BadType => 3,
603 NullType::ErrOverflow => 4,
604 NullType::UnknownProp => 5,
605 NullType::DivByZero => 6,
606 NullType::OutOfRange => 7,
607 }
608}
609
610fn decode_null_type(code: u8) -> Result<NullType, StorageError> {
611 match code {
612 0 => Ok(NullType::Null),
613 1 => Ok(NullType::NaN),
614 2 => Ok(NullType::BadData),
615 3 => Ok(NullType::BadType),
616 4 => Ok(NullType::ErrOverflow),
617 5 => Ok(NullType::UnknownProp),
618 6 => Ok(NullType::DivByZero),
619 7 => Ok(NullType::OutOfRange),
620 _ => Err(StorageError::deserialize_error(format!(
621 "invalid null type code {code}"
622 ))),
623 }
624}
625
626fn decode_escaped_bytes(
627 bytes: &[u8],
628 mut position: usize,
629) -> Result<(Vec<u8>, usize), StorageError> {
630 let mut data = Vec::new();
631 while position < bytes.len() {
632 let byte = bytes[position];
633 position += 1;
634 if byte != 0 {
635 data.push(byte);
636 continue;
637 }
638 let escape = *bytes.get(position).ok_or_else(|| {
639 StorageError::deserialize_error("missing variable-length value terminator")
640 })?;
641 position += 1;
642 match escape {
643 0 => return Ok((data, position)),
644 1 => data.push(0),
645 _ => {
646 return Err(StorageError::deserialize_error(
647 "invalid variable-length value escape",
648 ))
649 }
650 }
651 }
652 Err(StorageError::deserialize_error(
653 "missing variable-length value terminator",
654 ))
655}
656
657fn encode_decimal(
658 decimal: &crate::value::Decimal128Value,
659 buf: &mut Vec<u8>,
660) -> Result<(), StorageError> {
661 let text = decimal.to_string();
662 let negative = text.starts_with('-');
663 let unsigned = text
664 .strip_prefix('-')
665 .or_else(|| text.strip_prefix('+'))
666 .unwrap_or(&text);
667 let (mantissa, exponent_part) = unsigned
668 .find(['e', 'E'])
669 .map_or((unsigned, "0"), |position| {
670 (&unsigned[..position], &unsigned[position + 1..])
671 });
672 let exponent10 = exponent_part.parse::<i32>().map_err(|error| {
673 StorageError::serialize_error(format!("Invalid decimal exponent: {error}"))
674 })?;
675 let (whole, fractional) = mantissa.split_once('.').unwrap_or((mantissa, ""));
676 let mut digits = whole.bytes().chain(fractional.bytes()).collect::<Vec<_>>();
677 if digits.is_empty() || digits.iter().any(|digit| !digit.is_ascii_digit()) {
678 return Err(StorageError::serialize_error(format!(
679 "Invalid decimal value {text}"
680 )));
681 }
682 let is_zero = digits.iter().all(|digit| *digit == b'0');
683 let (digit_exponent, negative) = if is_zero {
684 digits.clear();
685 digits.push(b'0');
686 (i32::MIN, false)
687 } else {
688 let leading_zero_count = digits.iter().take_while(|digit| **digit == b'0').count();
689 let whole_len = i32::try_from(whole.len())
690 .map_err(|_| StorageError::serialize_error("Decimal integral part is too long"))?;
691 let leading_zero_count = i32::try_from(leading_zero_count)
692 .map_err(|_| StorageError::serialize_error("Decimal significand is too long"))?;
693 let digit_exponent = whole_len
694 .checked_add(exponent10)
695 .and_then(|value| value.checked_sub(leading_zero_count))
696 .ok_or_else(|| StorageError::serialize_error("Decimal exponent is out of range"))?;
697
698 digits.drain(..leading_zero_count as usize);
699 while digits.last() == Some(&b'0') {
700 digits.pop();
701 }
702 (digit_exponent, negative)
703 };
704 let biased = (digit_exponent as u32) ^ 0x8000_0000;
705 buf.push(TAG_DECIMAL);
706 buf.push(u8::from(!negative));
707 buf.extend_from_slice(&(if negative { !biased } else { biased }).to_be_bytes());
708 if negative {
709 buf.extend(digits.into_iter().map(|digit| !digit));
710 buf.push(0xFF);
711 } else {
712 buf.extend_from_slice(&digits);
713 buf.push(0x00);
714 }
715 Ok(())
716}
717
718fn decode_decimal(bytes: &[u8]) -> Result<(Value, usize), StorageError> {
719 if bytes.len() < 7 {
720 return Err(StorageError::deserialize_error("truncated decimal"));
721 }
722 let sign = bytes[1];
723 if sign > 1 {
724 return Err(StorageError::deserialize_error("invalid decimal sign"));
725 }
726 let raw = u32::from_be_bytes([bytes[2], bytes[3], bytes[4], bytes[5]]);
727 let wire_exponent = if sign == 0 { !raw } else { raw };
728 let exponent = (wire_exponent ^ 0x8000_0000) as i32;
729 let terminator = if sign == 0 { 0xFF } else { 0x00 };
730 let mut position = 6;
731 let mut digits = Vec::new();
732 while position < bytes.len() && bytes[position] != terminator {
733 let digit = if sign == 0 {
734 !bytes[position]
735 } else {
736 bytes[position]
737 };
738 if !digit.is_ascii_digit() {
739 return Err(StorageError::deserialize_error(
740 "invalid decimal significand",
741 ));
742 }
743 digits.push(digit);
744 position += 1;
745 }
746 if digits.is_empty() || position == bytes.len() {
747 return Err(StorageError::deserialize_error(
748 "missing decimal terminator",
749 ));
750 }
751 position += 1;
752 if digits.iter().all(|digit| *digit == b'0') {
753 let value = "0"
754 .parse::<crate::value::Decimal128Value>()
755 .map_err(|error| {
756 StorageError::deserialize_error(format!("invalid decimal: {error}"))
757 })?;
758 return Ok((Value::Decimal128(value), position));
759 }
760 let decimal_position = exponent;
761 let digit_count = i32::try_from(digits.len())
762 .map_err(|_| StorageError::deserialize_error("decimal significand is too long"))?;
763 let exponent10 = decimal_position
764 .checked_sub(digit_count)
765 .ok_or_else(|| StorageError::deserialize_error("decimal exponent is out of range"))?;
766 let mut text = String::new();
767 if sign == 0 && digits.iter().any(|digit| *digit != b'0') {
768 text.push('-');
769 }
770 text.extend(digits.iter().map(|digit| char::from(*digit)));
771 if exponent10 != 0 {
772 text.push('e');
773 text.push_str(&exponent10.to_string());
774 }
775 let value = text
776 .parse::<crate::value::Decimal128Value>()
777 .map_err(|error| StorageError::deserialize_error(format!("invalid decimal: {error}")))?;
778 Ok((Value::Decimal128(value), position))
779}
780
781impl Default for OrderedCodec {
782 fn default() -> Self {
783 Self::new()
784 }
785}
786
787fn write_vertex_id(vid: &VertexId, buf: &mut Vec<u8>) {
794 let bytes = vid.as_bytes();
795 buf.extend_from_slice(bytes);
796 let pad = 32usize.saturating_sub(bytes.len());
797 buf.extend(std::iter::repeat_n(0u8, pad));
798 buf.push(bytes.len() as u8);
799 buf.push(vid.kind().as_u8());
800}
801
802fn read_vertex_id(bytes: &[u8]) -> Result<(VertexId, usize), StorageError> {
804 use crate::types::storage_ids::VertexIdKind;
805 if bytes.len() < 34 {
806 return Err(StorageError::deserialize_error(
807 "truncated vertex id (need 34)",
808 ));
809 }
810 let len = bytes[32] as usize;
811 if len > 32 {
812 return Err(StorageError::deserialize_error("invalid vertex id length"));
813 }
814 if bytes[len..32].iter().any(|byte| *byte != 0) {
815 return Err(StorageError::deserialize_error(
816 "non-zero vertex id padding",
817 ));
818 }
819 let kind = VertexIdKind::from_u8(bytes[33])
820 .ok_or_else(|| StorageError::deserialize_error("unknown vertex id kind"))?;
821 let data = &bytes[..len];
822 VertexId::from_typed_bytes(kind, data)
823 .map(|vid| (vid, 34))
824 .map_err(StorageError::deserialize_error)
825}
826
827fn encode_f32_ordered(f: f32) -> u32 {
830 if f.is_nan() {
831 return 0;
832 }
833 if f == 0.0 {
834 return 0x8000_0001;
835 }
836 let bits = f.to_bits();
837 let ordered = if f.is_sign_negative() {
838 !bits
839 } else {
840 bits ^ 0x8000_0000
841 };
842 ordered + 1
843}
844
845fn decode_f32_ordered(bits: u32) -> f32 {
846 if bits == 0 {
847 return f32::NAN;
848 }
849 let ordered = bits - 1;
850 if ordered & 0x8000_0000 != 0 {
851 f32::from_bits(ordered ^ 0x8000_0000)
852 } else {
853 f32::from_bits(!ordered)
854 }
855}
856
857fn encode_f64_ordered(f: f64) -> u64 {
858 if f.is_nan() {
859 return 0;
860 }
861 if f == 0.0 {
862 return 0x8000_0000_0000_0001;
863 }
864 let bits = f.to_bits();
865 let ordered = if f.is_sign_negative() {
866 !bits
867 } else {
868 bits ^ 0x8000_0000_0000_0000
869 };
870 ordered + 1
871}
872
873fn decode_f64_ordered(bits: u64) -> f64 {
874 if bits == 0 {
875 return f64::NAN;
876 }
877 let ordered = bits - 1;
878 if ordered & 0x8000_0000_0000_0000 != 0 {
879 f64::from_bits(ordered ^ 0x8000_0000_0000_0000)
880 } else {
881 f64::from_bits(!ordered)
882 }
883}
884
885#[cfg(test)]
886mod tests {
887 use super::*;
888 use crate::value::date_time::{DateTimeValue, DateValue, TimeValue};
889 use crate::value::UuidValue;
890
891 fn codec() -> OrderedCodec {
892 OrderedCodec::new()
893 }
894
895 #[test]
896 fn test_null() {
897 let v = Value::Null(NullType::Null);
898 let enc = codec().encode(&v).unwrap();
899 let dec = codec().decode(&enc).unwrap();
900 assert_eq!(dec, v);
901 }
902
903 #[test]
904 fn test_null_variants_roundtrip_in_wire_order() {
905 let values = [
906 NullType::Null,
907 NullType::NaN,
908 NullType::BadData,
909 NullType::BadType,
910 NullType::ErrOverflow,
911 NullType::UnknownProp,
912 NullType::DivByZero,
913 NullType::OutOfRange,
914 ];
915 for pair in values.windows(2) {
916 let left = Value::Null(pair[0].clone());
917 let right = Value::Null(pair[1].clone());
918 assert_eq!(
919 codec()
920 .encode(&left)
921 .unwrap()
922 .cmp(&codec().encode(&right).unwrap()),
923 std::cmp::Ordering::Less
924 );
925 }
926 for null_type in values {
927 let value = Value::Null(null_type);
928 assert_eq!(
929 codec().decode(&codec().encode(&value).unwrap()).unwrap(),
930 value
931 );
932 }
933 }
934
935 #[test]
936 fn test_null_last_preserves_empty_and_null_variants() {
937 for value in [Value::Empty, Value::Null(NullType::BadType)] {
938 let encoded = codec().encode_null_last(&value).unwrap();
939 assert_eq!(codec().decode(&encoded).unwrap(), value);
940 }
941 }
942
943 #[test]
944 fn test_empty() {
945 let v = Value::Empty;
946 let enc = codec().encode(&v).unwrap();
947 let dec = codec().decode(&enc).unwrap();
948 assert_eq!(dec, v);
949 }
950
951 #[test]
952 fn test_bool() {
953 for v in &[Value::Bool(false), Value::Bool(true)] {
954 let enc = codec().encode(v).unwrap();
955 let dec = codec().decode(&enc).unwrap();
956 assert_eq!(dec, *v);
957 }
958 }
959
960 #[test]
961 fn test_bool_order() {
962 let f = codec().encode(&Value::Bool(false)).unwrap();
963 let t = codec().encode(&Value::Bool(true)).unwrap();
964 assert!(f < t, "false < true");
965 }
966
967 #[test]
968 fn test_ints() {
969 let cases = [
970 Value::SmallInt(i16::MIN),
971 Value::SmallInt(-1),
972 Value::SmallInt(0),
973 Value::SmallInt(42),
974 Value::SmallInt(i16::MAX),
975 Value::Int(i32::MIN),
976 Value::Int(-1),
977 Value::Int(0),
978 Value::Int(42),
979 Value::Int(i32::MAX),
980 Value::BigInt(i64::MIN),
981 Value::BigInt(-1),
982 Value::BigInt(0),
983 Value::BigInt(42),
984 Value::BigInt(i64::MAX),
985 ];
986 for v in &cases {
987 let enc = codec().encode(v).unwrap();
988 let dec = codec().decode(&enc).unwrap();
989 assert_eq!(dec, *v, "roundtrip failed for {:?}", v);
990 }
991 }
992
993 #[test]
994 fn test_int_order() {
995 let neg = codec().encode(&Value::Int(-5)).unwrap();
996 let zero = codec().encode(&Value::Int(0)).unwrap();
997 let pos = codec().encode(&Value::Int(5)).unwrap();
998 assert!(neg < zero, "-5 < 0");
999 assert!(zero < pos, "0 < 5");
1000 }
1001
1002 #[test]
1003 fn test_float() {
1004 let cases = [
1005 Value::Float(f32::NEG_INFINITY),
1006 Value::Float(-1.0),
1007 Value::Float(-0.0),
1008 Value::Float(0.0),
1009 Value::Float(1.0),
1010 Value::Float(f32::INFINITY),
1011 Value::Double(f64::NEG_INFINITY),
1012 Value::Double(-1.0),
1013 Value::Double(-0.0),
1014 Value::Double(0.0),
1015 Value::Double(1.0),
1016 Value::Double(f64::INFINITY),
1017 ];
1018 for v in &cases {
1019 let enc = codec().encode(v).unwrap();
1020 let dec = codec().decode(&enc).unwrap();
1021 assert_eq!(dec, *v, "roundtrip failed for {:?}", v);
1022 }
1023 }
1024
1025 #[test]
1026 fn test_float_order() {
1027 let neg = codec().encode(&Value::Float(-1.0)).unwrap();
1028 let zero = codec().encode(&Value::Float(0.0)).unwrap();
1029 let pos = codec().encode(&Value::Float(1.0)).unwrap();
1030 assert!(neg < zero, "-1 < 0");
1031 assert!(zero < pos, "0 < 1");
1032 }
1033
1034 #[test]
1035 fn test_float_special_values_follow_value_order() {
1036 let nan = Value::Float(f32::NAN);
1037 let negative_zero = Value::Float(-0.0);
1038 let positive_zero = Value::Float(0.0);
1039 let positive = Value::Float(1.0);
1040
1041 assert_eq!(
1042 codec().encode(&negative_zero).unwrap(),
1043 codec().encode(&positive_zero).unwrap()
1044 );
1045 assert_eq!(
1046 codec()
1047 .encode(&nan)
1048 .unwrap()
1049 .cmp(&codec().encode(&positive).unwrap()),
1050 nan.cmp(&positive)
1051 );
1052 assert_eq!(codec().decode(&codec().encode(&nan).unwrap()).unwrap(), nan);
1053 }
1054
1055 #[test]
1056 fn test_double_special_values_follow_value_order() {
1057 let nan = Value::Double(f64::NAN);
1058 let negative_zero = Value::Double(-0.0);
1059 let positive_zero = Value::Double(0.0);
1060 let positive = Value::Double(1.0);
1061
1062 assert_eq!(
1063 codec().encode(&negative_zero).unwrap(),
1064 codec().encode(&positive_zero).unwrap()
1065 );
1066 assert_eq!(
1067 codec()
1068 .encode(&nan)
1069 .unwrap()
1070 .cmp(&codec().encode(&positive).unwrap()),
1071 nan.cmp(&positive)
1072 );
1073 assert_eq!(codec().decode(&codec().encode(&nan).unwrap()).unwrap(), nan);
1074 }
1075
1076 #[test]
1077 fn test_string_roundtrip() {
1078 let cases = [
1079 Value::string(""),
1080 Value::string("hello"),
1081 Value::string("世界"),
1082 Value::FixedString("fixed".to_string()),
1083 ];
1084 for v in &cases {
1085 let enc = codec().encode(v).unwrap();
1086 let dec = codec().decode(&enc).unwrap();
1087 assert_eq!(dec, *v);
1088 }
1089 }
1090
1091 #[test]
1092 fn test_string_order_aa_less_than_b() {
1093 let aa = codec().encode(&Value::string("aa")).unwrap();
1094 let b = codec().encode(&Value::string("b")).unwrap();
1095 assert!(
1096 aa < b,
1097 "encoded('aa') < encoded('b') must hold for semantic ordering"
1098 );
1099 }
1100
1101 #[test]
1102 fn test_string_order() {
1103 let a = codec().encode(&Value::string("a")).unwrap();
1104 let b = codec().encode(&Value::string("b")).unwrap();
1105 assert!(a < b);
1106 }
1107
1108 #[test]
1109 fn test_blob_roundtrip() {
1110 let cases = vec![
1111 Value::Blob(vec![]),
1112 Value::Blob(vec![0x01, 0x02, 0x03]),
1113 Value::Blob(vec![0xFF, 0xFE]),
1114 ];
1115 for v in cases {
1116 let enc = codec().encode(&v).unwrap();
1117 let dec = codec().decode(&enc).unwrap();
1118 assert_eq!(dec, v, "roundtrip failed for {:?}", v);
1119 }
1120 }
1121
1122 #[test]
1123 fn test_blob_roundtrips_zero_byte() {
1124 let v = Value::Blob(vec![0x00, 0x01]);
1125 assert_eq!(codec().decode(&codec().encode(&v).unwrap()).unwrap(), v);
1126 }
1127
1128 #[test]
1129 fn test_string_roundtrips_zero_byte() {
1130 let v = Value::string("a\x00b");
1131 assert_eq!(codec().decode(&codec().encode(&v).unwrap()).unwrap(), v);
1132 }
1133
1134 #[test]
1135 fn test_prefix_bounds_string() {
1136 let (lower, upper) = codec().prefix_bounds(&Value::string("a")).unwrap();
1137 assert_eq!(lower[0], TAG_STRING);
1139 assert_eq!(&lower[1..lower.len() - 2], b"a");
1140 assert_eq!(lower[lower.len() - 1], 0x00);
1141
1142 assert_eq!(upper, vec![TAG_STRING, 0x62]);
1144
1145 for suffix in &["", "a", "aa", "az"] {
1147 let s_val = format!("a{}", suffix);
1148 let enc = codec().encode(&Value::string(s_val)).unwrap();
1149 assert!(enc.as_slice() >= lower.as_slice(), "{:?} >= lower", suffix);
1150 assert!(enc.as_slice() < upper.as_slice(), "{:?} < upper", suffix);
1151 }
1152
1153 let b_enc = codec().encode(&Value::string("b")).unwrap();
1155 assert!(b_enc.as_slice() >= upper.as_slice());
1156 }
1157
1158 #[test]
1159 fn test_prefix_bounds_multi_byte() {
1160 let (lower, upper) = codec().prefix_bounds(&Value::string("ab")).unwrap();
1161 assert_eq!(&lower[1..lower.len() - 2], b"ab");
1162 assert_eq!(upper, vec![TAG_STRING, 0x61, 0x63]);
1163
1164 let aba = codec().encode(&Value::string("aba")).unwrap();
1165 assert!(aba.as_slice() < upper.as_slice());
1166
1167 let ac = codec().encode(&Value::string("ac")).unwrap();
1168 assert!(ac.as_slice() >= upper.as_slice());
1169 }
1170
1171 #[test]
1172 fn test_prefix_bounds_blob() {
1173 let (lower, upper) = codec()
1174 .prefix_bounds(&Value::Blob(vec![0x01, 0x02]))
1175 .unwrap();
1176 assert_eq!(lower[0], TAG_BLOB);
1177 assert_eq!(&lower[1..lower.len() - 2], &[0x01, 0x02]);
1178 assert_eq!(upper, vec![TAG_BLOB, 0x01, 0x03]);
1179 }
1180
1181 #[test]
1182 fn test_prefix_bounds_int() {
1183 let (lower, upper) = codec().prefix_bounds(&Value::Int(42)).unwrap();
1184 assert!(lower < upper);
1185 let forty_two = codec().encode(&Value::Int(42)).unwrap();
1188 assert_eq!(lower, forty_two);
1189 }
1190
1191 #[test]
1192 fn test_encoded_order_matches_semantic_order() {
1193 let pairs: [(Value, Value); 4] = [
1196 (Value::string("aa"), Value::string("b")),
1197 (Value::string("a"), Value::string("aa")),
1198 (Value::string(""), Value::string("a")),
1199 (Value::string("a"), Value::string("ab")),
1200 ];
1201 for (a, b) in &pairs {
1202 let enc_a = codec().encode(a).unwrap();
1203 let enc_b = codec().encode(b).unwrap();
1204 assert!(
1205 enc_a < enc_b,
1206 "ordered_codec: {:?} < {:?} should hold, but enc({:?}) >= enc({:?})",
1207 a,
1208 b,
1209 a,
1210 b
1211 );
1212 }
1213 }
1214
1215 #[test]
1216 fn test_prefix_bounds_overflow() {
1217 let (lower, upper) = codec()
1219 .prefix_bounds(&Value::Blob(vec![0x01, 0xFF]))
1220 .unwrap();
1221 assert_eq!(&lower[1..lower.len() - 2], &[0x01, 0xFF]);
1222 assert_eq!(upper, vec![TAG_BLOB, 0x02, 0x00]);
1224
1225 let test = codec()
1227 .encode(&Value::Blob(vec![0x01, 0xFF, 0x01]))
1228 .unwrap();
1229 assert!(test.as_slice() < upper.as_slice(), "0x01,0xFF,0x01 < upper");
1230 let next = codec().encode(&Value::Blob(vec![0x02])).unwrap();
1232 assert!(next.as_slice() >= upper.as_slice(), "0x02 >= upper");
1233 }
1234
1235 #[test]
1236 fn test_uuid() {
1237 let u = Value::Uuid(UuidValue::from_bytes([
1238 0x55, 0x0E, 0x84, 0x00, 0xE2, 0x9B, 0x41, 0xD4, 0xA7, 0x16, 0x44, 0x66, 0x55, 0x44,
1239 0x00, 0x00,
1240 ]));
1241 let enc = codec().encode(&u).unwrap();
1242 let dec = codec().decode(&enc).unwrap();
1243 assert_eq!(dec, u);
1244 }
1245
1246 #[test]
1247 fn test_date() {
1248 let v = Value::Date(DateValue {
1249 year: 2024,
1250 month: 6,
1251 day: 15,
1252 });
1253 let enc = codec().encode(&v).unwrap();
1254 let dec = codec().decode(&enc).unwrap();
1255 assert_eq!(dec, v);
1256 }
1257
1258 #[test]
1259 fn test_time() {
1260 let v = Value::Time(TimeValue {
1261 hour: 14,
1262 minute: 30,
1263 sec: 0,
1264 microsec: 500_000,
1265 });
1266 let enc = codec().encode(&v).unwrap();
1267 let dec = codec().decode(&enc).unwrap();
1268 assert_eq!(dec, v);
1269 }
1270
1271 #[test]
1272 fn test_datetime() {
1273 let v = Value::DateTime(DateTimeValue {
1274 year: 2024,
1275 month: 6,
1276 day: 15,
1277 hour: 14,
1278 minute: 30,
1279 sec: 0,
1280 microsec: 500,
1281 });
1282 let enc = codec().encode(&v).unwrap();
1283 let dec = codec().decode(&enc).unwrap();
1284 assert_eq!(dec, v);
1285 }
1286
1287 #[test]
1288 fn test_composite_key() {
1289 let v1 = Value::string("name");
1290 let v2 = Value::Int(42);
1291 let vid = VertexId::try_from_int64(123).expect("test vertex id");
1292 let entity = EntityRef::Vertex(vid);
1293
1294 let key = codec()
1295 .encode_composite(&[&v1, &v2], Some(&entity), false)
1296 .unwrap();
1297 assert!(!key.is_empty());
1298
1299 let (dv1, c1) = codec().decode_value_inner(&key).unwrap();
1300 assert_eq!(dv1, v1);
1301 let (dv2, _c2) = codec().decode_value_inner(&key[c1..]).unwrap();
1302 assert_eq!(dv2, v2);
1303 }
1304
1305 #[test]
1306 fn test_composite_order() {
1307 let pre = Value::string("a");
1308 let k1 = codec()
1309 .encode_composite(&[&pre, &Value::Int(1)], None, false)
1310 .unwrap();
1311 let k2 = codec()
1312 .encode_composite(&[&pre, &Value::Int(2)], None, false)
1313 .unwrap();
1314 assert!(k1 < k2);
1315
1316 let k3 = codec()
1317 .encode_composite(&[&Value::string("b"), &Value::Int(0)], None, false)
1318 .unwrap();
1319 assert!(k1 < k3, "'a' prefix < 'b' prefix");
1320 }
1321
1322 #[test]
1323 fn test_prefix_upper_bound() {
1324 assert_eq!(OrderedCodec::prefix_upper_bound(&[1, 2, 3]), vec![1, 2, 4]);
1325 assert_eq!(OrderedCodec::prefix_upper_bound(&[1, 255]), vec![2, 0]);
1326 assert_eq!(
1327 OrderedCodec::prefix_upper_bound(&[255, 255, 255]),
1328 vec![0, 0, 0]
1329 );
1330 }
1331
1332 #[test]
1333 fn test_vertex_id_tie_breaker() {
1334 let vid = VertexId::try_from_int64(42).expect("test vertex id");
1335 let v = Value::string("hello");
1336 let key = codec()
1337 .encode_composite(&[&v], Some(&EntityRef::Vertex(vid)), false)
1338 .unwrap();
1339 let (dec, _c) = codec().decode_value_inner(&key).unwrap();
1340 assert_eq!(dec, v);
1341 }
1342
1343 #[test]
1344 fn test_vertex_id_entity_roundtrip_supports_max_length() {
1345 let vid =
1346 VertexId::try_from_string("12345678901234567890123456789012").expect("test vertex id");
1347 let entity = EntityRef::Vertex(vid);
1348 let mut encoded = Vec::new();
1349 codec().encode_entity(&entity, &mut encoded).unwrap();
1350
1351 let (decoded, consumed) = codec().decode_entity_bytes(&encoded).unwrap();
1352 assert_eq!(decoded, entity);
1353 assert_eq!(consumed, encoded.len());
1354 }
1355
1356 #[test]
1357 fn ordered_codec_integer_property() {
1358 let groups = [
1359 vec![
1360 Value::SmallInt(i16::MIN),
1361 Value::SmallInt(-1),
1362 Value::SmallInt(0),
1363 Value::SmallInt(i16::MAX),
1364 ],
1365 vec![
1366 Value::Int(i32::MIN),
1367 Value::Int(-1),
1368 Value::Int(0),
1369 Value::Int(i32::MAX),
1370 ],
1371 vec![
1372 Value::BigInt(i64::MIN),
1373 Value::BigInt(-1),
1374 Value::BigInt(0),
1375 Value::BigInt(i64::MAX),
1376 ],
1377 ];
1378 for values in groups {
1379 for pair in values.windows(2) {
1380 let semantic = pair[0].cmp(&pair[1]);
1381 let encoded = codec()
1382 .encode(&pair[0])
1383 .unwrap()
1384 .cmp(&codec().encode(&pair[1]).unwrap());
1385 assert_eq!(
1386 encoded, semantic,
1387 "integer order changed for {:?} and {:?}",
1388 pair[0], pair[1]
1389 );
1390 }
1391 }
1392 }
1393
1394 #[test]
1395 fn ordered_codec_string_and_blob_property() {
1396 let strings = ["", "a", "aa", "b", "世界", "z\0a"];
1397 for pair in strings.windows(2) {
1398 let left = Value::string(pair[0]);
1399 let right = Value::string(pair[1]);
1400 assert_eq!(
1401 codec()
1402 .encode(&left)
1403 .unwrap()
1404 .cmp(&codec().encode(&right).unwrap()),
1405 left.cmp(&right)
1406 );
1407 }
1408
1409 let blobs = [vec![], vec![0], vec![0, 1], vec![1], vec![1, 255], vec![2]];
1410 for pair in blobs.windows(2) {
1411 let left = Value::Blob(pair[0].clone());
1412 let right = Value::Blob(pair[1].clone());
1413 assert_eq!(
1414 codec()
1415 .encode(&left)
1416 .unwrap()
1417 .cmp(&codec().encode(&right).unwrap()),
1418 left.cmp(&right)
1419 );
1420 }
1421 }
1422
1423 #[test]
1424 fn ordered_codec_decimal_property() {
1425 let values = [
1426 "-100.5", "-1.25", "-0.01", "0", "0.01", "0.1", "1.2", "1.20", "10", "100.5", "1e3",
1427 ]
1428 .into_iter()
1429 .map(|text| Value::Decimal128(text.parse().expect("decimal fixture should parse")))
1430 .collect::<Vec<_>>();
1431 for pair in values.windows(2) {
1432 assert_eq!(
1433 codec()
1434 .encode(&pair[0])
1435 .unwrap()
1436 .cmp(&codec().encode(&pair[1]).unwrap()),
1437 pair[0].cmp(&pair[1])
1438 );
1439 assert_eq!(
1440 codec().decode(&codec().encode(&pair[0]).unwrap()).unwrap(),
1441 pair[0]
1442 );
1443 }
1444 }
1445
1446 #[test]
1447 fn ordered_codec_rejects_unrepresentable_decimal_exponents() {
1448 let bytes = [TAG_DECIMAL, 1, 0, 0, 0, 0, b'1', 0];
1449 assert!(codec().decode(&bytes).is_err());
1450 }
1451
1452 #[test]
1453 fn ordered_codec_composite_prefix_property() {
1454 let first = Value::string("user");
1455 let second = Value::Int(1);
1456 let third = Value::Int(2);
1457 let first_key = codec()
1458 .encode_composite(&[&first, &second], None, false)
1459 .unwrap();
1460 let second_key = codec()
1461 .encode_composite(&[&first, &third], None, false)
1462 .unwrap();
1463 let other_key = codec()
1464 .encode_composite(&[&Value::string("user2"), &second], None, false)
1465 .unwrap();
1466 assert!(first_key < second_key);
1467 assert!(second_key < other_key);
1468 let (decoded_first, consumed) = codec().decode_value_inner(&first_key).unwrap();
1469 let (decoded_second, _) = codec().decode_value_inner(&first_key[consumed..]).unwrap();
1470 assert_eq!(decoded_first, first);
1471 assert_eq!(decoded_second, second);
1472 }
1473
1474 #[test]
1475 fn ordered_codec_supported_type_tags_follow_value_priority() {
1476 let values = [
1477 Value::Empty,
1478 Value::Null(NullType::Null),
1479 Value::Bool(false),
1480 Value::SmallInt(0),
1481 Value::Int(0),
1482 Value::BigInt(0),
1483 Value::Float(0.0),
1484 Value::Double(0.0),
1485 Value::Decimal128("0".parse().expect("decimal fixture should parse")),
1486 Value::Date(DateValue {
1487 year: 2024,
1488 month: 1,
1489 day: 1,
1490 }),
1491 Value::Time(TimeValue {
1492 hour: 0,
1493 minute: 0,
1494 sec: 0,
1495 microsec: 0,
1496 }),
1497 Value::DateTime(DateTimeValue {
1498 year: 2024,
1499 month: 1,
1500 day: 1,
1501 hour: 0,
1502 minute: 0,
1503 sec: 0,
1504 microsec: 0,
1505 }),
1506 Value::string(""),
1507 Value::FixedString(String::new()),
1508 Value::Blob(Vec::new()),
1509 Value::Uuid(UuidValue::from_bytes([0; 16])),
1510 ];
1511 for pair in values.windows(2) {
1512 assert_eq!(
1513 codec()
1514 .encode(&pair[0])
1515 .unwrap()
1516 .cmp(&codec().encode(&pair[1]).unwrap()),
1517 std::cmp::Ordering::Less,
1518 "type order changed for {:?} and {:?}",
1519 pair[0],
1520 pair[1]
1521 );
1522 }
1523 }
1524}