1use crate::key_buckets::BucketError;
6use redb::{Key, Value};
7use std::cmp::Ordering;
8use std::fmt::Debug;
9
10#[derive(Debug, Clone)]
15pub struct KeyBuilder {
16 bucket_size: u64,
17}
18
19impl KeyBuilder {
20 pub fn new(bucket_size: u64) -> Result<Self, BucketError> {
28 if bucket_size == 0 {
29 return Err(BucketError::InvalidBucketSize(bucket_size));
30 }
31 Ok(Self { bucket_size })
32 }
33
34 pub fn bucketed_key<K: Key>(&self, base_key: K, sequence: u64) -> BucketedKey<K> {
45 let bucket = sequence / self.bucket_size;
46 BucketedKey { base_key, bucket }
47 }
48
49 pub fn bucket_size(&self) -> u64 {
51 self.bucket_size
52 }
53}
54
55#[derive(Debug, Clone)]
61pub struct BucketedKey<K: Key> {
62 pub base_key: K,
63 pub bucket: u64,
64}
65
66impl<K: Key> BucketedKey<K> {
67 pub fn new(base_key: K, bucket: u64) -> Self {
72 Self { base_key, bucket }
73 }
74
75 pub fn base_key(&self) -> &K {
77 &self.base_key
78 }
79
80 pub fn bucket(&self) -> u64 {
82 self.bucket
83 }
84}
85
86impl Value for BucketedKey<u64> {
88 type SelfType<'a>
89 = BucketedKey<u64>
90 where
91 Self: 'a;
92
93 type AsBytes<'a>
94 = Vec<u8>
95 where
96 Self: 'a;
97
98 fn fixed_width() -> Option<usize> {
99 Some(16) }
101
102 fn from_bytes<'a>(data: &'a [u8]) -> Self::SelfType<'a>
103 where
104 Self: 'a,
105 {
106 if data.len() < 16 {
107 panic!(
108 "BucketedKey data too short: expected at least 16 bytes, got {}",
109 data.len()
110 );
111 }
112
113 let bucket = u64::from_le_bytes([
115 data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
116 ]);
117
118 let base_key = u64::from_le_bytes([
120 data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15],
121 ]);
122
123 BucketedKey { base_key, bucket }
124 }
125
126 fn as_bytes<'a, 'b: 'a>(value: &'a Self::SelfType<'b>) -> Self::AsBytes<'a>
127 where
128 Self: 'a,
129 Self: 'b,
130 {
131 let bucket_bytes = value.bucket.to_le_bytes();
133
134 let base_key_bytes = value.base_key.to_le_bytes();
136
137 let mut result = Vec::with_capacity(16);
139 result.extend_from_slice(&bucket_bytes);
140 result.extend_from_slice(&base_key_bytes);
141
142 result
143 }
144
145 fn type_name() -> redb::TypeName {
146 redb::TypeName::new("redb_extras::key_buckets::BucketedKey<u64>")
147 }
148}
149
150impl Key for BucketedKey<u64> {
151 fn compare(data1: &[u8], data2: &[u8]) -> Ordering {
152 if data1.len() < 16 || data2.len() < 16 {
154 panic!("BucketedKey data too short for comparison");
155 }
156
157 let bucket1 = u64::from_le_bytes([
158 data1[0], data1[1], data1[2], data1[3], data1[4], data1[5], data1[6], data1[7],
159 ]);
160 let bucket2 = u64::from_le_bytes([
161 data2[0], data2[1], data2[2], data2[3], data2[4], data2[5], data2[6], data2[7],
162 ]);
163
164 match bucket1.cmp(&bucket2) {
166 Ordering::Equal => {
167 let base1 = u64::from_le_bytes([
169 data1[8], data1[9], data1[10], data1[11], data1[12], data1[13], data1[14],
170 data1[15],
171 ]);
172 let base2 = u64::from_le_bytes([
173 data2[8], data2[9], data2[10], data2[11], data2[12], data2[13], data2[14],
174 data2[15],
175 ]);
176 base1.cmp(&base2)
177 }
178 other => other,
179 }
180 }
181}
182
183#[cfg(test)]
184mod tests {
185 use super::*;
186
187 #[test]
188 fn test_key_builder_creation() {
189 let builder = KeyBuilder::new(1000);
191 assert!(builder.is_ok());
192 assert_eq!(builder.unwrap().bucket_size(), 1000);
193
194 let builder = KeyBuilder::new(0);
196 assert!(builder.is_err());
197 }
198
199 #[test]
200 fn test_bucketed_key_creation() {
201 let builder = KeyBuilder::new(1000).unwrap();
202
203 let key1 = builder.bucketed_key(123u64, 500);
205 assert_eq!(key1.bucket(), 0);
206 assert_eq!(key1.base_key(), &123u64);
207
208 let key2 = builder.bucketed_key(123u64, 1500);
209 assert_eq!(key2.bucket(), 1);
210 assert_eq!(key2.base_key(), &123u64);
211
212 let key3 = builder.bucketed_key(123u64, 2500);
213 assert_eq!(key3.bucket(), 2);
214 }
215
216 #[test]
217 fn test_bucketed_key_serialization() {
218 let builder = KeyBuilder::new(1000).unwrap();
219 let key = builder.bucketed_key(123u64, 1500); let bytes: Vec<u8> = BucketedKey::as_bytes(&key);
223 assert_eq!(bytes.len(), 16);
224
225 let deserialized: BucketedKey<u64> = BucketedKey::from_bytes(&bytes);
227 assert_eq!(deserialized.bucket(), 1);
228 assert_eq!(deserialized.base_key(), &123u64);
229 }
230
231 #[test]
232 fn test_bucketed_key_ordering() {
233 let builder = KeyBuilder::new(1000).unwrap();
234
235 let key1 = builder.bucketed_key(123u64, 500); let key2 = builder.bucketed_key(123u64, 1500); let key3 = builder.bucketed_key(456u64, 500); let bytes1: Vec<u8> = BucketedKey::as_bytes(&key1);
242 let bytes2: Vec<u8> = BucketedKey::as_bytes(&key2);
243 let bytes3: Vec<u8> = BucketedKey::as_bytes(&key3);
244
245 assert_eq!(
247 BucketedKey::<u64>::compare(&bytes1, &bytes2),
248 Ordering::Less
249 );
250 assert_eq!(
251 BucketedKey::<u64>::compare(&bytes2, &bytes1),
252 Ordering::Greater
253 );
254
255 assert_eq!(
257 BucketedKey::<u64>::compare(&bytes1, &bytes3),
258 Ordering::Less
259 );
260 assert_eq!(
261 BucketedKey::<u64>::compare(&bytes3, &bytes1),
262 Ordering::Greater
263 );
264 }
265}