From f1f8a999fe7ebf5a927d3cc7f1a16db73949ee17 Mon Sep 17 00:00:00 2001 From: jofas Date: Thu, 18 Aug 2022 15:24:24 +0100 Subject: [PATCH] btree based sets and maps --- README.md | 38 +++++++++++++++++++++++++++- TODO.md | 32 +++--------------------- src/lib.rs | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++ tests/tests.rs | 58 ++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 165 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index f78ce95..3d703f0 100644 --- a/README.md +++ b/README.md @@ -7,12 +7,17 @@ [![Docs](https://img.shields.io/badge/docs-latest-blue.svg)](https://docs.rs/map-macro/latest/map_macro) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) -Declarative `map!`, `set!` and `vec_no_clone!` macros. +Declarative `map!`, `set!`, `btree_map!`, `btree_set!` and +`vec_no_clone!` macros. The `map!` macro allows for statically initializing a `std::collections::HashMap`. The same goes for the `set!` macro only for `std::collections::HashSet`. +Both macros have an equivalent version using a b-tree data structure +rather than a hashtable-based implementation, `btree_map!` and +`btree_set!` for statically initializing `std::collections::BTreeMap` +and `std::collections::BTreeSet`, respectively. The macros are equivalent to the `vec!` macro from the rust standard library. @@ -188,6 +193,37 @@ assert_eq!(x.len(), 0); ``` +## B-tree based maps and sets + +Besides hashtable-based maps and sets, rust's standard library offers +maps and sets based on the b-tree data structure +(`std::collections::BTreeMap` and `std::collections::BTreeSet). +They offer similar functionality to their hashtable-based +counterparts. +`map-macro` offers the `btree_map!` and `btree_set!` macros to +statically initialize the b-tree-based maps and sets. +They work exactly like the `map!` and `set!` macros: + +```rust +use map_macro::{btree_map, btree_set}; + +let hello = btree_map! { + "en" => "Hello", + "de" => "Hallo", + "fr" => "Bonjour", + "es" => "Hola", +}; + +assert_eq!(hello["en"], "Hello"); + +let x = btree_set! { 1, 2, 3 }; + +assert!(x.contains(&1)); + +assert!(!x.contains(&4)) +``` + + ## Vectors without cloning When using the `vec![some_value; count]` syntax, the type of diff --git a/TODO.md b/TODO.md index a4acaba..ab4c053 100644 --- a/TODO.md +++ b/TODO.md @@ -1,33 +1,9 @@ # TODO -* [x] crate documentation - -* [x] exposed artefacts documentation - -* [x] build action - -* [x] badges - -* [x] clippy action - -* [x] publish `v0.2.1` - -* [x] `vec_no_clone` macro - -* [x] `vec_no_clone` function - -* [x] example with `Rc` - -* [x] tests - -* [x] toc for toplevel documentation (with actions) - -* [x] documentation - -* [x] publish `v0.2.2` - * [x] `vec_no_clone` fallback to `vec` -* [ ] `btree_map` +* [x] `btree_map` + +* [x] `btree_set` -* [ ] `btree_set` +* [ ] publish `v0.2.4` diff --git a/src/lib.rs b/src/lib.rs index e0155c0..c7f92f9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,6 +41,41 @@ macro_rules! map { }; } +/// Macro for creating a [map](std::collections::BTreeMap) based on +/// a b-tree data structure. +/// +/// Works just like the [map!] macro. +/// Set this [crate's](crate) documentation for more examples on how +/// to use this macro. +/// +/// **Example:** +/// +/// ```rust +/// use map_macro::btree_map; +/// +/// let goodbye = btree_map! { +/// "en" => "Goodbye", +/// "de" => "Auf Wiedersehen", +/// "fr" => "Au revoir", +/// "es" => "Adios", +/// }; +/// ``` +/// +#[macro_export] +macro_rules! btree_map { + {$($k: expr => $v: expr),* $(,)?} => { + { + let mut map = std::collections::BTreeMap::new(); + + $( + map.insert($k, $v); + )* + + map + } + }; +} + /// Macro for creating a [set](std::collections::HashSet). /// /// Equivalent to the [vec!] macro for [vectors](std::vec::Vec). @@ -79,6 +114,38 @@ macro_rules! set { }; } +/// Macro for creating a [set](std::collections::BTreeSet) based on +/// a b-tree data structure. +/// +/// Works just like the [set!] macro. +/// Set this [crate's](crate) documentation for more examples on how +/// to use this macro. +/// +/// **Example:** +/// +/// ```rust +/// use map_macro::btree_set; +/// +/// let x = btree_set! { 1, 2, 3, 3, 4 }; +/// +/// assert_eq!(x.len(), 4); +/// ``` +/// +#[macro_export] +macro_rules! btree_set { + {$($v: expr),* $(,)?} => { + { + let mut set = std::collections::BTreeSet::new(); + + $( + set.insert($v); + )* + + set + } + }; +} + /// More flexible version of the [vec](std::vec) macro from the /// standard library. /// diff --git a/tests/tests.rs b/tests/tests.rs index 957768b..c897c82 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -1,4 +1,4 @@ -use map_macro::{map, set, vec_no_clone}; +use map_macro::{btree_map, btree_set, map, set, vec_no_clone}; #[test] fn map1() { @@ -56,6 +56,62 @@ fn set2() { assert!(!s.contains(&4)); } +#[test] +fn btree_map1() { + let m = btree_map! { + "en" => "Hello", + "de" => "Hallo", + "fr" => "Bonjour", + "es" => "Hola", + }; + + assert_eq!(m["en"], "Hello"); + assert_eq!(m["de"], "Hallo"); + assert_eq!(m["fr"], "Bonjour"); + assert_eq!(m["es"], "Hola"); +} + +#[test] +fn btree_map2() { + let m = btree_map! { + 0 => "a", + 1 => "b", + 2 => "c", + }; + + assert_eq!(m[&0], "a"); + assert_eq!(m[&1], "b"); + assert_eq!(m[&2], "c"); +} + +#[test] +fn btree_set1() { + let s = btree_set! { "a", "b", "c", "d" }; + + assert_eq!(s.len(), 4); + + assert!(s.contains("a")); + assert!(s.contains("b")); + assert!(s.contains("c")); + assert!(s.contains("d")); + + assert!(!s.contains("e")); +} + +#[test] +fn btree_set2() { + let s = btree_set! { 0, 1, 2, 3, 0 }; + + assert_eq!(s.len(), 4); + + assert!(s.contains(&0)); + assert!(s.contains(&1)); + assert!(s.contains(&2)); + assert!(s.contains(&3)); + + assert!(!s.contains(&4)); +} + #[derive(PartialEq, Debug)] struct UnclonableWrapper(i8);