/rust/registry/src/index.crates.io-6f17d22bba15001f/zerotrie-0.1.3/src/helpers.rs
Line | Count | Source (jump to first uncovered line) |
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 returns an Option instead of panicking |
7 | | /// if the index is out of range. |
8 | | fn maybe_split_at(&self, mid: usize) -> Option<(&Self, &Self)>; |
9 | | /// Like slice::split_at but debug-panics and returns an empty second slice |
10 | | /// if the index is out of range. |
11 | | fn debug_split_at(&self, mid: usize) -> (&Self, &Self); |
12 | | } |
13 | | |
14 | | impl<T> MaybeSplitAt<T> for [T] { |
15 | | #[inline] |
16 | 0 | fn maybe_split_at(&self, mid: usize) -> Option<(&Self, &Self)> { |
17 | 0 | if mid > self.len() { |
18 | 0 | None |
19 | | } else { |
20 | | // Note: We're trusting the compiler to inline this and remove the assertion |
21 | | // hiding on the top of slice::split_at: `assert(mid <= self.len())` |
22 | 0 | Some(self.split_at(mid)) |
23 | | } |
24 | 0 | } Unexecuted instantiation: <[u8] as zerotrie::helpers::MaybeSplitAt<u8>>::maybe_split_at Unexecuted instantiation: <[_] as zerotrie::helpers::MaybeSplitAt<_>>::maybe_split_at |
25 | | #[inline] |
26 | 0 | fn debug_split_at(&self, mid: usize) -> (&Self, &Self) { |
27 | 0 | if mid > self.len() { |
28 | 0 | debug_assert!(false, "debug_split_at: index expected to be in range"); |
29 | 0 | (self, &[]) |
30 | | } else { |
31 | | // Note: We're trusting the compiler to inline this and remove the assertion |
32 | | // hiding on the top of slice::split_at: `assert(mid <= self.len())` |
33 | 0 | self.split_at(mid) |
34 | | } |
35 | 0 | } |
36 | | } |
37 | | |
38 | | pub(crate) trait DebugUnwrapOr<T> { |
39 | | /// Unwraps the option or panics in debug mode, returning the `gigo_value` |
40 | | fn debug_unwrap_or(self, gigo_value: T) -> T; |
41 | | } |
42 | | |
43 | | impl<T> DebugUnwrapOr<T> for Option<T> { |
44 | | #[inline] |
45 | 0 | fn debug_unwrap_or(self, gigo_value: T) -> T { |
46 | 0 | match self { |
47 | 0 | Some(x) => x, |
48 | | None => { |
49 | 0 | debug_assert!(false, "debug_unwrap_or called on a None value"); |
50 | 0 | gigo_value |
51 | | } |
52 | | } |
53 | 0 | } Unexecuted instantiation: <core::option::Option<&[u8]> as zerotrie::helpers::DebugUnwrapOr<&[u8]>>::debug_unwrap_or Unexecuted instantiation: <core::option::Option<&u8> as zerotrie::helpers::DebugUnwrapOr<&u8>>::debug_unwrap_or |
54 | | } |
55 | | |
56 | | macro_rules! debug_unwrap { |
57 | | ($expr:expr, return $retval:expr, $($arg:tt)+) => { |
58 | | match $expr { |
59 | | Some(x) => x, |
60 | | None => { |
61 | | debug_assert!(false, $($arg)*); |
62 | | return $retval; |
63 | | } |
64 | | } |
65 | | }; |
66 | | ($expr:expr, return $retval:expr) => { |
67 | | debug_unwrap!($expr, return $retval, "invalid trie") |
68 | | }; |
69 | | ($expr:expr, break, $($arg:tt)+) => { |
70 | | match $expr { |
71 | | Some(x) => x, |
72 | | None => { |
73 | | debug_assert!(false, $($arg)*); |
74 | | break; |
75 | | } |
76 | | } |
77 | | }; |
78 | | ($expr:expr, break) => { |
79 | | debug_unwrap!($expr, break, "invalid trie") |
80 | | }; |
81 | | ($expr:expr, $($arg:tt)+) => { |
82 | | debug_unwrap!($expr, return (), $($arg)*) |
83 | | }; |
84 | | ($expr:expr) => { |
85 | | debug_unwrap!($expr, return ()) |
86 | | }; |
87 | | } |
88 | | |
89 | | pub(crate) use debug_unwrap; |
90 | | |
91 | | /// The maximum number of base-10 digits required for rendering a usize. |
92 | | /// Note: 24/10 is an approximation of 8*log10(2) |
93 | | pub(crate) const MAX_USIZE_LEN_AS_DIGITS: usize = core::mem::size_of::<usize>() * 24 / 10 + 1; |
94 | | |
95 | | /// Formats a usize as a string of length N, padded with spaces, |
96 | | /// with the given prefix. |
97 | | /// |
98 | | /// If the string is too short, the function may panic. To prevent |
99 | | /// this, N should be MAX_USIZE_LEN_AS_DIGITS larger than M. |
100 | 0 | pub(crate) const fn const_fmt_int<const M: usize, const N: usize>( |
101 | 0 | prefix: [u8; M], |
102 | 0 | value: usize, |
103 | 0 | ) -> [u8; N] { |
104 | 0 | let mut output = [b' '; N]; |
105 | 0 | let mut i = 0; |
106 | 0 | while i < M { |
107 | 0 | output[i] = prefix[i]; |
108 | 0 | i += 1; |
109 | 0 | } |
110 | 0 | let mut int_only = [b' '; MAX_USIZE_LEN_AS_DIGITS]; |
111 | 0 | let mut value = value; |
112 | 0 | let mut i = MAX_USIZE_LEN_AS_DIGITS - 1; |
113 | | loop { |
114 | 0 | let x = (value % 10) as u8; |
115 | 0 | int_only[i] = x + b'0'; |
116 | 0 | value /= 10; |
117 | 0 | if value == 0 { |
118 | 0 | break; |
119 | 0 | } |
120 | 0 | i -= 1; |
121 | | } |
122 | 0 | let mut j = M; |
123 | 0 | while i < MAX_USIZE_LEN_AS_DIGITS { |
124 | 0 | output[j] = int_only[i]; |
125 | 0 | j += 1; |
126 | 0 | i += 1; |
127 | 0 | } |
128 | 0 | output |
129 | 0 | } |
130 | | |
131 | | #[test] |
132 | | fn test_const_fmt_int() { |
133 | | assert_eq!(*b"123", const_fmt_int::<0, 3>(*b"", 123)); |
134 | | assert_eq!(*b"123 ", const_fmt_int::<0, 6>(*b"", 123)); |
135 | | assert_eq!(*b"abc123", const_fmt_int::<3, 6>(*b"abc", 123)); |
136 | | } |