Skip to main content

reifydb_core/encoded/
key.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Copyright (c) 2025 ReifyDB
3
4use std::{
5	collections::{
6		Bound,
7		Bound::{Excluded, Included, Unbounded},
8	},
9	ops::{Deref, RangeBounds},
10};
11
12use reifydb_type::{
13	util::cowvec::CowVec,
14	value::{
15		Value,
16		blob::Blob,
17		date::Date,
18		datetime::DateTime,
19		decimal::Decimal,
20		duration::Duration,
21		identity::IdentityId,
22		int::Int,
23		row_number::RowNumber,
24		time::Time,
25		uint::Uint,
26		uuid::{Uuid4, Uuid7},
27	},
28};
29use serde::{Deserialize, Serialize};
30
31use crate::{
32	interface::catalog::{id::IndexId, primitive::PrimitiveId},
33	util::encoding::{binary::decode_binary, keycode::serializer::KeySerializer},
34};
35
36#[derive(Debug, Clone, PartialOrd, Ord, Hash, PartialEq, Eq, Serialize, Deserialize)]
37pub struct EncodedKey(pub CowVec<u8>);
38
39impl Deref for EncodedKey {
40	type Target = CowVec<u8>;
41
42	fn deref(&self) -> &Self::Target {
43		&self.0
44	}
45}
46
47impl AsRef<[u8]> for EncodedKey {
48	fn as_ref(&self) -> &[u8] {
49		self.0.as_ref()
50	}
51}
52
53impl EncodedKey {
54	pub fn new(key: impl Into<Vec<u8>>) -> Self {
55		Self(CowVec::new(key.into()))
56	}
57
58	/// Create a new builder for constructing an EncodedKey
59	pub fn builder() -> EncodedKeyBuilder {
60		EncodedKeyBuilder::new()
61	}
62
63	pub fn as_bytes(&self) -> &[u8] {
64		self.0.as_ref()
65	}
66
67	pub fn as_slice(&self) -> &[u8] {
68		self.0.as_ref()
69	}
70}
71
72/// A builder for constructing EncodedKey values using keycode encoding
73///
74/// This provides a fluent API for building composite keys with proper order-preserving encoding.
75pub struct EncodedKeyBuilder {
76	serializer: KeySerializer,
77}
78
79impl EncodedKeyBuilder {
80	/// Create a new builder
81	pub fn new() -> Self {
82		Self {
83			serializer: KeySerializer::new(),
84		}
85	}
86
87	/// Create a builder with pre-allocated capacity
88	pub fn with_capacity(capacity: usize) -> Self {
89		Self {
90			serializer: KeySerializer::with_capacity(capacity),
91		}
92	}
93
94	/// Build the EncodedKey
95	pub fn build(self) -> EncodedKey {
96		self.serializer.to_encoded_key()
97	}
98
99	/// Extend with bool value
100	pub fn bool(mut self, value: bool) -> Self {
101		self.serializer.extend_bool(value);
102		self
103	}
104
105	/// Extend with f32 value
106	pub fn f32(mut self, value: f32) -> Self {
107		self.serializer.extend_f32(value);
108		self
109	}
110
111	/// Extend with f64 value
112	pub fn f64(mut self, value: f64) -> Self {
113		self.serializer.extend_f64(value);
114		self
115	}
116
117	/// Extend with i8 value
118	pub fn i8<T: Into<i8>>(mut self, value: T) -> Self {
119		self.serializer.extend_i8(value);
120		self
121	}
122
123	/// Extend with i16 value
124	pub fn i16<T: Into<i16>>(mut self, value: T) -> Self {
125		self.serializer.extend_i16(value);
126		self
127	}
128
129	/// Extend with i32 value
130	pub fn i32<T: Into<i32>>(mut self, value: T) -> Self {
131		self.serializer.extend_i32(value);
132		self
133	}
134
135	/// Extend with i64 value
136	pub fn i64<T: Into<i64>>(mut self, value: T) -> Self {
137		self.serializer.extend_i64(value);
138		self
139	}
140
141	/// Extend with i128 value
142	pub fn i128<T: Into<i128>>(mut self, value: T) -> Self {
143		self.serializer.extend_i128(value);
144		self
145	}
146
147	/// Extend with u8 value
148	pub fn u8<T: Into<u8>>(mut self, value: T) -> Self {
149		self.serializer.extend_u8(value);
150		self
151	}
152
153	/// Extend with u16 value
154	pub fn u16<T: Into<u16>>(mut self, value: T) -> Self {
155		self.serializer.extend_u16(value);
156		self
157	}
158
159	/// Extend with u32 value
160	pub fn u32<T: Into<u32>>(mut self, value: T) -> Self {
161		self.serializer.extend_u32(value);
162		self
163	}
164
165	/// Extend with u64 value
166	pub fn u64<T: Into<u64>>(mut self, value: T) -> Self {
167		self.serializer.extend_u64(value);
168		self
169	}
170
171	/// Extend with u128 value
172	pub fn u128<T: Into<u128>>(mut self, value: T) -> Self {
173		self.serializer.extend_u128(value);
174		self
175	}
176
177	/// Extend with raw bytes (with encoding)
178	pub fn bytes<T: AsRef<[u8]>>(mut self, bytes: T) -> Self {
179		self.serializer.extend_bytes(bytes);
180		self
181	}
182
183	/// Extend with string (UTF-8 bytes)
184	pub fn str<T: AsRef<str>>(mut self, s: T) -> Self {
185		self.serializer.extend_str(s);
186		self
187	}
188
189	/// Extend with a PrimitiveId value
190	pub fn primitive_id(mut self, primitive: impl Into<PrimitiveId>) -> Self {
191		self.serializer.extend_primitive_id(primitive);
192		self
193	}
194
195	/// Extend with an IndexId value
196	pub fn index_id(mut self, index: impl Into<IndexId>) -> Self {
197		self.serializer.extend_index_id(index);
198		self
199	}
200
201	/// Extend with a serializable value using keycode encoding
202	pub fn serialize<T: Serialize>(mut self, value: &T) -> Self {
203		self.serializer.extend_serialize(value);
204		self
205	}
206
207	/// Extend with raw bytes (no encoding)
208	pub fn raw(mut self, bytes: &[u8]) -> Self {
209		self.serializer.extend_raw(bytes);
210		self
211	}
212
213	/// Get current buffer length
214	pub fn len(&self) -> usize {
215		self.serializer.len()
216	}
217
218	/// Check if buffer is empty
219	pub fn is_empty(&self) -> bool {
220		self.serializer.is_empty()
221	}
222
223	/// Extend with Date value
224	pub fn date(mut self, date: &Date) -> Self {
225		self.serializer.extend_date(date);
226		self
227	}
228
229	/// Extend with DateTime value
230	pub fn datetime(mut self, datetime: &DateTime) -> Self {
231		self.serializer.extend_datetime(datetime);
232		self
233	}
234
235	/// Extend with Time value
236	pub fn time(mut self, time: &Time) -> Self {
237		self.serializer.extend_time(time);
238		self
239	}
240
241	/// Extend with Duration value
242	pub fn duration(mut self, duration: &Duration) -> Self {
243		self.serializer.extend_duration(duration);
244		self
245	}
246
247	/// Extend with RowNumber value
248	pub fn row_number(mut self, row_number: &RowNumber) -> Self {
249		self.serializer.extend_row_number(row_number);
250		self
251	}
252
253	/// Extend with IdentityId value
254	pub fn identity_id(mut self, id: &IdentityId) -> Self {
255		self.serializer.extend_identity_id(id);
256		self
257	}
258
259	/// Extend with Uuid4 value
260	pub fn uuid4(mut self, uuid: &Uuid4) -> Self {
261		self.serializer.extend_uuid4(uuid);
262		self
263	}
264
265	/// Extend with Uuid7 value
266	pub fn uuid7(mut self, uuid: &Uuid7) -> Self {
267		self.serializer.extend_uuid7(uuid);
268		self
269	}
270
271	/// Extend with Blob value
272	pub fn blob(mut self, blob: &Blob) -> Self {
273		self.serializer.extend_blob(blob);
274		self
275	}
276
277	/// Extend with arbitrary precision Int value
278	pub fn int(mut self, int: &Int) -> Self {
279		self.serializer.extend_int(int);
280		self
281	}
282
283	/// Extend with arbitrary precision Uint value
284	pub fn uint(mut self, uint: &Uint) -> Self {
285		self.serializer.extend_uint(uint);
286		self
287	}
288
289	/// Extend with Decimal value
290	pub fn decimal(mut self, decimal: &Decimal) -> Self {
291		self.serializer.extend_decimal(decimal);
292		self
293	}
294
295	/// Extend with a Value based on its type
296	pub fn value(mut self, value: &Value) -> Self {
297		self.serializer.extend_value(value);
298		self
299	}
300}
301
302impl Default for EncodedKeyBuilder {
303	fn default() -> Self {
304		Self::new()
305	}
306}
307
308/// Trait for types that can be converted into an EncodedKey.
309/// Provides convenient conversions from common types to EncodedKey using proper order-preserving encoding.
310pub trait IntoEncodedKey {
311	fn into_encoded_key(self) -> EncodedKey;
312}
313
314// Direct passthrough for EncodedKey
315impl IntoEncodedKey for EncodedKey {
316	fn into_encoded_key(self) -> EncodedKey {
317		self
318	}
319}
320
321// String types - using extend_str for proper encoding
322impl IntoEncodedKey for &str {
323	fn into_encoded_key(self) -> EncodedKey {
324		let mut serializer = KeySerializer::new();
325		serializer.extend_str(self);
326		serializer.to_encoded_key()
327	}
328}
329
330impl IntoEncodedKey for String {
331	fn into_encoded_key(self) -> EncodedKey {
332		let mut serializer = KeySerializer::new();
333		serializer.extend_str(&self);
334		serializer.to_encoded_key()
335	}
336}
337
338// Byte arrays - using extend_bytes for escaped encoding
339impl IntoEncodedKey for Vec<u8> {
340	fn into_encoded_key(self) -> EncodedKey {
341		let mut serializer = KeySerializer::new();
342		serializer.extend_bytes(&self);
343		serializer.to_encoded_key()
344	}
345}
346
347impl IntoEncodedKey for &[u8] {
348	fn into_encoded_key(self) -> EncodedKey {
349		let mut serializer = KeySerializer::new();
350		serializer.extend_bytes(self);
351		serializer.to_encoded_key()
352	}
353}
354
355// Numeric types - using proper encoding for order preservation
356impl IntoEncodedKey for u64 {
357	fn into_encoded_key(self) -> EncodedKey {
358		let mut serializer = KeySerializer::with_capacity(8);
359		serializer.extend_u64(self);
360		serializer.to_encoded_key()
361	}
362}
363
364impl IntoEncodedKey for i64 {
365	fn into_encoded_key(self) -> EncodedKey {
366		let mut serializer = KeySerializer::with_capacity(8);
367		serializer.extend_i64(self);
368		serializer.to_encoded_key()
369	}
370}
371
372impl IntoEncodedKey for u32 {
373	fn into_encoded_key(self) -> EncodedKey {
374		let mut serializer = KeySerializer::with_capacity(4);
375		serializer.extend_u32(self);
376		serializer.to_encoded_key()
377	}
378}
379
380impl IntoEncodedKey for i32 {
381	fn into_encoded_key(self) -> EncodedKey {
382		let mut serializer = KeySerializer::with_capacity(4);
383		serializer.extend_i32(self);
384		serializer.to_encoded_key()
385	}
386}
387
388impl IntoEncodedKey for u16 {
389	fn into_encoded_key(self) -> EncodedKey {
390		let mut serializer = KeySerializer::with_capacity(2);
391		serializer.extend_u16(self);
392		serializer.to_encoded_key()
393	}
394}
395
396impl IntoEncodedKey for i16 {
397	fn into_encoded_key(self) -> EncodedKey {
398		let mut serializer = KeySerializer::with_capacity(2);
399		serializer.extend_i16(self);
400		serializer.to_encoded_key()
401	}
402}
403
404impl IntoEncodedKey for u8 {
405	fn into_encoded_key(self) -> EncodedKey {
406		let mut serializer = KeySerializer::with_capacity(1);
407		serializer.extend_u8(self);
408		serializer.to_encoded_key()
409	}
410}
411
412impl IntoEncodedKey for i8 {
413	fn into_encoded_key(self) -> EncodedKey {
414		let mut serializer = KeySerializer::with_capacity(1);
415		serializer.extend_i8(self);
416		serializer.to_encoded_key()
417	}
418}
419
420// Reference implementations for numeric types (for StateCache)
421impl IntoEncodedKey for &u64 {
422	fn into_encoded_key(self) -> EncodedKey {
423		(*self).into_encoded_key()
424	}
425}
426
427impl IntoEncodedKey for &i64 {
428	fn into_encoded_key(self) -> EncodedKey {
429		(*self).into_encoded_key()
430	}
431}
432
433impl IntoEncodedKey for &u32 {
434	fn into_encoded_key(self) -> EncodedKey {
435		(*self).into_encoded_key()
436	}
437}
438
439impl IntoEncodedKey for &i32 {
440	fn into_encoded_key(self) -> EncodedKey {
441		(*self).into_encoded_key()
442	}
443}
444
445impl IntoEncodedKey for &u16 {
446	fn into_encoded_key(self) -> EncodedKey {
447		(*self).into_encoded_key()
448	}
449}
450
451impl IntoEncodedKey for &i16 {
452	fn into_encoded_key(self) -> EncodedKey {
453		(*self).into_encoded_key()
454	}
455}
456
457impl IntoEncodedKey for &u8 {
458	fn into_encoded_key(self) -> EncodedKey {
459		(*self).into_encoded_key()
460	}
461}
462
463impl IntoEncodedKey for &i8 {
464	fn into_encoded_key(self) -> EncodedKey {
465		(*self).into_encoded_key()
466	}
467}
468
469// RowNumber implementations (for StateCache with RowNumber keys)
470impl IntoEncodedKey for RowNumber {
471	fn into_encoded_key(self) -> EncodedKey {
472		self.0.into_encoded_key()
473	}
474}
475
476impl IntoEncodedKey for &RowNumber {
477	fn into_encoded_key(self) -> EncodedKey {
478		self.0.into_encoded_key()
479	}
480}
481
482// Value types - using extend_value for proper encoding
483impl IntoEncodedKey for Value {
484	fn into_encoded_key(self) -> EncodedKey {
485		let mut serializer = KeySerializer::new();
486		serializer.extend_value(&self);
487		serializer.to_encoded_key()
488	}
489}
490
491impl IntoEncodedKey for &Value {
492	fn into_encoded_key(self) -> EncodedKey {
493		let mut serializer = KeySerializer::new();
494		serializer.extend_value(self);
495		serializer.to_encoded_key()
496	}
497}
498
499impl IntoEncodedKey for Vec<Value> {
500	fn into_encoded_key(self) -> EncodedKey {
501		let mut serializer = KeySerializer::new();
502		for value in self.iter() {
503			serializer.extend_value(value);
504		}
505		serializer.to_encoded_key()
506	}
507}
508
509impl IntoEncodedKey for &[Value] {
510	fn into_encoded_key(self) -> EncodedKey {
511		let mut serializer = KeySerializer::new();
512		for value in self.iter() {
513			serializer.extend_value(value);
514		}
515		serializer.to_encoded_key()
516	}
517}
518
519// Tuple types - composite keys
520impl IntoEncodedKey for (String, String) {
521	fn into_encoded_key(self) -> EncodedKey {
522		let mut serializer = KeySerializer::new();
523		serializer.extend_str(&self.0);
524		serializer.extend_str(&self.1);
525		serializer.to_encoded_key()
526	}
527}
528
529impl IntoEncodedKey for &(String, String) {
530	fn into_encoded_key(self) -> EncodedKey {
531		let mut serializer = KeySerializer::new();
532		serializer.extend_str(&self.0);
533		serializer.extend_str(&self.1);
534		serializer.to_encoded_key()
535	}
536}
537
538impl IntoEncodedKey for (&str, &str) {
539	fn into_encoded_key(self) -> EncodedKey {
540		let mut serializer = KeySerializer::new();
541		serializer.extend_str(self.0);
542		serializer.extend_str(self.1);
543		serializer.to_encoded_key()
544	}
545}
546
547impl IntoEncodedKey for (String, String, String) {
548	fn into_encoded_key(self) -> EncodedKey {
549		let mut serializer = KeySerializer::new();
550		serializer.extend_str(&self.0);
551		serializer.extend_str(&self.1);
552		serializer.extend_str(&self.2);
553		serializer.to_encoded_key()
554	}
555}
556
557impl IntoEncodedKey for &(String, String, String) {
558	fn into_encoded_key(self) -> EncodedKey {
559		let mut serializer = KeySerializer::new();
560		serializer.extend_str(&self.0);
561		serializer.extend_str(&self.1);
562		serializer.extend_str(&self.2);
563		serializer.to_encoded_key()
564	}
565}
566
567impl IntoEncodedKey for &String {
568	fn into_encoded_key(self) -> EncodedKey {
569		let mut serializer = KeySerializer::new();
570		serializer.extend_str(self);
571		serializer.to_encoded_key()
572	}
573}
574
575#[derive(Clone, Debug)]
576pub struct EncodedKeyRange {
577	pub start: Bound<EncodedKey>,
578	pub end: Bound<EncodedKey>,
579}
580
581impl EncodedKeyRange {
582	pub fn new(start: Bound<EncodedKey>, end: Bound<EncodedKey>) -> Self {
583		Self {
584			start,
585			end,
586		}
587	}
588
589	/// Generates a key range for a key prefix, used e.g. for prefix scans.
590	///
591	/// The exclusive end bound is generated by adding 1 to the value of the
592	/// last byte. If the last byte(s) is 0xff (so adding 1 would
593	/// saturation), we instead find the latest non-0xff byte, increment
594	/// that, and truncate the rest. If all bytes are 0xff, we scan to the
595	/// end of the range, since there can't be other prefixes after it.
596	pub fn prefix(prefix: &[u8]) -> Self {
597		let start = Bound::Included(EncodedKey::new(prefix));
598		let end = match prefix.iter().rposition(|&b| b != 0xff) {
599			Some(i) => Bound::Excluded(EncodedKey::new(
600				prefix.iter()
601					.take(i)
602					.copied()
603					.chain(std::iter::once(prefix[i] + 1))
604					.collect::<Vec<_>>(),
605			)),
606			None => Bound::Unbounded,
607		};
608		Self {
609			start,
610			end,
611		}
612	}
613
614	pub fn with_prefix(&self, prefix: EncodedKey) -> Self {
615		let start = match self.start_bound() {
616			Included(key) => {
617				let mut prefixed = Vec::with_capacity(prefix.len() + key.len());
618				prefixed.extend_from_slice(prefix.as_ref());
619				prefixed.extend_from_slice(key.as_ref());
620				Included(EncodedKey::new(prefixed))
621			}
622			Excluded(key) => {
623				let mut prefixed = Vec::with_capacity(prefix.len() + key.len());
624				prefixed.extend_from_slice(prefix.as_ref());
625				prefixed.extend_from_slice(key.as_ref());
626				Excluded(EncodedKey::new(prefixed))
627			}
628			Unbounded => Included(prefix.clone()),
629		};
630
631		let end = match self.end_bound() {
632			Included(key) => {
633				let mut prefixed = Vec::with_capacity(prefix.len() + key.len());
634				prefixed.extend_from_slice(prefix.as_ref());
635				prefixed.extend_from_slice(key.as_ref());
636				Included(EncodedKey::new(prefixed))
637			}
638			Excluded(key) => {
639				let mut prefixed = Vec::with_capacity(prefix.len() + key.len());
640				prefixed.extend_from_slice(prefix.as_ref());
641				prefixed.extend_from_slice(key.as_ref());
642				Excluded(EncodedKey::new(prefixed))
643			}
644			Unbounded => match prefix.as_ref().iter().rposition(|&b| b != 0xff) {
645				Some(i) => {
646					let mut next_prefix = prefix.as_ref()[..=i].to_vec();
647					next_prefix[i] += 1;
648					Excluded(EncodedKey::new(next_prefix))
649				}
650				None => Unbounded,
651			},
652		};
653
654		EncodedKeyRange::new(start, end)
655	}
656
657	/// Constructs a key range from an optional inclusive start key to an
658	/// optional inclusive end key.
659	///
660	/// - `start`: If provided, marks the inclusive lower bound of the range. If `None`, the range is unbounded
661	///   below.
662	/// - `end`: If provided, marks the inclusive upper bound of the range. If `None`, the range is unbounded above.
663	///
664	/// This function does not modify the input keys and assumes they are
665	/// already exact keys (not prefixes). If you need to scan all keys
666	/// with a given prefix, use [`EncodedKeyRange::prefix`] instead.
667	///
668	/// Useful for scanning between two explicit keys in a sorted key-value
669	/// store.
670	pub fn start_end(start: Option<EncodedKey>, end: Option<EncodedKey>) -> Self {
671		let start = match start {
672			Some(s) => Bound::Included(s),
673			None => Bound::Unbounded,
674		};
675
676		let end = match end {
677			Some(e) => Bound::Included(e),
678			None => Bound::Unbounded,
679		};
680
681		Self {
682			start,
683			end,
684		}
685	}
686
687	/// Constructs a key range that fragments the entire keyspace.
688	///
689	/// This range has no lower or upper bounds, making it suitable for full
690	/// scans over all keys in a sorted key-value store.
691	///
692	/// Equivalent to: `..` (in Rust range syntax)
693	pub fn all() -> Self {
694		Self {
695			start: Bound::Unbounded,
696			end: Bound::Unbounded,
697		}
698	}
699
700	/// Parses a human-readable range string into a `KeyRange`.
701	///
702	/// The expected format is `<start>..[=]<end>`, where:
703	/// - `<start>` is the inclusive lower bound (optional),
704	/// - `..` separates the bounds,
705	/// - `=` after `..` makes the upper bound inclusive,
706	/// - `<end>` is the upper bound (optional).
707	///
708	/// Examples:
709	/// - `"a..z"`       => start = Included("a"), end = Excluded("z")
710	/// - `"a..=z"`      => start = Included("a"), end = Included("z")
711	/// - `"..z"`        => start = Unbounded,     end = Excluded("z")
712	/// - `"a.."`        => start = Included("a"), end = Unbounded
713	///
714	/// If parsing fails, it defaults to a degenerate range from `0xff` to
715	/// `0xff` (empty).
716	pub fn parse(str: &str) -> Self {
717		let (mut start, mut end) = (Bound::<EncodedKey>::Unbounded, Bound::<EncodedKey>::Unbounded);
718
719		// Find the ".." separator
720		if let Some(dot_pos) = str.find("..") {
721			let start_part = &str[..dot_pos];
722			let end_part = &str[dot_pos + 2..];
723
724			// Parse start bound
725			if !start_part.is_empty() {
726				start = Bound::Included(EncodedKey(decode_binary(start_part)));
727			}
728
729			// Parse end bound - check for inclusive marker "="
730			if let Some(end_str) = end_part.strip_prefix('=') {
731				// Inclusive end: "..="
732				if !end_str.is_empty() {
733					end = Bound::Included(EncodedKey(decode_binary(end_str)));
734				}
735			} else {
736				// Exclusive end: ".."
737				if !end_part.is_empty() {
738					end = Bound::Excluded(EncodedKey(decode_binary(end_part)));
739				}
740			}
741
742			Self {
743				start,
744				end,
745			}
746		} else {
747			// Invalid format - return degenerate range
748			Self {
749				start: Bound::Included(EncodedKey::new([0xff])),
750				end: Bound::Excluded(EncodedKey::new([0xff])),
751			}
752		}
753	}
754}
755
756impl RangeBounds<EncodedKey> for EncodedKeyRange {
757	fn start_bound(&self) -> Bound<&EncodedKey> {
758		self.start.as_ref()
759	}
760
761	fn end_bound(&self) -> Bound<&EncodedKey> {
762		self.end.as_ref()
763	}
764}
765
766#[cfg(test)]
767pub mod tests {
768	use std::collections::Bound;
769
770	use super::EncodedKey;
771
772	macro_rules! as_key {
773		($key:expr) => {{ EncodedKey::new(keycode::serialize(&$key)) }};
774	}
775
776	mod prefix {
777		use std::ops::Bound;
778
779		use crate::encoded::key::{
780			EncodedKeyRange,
781			tests::{excluded, included},
782		};
783
784		#[test]
785		fn test_simple() {
786			let range = EncodedKeyRange::prefix(&[0x12, 0x34]);
787			assert_eq!(range.start, included(&[0x12, 0x34]));
788			assert_eq!(range.end, excluded(&[0x12, 0x35]));
789		}
790
791		#[test]
792		fn test_with_trailing_ff() {
793			let range = EncodedKeyRange::prefix(&[0x12, 0xff]);
794			assert_eq!(range.start, included(&[0x12, 0xff]));
795			assert_eq!(range.end, excluded(&[0x13]));
796		}
797
798		#[test]
799		fn test_with_multiple_trailing_ff() {
800			let range = EncodedKeyRange::prefix(&[0x12, 0xff, 0xff]);
801			assert_eq!(range.start, included(&[0x12, 0xff, 0xff]));
802			assert_eq!(range.end, excluded(&[0x13]));
803		}
804
805		#[test]
806		fn test_all_ff() {
807			let range = EncodedKeyRange::prefix(&[0xff, 0xff]);
808			assert_eq!(range.start, included(&[0xff, 0xff]));
809			assert_eq!(range.end, Bound::Unbounded);
810		}
811
812		#[test]
813		fn test_empty() {
814			let range = EncodedKeyRange::prefix(&[]);
815			assert_eq!(range.start, included(&[]));
816			assert_eq!(range.end, Bound::Unbounded);
817		}
818
819		#[test]
820		fn test_mid_increment() {
821			let range = EncodedKeyRange::prefix(&[0x12, 0x00, 0xff]);
822			assert_eq!(range.start, included(&[0x12, 0x00, 0xff]));
823			assert_eq!(range.end, excluded(&[0x12, 0x01]));
824		}
825	}
826
827	mod start_end {
828		use std::ops::Bound;
829
830		use crate::{
831			encoded::key::{EncodedKey, EncodedKeyRange, tests::included},
832			util::encoding::keycode,
833		};
834
835		#[test]
836		fn test_start_and_end() {
837			let range = EncodedKeyRange::start_end(Some(as_key!(1)), Some(as_key!(2)));
838			assert_eq!(range.start, included(&as_key!(1)));
839			assert_eq!(range.end, included(&as_key!(2)));
840		}
841
842		#[test]
843		fn test_start_only() {
844			let range = EncodedKeyRange::start_end(Some(as_key!(1)), None);
845			assert_eq!(range.start, included(&as_key!(1)));
846			assert_eq!(range.end, Bound::Unbounded);
847		}
848
849		#[test]
850		fn test_end_only() {
851			let range = EncodedKeyRange::start_end(None, Some(as_key!(2)));
852			assert_eq!(range.start, Bound::Unbounded);
853			assert_eq!(range.end, included(&as_key!(2)));
854		}
855
856		#[test]
857		fn test_unbounded_range() {
858			let range = EncodedKeyRange::start_end(None, None);
859			assert_eq!(range.start, Bound::Unbounded);
860			assert_eq!(range.end, Bound::Unbounded);
861		}
862
863		#[test]
864		fn test_full_byte_range() {
865			let range = EncodedKeyRange::start_end(Some(as_key!(0x00)), Some(as_key!(0xff)));
866			assert_eq!(range.start, included(&as_key!(0x00)));
867			assert_eq!(range.end, included(&as_key!(0xff)));
868		}
869
870		#[test]
871		fn test_identical_bounds() {
872			let range = EncodedKeyRange::start_end(Some(as_key!(0x42)), Some(as_key!(0x42)));
873			assert_eq!(range.start, included(&as_key!(0x42)));
874			assert_eq!(range.end, included(&as_key!(0x42)));
875		}
876	}
877
878	mod all {
879		use std::ops::Bound;
880
881		use crate::encoded::key::EncodedKeyRange;
882
883		#[test]
884		fn test_is_unbounded() {
885			let range = EncodedKeyRange::all();
886			assert_eq!(range.start, Bound::Unbounded);
887			assert_eq!(range.end, Bound::Unbounded);
888		}
889	}
890
891	mod parse {
892		use std::ops::Bound;
893
894		use crate::encoded::key::{
895			EncodedKey, EncodedKeyRange,
896			tests::{excluded, included},
897		};
898
899		#[test]
900		fn test_full_range() {
901			let r = EncodedKeyRange::parse("a..z");
902			assert_eq!(r.start, included(b"a"));
903			assert_eq!(r.end, excluded(b"z"));
904		}
905
906		#[test]
907		fn test_inclusive_end() {
908			let r = EncodedKeyRange::parse("a..=z");
909			assert_eq!(r.start, included(b"a"));
910			assert_eq!(r.end, included(b"z"));
911		}
912
913		#[test]
914		fn test_unbounded_start() {
915			let r = EncodedKeyRange::parse("..z");
916			assert_eq!(r.start, Bound::Unbounded);
917			assert_eq!(r.end, excluded(b"z"));
918		}
919
920		#[test]
921		fn test_unbounded_end() {
922			let r = EncodedKeyRange::parse("a..");
923			assert_eq!(r.start, included(b"a"));
924			assert_eq!(r.end, Bound::Unbounded);
925		}
926
927		#[test]
928		fn test_inclusive_only() {
929			let r = EncodedKeyRange::parse("..=z");
930			assert_eq!(r.start, Bound::Unbounded);
931			assert_eq!(r.end, included(b"z"));
932		}
933
934		#[test]
935		fn test_invalid_string_returns_degenerate_range() {
936			let r = EncodedKeyRange::parse("not a range");
937			let expected = EncodedKey::new([0xff]);
938			assert_eq!(r.start, Bound::Included(expected.clone()));
939			assert_eq!(r.end, Bound::Excluded(expected));
940		}
941
942		#[test]
943		fn test_empty_string_returns_degenerate_range() {
944			let r = EncodedKeyRange::parse("");
945			let expected = EncodedKey::new([0xff]);
946			assert_eq!(r.start, Bound::Included(expected.clone()));
947			assert_eq!(r.end, Bound::Excluded(expected));
948		}
949
950		#[test]
951		fn test_binary_encoded_values() {
952			let r = EncodedKeyRange::parse("0101..=0aff");
953			// decode_binary("0101") = [0x01, 0x01]
954			assert_eq!(r.start, included(b"0101"));
955			// decode_binary("0aff") = [0x0a, 0xff]
956			assert_eq!(r.end, included(b"0aff"));
957		}
958	}
959
960	fn included(key: &[u8]) -> Bound<EncodedKey> {
961		Bound::Included(EncodedKey::new(key))
962	}
963
964	fn excluded(key: &[u8]) -> Bound<EncodedKey> {
965		Bound::Excluded(EncodedKey::new(key))
966	}
967}