zerotrie/
helpers.rs

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
5pub(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.
8    fn debug_split_at(&self, mid: usize) -> (&Self, &Self);
9}
10
11impl<T> MaybeSplitAt<T> for [T] {
12    #[inline]
13    fn debug_split_at(&self, mid: usize) -> (&Self, &Self) {
14        self.split_at_checked(mid).unwrap_or_else(|| {
15            if true {
    if !false {
        {
            ::core::panicking::panic_fmt(format_args!("debug_split_at: {0} expected to be in range",
                    mid));
        }
    };
};debug_assert!(false, "debug_split_at: {mid} expected to be in range");
16            (self, &[])
17        })
18    }
19}
20
21pub(crate) trait DebugUnwrapOr<T> {
22    /// Unwraps the option or panics in debug mode, returning the `gigo_value`
23    fn debug_unwrap_or(self, gigo_value: T) -> T;
24}
25
26impl<T> DebugUnwrapOr<T> for Option<T> {
27    #[inline]
28    fn debug_unwrap_or(self, gigo_value: T) -> T {
29        match self {
30            Some(x) => x,
31            None => {
32                if true {
    if !false {
        {
            ::core::panicking::panic_fmt(format_args!("debug_unwrap_or called on a None value"));
        }
    };
};debug_assert!(false, "debug_unwrap_or called on a None value");
33                gigo_value
34            }
35        }
36    }
37}
38
39macro_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
72pub(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)
76pub(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/// # Panics
82///
83/// If the string is too short, the function may panic. To prevent
84/// this, N should be MAX_USIZE_LEN_AS_DIGITS larger than M.
85#[allow(clippy::indexing_slicing)] // documented, and based on const parameters
86pub(crate) const fn const_fmt_int<const M: usize, const N: usize>(
87    prefix: [u8; M],
88    value: usize,
89) -> [u8; N] {
90    let mut output = [b' '; N];
91    let mut i = 0;
92    while i < M {
93        output[i] = prefix[i];
94        i += 1;
95    }
96    let mut int_only = [b' '; MAX_USIZE_LEN_AS_DIGITS];
97    let mut value = value;
98    let mut i = MAX_USIZE_LEN_AS_DIGITS - 1;
99    loop {
100        let x = (value % 10) as u8;
101        int_only[i] = x + b'0';
102        value /= 10;
103        if value == 0 {
104            break;
105        }
106        i -= 1;
107    }
108    let mut j = M;
109    while i < MAX_USIZE_LEN_AS_DIGITS {
110        output[j] = int_only[i];
111        j += 1;
112        i += 1;
113    }
114    output
115}
116
117#[test]
118fn test_const_fmt_int() {
119    assert_eq!(*b"123", const_fmt_int::<0, 3>(*b"", 123));
120    assert_eq!(*b"123   ", const_fmt_int::<0, 6>(*b"", 123));
121    assert_eq!(*b"abc123", const_fmt_int::<3, 6>(*b"abc", 123));
122}