collect-all 0.1.0

vec! for everything: easily make literals of any collection!
Documentation
//! A macro to create collection literals for any type! Think of [`vec!`], but for any collection
//! type!
//!
//! Internally, this just uses the [`Iterator::collect()`] method. Since `collect` is powered by
//! [`FromIterator`], implement it to use this macro for your own types!
//!
//! # Examples
//!
//! Basic use, inferring the type of the collection
//! ```
//! use collect_all::collect;
//! use std::collections::HashSet;
//!
//! let hashset: HashSet<i32> = collect![1, 2, 3];
//! assert_eq!(HashSet::from_iter([1, 2, 3]), hashset);
//! ```
//!
//! Specifying the type in the macro invocation
//! ```
//! use collect_all::collect;
//! use std::collections::HashMap;
//!
//! let hashmap = collect![HashMap<&str, u8>: ("one", 1), ("two", 2)];
//! assert_eq!(HashMap::from_iter([("one", 1), ("two", 2)]), hashmap);
//! ```
//!
//! Creating with a given capacity
//! ```
//! use collect_all::collect;
//! use std::path::PathBuf;
//!
//! let pathbuf = collect![PathBuf: "path", "to", "file"; 10];
//! assert_eq!(PathBuf::from("path/to/file"), pathbuf);
//! assert!(pathbuf.capacity() >= 10);
//! ```
//! Note that this relies on a few things that are **not** strictly guaranteed for a given
//! collection:
//! 1. `with_capacity` is a method of the target type (for example, see [`Vec::with_capacity`])
//! 2. The target type implements [`Extend`]

/// The main macro of this crate. For use and examples, see the [crate level
/// docs](../collect_all/index.html).
#[macro_export]
macro_rules! collect {
    // Create empty
    ($type:ty) => {
        [].into_iter().collect::<$type>()
    };

    // Create empty with capacity
    ($type:ty; $n:expr) => {{
        <$type>::with_capacity($n)
    }};

    // Create with inline type
    ($type:ty: $($item:expr),*) => {
        [$($item),*].into_iter().collect::<$type>()
    };

    // Create with capacity
    ($type:ty: $($item:expr),*; $n:expr) => {{
        let mut collection = <$type>::with_capacity($n);
        collection.extend([$($item),*]);
        collection
    }};

    // Create with inferred type
    ($($item:expr),*) => {
        [$($item),*].into_iter().collect()
    };
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::collections::HashSet;

    #[test]
    fn create_with_inferred_type() {
        let collection: HashSet<i32> = collect![1, 2, 3];
        assert_eq!(HashSet::from_iter([1, 2, 3].into_iter()), collection);
    }

    #[test]
    fn create_with_inferred_type_with_no_items() {
        let collection: HashSet<i32> = collect![];
        assert_eq!(HashSet::new(), collection);
    }

    #[test]
    fn create_with_inline_type() {
        let collection = collect![HashSet<i32>: 1, 2, 3];
        assert_eq!(HashSet::from_iter([1, 2, 3].into_iter()), collection);
    }

    #[test]
    fn create_empty_with_inline_type() {
        let collection = collect![HashSet<i32>];
        assert_eq!(HashSet::new(), collection);
    }

    #[test]
    fn create_with_capacity() {
        let collection = collect![HashSet<i32>: 1, 2, 3; 14];
        assert_eq!(14, collection.capacity());
        assert_eq!(HashSet::from_iter([1, 2, 3].into_iter()), collection);
    }

    #[test]
    fn create_empty_with_capacity() {
        let collection = collect![HashSet<i32>; 14];
        assert_eq!(14, collection.capacity());
        assert_eq!(HashSet::new(), collection);
    }
}