xuko 0.10.0

Rust utility library
Documentation
//! xuko utility library

/// Construct a [`std::collections::HashMap`]
///
/// Example:
/// ```
/// use xuko::map;
/// let m1 = map!(String, String);
///
/// let m2 = map!{
///     "abc".to_string() => "def"
/// };
/// ```
#[macro_export]
macro_rules! map {
    // TODO: allow user to specify custom hasher
    ($key:ty, $val:ty) => {
        {
            use ::std::collections::HashMap;
            let map: HashMap<$key, $val> = HashMap::new();
            map
        }
    };

    ($($key: expr => $val:expr),*) => {
        {
            use ::std::collections::HashMap;
            let mut map = HashMap::new();
            $( map.insert($key, $val); )*;
            map
        }
    };
}

/// C-style for loop
///
/// # Examples
///
/// ```
/// use xuko::cfor;
/// cfor!((let mut x = 0; x != 5; x += 1) {
///     println!("Hello! #{}", x + 1);
/// });
/// ```
#[macro_export]
macro_rules! cfor {
    (($init:stmt;$cond:expr;$inc:stmt) $body:tt) => {
        $init
        while $cond {
            $body
            $inc
        }
    }
}

pub mod array;
pub mod bytes;
pub mod mem;
pub mod num;
pub mod path;
pub mod sparse_set;
pub mod timer;

#[cfg(feature = "logger")]
pub mod logger;

/// A type that calls a function when dropped
///
/// This is like the `defer` keyword found in some languages.
///
/// # Examples
///
/// ```
/// use xuko::{Defer, defer};
///
/// let _d1 = defer!(|| println!("Hello!"));
/// let _d2 = defer!(|| println!("Defer order works, unless manually drop()'d"));
///
/// println!("This will print before the deferred code!");
/// ```
pub struct Defer<F: FnOnce()> {
    callback: core::mem::ManuallyDrop<F>,
}

impl<F: FnOnce()> Defer<F> {
    /// Construct a [`Defer`]
    ///
    /// The return value must be stored in a temporary variable so the deferred function will run at
    /// the correct time.
    #[must_use = "Defers won't run unless assigned to a variable"]
    pub const fn new(f: F) -> Self {
        Self {
            callback: core::mem::ManuallyDrop::new(f),
        }
    }
}

impl<F: FnOnce()> Drop for Defer<F> {
    fn drop(&mut self) {
        // SAFETY: this is implemented in `Drop` so it doesn't matter
        unsafe {
            core::mem::ManuallyDrop::take(&mut self.callback)();
        }
    }
}

/// Shorthand for [`Defer::new`]
///
/// See [`Defer`] for more information.
#[macro_export]
macro_rules! defer {
    ($func:expr) => {
        $crate::Defer::new($func)
    };
}

#[cfg(test)]
mod tests {
    #[test]
    fn defer_test() {
        let _d1 = defer!(|| println!("This is defered"));
        let _d2 = defer!(|| println!("Goodbye"));

        fn funcptr() {
            println!("Callback from a function pointer");
        }
        let _d3 = defer!(funcptr);

        println!("Hey!");
    }
}