fast_map/
lib.rs

1/*!
2A small library and custom derive to create a map-like struct that uses match expressions to `get` and `insert` values.
3
4If you know your keys at compile-time, this library will likely be faster than `HashMap` for supported map operations.
5
6Provides the following operations on the wrapping struct (via `derive` macros):
7
8* `MyMap::get`, returns `Result<Option<&V>, Error>`
9* `MyMap::get_mut`, returns `Result<Option<&mut V>, Error>`
10* `MyMap::insert`, returns `Result<Option<V>, Error>`, where `V` is the old value if one exists
11* `MyMap::remove`, returns `Result<Option<V>, Error>`
12* `MyMap::values`, returns an iterator over `&V`s
13
14If you know that your operations cannot fail (e.g. if your key type is an `enum`, and you list all variants as keys),
15you can add `infallible = true` to your derive attributes, which will `unwrap` the result of your map operations.
16
17# Usage
18
19```rust,no_run
20
21fn main() {
22    pub enum A { A, B, C, D };
23
24    #[derive(Default, fast_map::FastMap)]
25    // We know this cannot fail, since we list all the `enum` variants, so we add `infallible = true`
26    #[fast_map(infallible = true, keys(A::A, A::B, A::C, A::D))]
27    struct Foo(fast_map::Map4<A, String>);
28
29    let mut foo = Foo::default();
30
31    foo.insert(A::B, "B".into());
32
33    assert_eq!(foo.get(A::B), Some(&"B".to_string()));
34
35    assert_eq!(foo.get(A::C), None);
36
37    foo.insert(A::C, "C".into());
38
39    assert_eq!(foo.values().collect::<Vec<_>>().len(), 2);
40}
41```
42
43# Changelog
44
45## 0.2.1
46
47* Add the non-erroring operations back as depending on macro attribute (`infallible = true`). Default is `false`.
48
49## 0.2.0
50
51* Removed `easy` and `strict` `MapLike` traits. It's better to handle unknown keys explicitly, even for `get`s.
52* Added `get_mut` operation to the wrapping struct
53
54*/
55
56pub use fast_map_derive::FastMap;
57
58/// Currently just `KeyNotFound`
59#[derive(Debug)]
60pub enum Error {
61    KeyNotFound,
62}
63
64impl std::fmt::Display for Error {
65    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66        match self {
67            Error::KeyNotFound => "Key not found".fmt(f),
68        }
69    }
70}
71
72impl std::error::Error for Error {}
73
74mod maps;
75
76pub use maps::*;
77
78/// Iterator over existing values
79pub struct Values<'fast_map, T>(std::vec::IntoIter<Option<&'fast_map T>>);
80
81impl<'fast_map, T> Values<'fast_map, T> {
82    #[doc(hidden)]
83    pub fn new(t: std::vec::IntoIter<Option<&'fast_map T>>) -> Self {
84        Values(t)
85    }
86}
87
88impl<'fast_map, T> Iterator for Values<'fast_map, T> {
89    type Item = &'fast_map T;
90    fn next(&mut self) -> Option<Self::Item> {
91        loop {
92            match self.0.next() {
93                Some(Some(ref inner)) => {
94                    return Some(inner);
95                }
96                Some(None) => {
97                    continue;
98                }
99                None => {
100                    return None;
101                }
102            }
103        }
104    }
105}
106
107#[cfg(test)]
108mod tests {
109
110    use super::*;
111
112    #[test]
113    fn it_works() {
114        pub enum A {
115            A,
116            B,
117            C,
118            D,
119        };
120
121        #[derive(Default, FastMap)]
122        #[fast_map(infallible = true, crate_name = "crate", keys(A::A, A::B, A::C, A::D))]
123        struct Foo(crate::Map64<A, String>);
124
125        let mut foo = Foo::default();
126
127        foo.insert(A::B, "B".into());
128
129        assert_eq!(foo.get(A::B), Some(&"B".to_string()));
130
131        assert_eq!(foo.get(A::C), None);
132
133        foo.insert(A::C, "C".into());
134
135        assert_eq!(foo.values().collect::<Vec<_>>().len(), 2);
136    }
137
138    #[test]
139    fn it_works_2() {
140
141        #[derive(Default, FastMap)]
142        #[fast_map(crate_name = "crate", keys("x", "y", "z"))]
143        struct Foo<'a>(crate::Map3<str, &'a str>);
144
145        let mut foo = Foo::default();
146
147        let insert_x = String::from("x");
148
149        foo.insert(insert_x.as_str(), &insert_x).unwrap();
150
151        assert_eq!(foo.values().collect::<Vec<_>>().len(), 1);
152
153        let x = foo.remove("x").ok().flatten().unwrap();
154
155        assert_eq!(x, "x");
156
157        assert!(foo.values().collect::<Vec<_>>().is_empty());
158    }
159
160    #[test]
161    fn it_works_3() {
162
163        #[derive(Default, FastMap)]
164        #[fast_map(crate_name = "crate", keys(1, 2, 3))]
165        struct Foo<'a>(crate::Map3<usize, &'a str>);
166
167        let mut foo = Foo::default();
168
169        foo.insert(1, "1");
170        foo.insert(2, "2");
171        foo.insert(3, "3");
172        foo.insert(4, "4");
173
174        let _ = foo.remove(1);
175
176        assert_eq!(foo.values().map(|x| *x).collect::<Vec<_>>(), vec!["2", "3"]);
177    }
178}