abi_stable/
const_utils.rs

1//! Utilities for const contexts.
2
3use crate::std_types::RStr;
4
5pub use abi_stable_shared::const_utils::low_bit_mask_u64;
6
7//////////////////////////////////////////////////////////////////
8
9// Used to test trait bounds in proc-macros.
10#[doc(hidden)]
11pub trait AssocStr {
12    const STR: RStr<'static>;
13}
14
15macro_rules! impl_assoc_str {
16    ( $($ty:ty),* ) => (
17        $(
18            impl AssocStr for $ty {
19                const STR:RStr<'static>=RStr::from_str(stringify!( $ty ));
20            }
21        )*
22    )
23}
24
25impl_assoc_str! { i8,i16,i32,i64,isize,u8,u16,u32,u64,usize }
26
27//////////////////////////////////////////////////////////////////
28
29// Used to test trait bounds in proc-macros.
30#[doc(hidden)]
31pub trait AssocInt {
32    const NUM: usize;
33}
34
35macro_rules! impl_assoc_str {
36    ( $($ty:ty=$val:expr),* $(,)* ) => (
37        $(
38            impl AssocInt for $ty {
39                const NUM:usize=$val;
40            }
41        )*
42    )
43}
44
45impl_assoc_str! {
46    i8=0,i16=1,i32=2,i64=3,isize=4,
47    u8=5,u16=6,u32=7,u64=8,usize=9,
48}
49
50//////////////////////////////////////
51
52/// Creates an empty slice.
53pub const fn empty_slice<'a, T>() -> &'a [T]
54where
55    T: 'a,
56{
57    GetEmptySlice::<'a, T>::EMPTY
58}
59
60struct GetEmptySlice<'a, T>(&'a T);
61
62impl<'a, T> GetEmptySlice<'a, T>
63where
64    T: 'a,
65{
66    const EMPTY: &'a [T] = &[];
67}
68
69//////////////////////////////////////
70
71macro_rules! min_max {
72    ($l:expr, $r:expr) => {
73        if $l < $r {
74            ($l, $r)
75        } else {
76            ($r, $l)
77        }
78    };
79}
80
81/// The minimum of two `u64`s
82pub const fn min_u8(l: u8, r: u8) -> u8 {
83    min_max!(l, r).0
84}
85
86/// The minimum of two `u64`s
87pub const fn min_u16(l: u16, r: u16) -> u16 {
88    min_max!(l, r).0
89}
90
91/// The minimum of two `u64`s
92pub const fn min_u64(l: u64, r: u64) -> u64 {
93    min_max!(l, r).0
94}
95
96/// The minimum of two `usize`s
97pub const fn min_usize(l: usize, r: usize) -> usize {
98    min_max!(l, r).0
99}
100
101/// The maximum of two `u64`s
102pub const fn max_u64(l: u64, r: u64) -> u64 {
103    min_max!(l, r).1
104}
105
106/// The maximum of two `usize`s
107pub const fn max_usize(l: usize, r: usize) -> usize {
108    min_max!(l, r).1
109}
110
111/// The minimum and maximum of two `usize`s
112pub const fn min_max_usize(l: usize, r: usize) -> (usize, usize) {
113    min_max!(l, r)
114}
115
116//////////////////////////////////////
117
118/// Gets the absolute value of a usize subtraction.
119pub const fn abs_sub_usize(l: usize, r: usize) -> usize {
120    let (min, max) = min_max_usize(l, r);
121    max - min
122}
123
124//////////////////////////////////////
125
126/// The base 2 logarithm of a usize.
127pub const fn log2_usize(n: usize) -> u8 {
128    const USIZE_BITS: u8 = (std::mem::size_of::<usize>() * 8) as u8;
129    (USIZE_BITS - n.leading_zeros() as u8).saturating_sub(1)
130}
131
132//////////////////////////////////////
133
134#[cfg(test)]
135mod tests {
136    use super::*;
137
138    const USIZE_BITS: u8 = (std::mem::size_of::<usize>() * 8) as u8;
139
140    #[test]
141    fn abs_sub_test() {
142        for p in 0..USIZE_BITS {
143            let n = 1usize << p;
144            assert_eq!(abs_sub_usize(0, n), n);
145            assert_eq!(abs_sub_usize(n, 0), n);
146        }
147        assert_eq!(abs_sub_usize(4, 5), 1);
148        assert_eq!(abs_sub_usize(5, 5), 0);
149        assert_eq!(abs_sub_usize(5, 4), 1);
150        assert_eq!(abs_sub_usize(5, 0), 5);
151        assert_eq!(abs_sub_usize(0, 5), 5);
152    }
153
154    #[test]
155    fn log2_usize_test() {
156        assert_eq!(log2_usize(0), 0);
157        assert_eq!(log2_usize(1), 0);
158        for power in 1..USIZE_BITS {
159            let n = 1usize << power;
160            assert_eq!(log2_usize(n - 1), power - 1, "power:{} n:{}", power, n);
161            assert_eq!(log2_usize(n), power, "power:{} n:{}", power, n);
162            assert_eq!(log2_usize(n + 1), power, "power:{} n:{}", power, n);
163        }
164    }
165}