av1an_core/util/
mod.rs

1#[cfg(test)]
2mod tests;
3
4use std::path::{Path, PathBuf};
5
6/// Count the number of elements passed to this macro.
7///
8/// Extra commas in between other commas are counted as an element.
9#[macro_export]
10macro_rules! count {
11  () => (0_usize);
12  ($x:tt, $($xs:tt),*) => (1_usize + $crate::count!($($xs)*));
13  ($x:tt, $($xs:tt)*) => (1_usize + $crate::count!($($xs)*));
14  ($x:tt $($xs:tt)*) => (1_usize + $crate::count!($($xs)*));
15}
16
17/// Equivalent to `into_vec!` when the inferred type is `Cow<'_, str>`.
18///
19/// Prefer this over `into_vec!` if you are using Cow<str>, as
20/// the compiler currently cannot optimize away the unnecessary
21/// drops, so this will have a smaller generated code size than
22/// `into_vec!` if you mix `format!` and static strings.
23///
24/// TODO: implement this optimization in rustc itself, possibly as
25/// as a MIR pass.
26#[macro_export]
27macro_rules! inplace_vec {
28  ($($x:expr),* $(,)?) => {{
29    use std::mem::{self, MaybeUninit};
30    use std::borrow::Cow;
31
32    const SIZE: usize = $crate::count!($($x)*);
33
34    #[allow(unused_assignments)]
35    #[expect(clippy::transmute_undefined_repr)]
36    #[expect(clippy::macro_metavars_in_unsafe)]
37    // SAFETY: the returned value ends up being a valid `Vec`
38    unsafe {
39      let mut v: Vec<MaybeUninit<Cow<_>>> = Vec::with_capacity(SIZE);
40      v.set_len(SIZE);
41
42      let mut idx = 0;
43      $(
44        v[idx] = MaybeUninit::new($x.into());
45        idx += 1;
46      )*
47
48      mem::transmute::<Vec<MaybeUninit<Cow<_>>>, Vec<Cow<_>>>(v)
49    }
50  }};
51}
52
53#[macro_export]
54macro_rules! ref_smallvec {
55  ($t:ty, $size:expr, [$($x:expr),* $(,)?]$(,)?) => {{
56    let mut sv = SmallVec::<[&$t; $size]>::new_const();
57
58    sv.extend(
59      [
60        $(
61          AsRef::<$t>::as_ref($x),
62        )*
63      ]
64    );
65
66    sv
67  }};
68}
69
70#[macro_export]
71macro_rules! into_vec {
72  ($($x:expr),* $(,)?) => {
73    vec![
74      $(
75        $x.into(),
76      )*
77    ]
78  };
79}
80
81#[macro_export]
82macro_rules! into_array {
83  ($($x:expr),* $(,)?) => {
84    [
85      $(
86        $x.into(),
87      )*
88    ]
89  };
90}
91
92#[macro_export]
93macro_rules! into_smallvec {
94  ($($x:expr),* $(,)?) => {
95    smallvec::smallvec![
96      $(
97        $x.into(),
98      )*
99    ]
100  };
101}
102
103/// Attempts to create the directory if it does not exist, logging and returning
104/// and error if creating the directory failed.
105#[macro_export]
106macro_rules! create_dir {
107    ($loc:expr) => {
108        match std::fs::create_dir_all(&$loc) {
109            Ok(()) => Ok(()),
110            Err(e) => match e.kind() {
111                std::io::ErrorKind::AlreadyExists => Ok(()),
112                _ => {
113                    error!("Error while creating directory {:?}: {}", &$loc, e);
114                    Err(e)
115                },
116            },
117        }
118    };
119}
120
121#[inline]
122pub(crate) fn printable_base10_digits(x: usize) -> u32 {
123    (((x as f64).log10() + 1.0).floor() as u32).max(1)
124}
125
126/// Reads dir and returns all files
127/// Depth 1
128#[inline]
129pub fn read_in_dir(path: &Path) -> anyhow::Result<impl Iterator<Item = PathBuf>> {
130    let dir = std::fs::read_dir(path)?;
131    Ok(dir.into_iter().filter_map(Result::ok).filter_map(|d| {
132        d.file_type().map_or(None, |file_type| (!file_type.is_dir()).then(|| d.path()))
133    }))
134}