Skip to main content

fxfs/serialized_types/
serialized_key.rs

1// Copyright 2026 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! This module implements a zero-copy/optimized byte representation for keys in Fxfs.
6//!
7//! Its goal is to facilitate lexicographically comparable key serialization, permitting optimal
8//! byte representations when performing operations across persistent layer structures in LSM trees.
9
10use crate::serialized_types::varint::{self, Buffer};
11use anyhow::{Error, anyhow, ensure};
12use std::cmp;
13
14/// Maximum length of a single key serialization chunk payload.
15pub const MAX_CHUNK_LEN: usize = 255;
16
17/// Evaluates comparison ordering between two serialized keys located at the beginning of `a` and
18/// `b`.
19///
20/// Both byte slices must start with chunked key data. If the serialized key is <= 254 bytes,
21/// it is prefixed by a 1-byte length. If 255 bytes or longer (>= 255 bytes), it is serialized
22/// as a sequence of 255-byte chunks. Any trailing bytes after each serialized key are ignored.
23#[inline(always)]
24pub fn compare_keys(a: &[u8], b: &[u8]) -> Result<cmp::Ordering, Error> {
25    if !a.is_empty() && !b.is_empty() {
26        let len_a = a[0] as usize;
27        let len_b = b[0] as usize;
28        if a.len() > len_a && b.len() > len_b {
29            let order = a[1..1 + len_a].cmp(&b[1..1 + len_b]);
30            if order.is_ne() || len_a != MAX_CHUNK_LEN {
31                return Ok(order);
32            }
33            return compare_keys_slow(&a[1 + MAX_CHUNK_LEN..], &b[1 + MAX_CHUNK_LEN..]);
34        }
35    }
36    compare_keys_slow(a, b)
37}
38
39/// Fallback path for `compare_keys` when either key spans multiple chunks (chunk length == 255)
40/// or buffers are malformed.
41#[cold]
42#[inline(never)]
43fn compare_keys_slow(mut a: &[u8], mut b: &[u8]) -> Result<cmp::Ordering, Error> {
44    #[inline]
45    fn get_chunk(chunk: &[u8]) -> Result<&[u8], Error> {
46        ensure!(!chunk.is_empty(), "Key buffer truncated");
47        let len = chunk[0] as usize;
48        ensure!(chunk.len() > len, "Key length exceeds buffer");
49        Ok(&chunk[1..1 + len])
50    }
51
52    loop {
53        let chunk_a = get_chunk(a)?;
54        let chunk_b = get_chunk(b)?;
55
56        let order = chunk_a.cmp(chunk_b);
57        let has_more_a = chunk_a.len() == MAX_CHUNK_LEN;
58
59        if order.is_ne() || !has_more_a {
60            return Ok(order);
61        }
62
63        a = &a[MAX_CHUNK_LEN + 1..];
64        b = &b[MAX_CHUNK_LEN + 1..];
65    }
66}
67
68/// Serializes keys sequentially into binary format suitable for lexicographical comparisons.
69///
70/// The key layout contains:
71/// - Sequences of 255-byte chunks, each prefixed with a 1-byte length.
72/// - If a serialized key is <= 254 bytes, it is represented as a single chunk with a 1-byte length.
73/// - If exactly a multiple of 255 bytes, it is terminated by a 0-length chunk.
74pub struct KeySerializer<'a, B: Buffer> {
75    buffer: &'a mut B,
76    start_pos: usize,
77    /// Optional delta base subtracted from the first `u64` payload item.
78    base: Option<u64>,
79}
80
81/// Proof token returned when key serialization has finalized its length headers.
82///
83/// Variable-length trailing types (`String`, `CasefoldString`, `Vec<u8>`) and terminal enums
84/// consume `KeySerializer` and return `KeySerializerFinalized`, making it a compile-time error to
85/// serialize any subsequent fields after a variable-length trailing field.
86#[derive(Debug)]
87pub struct KeySerializerFinalized(());
88
89impl<B: Buffer> From<KeySerializer<'_, B>> for KeySerializerFinalized {
90    #[inline]
91    fn from(serializer: KeySerializer<'_, B>) -> Self {
92        serializer.finalize()
93    }
94}
95
96/// Combines two `SerializeKey::Output` types across enum variants: produces `KeySerializer<'a, B>`
97/// if both variants are non-terminal, or `KeySerializerFinalized` if either variant is terminal.
98pub trait MergeSerializerOutput<Rhs>: Sized {
99    type Output: Into<KeySerializerFinalized> + From<Self> + From<Rhs>;
100}
101
102impl<'a, B: Buffer + 'a> MergeSerializerOutput<KeySerializer<'a, B>> for KeySerializer<'a, B> {
103    type Output = KeySerializer<'a, B>;
104}
105
106impl<'a, B: Buffer + 'a> MergeSerializerOutput<KeySerializerFinalized> for KeySerializer<'a, B> {
107    type Output = KeySerializerFinalized;
108}
109
110impl<'a, B: Buffer + 'a> MergeSerializerOutput<KeySerializer<'a, B>> for KeySerializerFinalized {
111    type Output = KeySerializerFinalized;
112}
113
114impl MergeSerializerOutput<KeySerializerFinalized> for KeySerializerFinalized {
115    type Output = KeySerializerFinalized;
116}
117
118impl<'a, B: Buffer> KeySerializer<'a, B> {
119    /// Creates a new `KeySerializer` attached to a persistent storage buffer.
120    #[inline]
121    pub fn new(buffer: &'a mut B, base: Option<u64>) -> Self {
122        let start_pos = buffer.as_ref().len();
123        buffer.put(&[0]);
124        Self { buffer, start_pos, base }
125    }
126
127    /// Writes an order-preserving varint-encoded 64-bit payload to the buffer without base delta encoding.
128    #[inline]
129    pub fn write_varint(&mut self, v: u64) {
130        let (bytes, len) = varint::encode_varint_bytes(v);
131        self.write_bytes(&bytes[..len]);
132    }
133
134    /// Writes an order-preserving varint-encoded 64-bit payload to the buffer.
135    ///
136    /// If a delta `base` was provided and this is the first item written, it writes the delta
137    /// `v - base`. Otherwise, writes `v` as an order-preserving varint.
138    #[inline]
139    pub fn write_u64(&mut self, v: u64) {
140        if let Some(base) = self.base.take() {
141            assert!(v >= base, "Delta encoding underflow: v ({v}) < base ({base})");
142            self.write_varint(v - base);
143        } else {
144            self.write_varint(v);
145        }
146    }
147
148    /// Writes a raw byte slice into the serialization stream. Non-terminal fields are assumed to
149    /// fit within the initial chunk.
150    #[inline]
151    pub fn write_bytes(&mut self, bytes: &[u8]) {
152        assert!(self.base.is_none(), "write_u64 with base must be the first item");
153        assert!(
154            self.buffer.as_ref().len() - self.start_pos - 1 + bytes.len() <= MAX_CHUNK_LEN,
155            "Non-terminal key fields must fit within the initial chunk"
156        );
157        self.buffer.put(bytes);
158    }
159
160    /// Writes trailing variable-length dynamic bytes to the serialization buffer, crossing chunk
161    /// boundaries as needed, then immediately finalizes the key.
162    #[inline]
163    pub fn write_last(self, mut bytes: &[u8]) -> KeySerializerFinalized {
164        assert!(self.base.is_none(), "write_u64 with base must be the first item");
165        while !bytes.is_empty() {
166            let total_minus_1 = self.buffer.as_ref().len() - self.start_pos - 1;
167            let chunk_len = total_minus_1 & 0xff;
168            let space = MAX_CHUNK_LEN - chunk_len;
169            if space == 0 {
170                let chunk_start = self.start_pos + (total_minus_1 & !0xff);
171                self.buffer.as_mut()[chunk_start] = MAX_CHUNK_LEN as u8;
172                self.buffer.put(&[0]);
173                continue;
174            }
175            let to_write = std::cmp::min(bytes.len(), space);
176            self.buffer.put(&bytes[..to_write]);
177            bytes = &bytes[to_write..];
178        }
179        self.finalize()
180    }
181
182    /// Resolves chunk lengths and finalizes the key serialization.
183    #[inline]
184    pub fn finalize(self) -> KeySerializerFinalized {
185        assert!(self.base.is_none(), "write_u64 with base must be the first item");
186        let total_minus_1 = self.buffer.as_ref().len() - self.start_pos - 1;
187        let chunk_len = total_minus_1 & 0xff;
188        let chunk_start = self.start_pos + (total_minus_1 & !0xff);
189        if chunk_len == MAX_CHUNK_LEN {
190            self.buffer.as_mut()[chunk_start] = MAX_CHUNK_LEN as u8;
191            self.buffer.put(&[0]);
192        } else {
193            self.buffer.as_mut()[chunk_start] = chunk_len as u8;
194        }
195        KeySerializerFinalized(())
196    }
197}
198
199/// Handles decoding of sequential serialized key payloads.
200pub struct KeyDeserializer<'a> {
201    /// Current chunk unconsumed payload bytes.
202    chunk: &'a [u8],
203    /// Remaining buffer starting at next chunk header (or empty if no more chunks).
204    remaining_chunks: &'a [u8],
205    /// Optional delta base added to the first `u64` payload item.
206    base: Option<u64>,
207}
208
209impl<'a> KeyDeserializer<'a> {
210    /// Parses a serialized chunked key from the front of `data`.
211    ///
212    /// Returns the deserializer positioned at the key payload, along with the total
213    /// bytes consumed in `data` (headers + payload chunks).
214    #[inline]
215    pub fn new(data: &'a [u8], base: Option<u64>) -> Result<(Self, usize), Error> {
216        ensure!(!data.is_empty(), "Key buffer truncated");
217        let first_len = data[0] as usize;
218        ensure!(data.len() > first_len, "Key length exceeds buffer");
219        let chunk = &data[1..1 + first_len];
220        let mut total_len = 1 + first_len;
221        let remaining_chunks = if first_len == MAX_CHUNK_LEN {
222            let mut rem = &data[MAX_CHUNK_LEN + 1..];
223            let mut last_len = first_len;
224            while last_len == MAX_CHUNK_LEN {
225                ensure!(!rem.is_empty(), "Key buffer truncated");
226                let l = rem[0] as usize;
227                ensure!(rem.len() > l, "Key length exceeds buffer");
228                total_len += 1 + l;
229                rem = if l == MAX_CHUNK_LEN { &rem[MAX_CHUNK_LEN + 1..] } else { &[] };
230                last_len = l;
231            }
232            &data[MAX_CHUNK_LEN + 1..total_len]
233        } else {
234            &[]
235        };
236        Ok((Self { chunk, remaining_chunks, base }, total_len))
237    }
238
239    /// Returns true if all payload bytes have been consumed.
240    #[inline]
241    pub fn is_empty(&self) -> bool {
242        self.chunk.is_empty() && self.remaining_chunks.is_empty()
243    }
244
245    /// Reads exactly `buf.len()` bytes into `buf`. Non-terminal fields are assumed to fit within
246    /// the initial chunk.
247    #[inline]
248    pub fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Error> {
249        ensure!(self.base.is_none(), "read_u64 with base must be the first item");
250        ensure!(self.chunk.len() >= buf.len(), "Data array boundary overrun");
251        buf.copy_from_slice(&self.chunk[..buf.len()]);
252        self.chunk = &self.chunk[buf.len()..];
253        Ok(())
254    }
255
256    /// Reads a 64-bit unsigned integer. If a base was provided and this is the first item,
257    /// adds the base to reconstruct the original value.
258    #[inline]
259    pub fn read_u64(&mut self) -> Result<u64, Error> {
260        let base = self.base.take();
261        let v = self.read_varint()?;
262        if let Some(base) = base {
263            Ok(v.checked_add(base).ok_or_else(|| {
264                anyhow::anyhow!("Delta decoding overflow: v ({}) + base ({})", v, base)
265            })?)
266        } else {
267            Ok(v)
268        }
269    }
270
271    /// Extracts an order-preserving decoded 64-bit variable length integer from stream.
272    #[inline]
273    pub fn read_varint(&mut self) -> Result<u64, Error> {
274        ensure!(self.base.is_none(), "read_u64 with base must be the first item");
275        let (v, remainder) = varint::decode_varint(self.chunk)?;
276        self.chunk = remainder;
277        Ok(v)
278    }
279
280    /// Consumes and returns all remaining bytes in the key payload.
281    #[inline]
282    pub fn read_last(&mut self) -> Result<Vec<u8>, Error> {
283        ensure!(self.base.is_none(), "read_u64 with base must be the first item");
284        let mut result = Vec::with_capacity(self.chunk.len() + self.remaining_chunks.len());
285        result.extend_from_slice(self.chunk);
286        self.chunk = &[];
287        while !self.remaining_chunks.is_empty() {
288            let len = self.remaining_chunks[0] as usize;
289            result.extend_from_slice(&self.remaining_chunks[1..1 + len]);
290            self.remaining_chunks = if len == MAX_CHUNK_LEN {
291                &self.remaining_chunks[MAX_CHUNK_LEN + 1..]
292            } else {
293                &[]
294            };
295        }
296        Ok(result)
297    }
298}
299
300/// Trait defining the translation logic from Fxfs types into order-consistent binaries.
301pub trait SerializeKey: Sized {
302    /// The serializer state returned after writing this type (`KeySerializer` for non-terminal
303    /// types, or `KeySerializerFinalized` for variable-length trailing types).
304    type Output<'a, B: Buffer + 'a>: Into<KeySerializerFinalized>;
305
306    /// Encodes key representation sequentially into serialization stream.
307    fn serialize_key_to<'a, B: Buffer>(
308        &self,
309        serializer: KeySerializer<'a, B>,
310    ) -> Self::Output<'a, B>;
311
312    /// Decodes serializations sequentially from underlying raw bytes.
313    fn deserialize_key_from(deserializer: &mut KeyDeserializer<'_>) -> Result<Self, Error>;
314
315    /// Serializes this key directly into `buffer` with its length prefix and no delta base.
316    ///
317    /// Matches the ergonomics of serde/bincode `serialize_into`.
318    #[inline]
319    fn serialize_key_into<B: Buffer>(&self, buffer: &mut B) {
320        let serializer = KeySerializer::new(buffer, None);
321        let _: KeySerializerFinalized = self.serialize_key_to(serializer).into();
322    }
323
324    /// Serializes this key directly into `buffer` with its length prefix and delta `base`
325    /// subtracted from the leading `u64`.
326    #[inline]
327    fn serialize_key_with_base_into<B: Buffer>(&self, buffer: &mut B, base: u64)
328    where
329        Self: crate::lsm_tree::types::SortByU64,
330    {
331        let serializer = KeySerializer::new(buffer, Some(base));
332        let _: KeySerializerFinalized = self.serialize_key_to(serializer).into();
333    }
334}
335
336impl SerializeKey for u8 {
337    type Output<'a, B: Buffer + 'a> = KeySerializer<'a, B>;
338
339    #[inline]
340    fn serialize_key_to<'a, B: Buffer>(
341        &self,
342        mut serializer: KeySerializer<'a, B>,
343    ) -> Self::Output<'a, B> {
344        serializer.write_bytes(std::slice::from_ref(self));
345        serializer
346    }
347    #[inline]
348    fn deserialize_key_from(deserializer: &mut KeyDeserializer<'_>) -> Result<Self, Error> {
349        let mut b = [0u8; 1];
350        deserializer.read_exact(&mut b)?;
351        Ok(b[0])
352    }
353}
354
355impl SerializeKey for u32 {
356    type Output<'a, B: Buffer + 'a> = KeySerializer<'a, B>;
357
358    #[inline]
359    fn serialize_key_to<'a, B: Buffer>(
360        &self,
361        mut serializer: KeySerializer<'a, B>,
362    ) -> Self::Output<'a, B> {
363        serializer.write_varint(*self as u64);
364        serializer
365    }
366    #[inline]
367    fn deserialize_key_from(deserializer: &mut KeyDeserializer<'_>) -> Result<Self, Error> {
368        Ok(deserializer.read_varint()?.try_into()?)
369    }
370}
371
372impl SerializeKey for u64 {
373    type Output<'a, B: Buffer + 'a> = KeySerializer<'a, B>;
374
375    #[inline]
376    fn serialize_key_to<'a, B: Buffer>(
377        &self,
378        mut serializer: KeySerializer<'a, B>,
379    ) -> Self::Output<'a, B> {
380        serializer.write_u64(*self);
381        serializer
382    }
383    #[inline]
384    fn deserialize_key_from(deserializer: &mut KeyDeserializer<'_>) -> Result<Self, Error> {
385        deserializer.read_u64()
386    }
387}
388
389impl SerializeKey for String {
390    type Output<'a, B: Buffer + 'a> = KeySerializerFinalized;
391
392    fn serialize_key_to<'a, B: Buffer>(
393        &self,
394        serializer: KeySerializer<'a, B>,
395    ) -> Self::Output<'a, B> {
396        serializer.write_last(self.as_bytes())
397    }
398    fn deserialize_key_from(deserializer: &mut KeyDeserializer<'_>) -> Result<Self, Error> {
399        Ok(String::from_utf8(deserializer.read_last()?)?)
400    }
401}
402
403impl SerializeKey for fxfs_unicode::CasefoldString {
404    type Output<'a, B: Buffer + 'a> = KeySerializerFinalized;
405
406    fn serialize_key_to<'a, B: Buffer>(
407        &self,
408        serializer: KeySerializer<'a, B>,
409    ) -> Self::Output<'a, B> {
410        let s: &str = self.as_str();
411        serializer.write_last(s.as_bytes())
412    }
413    fn deserialize_key_from(deserializer: &mut KeyDeserializer<'_>) -> Result<Self, Error> {
414        Ok(Self::new(String::deserialize_key_from(deserializer)?))
415    }
416}
417
418impl SerializeKey for Vec<u8> {
419    type Output<'a, B: Buffer + 'a> = KeySerializerFinalized;
420
421    fn serialize_key_to<'a, B: Buffer>(
422        &self,
423        serializer: KeySerializer<'a, B>,
424    ) -> Self::Output<'a, B> {
425        serializer.write_last(self)
426    }
427    fn deserialize_key_from(deserializer: &mut KeyDeserializer<'_>) -> Result<Self, Error> {
428        deserializer.read_last()
429    }
430}
431
432impl SerializeKey for std::ops::Range<u64> {
433    type Output<'a, B: Buffer + 'a> = KeySerializer<'a, B>;
434
435    #[inline]
436    fn serialize_key_to<'a, B: Buffer>(
437        &self,
438        serializer: KeySerializer<'a, B>,
439    ) -> Self::Output<'a, B> {
440        // Range upper-bounds are typically critical when evaluating extent allocations
441        // in tree merges, so we write end values before length (end - start) values,
442        // which makes narrower ranges sort first on ties, matching OrdUpperBound.
443        assert!(self.start <= self.end, "Range start must be <= end");
444        let serializer = self.end.serialize_key_to(serializer);
445        (self.end - self.start).serialize_key_to(serializer)
446    }
447    #[inline]
448    fn deserialize_key_from(deserializer: &mut KeyDeserializer<'_>) -> Result<Self, Error> {
449        let end = u64::deserialize_key_from(deserializer)?;
450        let len = u64::deserialize_key_from(deserializer)?;
451        let start = end.checked_sub(len).ok_or_else(|| anyhow!("Underflow in range start"))?;
452        Ok(start..end)
453    }
454}
455
456impl SerializeKey for std::num::NonZeroU64 {
457    type Output<'a, B: Buffer + 'a> = KeySerializer<'a, B>;
458
459    #[inline]
460    fn serialize_key_to<'a, B: Buffer>(
461        &self,
462        serializer: KeySerializer<'a, B>,
463    ) -> Self::Output<'a, B> {
464        self.get().serialize_key_to(serializer)
465    }
466    #[inline]
467    fn deserialize_key_from(deserializer: &mut KeyDeserializer<'_>) -> Result<Self, Error> {
468        let raw = u64::deserialize_key_from(deserializer)?;
469        Self::new(raw).ok_or_else(|| anyhow::anyhow!("Expected non-zero value"))
470    }
471}
472
473#[cfg(test)]
474mod tests {
475    use super::*;
476    use crate::lsm_tree::types::OrdUpperBound;
477    use crate::object_store::allocator::AllocatorKey;
478    use crate::object_store::object_record::{ObjectKey, ObjectKeyData};
479    use crate::object_store::{AttributeId, Extent};
480
481    #[test]
482    fn test_object_key_order_matches_cmp_upper_bound() {
483        let mut keys = Vec::new();
484        // Varint edge cases
485        keys.push(ObjectKey::object(0));
486        keys.push(ObjectKey::object(1));
487        keys.push(ObjectKey::object(0xbe));
488        keys.push(ObjectKey::object(0xbf));
489        keys.push(ObjectKey::object(0xc0));
490        keys.push(ObjectKey::object(0x1ffe));
491        keys.push(ObjectKey::object(0x1fff));
492        keys.push(ObjectKey::object(0x2000));
493        keys.push(ObjectKey::object(0x0fff_ffff));
494        keys.push(ObjectKey::object(0x1000_0000));
495
496        // String edge cases
497        keys.push(ObjectKey { object_id: 1, data: ObjectKeyData::Child { name: "".to_string() } });
498        keys.push(ObjectKey { object_id: 1, data: ObjectKeyData::Child { name: "a".to_string() } });
499        keys.push(ObjectKey { object_id: 1, data: ObjectKeyData::Child { name: "b".to_string() } });
500        keys.push(ObjectKey {
501            object_id: 1,
502            data: ObjectKeyData::Child { name: "aa".to_string() },
503        });
504        keys.push(ObjectKey { object_id: 1, data: ObjectKeyData::Child { name: "a".repeat(300) } });
505
506        // Extent edge cases
507        keys.push(ObjectKey::extent(1, AttributeId::TEST_ID, 100 * 512..200 * 512));
508        keys.push(ObjectKey::extent(1, AttributeId::TEST_ID, 100 * 512..150 * 512));
509        keys.push(ObjectKey::extent(1, AttributeId::TEST_ID, 50 * 512..150 * 512));
510        keys.push(ObjectKey::extent(1, AttributeId::TEST_ID, 150 * 512..200 * 512));
511        keys.push(ObjectKey::extent(2, AttributeId::TEST_ID, 100 * 512..200 * 512));
512        keys.push(ObjectKey::extent(1, AttributeId::TEST_ID, 0..100 * 512));
513        keys.push(ObjectKey::extent(1, AttributeId::TEST_ID, 50 * 512..100 * 512));
514
515        // Compare all pairs. We compare against `cmp_upper_bound` which is now a total order
516        // for ranges (comparing end then start), matching serialization order.
517        for i in 0..keys.len() {
518            for j in 0..keys.len() {
519                let mut buf_a = Vec::new();
520                keys[i].serialize_key_with_base_into(&mut buf_a, 0);
521
522                let mut buf_b = Vec::new();
523                keys[j].serialize_key_with_base_into(&mut buf_b, 0);
524
525                let cmp = keys[i].cmp_upper_bound(&keys[j]);
526                let ser_cmp = compare_keys(&buf_a, &buf_b).unwrap();
527                assert_eq!(cmp, ser_cmp, "Mismatch for keys {:?} and {:?}", keys[i], keys[j]);
528            }
529        }
530    }
531
532    #[test]
533    fn test_allocator_key_order_matches_cmp_upper_bound() {
534        let mut keys = Vec::new();
535        keys.push(AllocatorKey { device_range: Extent(0..100 * 512) });
536        keys.push(AllocatorKey { device_range: Extent(0..200 * 512) });
537        keys.push(AllocatorKey { device_range: Extent(100 * 512..200 * 512) });
538        keys.push(AllocatorKey { device_range: Extent(100 * 512..150 * 512) });
539        keys.push(AllocatorKey { device_range: Extent(50 * 512..150 * 512) });
540        keys.push(AllocatorKey { device_range: Extent(0..50 * 512) });
541        keys.push(AllocatorKey { device_range: Extent(50 * 512..100 * 512) });
542
543        // Compare all pairs. We compare against `cmp_upper_bound` which is now a total order
544        // for ranges, matching serialization order.
545        for i in 0..keys.len() {
546            let base = crate::lsm_tree::types::SortByU64::get_leading_u64(&keys[i]);
547            let mut buf_base = Vec::new();
548            keys[i].serialize_key_with_base_into(&mut buf_base, base);
549            let (mut deser, _) = KeyDeserializer::new(&buf_base, Some(base)).unwrap();
550            assert_eq!(AllocatorKey::deserialize_key_from(&mut deser).unwrap(), keys[i]);
551            assert!(deser.is_empty());
552
553            for j in 0..keys.len() {
554                let mut buf_a = Vec::new();
555                keys[i].serialize_key_with_base_into(&mut buf_a, 0);
556
557                let mut buf_b = Vec::new();
558                keys[j].serialize_key_with_base_into(&mut buf_b, 0);
559
560                let cmp = keys[i].cmp_upper_bound(&keys[j]);
561                let ser_cmp = compare_keys(&buf_a, &buf_b).unwrap();
562
563                assert_eq!(cmp, ser_cmp, "Mismatch for keys {:?} and {:?}", keys[i], keys[j]);
564            }
565        }
566    }
567
568    #[test]
569    fn test_delta_encoding() {
570        let mut buf = Vec::new();
571        let base = 100;
572        let val = 150;
573
574        // Serialize
575        {
576            let mut ser = KeySerializer::new(&mut buf, Some(base));
577            ser.write_u64(val);
578            ser.finalize();
579        }
580
581        // Deserialize
582        let (mut deser, length) = KeyDeserializer::new(&buf, Some(base)).unwrap();
583        assert_eq!(length, buf.len());
584        let decoded_val = deser.read_u64().unwrap();
585
586        assert_eq!(val, decoded_val);
587
588        // Verify bytes (val - base = 50)
589        assert_eq!(buf, vec![1, 50]);
590    }
591
592    #[test]
593    #[should_panic(expected = "Delta encoding underflow")]
594    fn test_delta_encoding_underflow_panics() {
595        let mut buf = Vec::new();
596        let mut ser = KeySerializer::new(&mut buf, Some(100));
597        ser.write_u64(50);
598    }
599
600    #[test]
601    fn test_delta_encoding_only_first() {
602        let mut buf = Vec::new();
603        let base = 100;
604        let val1 = 150;
605        let val2 = 200;
606
607        // Serialize
608        {
609            let mut ser = KeySerializer::new(&mut buf, Some(base));
610            ser.write_u64(val1);
611            ser.write_u64(val2);
612            ser.finalize();
613        }
614
615        // Deserialize
616        let (mut deser, length) = KeyDeserializer::new(&buf, Some(base)).unwrap();
617        assert_eq!(length, buf.len());
618        let decoded_val1 = deser.read_u64().unwrap();
619        let decoded_val2 = deser.read_u64().unwrap();
620
621        assert_eq!(val1, decoded_val1);
622        assert_eq!(val2, decoded_val2);
623    }
624
625    #[test]
626    fn test_delta_encoding_none() {
627        let mut buf = Vec::new();
628        let val = 150;
629
630        // Serialize
631        {
632            let mut ser = KeySerializer::new(&mut buf, None);
633            ser.write_u64(val);
634            ser.finalize();
635        }
636
637        // Deserialize
638        let (mut deser, length) = KeyDeserializer::new(&buf, None).unwrap();
639        assert_eq!(length, buf.len());
640        let decoded_val = deser.read_u64().unwrap();
641
642        assert_eq!(val, decoded_val);
643
644        // Verify bytes (should be regular varint of 150, which fits in 1 byte in this encoding)
645        assert_eq!(buf, vec![1, 150]);
646    }
647
648    #[test]
649    fn test_delta_encoding_overflow_on_read_returns_error() {
650        // Forge a buffer with a large varint.
651        // Varint of u64::MAX is 9 bytes of 0xff.
652        let buf = vec![9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];
653
654        // Deserialize with base = Some(1).
655        // read_u64 should try to add 1 to u64::MAX and return error.
656        let (mut deser, length) = KeyDeserializer::new(&buf, Some(1)).unwrap();
657        assert_eq!(length, buf.len());
658        assert!(deser.read_u64().is_err());
659    }
660
661    #[test]
662    #[should_panic(expected = "write_u64 with base must be the first item")]
663    fn test_write_u64_with_base_not_first_panics() {
664        let mut buf = Vec::new();
665        let base = 100;
666        let val = 150;
667
668        let mut ser = KeySerializer::new(&mut buf, Some(base));
669        ser.write_varint(5); // Write something else first
670        ser.write_u64(val);
671    }
672
673    #[test]
674    #[should_panic(expected = "read_u64 with base must be the first item")]
675    fn test_read_u64_with_base_not_first_panics() {
676        let mut buf = Vec::new();
677        let base = 100;
678        let val1 = 150;
679        let val2 = 200;
680
681        {
682            let mut ser = KeySerializer::new(&mut buf, Some(base));
683            ser.write_u64(val1);
684            ser.write_u64(val2);
685            ser.finalize();
686        }
687
688        let (mut deser, length) = KeyDeserializer::new(&buf, Some(base)).unwrap();
689        assert_eq!(length, buf.len());
690        deser.read_varint().unwrap(); // Reads val1 (delta)
691        deser.read_u64().unwrap(); // Tries to read val2 as u64.
692    }
693
694    #[test]
695    fn test_casefold_string_serialization_preserves_case() {
696        use fxfs_unicode::CasefoldString;
697        let s = CasefoldString::new("Hello World".to_string());
698
699        let mut buf = Vec::new();
700        s.serialize_key_into(&mut buf);
701
702        let (mut deser, len) = KeyDeserializer::new(&buf, None).unwrap();
703        assert_eq!(len, buf.len());
704        let deserialized = CasefoldString::deserialize_key_from(&mut deser).unwrap();
705        assert_eq!(deserialized.as_str(), "Hello World");
706        assert_eq!(deserialized, s);
707    }
708
709    #[test]
710    fn test_chunk_prefix_lengths() {
711        use std::cmp::Ordering;
712
713        // Key < 254 bytes: single byte prefix.
714        let key_100 = vec![42u8; 100];
715        let mut buf_100 = Vec::new();
716        key_100.serialize_key_into(&mut buf_100);
717        assert_eq!(buf_100[0], 100);
718        assert_eq!(buf_100.len(), 101);
719        let (mut deser, len) = KeyDeserializer::new(&buf_100, None).unwrap();
720        assert_eq!(len, 101);
721        assert_eq!(deser.read_last().unwrap(), key_100.as_slice());
722        assert!(deser.is_empty());
723
724        // Key == 254 bytes: single byte prefix (254).
725        let key_254 = vec![42u8; 254];
726        let mut buf_254 = Vec::new();
727        key_254.serialize_key_into(&mut buf_254);
728        assert_eq!(buf_254[0], 254);
729        assert_eq!(buf_254.len(), 255);
730        let (mut deser, len) = KeyDeserializer::new(&buf_254, None).unwrap();
731        assert_eq!(len, 255);
732        assert_eq!(deser.read_last().unwrap(), key_254.as_slice());
733        assert!(deser.is_empty());
734
735        // Key == 255 bytes: chunk 0 has len 255 (256 bytes), chunk 1 has len 0 (1 byte).
736        let key_255 = vec![42u8; 255];
737        let mut buf_255 = Vec::new();
738        key_255.serialize_key_into(&mut buf_255);
739        assert_eq!(buf_255[0], 255);
740        assert_eq!(buf_255[256], 0);
741        assert_eq!(buf_255.len(), 257);
742        let (mut deser, len) = KeyDeserializer::new(&buf_255, None).unwrap();
743        assert_eq!(len, 257);
744        assert_eq!(deser.read_last().unwrap(), key_255.as_slice());
745        assert!(deser.is_empty());
746
747        // Key == 256 bytes: chunk 0 has len 255 (256 bytes), chunk 1 has len 1 (2 bytes).
748        let key_256 = vec![42u8; 256];
749        let mut buf_256 = Vec::new();
750        key_256.serialize_key_into(&mut buf_256);
751        assert_eq!(buf_256[0], 255);
752        assert_eq!(buf_256[256], 1);
753        assert_eq!(buf_256.len(), 258);
754        let (mut deser, len) = KeyDeserializer::new(&buf_256, None).unwrap();
755        assert_eq!(len, 258);
756        assert_eq!(deser.read_last().unwrap(), key_256.as_slice());
757        assert!(deser.is_empty());
758
759        // Key == 510 bytes: chunk 0 (256 bytes), chunk 1 (256 bytes), chunk 2 has len 0 (1 byte).
760        let key_510 = vec![42u8; 510];
761        let mut buf_510 = Vec::new();
762        key_510.serialize_key_into(&mut buf_510);
763        assert_eq!(buf_510[0], 255);
764        assert_eq!(buf_510[256], 255);
765        assert_eq!(buf_510[512], 0);
766        assert_eq!(buf_510.len(), 513);
767        let (mut deser, len) = KeyDeserializer::new(&buf_510, None).unwrap();
768        assert_eq!(len, 513);
769        assert_eq!(deser.read_last().unwrap(), key_510.as_slice());
770        assert!(deser.is_empty());
771
772        // Relative ordering: shorter prefixes compare Less than longer extensions.
773        assert_eq!(compare_keys(&buf_100, &buf_254).unwrap(), Ordering::Less);
774        assert_eq!(compare_keys(&buf_254, &buf_100).unwrap(), Ordering::Greater);
775        assert_eq!(compare_keys(&buf_254, &buf_255).unwrap(), Ordering::Less);
776        assert_eq!(compare_keys(&buf_255, &buf_254).unwrap(), Ordering::Greater);
777        assert_eq!(compare_keys(&buf_255, &buf_256).unwrap(), Ordering::Less);
778        assert_eq!(compare_keys(&buf_256, &buf_255).unwrap(), Ordering::Greater);
779        assert_eq!(compare_keys(&buf_256, &buf_510).unwrap(), Ordering::Less);
780        assert_eq!(compare_keys(&buf_510, &buf_256).unwrap(), Ordering::Greater);
781        assert_eq!(compare_keys(&buf_255, &buf_255).unwrap(), Ordering::Equal);
782        assert_eq!(compare_keys(&buf_510, &buf_510).unwrap(), Ordering::Equal);
783    }
784
785    #[test]
786    fn test_chunk_empty_key() {
787        use std::cmp::Ordering;
788
789        let empty: Vec<u8> = Vec::new();
790        let mut buf = Vec::new();
791        empty.serialize_key_into(&mut buf);
792        assert_eq!(buf, &[0]);
793
794        let (mut deser, len) = KeyDeserializer::new(&buf, None).unwrap();
795        assert_eq!(len, 1);
796        assert!(deser.is_empty());
797        assert_eq!(deser.read_last().unwrap(), &[0u8; 0]);
798
799        let non_empty: Vec<u8> = vec![1];
800        let mut buf_non_empty = Vec::new();
801        non_empty.serialize_key_into(&mut buf_non_empty);
802
803        assert_eq!(compare_keys(&buf, &buf).unwrap(), Ordering::Equal);
804        assert_eq!(compare_keys(&buf, &buf_non_empty).unwrap(), Ordering::Less);
805        assert_eq!(compare_keys(&buf_non_empty, &buf).unwrap(), Ordering::Greater);
806    }
807
808    #[test]
809    fn test_chunk_multiples_of_255() {
810        use std::cmp::Ordering;
811
812        // Multiples: 1 * 255, 2 * 255, 3 * 255, 4 * 255.
813        for multiple in 1..=4 {
814            let num_bytes = multiple * MAX_CHUNK_LEN;
815            let payload: Vec<u8> = (0..num_bytes).map(|i| (i % 251) as u8).collect();
816            let mut buf = Vec::new();
817            payload.serialize_key_into(&mut buf);
818
819            // Expected buffer layout: `multiple` chunks of (1 byte length 255 + 255 bytes payload),
820            // followed by a single 0 byte (terminating chunk).
821            let expected_len = multiple * (1 + MAX_CHUNK_LEN) + 1;
822            assert_eq!(buf.len(), expected_len, "Failed for multiple {}", multiple);
823
824            for c in 0..multiple {
825                assert_eq!(buf[c * (1 + MAX_CHUNK_LEN)], MAX_CHUNK_LEN as u8);
826            }
827            assert_eq!(buf[multiple * (1 + MAX_CHUNK_LEN)], 0);
828
829            // Deserialization round-trip.
830            let (mut deser, len) = KeyDeserializer::new(&buf, None).unwrap();
831            assert_eq!(len, expected_len);
832            let read_back = deser.read_last().unwrap();
833            assert_eq!(read_back, payload.as_slice());
834            assert!(deser.is_empty());
835
836            // Self-comparison.
837            assert_eq!(compare_keys(&buf, &buf).unwrap(), Ordering::Equal);
838        }
839    }
840
841    #[test]
842    fn test_chunk_off_by_one_boundaries() {
843        let sizes = [
844            0, 1, 2, 253, 254, 255, 256, 257, 508, 509, 510, 511, 512, 763, 764, 765, 766, 767,
845            1019, 1020, 1021,
846        ];
847
848        let mut buffers = Vec::new();
849        for &size in &sizes {
850            let payload = vec![0x77u8; size];
851            let mut buf = Vec::new();
852            payload.serialize_key_into(&mut buf);
853
854            let (mut deser, len) = KeyDeserializer::new(&buf, None).unwrap();
855            assert_eq!(len, buf.len());
856            assert_eq!(deser.read_last().unwrap(), payload.as_slice());
857            assert!(deser.is_empty());
858
859            buffers.push((size, buf));
860        }
861
862        // Pairwise comparison ordering matches length ordering since all payloads are identical bytes.
863        for i in 0..buffers.len() {
864            for j in 0..buffers.len() {
865                let (len_i, ref buf_i) = buffers[i];
866                let (len_j, ref buf_j) = buffers[j];
867
868                let expected = len_i.cmp(&len_j);
869                let actual = compare_keys(buf_i, buf_j).unwrap();
870                assert_eq!(
871                    actual, expected,
872                    "Comparison mismatch between size {} and size {}",
873                    len_i, len_j
874                );
875            }
876        }
877    }
878
879    #[test]
880    fn test_chunk_boundary_divergence() {
881        use std::cmp::Ordering;
882
883        let divergence_indices = [0, 1, 100, 253, 254, 255, 256, 300, 508, 509, 510, 511, 600];
884        let total_len = 700;
885
886        for &idx in &divergence_indices {
887            let mut p_a = vec![0x33u8; total_len];
888            let mut p_b = vec![0x33u8; total_len];
889            p_a[idx] = 0x10;
890            p_b[idx] = 0x20;
891
892            let mut buf_a = Vec::new();
893            p_a.serialize_key_into(&mut buf_a);
894            let mut buf_b = Vec::new();
895            p_b.serialize_key_into(&mut buf_b);
896
897            assert_eq!(
898                compare_keys(&buf_a, &buf_b).unwrap(),
899                Ordering::Less,
900                "Failed at divergence index {}",
901                idx
902            );
903            assert_eq!(
904                compare_keys(&buf_b, &buf_a).unwrap(),
905                Ordering::Greater,
906                "Failed at divergence index {}",
907                idx
908            );
909        }
910    }
911
912    #[test]
913    fn test_chunk_prefix_and_multi_chunk_last() {
914        use std::cmp::Ordering;
915
916        let prefix_val = 12345u64;
917        let trailing_payload: Vec<u8> = (0..600).map(|i| (i * 7 % 256) as u8).collect();
918
919        let mut buf = Vec::new();
920        {
921            let mut ser = KeySerializer::new(&mut buf, None);
922            ser.write_u64(prefix_val);
923            ser.write_last(&trailing_payload);
924        }
925
926        let (mut deser, len) = KeyDeserializer::new(&buf, None).unwrap();
927        assert_eq!(len, buf.len());
928        assert_eq!(deser.read_u64().unwrap(), prefix_val);
929        assert_eq!(deser.read_last().unwrap(), trailing_payload.as_slice());
930        assert!(deser.is_empty());
931
932        // Test comparison: difference in prefix vs difference in trailing payload.
933        let mut buf_diff_prefix = Vec::new();
934        {
935            let mut ser = KeySerializer::new(&mut buf_diff_prefix, None);
936            ser.write_u64(prefix_val + 1);
937            ser.write_last(&trailing_payload);
938        }
939        assert_eq!(compare_keys(&buf, &buf_diff_prefix).unwrap(), Ordering::Less);
940        assert_eq!(compare_keys(&buf_diff_prefix, &buf).unwrap(), Ordering::Greater);
941
942        let mut buf_diff_trailing = Vec::new();
943        let mut diff_trailing_payload = trailing_payload.clone();
944        diff_trailing_payload[400] = diff_trailing_payload[400].wrapping_add(1);
945        {
946            let mut ser = KeySerializer::new(&mut buf_diff_trailing, None);
947            ser.write_u64(prefix_val);
948            ser.write_last(&diff_trailing_payload);
949        }
950        assert_ne!(compare_keys(&buf, &buf_diff_trailing).unwrap(), Ordering::Equal);
951    }
952
953    #[test]
954    fn test_chunk_trailing_garbage() {
955        use std::cmp::Ordering;
956
957        let test_payloads = [
958            vec![0x11; 50],  // Single chunk (< 255)
959            vec![0x22; 255], // Exact 255 (with 0-terminator)
960            vec![0x33; 300], // Multi-chunk (255 + 45)
961            vec![0x44; 510], // Exact 510 (with 0-terminator)
962        ];
963
964        for payload in &test_payloads {
965            let mut clean_buf = Vec::new();
966            payload.serialize_key_into(&mut clean_buf);
967
968            // Append garbage to buffer A and different garbage to buffer B.
969            let mut buf_with_garbage_a = clean_buf.clone();
970            buf_with_garbage_a.extend_from_slice(&[0xde, 0xad, 0xbe, 0xef, 0x99, 0x88]);
971
972            let mut buf_with_garbage_b = clean_buf.clone();
973            buf_with_garbage_b.extend_from_slice(&[0x12, 0x34, 0x56, 0x78]);
974
975            // compare_keys must only inspect key chunks and ignore trailing bytes.
976            assert_eq!(
977                compare_keys(&buf_with_garbage_a, &buf_with_garbage_b).unwrap(),
978                Ordering::Equal
979            );
980            assert_eq!(compare_keys(&clean_buf, &buf_with_garbage_a).unwrap(), Ordering::Equal);
981
982            // KeyDeserializer::new must return the exact length of the serialized key, not the full buffer.
983            let (mut deser, parsed_len) = KeyDeserializer::new(&buf_with_garbage_a, None).unwrap();
984            assert_eq!(parsed_len, clean_buf.len());
985            assert_eq!(deser.read_last().unwrap(), payload.as_slice());
986            assert!(deser.is_empty());
987        }
988    }
989
990    #[test]
991    fn test_chunk_malformed_buffers() {
992        // 1. Completely empty buffer.
993        assert!(compare_keys(&[], &[0]).is_err());
994        assert!(compare_keys(&[0], &[]).is_err());
995        assert!(KeyDeserializer::new(&[], None).is_err());
996
997        // 2. Chunk 0 specifies length beyond buffer.
998        let truncated1 = [5u8, 1, 2]; // Claims 5 bytes, only 2 exist.
999        assert!(compare_keys(&truncated1, &[0]).is_err());
1000        assert!(KeyDeserializer::new(&truncated1, None).is_err());
1001
1002        // 3. Chunk 0 specifies 255, but fewer than 255 payload bytes exist.
1003        let mut truncated2 = vec![255u8];
1004        truncated2.extend_from_slice(&[0xaa; 200]);
1005        assert!(compare_keys(&truncated2, &[0]).is_err());
1006        assert!(KeyDeserializer::new(&truncated2, None).is_err());
1007
1008        // 4. Chunk 0 has exactly 255 bytes, but buffer ends abruptly without next chunk header.
1009        let mut truncated3 = vec![255u8];
1010        truncated3.extend_from_slice(&[0xaa; 255]);
1011        // When chunk 0 matches, compare_keys must inspect chunk 1 and fail because it is missing.
1012        assert!(compare_keys(&truncated3, &truncated3).is_err());
1013        assert!(KeyDeserializer::new(&truncated3, None).is_err());
1014
1015        // 5. Next chunk specifies length beyond buffer.
1016        let mut truncated4 = truncated3.clone();
1017        truncated4.push(10); // Next chunk claims 10 bytes
1018        truncated4.extend_from_slice(&[0xbb; 3]); // only 3 provided
1019        assert!(compare_keys(&truncated4, &truncated4).is_err());
1020        assert!(KeyDeserializer::new(&truncated4, None).is_err());
1021
1022        // 6. Overrun on deser.read_exact.
1023        let valid = [2u8, 0x11, 0x22];
1024        let (mut deser, _) = KeyDeserializer::new(&valid, None).unwrap();
1025        let mut dst = [0u8; 5];
1026        assert!(deser.read_exact(&mut dst).is_err());
1027    }
1028
1029    #[test]
1030    fn test_word_probe_comparison() {
1031        use std::cmp::Ordering;
1032
1033        // Keys with early divergence (first 8 bytes differ).
1034        let mut key1 = Vec::new();
1035        100u64.serialize_key_into(&mut key1);
1036        let mut key2 = Vec::new();
1037        200u64.serialize_key_into(&mut key2);
1038        assert_eq!(compare_keys(&key1, &key2).unwrap(), Ordering::Less);
1039        assert_eq!(compare_keys(&key2, &key1).unwrap(), Ordering::Greater);
1040        assert_eq!(compare_keys(&key1, &key1).unwrap(), Ordering::Equal);
1041
1042        // Keys with late divergence (first 8 bytes identical, differing at byte 8+).
1043        let mut long1 = Vec::new();
1044        {
1045            let mut ser = KeySerializer::new(&mut long1, None);
1046            ser.write_u64(500);
1047            ser.write_last(b"abc");
1048        }
1049        let mut long2 = Vec::new();
1050        {
1051            let mut ser = KeySerializer::new(&mut long2, None);
1052            ser.write_u64(500);
1053            ser.write_last(b"abd");
1054        }
1055        let mut long3 = Vec::new();
1056        {
1057            let mut ser = KeySerializer::new(&mut long3, None);
1058            ser.write_u64(500);
1059            ser.write_last(b"abcd");
1060        }
1061        assert_eq!(compare_keys(&long1, &long2).unwrap(), Ordering::Less);
1062        assert_eq!(compare_keys(&long2, &long1).unwrap(), Ordering::Greater);
1063        assert_eq!(compare_keys(&long1, &long3).unwrap(), Ordering::Less);
1064        assert_eq!(compare_keys(&long3, &long1).unwrap(), Ordering::Greater);
1065        assert_eq!(compare_keys(&long1, &long1).unwrap(), Ordering::Equal);
1066
1067        // Keys shorter than 8 bytes.
1068        let mut short1 = Vec::new();
1069        10u32.serialize_key_into(&mut short1);
1070        let mut short2 = Vec::new();
1071        20u32.serialize_key_into(&mut short2);
1072        assert_eq!(compare_keys(&short1, &short2).unwrap(), Ordering::Less);
1073        assert_eq!(compare_keys(&short2, &short1).unwrap(), Ordering::Greater);
1074        assert_eq!(compare_keys(&short1, &short1).unwrap(), Ordering::Equal);
1075    }
1076
1077    #[test]
1078    fn test_compare_properties() {
1079        use std::cmp::Ordering;
1080
1081        let vals = [0u64, 1, 50, 100, 191, 192, 200, 1000, 50000, u64::MAX / 2, u64::MAX];
1082        let bases = [None, Some(0)];
1083
1084        for &base in &bases {
1085            for i in 0..vals.len() {
1086                for j in 0..vals.len() {
1087                    let a = vals[i];
1088                    let b = vals[j];
1089
1090                    let mut buf_a = Vec::new();
1091                    a.serialize_key_to(KeySerializer::new(&mut buf_a, base)).finalize();
1092                    let mut buf_b = Vec::new();
1093                    b.serialize_key_to(KeySerializer::new(&mut buf_b, base)).finalize();
1094
1095                    let cmp_ab = compare_keys(&buf_a, &buf_b).unwrap();
1096                    let cmp_ba = compare_keys(&buf_b, &buf_a).unwrap();
1097
1098                    // Anti-symmetry: cmp(a, b) == cmp(b, a).reverse()
1099                    assert_eq!(cmp_ab, cmp_ba.reverse());
1100                    assert_eq!(cmp_ab, a.cmp(&b));
1101
1102                    // Transitivity check with a third element
1103                    for k in 0..vals.len() {
1104                        let c = vals[k];
1105                        let mut buf_c = Vec::new();
1106                        c.serialize_key_to(KeySerializer::new(&mut buf_c, base)).finalize();
1107                        let cmp_bc = compare_keys(&buf_b, &buf_c).unwrap();
1108                        let cmp_ac = compare_keys(&buf_a, &buf_c).unwrap();
1109
1110                        if cmp_ab == Ordering::Less && cmp_bc == Ordering::Less {
1111                            assert_eq!(cmp_ac, Ordering::Less);
1112                        }
1113                    }
1114                }
1115            }
1116        }
1117    }
1118
1119    #[test]
1120    fn test_non_terminal_enum_in_struct() {
1121        #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, fxfs_macros::SerializeKey)]
1122        enum MyEnum {
1123            Unit,
1124            Tuple(u32),
1125            Struct { x: u64 },
1126        }
1127
1128        #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, fxfs_macros::SerializeKey)]
1129        struct Foo {
1130            bar: MyEnum,
1131            baz: String,
1132        }
1133
1134        let items = [
1135            Foo { bar: MyEnum::Unit, baz: "a".to_string() },
1136            Foo { bar: MyEnum::Unit, baz: "b".to_string() },
1137            Foo { bar: MyEnum::Tuple(1), baz: "a".to_string() },
1138            Foo { bar: MyEnum::Struct { x: 10 }, baz: "z".to_string() },
1139        ];
1140        for (i, a) in items.iter().enumerate() {
1141            let mut buf_a = Vec::new();
1142            a.serialize_key_into(&mut buf_a);
1143            let (mut deser, _) = KeyDeserializer::new(&buf_a, None).unwrap();
1144            let decoded = Foo::deserialize_key_from(&mut deser).unwrap();
1145            assert_eq!(&decoded, a);
1146            for (j, b) in items.iter().enumerate() {
1147                let mut buf_b = Vec::new();
1148                b.serialize_key_into(&mut buf_b);
1149                assert_eq!(compare_keys(&buf_a, &buf_b).unwrap(), i.cmp(&j));
1150            }
1151        }
1152    }
1153}
1154
1155#[cfg(fuzz)]
1156#[cfg(fuzz_target = "fuzz_object_key_compare")]
1157mod fuzz_object_key_compare {
1158    use super::*;
1159    use crate::lsm_tree::types::OrdUpperBound;
1160    use crate::object_store::object_record::{ObjectKey, ObjectKeyData};
1161    use ::fuzz::fuzz;
1162
1163    #[fuzz]
1164    fn fuzz_object_key_compare(input: (Vec<u8>, Vec<u8>)) {
1165        let Ok((mut deser_a, len_a)) = KeyDeserializer::new(&input.0, None) else {
1166            return;
1167        };
1168        let Ok(key_a) = ObjectKey::deserialize_key_from(&mut deser_a) else {
1169            return;
1170        };
1171        // LegacyCasefoldChild is ignored because it is not order-preserving (uses
1172        // case-preserving serialization but case-insensitive comparison) and is not used in
1173        // recently written formats.
1174        if matches!(key_a.data, ObjectKeyData::LegacyCasefoldChild(_)) {
1175            return;
1176        }
1177        if !deser_a.is_empty() {
1178            return;
1179        }
1180
1181        let Ok((mut deser_b, len_b)) = KeyDeserializer::new(&input.1, None) else {
1182            return;
1183        };
1184        let Ok(key_b) = ObjectKey::deserialize_key_from(&mut deser_b) else {
1185            return;
1186        };
1187        if matches!(key_b.data, ObjectKeyData::LegacyCasefoldChild(_)) {
1188            return;
1189        }
1190        if !deser_b.is_empty() {
1191            return;
1192        }
1193
1194        let mut buf_a = Vec::new();
1195        key_a.serialize_key_with_base_into(&mut buf_a, 0);
1196        assert_eq!(buf_a, input.0[..len_a]);
1197
1198        let mut buf_b = Vec::new();
1199        key_b.serialize_key_with_base_into(&mut buf_b, 0);
1200        assert_eq!(buf_b, input.1[..len_b]);
1201
1202        let cmp = key_a.cmp_upper_bound(&key_b);
1203        let ser_cmp = compare_keys(&buf_a, &buf_b).unwrap();
1204        assert_eq!(cmp, ser_cmp, "Mismatch for keys {:?} and {:?}", key_a, key_b);
1205    }
1206}
1207
1208#[cfg(fuzz)]
1209#[cfg(fuzz_target = "fuzz_allocator_key_compare")]
1210mod fuzz_allocator_key_compare {
1211    use super::*;
1212    use crate::lsm_tree::types::OrdUpperBound;
1213    use crate::object_store::allocator::AllocatorKey;
1214    use ::fuzz::fuzz;
1215
1216    #[fuzz]
1217    fn fuzz_allocator_key_compare(input: (Vec<u8>, Vec<u8>)) {
1218        let Ok((mut deser_a, len_a)) = KeyDeserializer::new(&input.0, None) else {
1219            return;
1220        };
1221        let Ok(key_a) = AllocatorKey::deserialize_key_from(&mut deser_a) else {
1222            return;
1223        };
1224        if !deser_a.is_empty() {
1225            return;
1226        }
1227
1228        let Ok((mut deser_b, len_b)) = KeyDeserializer::new(&input.1, None) else {
1229            return;
1230        };
1231        let Ok(key_b) = AllocatorKey::deserialize_key_from(&mut deser_b) else {
1232            return;
1233        };
1234        if !deser_b.is_empty() {
1235            return;
1236        }
1237
1238        let mut buf_a = Vec::new();
1239        key_a.serialize_key_with_base_into(&mut buf_a, 0);
1240        assert_eq!(buf_a, input.0[..len_a]);
1241
1242        let mut buf_b = Vec::new();
1243        key_b.serialize_key_with_base_into(&mut buf_b, 0);
1244        assert_eq!(buf_b, input.1[..len_b]);
1245
1246        let cmp = key_a.cmp_upper_bound(&key_b);
1247        let ser_cmp = compare_keys(&buf_a, &buf_b).unwrap();
1248        assert_eq!(cmp, ser_cmp, "Mismatch for keys {:?} and {:?}", key_a, key_b);
1249    }
1250}