1use std::ops::{Bound, RangeBounds};
6
7use bincode::Options;
8use serde::Serialize;
9
10#[inline]
11pub fn be_fix_int_ser<S>(t: &S) -> Vec<u8>
12where
13 S: ?Sized + serde::Serialize,
14{
15 bincode::DefaultOptions::new()
16 .with_big_endian()
17 .with_fixint_encoding()
18 .serialize(t)
19 .expect("failed to serialize via be_fix_int_ser method")
20}
21
22pub(crate) fn iterator_bounds_with_range<K>(
23 range: impl RangeBounds<K>,
24) -> (Option<Vec<u8>>, Option<Vec<u8>>)
25where
26 K: Serialize,
27{
28 let iterator_lower_bound = match range.start_bound() {
29 Bound::Included(lower_bound) => {
30 Some(be_fix_int_ser(&lower_bound))
32 }
33 Bound::Excluded(lower_bound) => {
34 let mut key_buf = be_fix_int_ser(&lower_bound);
35
36 if is_max(&key_buf) {
37 key_buf.push(0);
42 } else {
43 big_endian_add_one(&mut key_buf);
45 }
46 Some(key_buf)
47 }
48 Bound::Unbounded => None,
49 };
50 let iterator_upper_bound = match range.end_bound() {
51 Bound::Included(upper_bound) => {
52 let mut key_buf = be_fix_int_ser(&upper_bound);
53
54 if is_max(&key_buf) {
55 key_buf.push(0);
60 } else {
61 big_endian_add_one(&mut key_buf);
64 }
65 Some(key_buf)
66 }
67 Bound::Excluded(upper_bound) => {
68 Some(be_fix_int_ser(&upper_bound))
70 }
71 Bound::Unbounded => None,
72 };
73 (iterator_lower_bound, iterator_upper_bound)
74}
75
76pub(crate) fn prefix_iterator_bounds<P>(prefix: &P) -> (Option<Vec<u8>>, Option<Vec<u8>>)
86where
87 P: ?Sized + Serialize,
88{
89 let lower = be_fix_int_ser(prefix);
90 let upper = if is_max(&lower) {
91 None
92 } else {
93 let mut upper = lower.clone();
94 big_endian_add_one(&mut upper);
95 Some(upper)
96 };
97 (Some(lower), upper)
98}
99
100pub(crate) fn prefix_iterator_bounds_with_range<P, K>(
108 prefix: &P,
109 range: impl RangeBounds<K>,
110) -> (Option<Vec<u8>>, Option<Vec<u8>>)
111where
112 P: ?Sized + Serialize,
113 K: Serialize,
114{
115 let prefix_buf = be_fix_int_ser(prefix);
116 let (lower_bound, upper_bound) = iterator_bounds_with_range(range);
117
118 let mut iterator_lower_bound = prefix_buf.clone();
119 if let Some(lower_bound) = lower_bound {
120 iterator_lower_bound.extend_from_slice(&lower_bound);
121 }
122
123 let iterator_upper_bound = match upper_bound {
124 Some(upper_bound) => {
125 let mut key_buf = prefix_buf;
126 key_buf.extend_from_slice(&upper_bound);
127 Some(key_buf)
128 }
129 None => prefix_iterator_bounds(prefix).1,
131 };
132
133 (Some(iterator_lower_bound), iterator_upper_bound)
134}
135
136fn big_endian_add_one(v: &mut [u8]) {
147 for i in (0..v.len()).rev() {
148 if v[i] == u8::MAX {
149 v[i] = 0;
150 } else {
151 v[i] += 1;
152 return;
153 }
154 }
155 unreachable!("big_endian_add_one called on an all-0xFF value")
159}
160
161fn is_max(v: &[u8]) -> bool {
163 v.iter().all(|&x| x == u8::MAX)
164}
165
166#[expect(clippy::assign_op_pattern, clippy::manual_div_ceil)]
167#[test]
168fn test_helpers() {
169 let v = vec![];
170 assert!(is_max(&v));
171
172 fn check_add(v: Vec<u8>) {
173 let mut v = v;
174 let num = Num32::from_big_endian(&v);
175 big_endian_add_one(&mut v);
176 assert!(num + 1 == Num32::from_big_endian(&v));
177 }
178
179 uint::construct_uint! {
180 struct Num32(4);
182 }
183
184 check_add(vec![1; 32]);
185 check_add(vec![6; 32]);
186 check_add(vec![254; 32]);
187
188 }
190
191#[test]
192#[should_panic(expected = "all-0xFF")]
193fn big_endian_add_one_panics_on_max() {
194 big_endian_add_one(&mut [0xFFu8; 4]);
195}
196
197#[test]
198fn test_inclusive_upper_bound_at_max() {
199 fn check_max<K: Serialize>(max: K) {
206 let hi = be_fix_int_ser(&max);
207 assert!(is_max(&hi), "test value must serialize to all-0xFF");
208 let (_, upper) = iterator_bounds_with_range::<K>((Bound::Unbounded, Bound::Included(max)));
209 let upper = upper.expect("inclusive upper at the max must be bounded, not None");
210
211 let mut extension = hi.clone();
213 extension.push(0);
214 assert!(hi < upper, "the max key itself must stay in range");
215 assert!(
216 extension >= upper,
217 "a key extending the max must be excluded"
218 );
219 assert_eq!(upper, extension, "bound must be exactly ser(hi) ++ [0]");
220 }
221 check_max(u8::MAX);
222 check_max(u64::MAX);
223 check_max([0xFFu8; 32]);
224
225 let (lower, _) = iterator_bounds_with_range::<u8>((Bound::Excluded(u8::MAX), Bound::Unbounded));
227 assert_eq!(lower, Some(vec![0xFF, 0x00]));
228}
229
230#[test]
231fn prefixed_bounds_stay_within_the_prefix() {
232 fn check_max<K: Serialize + Copy>(max: K) {
237 assert!(
238 is_max(&be_fix_int_ser(&max)),
239 "test value must serialize to all-0xFF"
240 );
241 let (lower, upper) = prefix_iterator_bounds_with_range(&0u8, ..=max);
242 let upper = upper.expect("an inclusive upper bound must be bounded, not None");
243
244 assert_eq!(lower, Some(be_fix_int_ser(&0u8)));
245 assert!(
246 be_fix_int_ser(&(0u8, max)) < upper,
247 "the maximum key of the prefix must stay in range"
248 );
249 assert!(
250 upper <= be_fix_int_ser(&1u8),
251 "the bound must not reach into the next prefix"
252 );
253 }
254 check_max(u8::MAX);
255 check_max(u32::MAX);
256 check_max(u64::MAX);
257
258 let (lower, _) = prefix_iterator_bounds_with_range::<u8, u8>(
260 &0u8,
261 (Bound::Excluded(u8::MAX), Bound::Unbounded),
262 );
263 assert_eq!(lower, Some(vec![0x00, 0xFF, 0x00]));
264
265 assert_eq!(
268 prefix_iterator_bounds_with_range::<u8, u32>(&0u8, ..),
269 (Some(vec![0x00]), Some(vec![0x01]))
270 );
271 assert_eq!(
272 prefix_iterator_bounds_with_range::<u8, u32>(&u8::MAX, ..),
273 prefix_iterator_bounds(&u8::MAX)
274 );
275}