1use std::cmp::Ordering;
2use std::convert::TryInto;
3use std::fmt::Debug;
4use std::mem::size_of;
5
6#[derive(Eq, PartialEq, Clone, Debug)]
7enum TypeClassification {
8 Internal,
9 UserDefined,
10}
11
12impl TypeClassification {
13 fn to_byte(&self) -> u8 {
14 match self {
15 TypeClassification::Internal => 1,
16 TypeClassification::UserDefined => 2,
17 }
18 }
19
20 fn from_byte(value: u8) -> Self {
21 match value {
22 1 => TypeClassification::Internal,
23 2 => TypeClassification::UserDefined,
24 _ => unreachable!(),
25 }
26 }
27}
28
29#[derive(Eq, PartialEq, Debug, Clone)]
30pub struct TypeName {
31 classification: TypeClassification,
32 name: String,
33}
34
35impl TypeName {
36 pub fn new(name: &str) -> Self {
39 Self {
40 classification: TypeClassification::UserDefined,
41 name: name.to_string(),
42 }
43 }
44
45 pub(crate) fn internal(name: &str) -> Self {
46 Self {
47 classification: TypeClassification::Internal,
48 name: name.to_string(),
49 }
50 }
51
52 pub(crate) fn to_bytes(&self) -> Vec<u8> {
53 let mut result = Vec::with_capacity(self.name.as_bytes().len() + 1);
54 result.push(self.classification.to_byte());
55 result.extend_from_slice(self.name.as_bytes());
56 result
57 }
58
59 pub(crate) fn from_bytes(bytes: &[u8]) -> Self {
60 let classification = TypeClassification::from_byte(bytes[0]);
61 let name = std::str::from_utf8(&bytes[1..]).unwrap().to_string();
62
63 Self {
64 classification,
65 name,
66 }
67 }
68
69 pub(crate) fn name(&self) -> &str {
70 &self.name
71 }
72}
73
74pub trait Value: Debug {
75 type SelfType<'a>: Debug + 'a
77 where
78 Self: 'a;
79
80 type AsBytes<'a>: AsRef<[u8]> + 'a
81 where
82 Self: 'a;
83
84 fn fixed_width() -> Option<usize>;
86
87 fn from_bytes<'a>(data: &'a [u8]) -> Self::SelfType<'a>
90 where
91 Self: 'a;
92
93 fn as_bytes<'a, 'b: 'a>(value: &'a Self::SelfType<'b>) -> Self::AsBytes<'a>
95 where
96 Self: 'b;
97
98 fn type_name() -> TypeName;
100}
101
102pub trait MutInPlaceValue: Value {
105 type BaseRefType: Debug + ?Sized;
107
108 fn initialize(data: &mut [u8]);
111
112 fn from_bytes_mut(data: &mut [u8]) -> &mut Self::BaseRefType;
113}
114
115impl MutInPlaceValue for &[u8] {
116 type BaseRefType = [u8];
117
118 fn initialize(_data: &mut [u8]) {
119 }
121
122 fn from_bytes_mut(data: &mut [u8]) -> &mut Self::BaseRefType {
123 data
124 }
125}
126
127pub trait Key: Value {
128 fn compare(data1: &[u8], data2: &[u8]) -> Ordering;
130}
131
132impl Value for () {
133 type SelfType<'a> = ()
134 where
135 Self: 'a;
136 type AsBytes<'a> = &'a [u8]
137 where
138 Self: 'a;
139
140 fn fixed_width() -> Option<usize> {
141 Some(0)
142 }
143
144 #[allow(clippy::unused_unit, clippy::semicolon_if_nothing_returned)]
145 fn from_bytes<'a>(_data: &'a [u8]) -> ()
146 where
147 Self: 'a,
148 {
149 ()
150 }
151
152 #[allow(clippy::ignored_unit_patterns)]
153 fn as_bytes<'a, 'b: 'a>(_: &'a Self::SelfType<'b>) -> &'a [u8]
154 where
155 Self: 'b,
156 {
157 &[]
158 }
159
160 fn type_name() -> TypeName {
161 TypeName::internal("()")
162 }
163}
164
165impl Key for () {
166 fn compare(_data1: &[u8], _data2: &[u8]) -> Ordering {
167 Ordering::Equal
168 }
169}
170
171impl Value for bool {
172 type SelfType<'a> = bool
173 where
174 Self: 'a;
175 type AsBytes<'a> = &'a [u8]
176 where
177 Self: 'a;
178
179 fn fixed_width() -> Option<usize> {
180 Some(1)
181 }
182
183 fn from_bytes<'a>(data: &'a [u8]) -> bool
184 where
185 Self: 'a,
186 {
187 match data[0] {
188 0 => false,
189 1 => true,
190 _ => unreachable!(),
191 }
192 }
193
194 fn as_bytes<'a, 'b: 'a>(value: &'a Self::SelfType<'b>) -> &'a [u8]
195 where
196 Self: 'b,
197 {
198 match value {
199 true => &[1],
200 false => &[0],
201 }
202 }
203
204 fn type_name() -> TypeName {
205 TypeName::internal("bool")
206 }
207}
208
209impl Key for bool {
210 fn compare(data1: &[u8], data2: &[u8]) -> Ordering {
211 let value1 = Self::from_bytes(data1);
212 let value2 = Self::from_bytes(data2);
213 value1.cmp(&value2)
214 }
215}
216
217impl<T: Value> Value for Option<T> {
218 type SelfType<'a> = Option<T::SelfType<'a>>
219 where
220 Self: 'a;
221 type AsBytes<'a> = Vec<u8>
222 where
223 Self: 'a;
224
225 fn fixed_width() -> Option<usize> {
226 T::fixed_width().map(|x| x + 1)
227 }
228
229 fn from_bytes<'a>(data: &'a [u8]) -> Option<T::SelfType<'a>>
230 where
231 Self: 'a,
232 {
233 match data[0] {
234 0 => None,
235 1 => Some(T::from_bytes(&data[1..])),
236 _ => unreachable!(),
237 }
238 }
239
240 fn as_bytes<'a, 'b: 'a>(value: &'a Self::SelfType<'b>) -> Vec<u8>
241 where
242 Self: 'b,
243 {
244 let mut result = vec![0];
245 if let Some(x) = value {
246 result[0] = 1;
247 result.extend_from_slice(T::as_bytes(x).as_ref());
248 } else if let Some(fixed_width) = T::fixed_width() {
249 result.extend_from_slice(&vec![0; fixed_width]);
250 }
251 result
252 }
253
254 fn type_name() -> TypeName {
255 TypeName::internal(&format!("Option<{}>", T::type_name().name()))
256 }
257}
258
259impl<T: Key> Key for Option<T> {
260 #[allow(clippy::collapsible_else_if)]
261 fn compare(data1: &[u8], data2: &[u8]) -> Ordering {
262 if data1[0] == 0 {
263 if data2[0] == 0 {
264 Ordering::Equal
265 } else {
266 Ordering::Less
267 }
268 } else {
269 if data2[0] == 0 {
270 Ordering::Greater
271 } else {
272 T::compare(&data1[1..], &data2[1..])
273 }
274 }
275 }
276}
277
278impl Value for &[u8] {
279 type SelfType<'a> = &'a [u8]
280 where
281 Self: 'a;
282 type AsBytes<'a> = &'a [u8]
283 where
284 Self: 'a;
285
286 fn fixed_width() -> Option<usize> {
287 None
288 }
289
290 fn from_bytes<'a>(data: &'a [u8]) -> &'a [u8]
291 where
292 Self: 'a,
293 {
294 data
295 }
296
297 fn as_bytes<'a, 'b: 'a>(value: &'a Self::SelfType<'b>) -> &'a [u8]
298 where
299 Self: 'b,
300 {
301 value
302 }
303
304 fn type_name() -> TypeName {
305 TypeName::internal("&[u8]")
306 }
307}
308
309impl Key for &[u8] {
310 fn compare(data1: &[u8], data2: &[u8]) -> Ordering {
311 data1.cmp(data2)
312 }
313}
314
315impl<const N: usize> Value for &[u8; N] {
316 type SelfType<'a> = &'a [u8; N]
317 where
318 Self: 'a;
319 type AsBytes<'a> = &'a [u8; N]
320 where
321 Self: 'a;
322
323 fn fixed_width() -> Option<usize> {
324 Some(N)
325 }
326
327 fn from_bytes<'a>(data: &'a [u8]) -> &'a [u8; N]
328 where
329 Self: 'a,
330 {
331 data.try_into().unwrap()
332 }
333
334 fn as_bytes<'a, 'b: 'a>(value: &'a Self::SelfType<'b>) -> &'a [u8; N]
335 where
336 Self: 'b,
337 {
338 value
339 }
340
341 fn type_name() -> TypeName {
342 TypeName::internal(&format!("[u8;{N}]"))
343 }
344}
345
346impl<const N: usize> Key for &[u8; N] {
347 fn compare(data1: &[u8], data2: &[u8]) -> Ordering {
348 data1.cmp(data2)
349 }
350}
351
352impl<const N: usize, T: Value> Value for [T; N] {
353 type SelfType<'a> = [T::SelfType<'a>; N]
354 where
355 Self: 'a;
356 type AsBytes<'a> = Vec<u8>
357 where
358 Self: 'a;
359
360 fn fixed_width() -> Option<usize> {
361 T::fixed_width().map(|x| x * N)
362 }
363
364 fn from_bytes<'a>(data: &'a [u8]) -> [T::SelfType<'a>; N]
365 where
366 Self: 'a,
367 {
368 let mut result = Vec::with_capacity(N);
369 if let Some(fixed) = T::fixed_width() {
370 for i in 0..N {
371 result.push(T::from_bytes(&data[fixed * i..fixed * (i + 1)]));
372 }
373 } else {
374 let mut start = size_of::<u32>() * N;
376 for i in 0..N {
377 let range = size_of::<u32>() * i..size_of::<u32>() * (i + 1);
378 let end = u32::from_le_bytes(data[range].try_into().unwrap()) as usize;
379 result.push(T::from_bytes(&data[start..end]));
380 start = end;
381 }
382 }
383 result.try_into().unwrap()
384 }
385
386 fn as_bytes<'a, 'b: 'a>(value: &'a Self::SelfType<'b>) -> Vec<u8>
387 where
388 Self: 'b,
389 {
390 if let Some(fixed) = T::fixed_width() {
391 let mut result = Vec::with_capacity(fixed * N);
392 for item in value {
393 result.extend_from_slice(T::as_bytes(item).as_ref());
394 }
395 result
396 } else {
397 let mut result = vec![0u8; size_of::<u32>() * N];
399 for i in 0..N {
400 result.extend_from_slice(T::as_bytes(&value[i]).as_ref());
401 let end: u32 = result.len().try_into().unwrap();
402 result[size_of::<u32>() * i..size_of::<u32>() * (i + 1)]
403 .copy_from_slice(&end.to_le_bytes());
404 }
405 result
406 }
407 }
408
409 fn type_name() -> TypeName {
410 TypeName::internal(&format!("[{};{N}]", T::type_name().name()))
413 }
414}
415
416impl<const N: usize, T: Key> Key for [T; N] {
417 fn compare(data1: &[u8], data2: &[u8]) -> Ordering {
418 if let Some(fixed) = T::fixed_width() {
419 for i in 0..N {
420 let range = fixed * i..fixed * (i + 1);
421 let comparison = T::compare(&data1[range.clone()], &data2[range]);
422 if !comparison.is_eq() {
423 return comparison;
424 }
425 }
426 } else {
427 let mut start1 = size_of::<u32>() * N;
429 let mut start2 = size_of::<u32>() * N;
430 for i in 0..N {
431 let range = size_of::<u32>() * i..size_of::<u32>() * (i + 1);
432 let end1 = u32::from_le_bytes(data1[range.clone()].try_into().unwrap()) as usize;
433 let end2 = u32::from_le_bytes(data2[range].try_into().unwrap()) as usize;
434 let comparison = T::compare(&data1[start1..end1], &data2[start2..end2]);
435 if !comparison.is_eq() {
436 return comparison;
437 }
438 start1 = end1;
439 start2 = end2;
440 }
441 }
442 Ordering::Equal
443 }
444}
445
446impl Value for &str {
447 type SelfType<'a> = &'a str
448 where
449 Self: 'a;
450 type AsBytes<'a> = &'a str
451 where
452 Self: 'a;
453
454 fn fixed_width() -> Option<usize> {
455 None
456 }
457
458 fn from_bytes<'a>(data: &'a [u8]) -> &'a str
459 where
460 Self: 'a,
461 {
462 std::str::from_utf8(data).unwrap()
463 }
464
465 fn as_bytes<'a, 'b: 'a>(value: &'a Self::SelfType<'b>) -> &'a str
466 where
467 Self: 'b,
468 {
469 value
470 }
471
472 fn type_name() -> TypeName {
473 TypeName::internal("&str")
474 }
475}
476
477impl Key for &str {
478 fn compare(data1: &[u8], data2: &[u8]) -> Ordering {
479 let str1 = Self::from_bytes(data1);
480 let str2 = Self::from_bytes(data2);
481 str1.cmp(str2)
482 }
483}
484
485impl Value for String {
486 type SelfType<'a> = String
487 where
488 Self: 'a;
489 type AsBytes<'a> = &'a str
490 where
491 Self: 'a;
492
493 fn fixed_width() -> Option<usize> {
494 None
495 }
496
497 fn from_bytes<'a>(data: &'a [u8]) -> String
498 where
499 Self: 'a,
500 {
501 std::str::from_utf8(data).unwrap().to_string()
502 }
503
504 fn as_bytes<'a, 'b: 'a>(value: &'a Self::SelfType<'b>) -> &'a str
505 where
506 Self: 'b,
507 {
508 value.as_str()
509 }
510
511 fn type_name() -> TypeName {
512 TypeName::internal("String")
513 }
514}
515
516impl Key for String {
517 fn compare(data1: &[u8], data2: &[u8]) -> Ordering {
518 let str1 = std::str::from_utf8(data1).unwrap();
519 let str2 = std::str::from_utf8(data2).unwrap();
520 str1.cmp(str2)
521 }
522}
523
524impl Value for char {
525 type SelfType<'a> = char;
526 type AsBytes<'a> = [u8; 3] where Self: 'a;
527
528 fn fixed_width() -> Option<usize> {
529 Some(3)
530 }
531
532 fn from_bytes<'a>(data: &'a [u8]) -> char
533 where
534 Self: 'a,
535 {
536 char::from_u32(u32::from_le_bytes([data[0], data[1], data[2], 0])).unwrap()
537 }
538
539 fn as_bytes<'a, 'b: 'a>(value: &'a Self::SelfType<'b>) -> [u8; 3]
540 where
541 Self: 'b,
542 {
543 let bytes = u32::from(*value).to_le_bytes();
544 [bytes[0], bytes[1], bytes[2]]
545 }
546
547 fn type_name() -> TypeName {
548 TypeName::internal(stringify!(char))
549 }
550}
551
552impl Key for char {
553 fn compare(data1: &[u8], data2: &[u8]) -> Ordering {
554 Self::from_bytes(data1).cmp(&Self::from_bytes(data2))
555 }
556}
557
558macro_rules! le_value {
559 ($t:ty) => {
560 impl Value for $t {
561 type SelfType<'a> = $t;
562 type AsBytes<'a> = [u8; std::mem::size_of::<$t>()] where Self: 'a;
563
564 fn fixed_width() -> Option<usize> {
565 Some(std::mem::size_of::<$t>())
566 }
567
568 fn from_bytes<'a>(data: &'a [u8]) -> $t
569 where
570 Self: 'a,
571 {
572 <$t>::from_le_bytes(data.try_into().unwrap())
573 }
574
575 fn as_bytes<'a, 'b: 'a>(
576 value: &'a Self::SelfType<'b>,
577 ) -> [u8; std::mem::size_of::<$t>()]
578 where
579 Self: 'a,
580 Self: 'b,
581 {
582 value.to_le_bytes()
583 }
584
585 fn type_name() -> TypeName {
586 TypeName::internal(stringify!($t))
587 }
588 }
589 };
590}
591
592macro_rules! le_impl {
593 ($t:ty) => {
594 le_value!($t);
595
596 impl Key for $t {
597 fn compare(data1: &[u8], data2: &[u8]) -> Ordering {
598 Self::from_bytes(data1).cmp(&Self::from_bytes(data2))
599 }
600 }
601 };
602}
603
604le_impl!(u8);
605le_impl!(u16);
606le_impl!(u32);
607le_impl!(u64);
608le_impl!(u128);
609le_impl!(i8);
610le_impl!(i16);
611le_impl!(i32);
612le_impl!(i64);
613le_impl!(i128);
614le_value!(f32);
615le_value!(f64);