• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // This file is part of ICU4X. For terms of use, please see the file
2 // called LICENSE at the top level of the ICU4X source tree
3 // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
4 
5 pub(crate) trait MaybeSplitAt<T> {
6     /// Like slice::split_at but debug-panics and returns an empty second slice
7     /// if the index is out of range.
debug_split_at(&self, mid: usize) -> (&Self, &Self)8     fn debug_split_at(&self, mid: usize) -> (&Self, &Self);
9 }
10 
11 impl<T> MaybeSplitAt<T> for [T] {
12     #[inline]
debug_split_at(&self, mid: usize) -> (&Self, &Self)13     fn debug_split_at(&self, mid: usize) -> (&Self, &Self) {
14         self.split_at_checked(mid).unwrap_or_else(|| {
15             debug_assert!(false, "debug_split_at: {mid} expected to be in range");
16             (self, &[])
17         })
18     }
19 }
20 
21 pub(crate) trait DebugUnwrapOr<T> {
22     /// Unwraps the option or panics in debug mode, returning the `gigo_value`
debug_unwrap_or(self, gigo_value: T) -> T23     fn debug_unwrap_or(self, gigo_value: T) -> T;
24 }
25 
26 impl<T> DebugUnwrapOr<T> for Option<T> {
27     #[inline]
debug_unwrap_or(self, gigo_value: T) -> T28     fn debug_unwrap_or(self, gigo_value: T) -> T {
29         match self {
30             Some(x) => x,
31             None => {
32                 debug_assert!(false, "debug_unwrap_or called on a None value");
33                 gigo_value
34             }
35         }
36     }
37 }
38 
39 macro_rules! debug_unwrap {
40     ($expr:expr, return $retval:expr, $($arg:tt)+) => {
41         match $expr {
42             Some(x) => x,
43             None => {
44                 debug_assert!(false, $($arg)*);
45                 return $retval;
46             }
47         }
48     };
49     ($expr:expr, return $retval:expr) => {
50         debug_unwrap!($expr, return $retval, "invalid trie")
51     };
52     ($expr:expr, break, $($arg:tt)+) => {
53         match $expr {
54             Some(x) => x,
55             None => {
56                 debug_assert!(false, $($arg)*);
57                 break;
58             }
59         }
60     };
61     ($expr:expr, break) => {
62         debug_unwrap!($expr, break, "invalid trie")
63     };
64     ($expr:expr, $($arg:tt)+) => {
65         debug_unwrap!($expr, return (), $($arg)*)
66     };
67     ($expr:expr) => {
68         debug_unwrap!($expr, return ())
69     };
70 }
71 
72 pub(crate) use debug_unwrap;
73 
74 /// The maximum number of base-10 digits required for rendering a usize.
75 /// Note: 24/10 is an approximation of 8*log10(2)
76 pub(crate) const MAX_USIZE_LEN_AS_DIGITS: usize = core::mem::size_of::<usize>() * 24 / 10 + 1;
77 
78 /// Formats a usize as a string of length N, padded with spaces,
79 /// with the given prefix.
80 ///
81 /// If the string is too short, the function may panic. To prevent
82 /// this, N should be MAX_USIZE_LEN_AS_DIGITS larger than M.
const_fmt_int<const M: usize, const N: usize>( prefix: [u8; M], value: usize, ) -> [u8; N]83 pub(crate) const fn const_fmt_int<const M: usize, const N: usize>(
84     prefix: [u8; M],
85     value: usize,
86 ) -> [u8; N] {
87     let mut output = [b' '; N];
88     let mut i = 0;
89     while i < M {
90         output[i] = prefix[i];
91         i += 1;
92     }
93     let mut int_only = [b' '; MAX_USIZE_LEN_AS_DIGITS];
94     let mut value = value;
95     let mut i = MAX_USIZE_LEN_AS_DIGITS - 1;
96     loop {
97         let x = (value % 10) as u8;
98         int_only[i] = x + b'0';
99         value /= 10;
100         if value == 0 {
101             break;
102         }
103         i -= 1;
104     }
105     let mut j = M;
106     while i < MAX_USIZE_LEN_AS_DIGITS {
107         output[j] = int_only[i];
108         j += 1;
109         i += 1;
110     }
111     output
112 }
113 
114 #[test]
test_const_fmt_int()115 fn test_const_fmt_int() {
116     assert_eq!(*b"123", const_fmt_int::<0, 3>(*b"", 123));
117     assert_eq!(*b"123   ", const_fmt_int::<0, 6>(*b"", 123));
118     assert_eq!(*b"abc123", const_fmt_int::<3, 6>(*b"abc", 123));
119 }
120