1use serde::{de::DeserializeOwned, Serialize};
45
46use crate::error::{StoreError, StoreResult};
47
48pub fn encode_value<T: Serialize>(value: &T) -> StoreResult<Vec<u8>> {
52 postcard::to_allocvec(value).map_err(StoreError::value_codec)
53}
54
55pub fn decode_value<T: DeserializeOwned>(bytes: &[u8]) -> StoreResult<T> {
57 postcard::from_bytes(bytes).map_err(StoreError::value_codec)
58}
59
60pub trait KeyEncode {
68 fn encode_into(&self, out: &mut Vec<u8>);
70
71 fn encode(&self) -> Vec<u8> {
73 let mut out = Vec::new();
74 self.encode_into(&mut out);
75 out
76 }
77}
78
79pub trait KeyDecode: Sized {
83 fn decode_from(buf: &mut &[u8]) -> StoreResult<Self>;
85
86 fn decode(bytes: &[u8]) -> StoreResult<Self> {
89 let mut cur = bytes;
90 let value = Self::decode_from(&mut cur)?;
91 if !cur.is_empty() {
92 return Err(StoreError::key_decode(format!(
93 "{} trailing byte(s) after key",
94 cur.len()
95 )));
96 }
97 Ok(value)
98 }
99}
100
101const ESC: u8 = 0x00;
104const ESC_LITERAL: u8 = 0x01; const ESC_TERM: u8 = 0x00; fn encode_bytes_escaped(bytes: &[u8], out: &mut Vec<u8>) {
108 for &b in bytes {
109 if b == ESC {
110 out.push(ESC);
111 out.push(ESC_LITERAL);
112 } else {
113 out.push(b);
114 }
115 }
116 out.push(ESC);
117 out.push(ESC_TERM);
118}
119
120fn decode_bytes_escaped(buf: &mut &[u8]) -> StoreResult<Vec<u8>> {
121 let data = *buf;
122 let mut out = Vec::new();
123 let mut i = 0;
124 while i < data.len() {
125 let b = data[i];
126 if b != ESC {
127 out.push(b);
128 i += 1;
129 continue;
130 }
131 let next = *data
133 .get(i + 1)
134 .ok_or_else(|| StoreError::key_decode("truncated escape sequence in key"))?;
135 match next {
136 ESC_TERM => {
137 *buf = &data[i + 2..];
138 return Ok(out);
139 }
140 ESC_LITERAL => {
141 out.push(0x00);
142 i += 2;
143 }
144 other => {
145 return Err(StoreError::key_decode(format!(
146 "invalid escape 0x00 0x{other:02x} in key"
147 )))
148 }
149 }
150 }
151 Err(StoreError::key_decode("unterminated byte string in key"))
152}
153
154impl KeyEncode for u64 {
157 fn encode_into(&self, out: &mut Vec<u8>) {
158 out.extend_from_slice(&self.to_be_bytes());
159 }
160}
161
162impl KeyDecode for u64 {
163 fn decode_from(buf: &mut &[u8]) -> StoreResult<Self> {
164 if buf.len() < 8 {
165 return Err(StoreError::key_decode("need 8 bytes for u64 key"));
166 }
167 let (head, tail) = buf.split_at(8);
168 *buf = tail;
169 let arr: [u8; 8] = head.try_into().expect("split_at(8) yields 8 bytes");
170 Ok(u64::from_be_bytes(arr))
171 }
172}
173
174const I64_SIGN_FLIP: u64 = 1 << 63;
177
178impl KeyEncode for i64 {
179 fn encode_into(&self, out: &mut Vec<u8>) {
180 let biased = (*self as u64) ^ I64_SIGN_FLIP;
181 out.extend_from_slice(&biased.to_be_bytes());
182 }
183}
184
185impl KeyDecode for i64 {
186 fn decode_from(buf: &mut &[u8]) -> StoreResult<Self> {
187 if buf.len() < 8 {
188 return Err(StoreError::key_decode("need 8 bytes for i64 key"));
189 }
190 let (head, tail) = buf.split_at(8);
191 *buf = tail;
192 let arr: [u8; 8] = head.try_into().expect("split_at(8) yields 8 bytes");
193 Ok((u64::from_be_bytes(arr) ^ I64_SIGN_FLIP) as i64)
194 }
195}
196
197impl KeyEncode for String {
200 fn encode_into(&self, out: &mut Vec<u8>) {
201 encode_bytes_escaped(self.as_bytes(), out);
202 }
203}
204
205impl KeyEncode for str {
206 fn encode_into(&self, out: &mut Vec<u8>) {
207 encode_bytes_escaped(self.as_bytes(), out);
208 }
209}
210
211impl KeyEncode for &str {
212 fn encode_into(&self, out: &mut Vec<u8>) {
213 encode_bytes_escaped(self.as_bytes(), out);
214 }
215}
216
217impl KeyDecode for String {
218 fn decode_from(buf: &mut &[u8]) -> StoreResult<Self> {
219 let bytes = decode_bytes_escaped(buf)?;
220 String::from_utf8(bytes).map_err(|e| StoreError::key_decode(format!("key not utf-8: {e}")))
221 }
222}
223
224impl<A: KeyEncode, B: KeyEncode> KeyEncode for (A, B) {
227 fn encode_into(&self, out: &mut Vec<u8>) {
228 self.0.encode_into(out);
229 self.1.encode_into(out);
230 }
231}
232
233impl<A: KeyDecode, B: KeyDecode> KeyDecode for (A, B) {
234 fn decode_from(buf: &mut &[u8]) -> StoreResult<Self> {
235 let a = A::decode_from(buf)?;
236 let b = B::decode_from(buf)?;
237 Ok((a, b))
238 }
239}
240
241impl<A: KeyEncode, B: KeyEncode, C: KeyEncode> KeyEncode for (A, B, C) {
242 fn encode_into(&self, out: &mut Vec<u8>) {
243 self.0.encode_into(out);
244 self.1.encode_into(out);
245 self.2.encode_into(out);
246 }
247}
248
249impl<A: KeyDecode, B: KeyDecode, C: KeyDecode> KeyDecode for (A, B, C) {
250 fn decode_from(buf: &mut &[u8]) -> StoreResult<Self> {
251 let a = A::decode_from(buf)?;
252 let b = B::decode_from(buf)?;
253 let c = C::decode_from(buf)?;
254 Ok((a, b, c))
255 }
256}
257
258#[cfg(test)]
259mod tests {
260 use super::*;
261 use proptest::prelude::*;
262
263 #[test]
266 fn value_codec_round_trips_and_is_deterministic() {
267 #[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
268 struct V {
269 a: u32,
270 b: String,
271 c: Vec<u8>,
272 }
273 let v = V {
274 a: 7,
275 b: "hello".into(),
276 c: vec![1, 2, 3],
277 };
278 let e1 = encode_value(&v).unwrap();
279 let e2 = encode_value(&v).unwrap();
280 assert_eq!(e1, e2, "postcard must be deterministic");
281 assert_eq!(decode_value::<V>(&e1).unwrap(), v);
282 }
283
284 fn enc<K: KeyEncode>(k: &K) -> Vec<u8> {
287 k.encode()
288 }
289
290 #[test]
291 fn string_prefix_sorts_before_extension() {
292 assert!(enc(&"aa".to_string()) < enc(&"aab".to_string()));
294 assert!(enc(&"aa".to_string()) < enc(&"ab".to_string()));
295 assert!(enc(&"".to_string()) < enc(&"a".to_string()));
296 }
297
298 #[test]
299 fn string_with_embedded_null_round_trips_and_orders() {
300 let with_null = String::from_utf8(vec![b'a', 0x00, b'b']).unwrap();
301 let mut buf = enc(&with_null);
302 assert_eq!(String::decode(&buf).unwrap(), with_null);
304 buf.clear();
306 with_null.encode_into(&mut buf);
307 assert!(buf.windows(2).filter(|w| *w == [0x00, 0x00]).count() == 1,
308 "only the terminator may be 0x00 0x00");
309 }
310
311 #[test]
312 fn i64_negatives_sort_below_non_negatives() {
313 assert!(enc(&-1i64) < enc(&0i64));
314 assert!(enc(&i64::MIN) < enc(&i64::MAX));
315 assert!(enc(&-5i64) < enc(&-1i64));
316 }
317
318 #[test]
319 fn tuple_orders_by_first_then_second_component() {
320 assert!(enc(&(1u64, "z".to_string())) < enc(&(2u64, "a".to_string())));
321 assert!(enc(&(2u64, "a".to_string())) < enc(&(2u64, "b".to_string())));
322 assert!(enc(&("a".to_string(), "z".to_string())) < enc(&("ab".to_string(), "a".to_string())));
324 }
325
326 fn assert_order_law<K: KeyEncode + Ord>(a: &K, b: &K) {
331 assert_eq!(
332 a.cmp(b),
333 enc(a).cmp(&enc(b)),
334 "encoding must preserve order"
335 );
336 }
337
338 proptest! {
339 #[test]
340 fn u64_round_trips(x in any::<u64>()) {
341 prop_assert_eq!(u64::decode(&x.encode()).unwrap(), x);
342 }
343
344 #[test]
345 fn i64_round_trips(x in any::<i64>()) {
346 prop_assert_eq!(i64::decode(&x.encode()).unwrap(), x);
347 }
348
349 #[test]
350 fn string_round_trips(s in any::<String>()) {
351 prop_assert_eq!(String::decode(&s.encode()).unwrap(), s);
352 }
353
354 #[test]
355 fn u64_order_preserving(a in any::<u64>(), b in any::<u64>()) {
356 assert_order_law(&a, &b);
357 }
358
359 #[test]
360 fn i64_order_preserving(a in any::<i64>(), b in any::<i64>()) {
361 assert_order_law(&a, &b);
362 }
363
364 #[test]
365 fn string_order_preserving(a in any::<String>(), b in any::<String>()) {
366 assert_order_law(&a, &b);
367 }
368
369 #[test]
370 fn tuple_u64_string_order_preserving(
371 a in any::<(u64, String)>(),
372 b in any::<(u64, String)>(),
373 ) {
374 assert_order_law(&a, &b);
375 }
376
377 #[test]
378 fn tuple_string_string_round_trips_and_orders(
379 a in any::<(String, String)>(),
380 b in any::<(String, String)>(),
381 ) {
382 prop_assert_eq!(<(String, String)>::decode(&a.encode()).unwrap(), a.clone());
383 assert_order_law(&a, &b);
384 }
385 }
386}