gadget_std/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2#![allow(ambiguous_glob_reexports)]
3
4#[cfg(not(feature = "std"))]
5pub extern crate alloc;
6
7#[cfg(not(feature = "std"))]
8pub use alloc::*;
9
10#[cfg(not(feature = "std"))]
11pub use core::*;
12
13#[cfg(not(feature = "std"))]
14pub mod fmt {
15    pub use alloc::fmt::*;
16}
17
18#[cfg(not(feature = "std"))]
19pub mod borrow {
20    pub use alloc::borrow::*;
21}
22
23#[cfg(not(feature = "std"))]
24pub mod slice {
25    pub use alloc::slice::*;
26    pub use core::slice::*;
27}
28
29#[cfg(not(feature = "std"))]
30pub mod str {
31    pub use alloc::str::*;
32    pub use core::str::*;
33}
34
35#[cfg(not(feature = "std"))]
36pub mod io;
37
38#[cfg(feature = "std")]
39#[doc(hidden)]
40pub use std::*;
41
42#[cfg(target_has_atomic = "ptr")]
43#[doc(hidden)]
44pub mod sync {
45    #[cfg(not(feature = "std"))]
46    pub use alloc::sync::*;
47    #[cfg(feature = "std")]
48    pub use std::sync::*;
49}
50
51mod rand_helper;
52pub use rand_helper::*;
53
54pub mod perf_trace;
55#[cfg(feature = "tokio")]
56pub mod tokio_ext;
57
58pub use num_traits::{One, Zero};
59
60/// Returns the ceiling of the base-2 logarithm of `x`.
61///
62/// ```
63/// use gadget_std::log2;
64///
65/// assert_eq!(log2(16), 4);
66/// assert_eq!(log2(17), 5);
67/// assert_eq!(log2(1), 0);
68/// assert_eq!(log2(0), 0);
69/// assert_eq!(log2(usize::MAX), (core::mem::size_of::<usize>() * 8) as u32);
70/// assert_eq!(log2(1 << 15), 15);
71/// assert_eq!(log2(2usize.pow(18)), 18);
72/// ```
73#[inline(always)]
74pub const fn log2(x: usize) -> u32 {
75    if x == 0 {
76        0
77    } else if x.is_power_of_two() {
78        1usize.leading_zeros() - x.leading_zeros()
79    } else {
80        0usize.leading_zeros() - x.leading_zeros()
81    }
82}
83
84/// Creates parallel iterator over refs if `parallel` feature is enabled.
85///
86/// Additionally, if the object being iterated implements
87/// `IndexedParallelIterator`, then one can specify a minimum size for
88/// iteration.
89#[macro_export]
90macro_rules! cfg_iter {
91    ($e: expr, $min_len: expr) => {{
92        #[cfg(feature = "parallel")]
93        let result = $e.par_iter().with_min_len($min_len);
94
95        #[cfg(not(feature = "parallel"))]
96        let result = $e.iter();
97
98        result
99    }};
100    ($e: expr) => {{
101        #[cfg(feature = "parallel")]
102        let result = $e.par_iter();
103
104        #[cfg(not(feature = "parallel"))]
105        let result = $e.iter();
106
107        result
108    }};
109}
110
111/// Creates parallel iterator over mut refs if `parallel` feature is enabled.
112///
113/// Additionally, if the object being iterated implements
114/// `IndexedParallelIterator`, then one can specify a minimum size for
115/// iteration.
116#[macro_export]
117macro_rules! cfg_iter_mut {
118    ($e: expr, $min_len: expr) => {{
119        #[cfg(feature = "parallel")]
120        let result = $e.par_iter_mut().with_min_len($min_len);
121
122        #[cfg(not(feature = "parallel"))]
123        let result = $e.iter_mut();
124
125        result
126    }};
127    ($e: expr) => {{
128        #[cfg(feature = "parallel")]
129        let result = $e.par_iter_mut();
130
131        #[cfg(not(feature = "parallel"))]
132        let result = $e.iter_mut();
133
134        result
135    }};
136}
137
138/// Creates parallel iterator if `parallel` feature is enabled.
139/// Additionally, if the object being iterated implements
140/// `IndexedParallelIterator`, then one can specify a minimum size for
141/// iteration.
142#[macro_export]
143macro_rules! cfg_into_iter {
144    ($e: expr, $min_len: expr) => {{
145        #[cfg(feature = "parallel")]
146        let result = $e.into_par_iter().with_min_len($min_len);
147
148        #[cfg(not(feature = "parallel"))]
149        let result = $e.into_iter();
150
151        result
152    }};
153    ($e: expr) => {{
154        #[cfg(feature = "parallel")]
155        let result = $e.into_par_iter();
156
157        #[cfg(not(feature = "parallel"))]
158        let result = $e.into_iter();
159
160        result
161    }};
162}
163
164/// Returns an iterator over `chunk_size` elements of the slice at a
165/// time.
166#[macro_export]
167macro_rules! cfg_chunks {
168    ($e: expr, $size: expr) => {{
169        #[cfg(feature = "parallel")]
170        let result = $e.par_chunks($size);
171
172        #[cfg(not(feature = "parallel"))]
173        let result = $e.chunks($size);
174
175        result
176    }};
177}
178
179/// Returns an iterator over `chunk_size` mutable elements of the slice at a
180/// time.
181#[macro_export]
182macro_rules! cfg_chunks_mut {
183    ($e: expr, $size: expr) => {{
184        #[cfg(feature = "parallel")]
185        let result = $e.par_chunks_mut($size);
186
187        #[cfg(not(feature = "parallel"))]
188        let result = $e.chunks_mut($size);
189
190        result
191    }};
192}
193
194#[cfg(test)]
195mod test {
196    use super::*;
197    #[cfg(feature = "parallel")]
198    use rayon::prelude::*;
199
200    #[test]
201    fn test_cfg_macros() {
202        #[cfg(feature = "parallel")]
203        println!("In parallel mode");
204
205        let mut thing = crate::vec![1, 2, 3, 4, 5u64];
206        println!("Iterating");
207        cfg_iter!(&thing).for_each(|i| println!("{:?}", i));
208        println!("Iterating Mut");
209        cfg_iter_mut!(&mut thing).for_each(|i| *i += 1);
210        println!("Iterating By Value");
211        cfg_into_iter!(thing.clone()).for_each(|i| println!("{:?}", i));
212        println!("Chunks");
213        cfg_chunks!(&thing, 2).for_each(|chunk| println!("{:?}", chunk));
214        println!("Chunks Mut");
215        cfg_chunks_mut!(&mut thing, 2).for_each(|chunk| println!("{:?}", chunk));
216
217        println!("Iterating");
218        cfg_iter!(&thing, 3).for_each(|i| println!("{:?}", i));
219        println!("Iterating Mut");
220        cfg_iter_mut!(&mut thing, 3).for_each(|i| *i += 1);
221        println!("Iterating By Value");
222        cfg_into_iter!(thing, 3).for_each(|i| println!("{:?}", i));
223    }
224}