1impl_fixed_orderable_bytes! {
66 bool, 1, |value| {
67 [*value as u8]
70 }
71}
72
73impl_fixed_orderable_bytes! {
74 u8, 1, |value| {
75 [*value]
76 }
77}
78
79impl_fixed_orderable_bytes! {
80 i8, 1, |value| {
81 [(*value as u8) ^ (1u8 << 7)]
82 }
83}
84
85impl_fixed_orderable_bytes! {
86 u16, 2, |value| {
87 value.to_be_bytes()
88 }
89}
90
91impl_fixed_orderable_bytes! {
92 i16, 2, |value| {
93 ((*value as u16) ^ (1u16 << 15)).to_be_bytes()
94 }
95}
96
97impl_fixed_orderable_bytes! {
98 u32, 4, |value| {
99 value.to_be_bytes()
100 }
101}
102
103impl_fixed_orderable_bytes! {
104 i32, 4, |value| {
105 ((*value as u32) ^ (1u32 << 31)).to_be_bytes()
106 }
107}
108
109impl_fixed_orderable_bytes! {
110 u64, 8, |value| {
111 value.to_be_bytes()
112 }
113}
114
115impl_fixed_orderable_bytes! {
116 i64, 8, |value| {
117 ((*value as u64) ^ (1u64 << 63)).to_be_bytes()
118 }
119}
120
121impl_fixed_orderable_bytes! {
122 u128, 16, |value| {
123 value.to_be_bytes()
124 }
125}
126
127impl_fixed_orderable_bytes! {
128 i128, 16, |value| {
129 ((*value as u128) ^ (1u128 << 127)).to_be_bytes()
130 }
131}
132
133impl_fixed_orderable_bytes! {
134 char, 4, |value| {
135 (*value as u32).to_be_bytes()
136 }
137}
138
139impl_fixed_orderable_bytes! {
140 f32, 4, |value| {
141 let value = if *value == -0.0 { 0.0 } else { *value };
144 let bits = value.to_bits();
145 let sign_extension = (bits as i32 >> 31) as u32;
147 let mask = sign_extension | (1u32 << 31);
148 (bits ^ mask).to_be_bytes()
149 }
150}
151
152impl_fixed_orderable_bytes! {
153 f64, 8, |value| {
154 let value = if *value == -0.0 { 0.0 } else { *value };
157 let bits = value.to_bits();
158 let sign_extension = (bits as i64 >> 63) as u64;
164 let mask = sign_extension | (1u64 << 63);
165 (bits ^ mask).to_be_bytes()
166 }
167}
168
169impl<const N: usize> crate::private::Sealed for [u8; N] {}
170
171impl<const N: usize> crate::OrderableBytes for [u8; N] {
175 type Bytes<'a> = &'a [u8];
176
177 fn to_orderable_bytes(&self) -> &[u8] {
178 self
179 }
180}
181
182impl<const N: usize> crate::FixedOrderableBytes for [u8; N] {
183 const ENCODED_LEN: usize = N;
184
185 type Array = [u8; N];
186
187 fn to_fixed_orderable_bytes(&self) -> [u8; N] {
188 *self
189 }
190}
191
192#[cfg(test)]
193mod tests {
194 use crate::{FixedOrderableBytes, OrderableBytes};
195
196 #[test]
199 fn byte_array_encodes_to_itself() {
200 let a = [1u8, 2, 3];
201 assert_eq!(a.to_orderable_bytes(), &a);
202 assert_eq!(a.to_orderable_bytes().as_ptr(), a.as_ptr());
203 assert_eq!(a.to_fixed_orderable_bytes(), a);
204 assert_eq!(<[u8; 3] as FixedOrderableBytes>::ENCODED_LEN, 3);
205 }
206
207 quickcheck! {
208 fn byte_array_order_matches_array_order(a: Vec<u8>, b: Vec<u8>) -> bool {
209 let mut x = [0u8; 8];
210 let mut y = [0u8; 8];
211 for (dst, src) in x.iter_mut().zip(&a) { *dst = *src; }
212 for (dst, src) in y.iter_mut().zip(&b) { *dst = *src; }
213 x.to_orderable_bytes().cmp(y.to_orderable_bytes()) == x.cmp(&y)
214 }
215 }
216
217 #[test]
220 fn bool_known_anchors() {
221 assert_eq!(false.to_orderable_bytes(), [0x00]);
222 assert_eq!(true.to_orderable_bytes(), [0x01]);
223 }
224
225 #[test]
226 fn bool_byte_order_matches_natural_order() {
227 assert!(false.to_orderable_bytes() < true.to_orderable_bytes());
228 }
229
230 #[test]
233 fn u8_known_anchors() {
234 assert_eq!(u8::MIN.to_orderable_bytes(), [0x00]);
236 assert_eq!(0x42u8.to_orderable_bytes(), [0x42]);
237 assert_eq!(u8::MAX.to_orderable_bytes(), [0xFF]);
238 }
239
240 #[test]
241 fn u8_byte_order_matches_natural_order() {
242 let ascending = [u8::MIN, 1, 100, 200, u8::MAX];
243 for window in ascending.windows(2) {
244 assert!(
245 window[0].to_orderable_bytes() < window[1].to_orderable_bytes(),
246 "{} < {} failed",
247 window[0],
248 window[1]
249 );
250 }
251 }
252
253 #[test]
256 fn i8_known_anchors() {
257 assert_eq!(i8::MIN.to_orderable_bytes(), [0x00]);
259 assert_eq!(0i8.to_orderable_bytes(), [0x80]);
260 assert_eq!(i8::MAX.to_orderable_bytes(), [0xFF]);
261 }
262
263 #[test]
264 fn i8_byte_order_matches_natural_order() {
265 let ascending = [i8::MIN, -100, -1, 0, 1, 100, i8::MAX];
266 for window in ascending.windows(2) {
267 assert!(
268 window[0].to_orderable_bytes() < window[1].to_orderable_bytes(),
269 "{} < {} failed",
270 window[0],
271 window[1]
272 );
273 }
274 }
275
276 #[test]
279 fn u16_known_anchors() {
280 assert_eq!(u16::MIN.to_orderable_bytes(), [0x00, 0x00]);
281 assert_eq!(u16::MAX.to_orderable_bytes(), [0xFF, 0xFF]);
282 assert_eq!(0x1234u16.to_orderable_bytes(), [0x12, 0x34]);
283 }
284
285 #[test]
286 fn u16_byte_order_matches_natural_order() {
287 let ascending = [u16::MIN, 1, 256, 10000, u16::MAX - 1, u16::MAX];
288 for window in ascending.windows(2) {
289 assert!(
290 window[0].to_orderable_bytes() < window[1].to_orderable_bytes(),
291 "{} < {} failed",
292 window[0],
293 window[1]
294 );
295 }
296 }
297
298 #[test]
301 fn i16_known_anchors() {
302 assert_eq!(i16::MIN.to_orderable_bytes(), [0x00, 0x00]);
304 assert_eq!(0i16.to_orderable_bytes(), [0x80, 0x00]);
305 assert_eq!(i16::MAX.to_orderable_bytes(), [0xFF, 0xFF]);
306 }
307
308 #[test]
309 fn i16_byte_order_matches_natural_order() {
310 let ascending = [i16::MIN, -10000, -1, 0, 1, 10000, i16::MAX];
311 for window in ascending.windows(2) {
312 assert!(
313 window[0].to_orderable_bytes() < window[1].to_orderable_bytes(),
314 "{} < {} failed",
315 window[0],
316 window[1]
317 );
318 }
319 }
320
321 #[test]
324 fn u32_known_anchors() {
325 assert_eq!(u32::MIN.to_orderable_bytes(), [0x00; 4]);
326 assert_eq!(u32::MAX.to_orderable_bytes(), [0xFF; 4]);
327 assert_eq!(
328 0x1234_5678u32.to_orderable_bytes(),
329 [0x12, 0x34, 0x56, 0x78]
330 );
331 }
332
333 #[test]
334 fn u32_byte_order_matches_natural_order() {
335 let ascending = [
336 u32::MIN,
337 1,
338 1 << 8,
339 1 << 16,
340 1 << 24,
341 u32::MAX - 1,
342 u32::MAX,
343 ];
344 for window in ascending.windows(2) {
345 assert!(
346 window[0].to_orderable_bytes() < window[1].to_orderable_bytes(),
347 "{} < {} failed",
348 window[0],
349 window[1]
350 );
351 }
352 }
353
354 #[test]
357 fn i32_known_anchors() {
358 assert_eq!(i32::MIN.to_orderable_bytes(), [0x00, 0x00, 0x00, 0x00]);
360 assert_eq!(0i32.to_orderable_bytes(), [0x80, 0x00, 0x00, 0x00]);
361 assert_eq!(i32::MAX.to_orderable_bytes(), [0xFF, 0xFF, 0xFF, 0xFF]);
362 }
363
364 #[test]
365 fn i32_byte_order_matches_natural_order() {
366 let ascending = [i32::MIN, -1_000_000_000, -1, 0, 1, 1_000_000_000, i32::MAX];
367 for window in ascending.windows(2) {
368 assert!(
369 window[0].to_orderable_bytes() < window[1].to_orderable_bytes(),
370 "{} < {} failed",
371 window[0],
372 window[1]
373 );
374 }
375 }
376
377 #[test]
380 fn u64_known_anchors() {
381 assert_eq!(u64::MIN.to_orderable_bytes(), [0x00; 8]);
382 assert_eq!(u64::MAX.to_orderable_bytes(), [0xFF; 8]);
383 let one = 1u64.to_orderable_bytes();
384 let mut expected_one = [0u8; 8];
385 expected_one[7] = 1;
386 assert_eq!(one, expected_one);
387 }
388
389 #[test]
390 fn u64_byte_order_matches_natural_order() {
391 let ascending = [
392 u64::MIN,
393 1,
394 1 << 16,
395 1 << 32,
396 1 << 48,
397 u64::MAX - 1,
398 u64::MAX,
399 ];
400 for window in ascending.windows(2) {
401 assert!(
402 window[0].to_orderable_bytes() < window[1].to_orderable_bytes(),
403 "{} < {} failed",
404 window[0],
405 window[1]
406 );
407 }
408 }
409
410 #[test]
413 fn i64_known_anchors() {
414 assert_eq!(i64::MIN.to_orderable_bytes(), [0x00; 8]);
415 assert_eq!(
416 0i64.to_orderable_bytes(),
417 [0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
418 );
419 assert_eq!(i64::MAX.to_orderable_bytes(), [0xFF; 8]);
420 }
421
422 #[test]
423 fn i64_byte_order_matches_natural_order() {
424 let ascending = [
425 i64::MIN,
426 -1_000_000_000_000,
427 -1,
428 0,
429 1,
430 1_000_000_000_000,
431 i64::MAX,
432 ];
433 for window in ascending.windows(2) {
434 assert!(
435 window[0].to_orderable_bytes() < window[1].to_orderable_bytes(),
436 "{} < {} failed",
437 window[0],
438 window[1]
439 );
440 }
441 }
442
443 #[test]
446 fn u128_known_anchors() {
447 assert_eq!(u128::MIN.to_orderable_bytes(), [0; 16]);
448 assert_eq!(u128::MAX.to_orderable_bytes(), [0xFF; 16]);
449 let one = 1u128.to_orderable_bytes();
450 let mut expected_one = [0u8; 16];
451 expected_one[15] = 1;
452 assert_eq!(one, expected_one);
453 }
454
455 #[test]
456 fn u128_byte_order_matches_natural_order() {
457 let ascending = [
458 u128::MIN,
459 1,
460 (1u128 << 32),
461 (1u128 << 64),
462 (1u128 << 96),
463 u128::MAX - 1,
464 u128::MAX,
465 ];
466 for window in ascending.windows(2) {
467 assert!(
468 window[0].to_orderable_bytes() < window[1].to_orderable_bytes(),
469 "{} < {} failed",
470 window[0],
471 window[1]
472 );
473 }
474 }
475
476 #[test]
479 fn i128_known_anchors() {
480 assert_eq!(i128::MIN.to_orderable_bytes(), [0; 16]);
481 assert_eq!(i128::MAX.to_orderable_bytes(), [0xFF; 16]);
482 let mut expected_zero = [0u8; 16];
483 expected_zero[0] = 0x80;
484 assert_eq!(0i128.to_orderable_bytes(), expected_zero);
485 }
486
487 #[test]
488 fn i128_byte_order_matches_natural_order() {
489 let ascending = [
490 i128::MIN,
491 -(1i128 << 96),
492 -(1i128 << 64),
493 -1,
494 0,
495 1,
496 (1i128 << 64),
497 (1i128 << 96),
498 i128::MAX,
499 ];
500 for window in ascending.windows(2) {
501 assert!(
502 window[0].to_orderable_bytes() < window[1].to_orderable_bytes(),
503 "{} < {} failed",
504 window[0],
505 window[1]
506 );
507 }
508 }
509
510 #[test]
513 fn char_known_anchors() {
514 assert_eq!('A'.to_orderable_bytes(), [0x00, 0x00, 0x00, 0x41]);
516 assert_eq!('\0'.to_orderable_bytes(), [0x00, 0x00, 0x00, 0x00]);
518 assert_eq!(char::MAX.to_orderable_bytes(), [0x00, 0x10, 0xFF, 0xFF]);
520 }
521
522 #[test]
523 fn char_byte_order_matches_natural_order() {
524 let ascending = [
526 '\0',
527 '0',
528 'A',
529 'a',
530 '\u{7F}',
531 '\u{D7FF}',
532 '\u{E000}',
533 '\u{1F600}',
534 char::MAX,
535 ];
536 for window in ascending.windows(2) {
537 assert!(
538 window[0].to_orderable_bytes() < window[1].to_orderable_bytes(),
539 "{:?} < {:?} failed",
540 window[0],
541 window[1]
542 );
543 }
544 }
545
546 #[test]
549 fn f32_zero_canonical_bytes() {
550 assert_eq!(0.0f32.to_orderable_bytes(), [0x80, 0x00, 0x00, 0x00]);
552 }
553
554 #[test]
555 fn f32_negative_zero_canonicalises_with_zero() {
556 assert_eq!((-0.0f32).to_orderable_bytes(), 0.0f32.to_orderable_bytes());
557 }
558
559 #[test]
560 fn f32_byte_order_matches_natural_order() {
561 let ascending = [
562 f32::NEG_INFINITY,
563 f32::MIN,
564 -1e30,
565 -1.0,
566 -f32::MIN_POSITIVE,
567 0.0,
568 f32::MIN_POSITIVE,
569 1.0,
570 1e30,
571 f32::MAX,
572 f32::INFINITY,
573 ];
574 for window in ascending.windows(2) {
575 let a = window[0].to_orderable_bytes();
576 let b = window[1].to_orderable_bytes();
577 assert!(a < b, "{} < {} failed", window[0], window[1]);
578 }
579 }
580
581 #[test]
582 fn f32_subnormals_sort_above_zero_below_normals() {
583 let subnormal = f32::from_bits(1);
586 assert!(0.0f32.to_orderable_bytes() < subnormal.to_orderable_bytes());
587 assert!(subnormal.to_orderable_bytes() < f32::MIN_POSITIVE.to_orderable_bytes());
588 }
589
590 #[test]
593 fn f64_zero_canonical_bytes() {
594 assert_eq!(
596 0.0f64.to_orderable_bytes(),
597 [0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
598 );
599 }
600
601 #[test]
602 fn f64_negative_zero_canonicalises_with_zero() {
603 assert_eq!((-0.0f64).to_orderable_bytes(), 0.0f64.to_orderable_bytes());
604 }
605
606 #[test]
607 fn f64_byte_order_matches_natural_order() {
608 let ascending = [
609 f64::NEG_INFINITY,
610 f64::MIN,
611 -1e100,
612 -1.0,
613 -f64::MIN_POSITIVE,
614 0.0,
615 f64::MIN_POSITIVE,
616 1.0,
617 1e100,
618 f64::MAX,
619 f64::INFINITY,
620 ];
621 for window in ascending.windows(2) {
622 let a = window[0].to_orderable_bytes();
623 let b = window[1].to_orderable_bytes();
624 assert!(a < b, "{} < {} failed", window[0], window[1]);
625 }
626 }
627
628 #[test]
629 fn f64_subnormals_sort_above_zero_below_normals() {
630 let subnormal = f64::from_bits(1);
633 assert!(0.0f64.to_orderable_bytes() < subnormal.to_orderable_bytes());
634 assert!(subnormal.to_orderable_bytes() < f64::MIN_POSITIVE.to_orderable_bytes());
635 }
636}