// :: debug macros.

// represents a debug-only string.
//
// in debug builds, this string will be included verbatim. in release builds, it will be replaced with an empty static
// string.
#[cfg(not(debug))]
#[macro_export]
macro_rules! d {
    ($value: tt) => {
        $value
    };
}
#[cfg(debug)]
#[macro_export]
macro_rules! d {
    ($value: tt) => {
        ""
    };
}


/// a macro that prints a line to stdout only in debug builds.
#[cfg(debug)]
#[macro_export]
macro_rules! dlog {
    ()             => (println!());
    ($fmt: expr)   => (println!($fmt));
    ($($arg: tt)*) => (println!($($arg)*));
}

#[cfg(not(debug))]
#[macro_export]
macro_rules! dlog {
    () => {};
    ($fmt: expr) => {};
    ($($arg: tt)*) => {};
}


// :: collection macros.

// a helper macro that returns the number of items passed to it.
#[macro_export]
macro_rules! __hina_item_count {
    (=a $($x: tt)*) => (
        ()
    );

    ($($items: expr),*) => (
        <[()]>::len(&[
            $(
                __hina_item_count![=a $items]
            ), *
        ])
    );
}

#[macro_export]
macro_rules! hash_map {
    ($($key: expr => $value: expr),* $(,)*) => ({
        let count      = __hina_item_count!($($key), *);
        let mut object = ::std::collections::HashMap::with_capacity(count);

        $(
            object.insert($key, $value);
        )*

        object
    });
}

#[macro_export]
macro_rules! btree_map {
    ($($key: expr => $value: expr),* $(,)*) => ({
        let mut object = ::std::collections::BTreeMap::new();

        $(
            object.insert($key, $value);
        )*

        object
    });
}

#[macro_export]
macro_rules! hash_set {
    ($($key: expr),* $(,)*) => ({
        let count      = __hina_item_count!($($key), *);
        let mut object = ::std::collections::HashSet::with_capacity(count);

        $(
            object.insert($key);
        )*

        object
    });
}

#[macro_export]
macro_rules! btree_set {
    ($($key: expr),* $(,)*) => ({
        let mut object = ::std::collections::BTreeSet::new();

        $(
            object.insert($key);
        )*

        object
    });
}