diff options
| author | mo khan <mo@mokhan.ca> | 2025-07-02 18:36:06 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2025-07-02 18:36:06 -0600 |
| commit | 8cdfa445d6629ffef4cb84967ff7017654045bc2 (patch) | |
| tree | 22f0b0907c024c78d26a731e2e1f5219407d8102 /vendor/multimap | |
| parent | 4351c74c7c5f97156bc94d3a8549b9940ac80e3f (diff) | |
chore: add vendor directory
Diffstat (limited to 'vendor/multimap')
| -rw-r--r-- | vendor/multimap/.cargo-checksum.json | 1 | ||||
| -rw-r--r-- | vendor/multimap/Cargo.lock | 75 | ||||
| -rw-r--r-- | vendor/multimap/Cargo.toml | 46 | ||||
| -rw-r--r-- | vendor/multimap/LICENSE-APACHE | 201 | ||||
| -rw-r--r-- | vendor/multimap/LICENSE-MIT | 25 | ||||
| -rw-r--r-- | vendor/multimap/README.md | 86 | ||||
| -rw-r--r-- | vendor/multimap/src/entry.rs | 127 | ||||
| -rw-r--r-- | vendor/multimap/src/lib.rs | 1650 | ||||
| -rw-r--r-- | vendor/multimap/src/serde.rs | 149 |
9 files changed, 2360 insertions, 0 deletions
diff --git a/vendor/multimap/.cargo-checksum.json b/vendor/multimap/.cargo-checksum.json new file mode 100644 index 00000000..49d9944c --- /dev/null +++ b/vendor/multimap/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.lock":"2a77ea1e9eb835d7bcb2fbc623ebb8e3007636924f0c0294fb86b4c39232e019","Cargo.toml":"0c3f4c3736c04ab1426d0bd64cc5de8bd895cf554e19497ed9072bae73b0be7a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23ce717d2face34a1ae9af6a8c8fbbf488875afee16374d7a10ce79d41e22f37","README.md":"e389f7a05574cf84bcab6080ce1e056be3d50e48b8388594d3d91c88a0975754","src/entry.rs":"f90f875b6a8e81bcdc42c68dec3b1ec375e79cdf5f4149254635597a5756dc31","src/lib.rs":"7d1c3417d7ebe2ecd85bf5a7870224890d497907c2f65913f35cb0601622d14a","src/serde.rs":"53f54bada221fdbfb038a3c49f004514258cb709a38c7e0b51eb3abaee8ba9eb"},"package":"1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084"}
\ No newline at end of file diff --git a/vendor/multimap/Cargo.lock b/vendor/multimap/Cargo.lock new file mode 100644 index 00000000..f848f605 --- /dev/null +++ b/vendor/multimap/Cargo.lock @@ -0,0 +1,75 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "multimap" +version = "0.10.1" +dependencies = [ + "serde", + "serde_test", +] + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_test" +version = "1.0.177" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f901ee573cab6b3060453d2d5f0bae4e6d628c23c0a962ff9b5f1d7c8d4f1ed" +dependencies = [ + "serde", +] + +[[package]] +name = "syn" +version = "2.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" diff --git a/vendor/multimap/Cargo.toml b/vendor/multimap/Cargo.toml new file mode 100644 index 00000000..b4b8b906 --- /dev/null +++ b/vendor/multimap/Cargo.toml @@ -0,0 +1,46 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "multimap" +version = "0.10.1" +authors = ["Håvar Nøvik <havar.novik@gmail.com>"] +build = false +exclude = [ + ".github/**", + ".gitignore", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "A multimap implementation." +documentation = "https://docs.rs/multimap" +readme = "README.md" +license = "MIT OR Apache-2.0" +repository = "https://github.com/havarnov/multimap" + +[features] +default = ["serde_impl"] +serde_impl = ["serde"] + +[lib] +name = "multimap" +path = "src/lib.rs" + +[dependencies.serde] +version = "1.0" +optional = true + +[dev-dependencies.serde_test] +version = "1.0" diff --git a/vendor/multimap/LICENSE-APACHE b/vendor/multimap/LICENSE-APACHE new file mode 100644 index 00000000..16fe87b0 --- /dev/null +++ b/vendor/multimap/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/vendor/multimap/LICENSE-MIT b/vendor/multimap/LICENSE-MIT new file mode 100644 index 00000000..8b2dbea9 --- /dev/null +++ b/vendor/multimap/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2016 multimap developers + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/vendor/multimap/README.md b/vendor/multimap/README.md new file mode 100644 index 00000000..93e745c1 --- /dev/null +++ b/vendor/multimap/README.md @@ -0,0 +1,86 @@ +[](https://crates.io/crates/multimap) +[](https://docs.rs/multimap) + +# Multimap implementation for Rust + +This is a multimap implementation for Rust. Implemented as a thin wrapper around +`std::collections::HashMap`. + +## Example + +````rust +extern crate multimap; + +use multimap::MultiMap; + +fn main () { + let mut map = MultiMap::new(); + + map.insert("key1", 42); + map.insert("key1", 1337); + map.insert("key2", 2332); + + assert_eq!(map["key1"], 42); + assert_eq!(map.get("key1"), Some(&42)); + assert_eq!(map.get_vec("key1"), Some(&vec![42, 1337])); +} +```` + +## Changelog + +### 0.10.1 + +* Fix docs for flat_iter #45 +* Clippy warnings + +### 0.10.0 + +* Added `FromIterator<(K, Vec<V>)>` [#48](https://github.com/havarnov/multimap/pull/48). + +### 0.9.1 + +* Fixes a bug where iteration would panic on empty (inner) vectors [#46](https://github.com/havarnov/multimap/issues/46). + +### 0.9.0 + +* Added ```flat_iter``` and ```flat_iter_mut``` +* Fixed bug where ```get``` and ```get_mut``` could panic. + +### 0.8.3 + +* `multimap!` macro fixes; allow trailing comma, naming hygiene and create with + enough capacity for all elements. + +### 0.8.2 + +* Added ```#![forbid(unsafe_code)]```. + +### 0.8.1 + +* Fixed wrong link to documentation in `Cargo.toml`. + +### 0.8.0 + +* Added ```MultiMap::insert_many```. +* Added ```MultiMap::insert_many_from_slice```. + +### 0.7.0 + +* Added possibility to replace the default hasher for the underlying + ```HashMap```. +* Fix build warning by removing an unnecessary ```mut```. + +## License + +Licensed under either of + * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or + https://www.apache.org/licenses/LICENSE-2.0) + * MIT license ([LICENSE-MIT](LICENSE-MIT) or + https://opensource.org/licenses/MIT) +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. diff --git a/vendor/multimap/src/entry.rs b/vendor/multimap/src/entry.rs new file mode 100644 index 00000000..f5420491 --- /dev/null +++ b/vendor/multimap/src/entry.rs @@ -0,0 +1,127 @@ +// Copyright (c) 2016 multimap developers +// +// Licensed under the Apache License, Version 2.0 +// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0> or the MIT +// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your +// option. All files in the project carrying such notice may not be copied, +// modified, or distributed except according to those terms. + +use std::collections::hash_map::OccupiedEntry as HashMapOccupiedEntry; +use std::collections::hash_map::VacantEntry as HashMapVacantEntry; + +/// A view into a single occupied location in a MultiMap. +pub struct OccupiedEntry<'a, K: 'a, V: 'a> { + #[doc(hidden)] + pub inner: HashMapOccupiedEntry<'a, K, Vec<V>>, +} + +/// A view into a single empty location in a MultiMap. +pub struct VacantEntry<'a, K: 'a, V: 'a> { + #[doc(hidden)] + pub inner: HashMapVacantEntry<'a, K, Vec<V>>, +} + +/// A view into a single location in a map, which may be vacant or occupied. +pub enum Entry<'a, K: 'a, V: 'a> { + /// An occupied Entry. + Occupied(OccupiedEntry<'a, K, V>), + + /// A vacant Entry. + Vacant(VacantEntry<'a, K, V>), +} + +impl<'a, K: 'a, V: 'a> OccupiedEntry<'a, K, V> { + /// Gets a reference to the first item in value in the vector corresponding to entry. + /// + /// # Panics + /// + /// This method will panic if the key has zero values. + pub fn get(&self) -> &V { + self.inner.get().first().expect("no values in entry") + } + + /// Gets a reference to the values (vector) corresponding to entry. + pub fn get_vec(&self) -> &Vec<V> { + self.inner.get() + } + + /// Gets a mut reference to the first item in value in the vector corresponding to entry. + /// + /// # Panics + /// + /// This method will panic if the key has zero values. + pub fn get_mut(&mut self) -> &mut V { + self.inner + .get_mut() + .first_mut() + .expect("no values in entry") + } + + /// Gets a mut reference to the values (vector) corresponding to entry. + pub fn get_vec_mut(&mut self) -> &mut Vec<V> { + self.inner.get_mut() + } + + /// Converts the OccupiedEntry into a mutable reference to the first item in value in the entry + /// with a lifetime bound to the map itself + pub fn into_mut(self) -> &'a mut V { + &mut self.inner.into_mut()[0] + } + + /// Converts the OccupiedEntry into a mutable reference to the values (vector) in the entry + /// with a lifetime bound to the map itself + pub fn into_vec_mut(self) -> &'a mut Vec<V> { + self.inner.into_mut() + } + + /// Inserts a new value onto the vector of the entry. + pub fn insert(&mut self, value: V) { + self.get_vec_mut().push(value); + } + + /// Extends the existing vector with the specified values. + pub fn insert_vec(&mut self, values: Vec<V>) { + self.get_vec_mut().extend(values); + } + + /// Takes the values (vector) out of the entry, and returns it + pub fn remove(self) -> Vec<V> { + self.inner.remove() + } +} + +impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> { + /// Sets the first value in the vector of the entry with the VacantEntry's key, + /// and returns a mutable reference to it. + pub fn insert(self, value: V) -> &'a mut V { + &mut self.inner.insert(vec![value])[0] + } + + /// Sets values in the entry with the VacantEntry's key, + /// and returns a mutable reference to it. + pub fn insert_vec(self, values: Vec<V>) -> &'a mut Vec<V> { + self.inner.insert(values) + } +} + +impl<'a, K: 'a, V: 'a> Entry<'a, K, V> { + /// Ensures a value is in the entry by inserting the default if empty, and returns + /// a mutable reference to the value in the entry. This will return a mutable reference to the + /// first value in the vector corresponding to the specified key. + pub fn or_insert(self, default: V) -> &'a mut V { + match self { + Entry::Occupied(entry) => entry.into_mut(), + Entry::Vacant(entry) => entry.insert(default), + } + } + + /// Ensures a value is in the entry by inserting the default values if empty, and returns + /// a mutable reference to the values (the corresponding vector to the specified key) in + /// the entry. + pub fn or_insert_vec(self, defaults: Vec<V>) -> &'a mut Vec<V> { + match self { + Entry::Occupied(entry) => entry.into_vec_mut(), + Entry::Vacant(entry) => entry.insert_vec(defaults), + } + } +} diff --git a/vendor/multimap/src/lib.rs b/vendor/multimap/src/lib.rs new file mode 100644 index 00000000..35d5952c --- /dev/null +++ b/vendor/multimap/src/lib.rs @@ -0,0 +1,1650 @@ +#![forbid(unsafe_code)] +// Copyright (c) 2016 multimap developers +// +// Licensed under the Apache License, Version 2.0 +// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0> or the MIT +// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your +// option. All files in the project carrying such notice may not be copied, +// modified, or distributed except according to those terms. + +//! A map implementation which allows storing multiple values per key. +//! +//! The interface is roughly based on std::collections::HashMap, but is changed +//! and extended to accomodate the multi-value use case. In fact, MultiMap is +//! implemented mostly as a thin wrapper around std::collections::HashMap and +//! stores its values as a std::Vec per key. +//! +//! Values are guaranteed to be in insertion order as long as not manually +//! changed. Keys are not ordered. Multiple idential key-value-pairs can exist +//! in the MultiMap. A key can exist in the MultiMap with no associated value. +//! +//! # Examples +//! +//! ``` +//! use multimap::MultiMap; +//! +//! // create a new MultiMap. An explicit type signature can be omitted because of the +//! // type inference. +//! let mut queries = MultiMap::new(); +//! +//! // insert some queries. +//! queries.insert("urls", "http://rust-lang.org"); +//! queries.insert("urls", "http://mozilla.org"); +//! queries.insert("urls", "http://wikipedia.org"); +//! queries.insert("id", "42"); +//! queries.insert("name", "roger"); +//! +//! // check if there's any urls. +//! println!("Are there any urls in the multimap? {:?}.", +//! if queries.contains_key("urls") {"Yes"} else {"No"} ); +//! +//! // get the first item in a key's vector. +//! assert_eq!(queries.get("urls"), Some(&"http://rust-lang.org")); +//! +//! // get all the urls. +//! assert_eq!(queries.get_vec("urls"), +//! Some(&vec!["http://rust-lang.org", "http://mozilla.org", "http://wikipedia.org"])); +//! +//! // iterate over all keys and the first value in the key's vector. +//! for (key, value) in queries.iter() { +//! println!("key: {:?}, val: {:?}", key, value); +//! } +//! +//! // iterate over all keys and the key's vector. +//! for (key, values) in queries.iter_all() { +//! println!("key: {:?}, values: {:?}", key, values); +//! } +//! +//! // the different methods for getting value(s) from the multimap. +//! let mut map = MultiMap::new(); +//! +//! map.insert("key1", 42); +//! map.insert("key1", 1337); +//! +//! assert_eq!(map["key1"], 42); +//! assert_eq!(map.get("key1"), Some(&42)); +//! assert_eq!(map.get_vec("key1"), Some(&vec![42, 1337])); +//! ``` + +use std::borrow::Borrow; +use std::collections::hash_map::{IntoIter, Keys, RandomState}; +use std::collections::HashMap; +use std::fmt::{self, Debug}; +use std::hash::{BuildHasher, Hash}; +use std::iter::{FromIterator, IntoIterator, Iterator}; +use std::ops::Index; + +pub use std::collections::hash_map::Iter as IterAll; +pub use std::collections::hash_map::IterMut as IterAllMut; + +pub use entry::{Entry, OccupiedEntry, VacantEntry}; + +mod entry; + +#[cfg(feature = "serde_impl")] +pub mod serde; + +#[derive(Clone)] +pub struct MultiMap<K, V, S = RandomState> { + inner: HashMap<K, Vec<V>, S>, +} + +impl<K, V> MultiMap<K, V> +where + K: Eq + Hash, +{ + /// Creates an empty MultiMap + /// + /// # Examples + /// + /// ``` + /// use multimap::MultiMap; + /// + /// let mut map: MultiMap<&str, isize> = MultiMap::new(); + /// ``` + pub fn new() -> MultiMap<K, V> { + MultiMap { + inner: HashMap::new(), + } + } + + /// Creates an empty multimap with the given initial capacity. + /// + /// # Examples + /// + /// ``` + /// use multimap::MultiMap; + /// + /// let mut map: MultiMap<&str, isize> = MultiMap::with_capacity(20); + /// ``` + pub fn with_capacity(capacity: usize) -> MultiMap<K, V> { + MultiMap { + inner: HashMap::with_capacity(capacity), + } + } +} + +impl<K, V, S> MultiMap<K, V, S> +where + K: Eq + Hash, + S: BuildHasher, +{ + /// Creates an empty MultiMap which will use the given hash builder to hash keys. + /// + /// # Examples + /// + /// ``` + /// use multimap::MultiMap; + /// use std::collections::hash_map::RandomState; + /// + /// let s = RandomState::new(); + /// let mut map: MultiMap<&str, isize> = MultiMap::with_hasher(s); + /// ``` + pub fn with_hasher(hash_builder: S) -> MultiMap<K, V, S> { + MultiMap { + inner: HashMap::with_hasher(hash_builder), + } + } + + /// Creates an empty MultiMap with the given intial capacity and hash builder. + /// + /// # Examples + /// + /// ``` + /// use multimap::MultiMap; + /// use std::collections::hash_map::RandomState; + /// + /// let s = RandomState::new(); + /// let mut map: MultiMap<&str, isize> = MultiMap::with_capacity_and_hasher(20, s); + /// ``` + pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> MultiMap<K, V, S> { + MultiMap { + inner: HashMap::with_capacity_and_hasher(capacity, hash_builder), + } + } + + /// Inserts a key-value pair into the multimap. If the key does exist in + /// the map then the value is pushed to that key's vector. If the key doesn't + /// exist in the map a new vector with the given value is inserted. + /// + /// # Examples + /// + /// ``` + /// use multimap::MultiMap; + /// + /// let mut map = MultiMap::new(); + /// map.insert("key", 42); + /// ``` + pub fn insert(&mut self, k: K, v: V) { + match self.entry(k) { + Entry::Occupied(mut entry) => { + entry.get_vec_mut().push(v); + } + Entry::Vacant(entry) => { + entry.insert_vec(vec![v]); + } + } + } + + /// Inserts multiple key-value pairs into the multimap. If the key does exist in + /// the map then the values are extended into that key's vector. If the key + /// doesn't exist in the map a new vector collected from the given values is inserted. + /// + /// This may be more efficient than inserting values independently. + /// + /// # Examples + /// + /// ``` + /// use multimap::MultiMap; + /// + /// let mut map = MultiMap::<&str, &usize>::new(); + /// map.insert_many("key", &[42, 43]); + /// ``` + pub fn insert_many<I: IntoIterator<Item = V>>(&mut self, k: K, v: I) { + match self.entry(k) { + Entry::Occupied(mut entry) => { + entry.get_vec_mut().extend(v); + } + Entry::Vacant(entry) => { + entry.insert_vec(v.into_iter().collect::<Vec<_>>()); + } + } + } + + /// Inserts multiple key-value pairs into the multimap. If the key does exist in + /// the map then the values are extended into that key's vector. If the key + /// doesn't exist in the map a new vector collected from the given values is inserted. + /// + /// This may be more efficient than inserting values independently. + /// + /// # Examples + /// + /// ``` + /// use multimap::MultiMap; + /// + /// let mut map = MultiMap::<&str, usize>::new(); + /// map.insert_many_from_slice("key", &[42, 43]); + /// ``` + pub fn insert_many_from_slice(&mut self, k: K, v: &[V]) + where + V: Clone, + { + match self.entry(k) { + Entry::Occupied(mut entry) => { + entry.get_vec_mut().extend_from_slice(v); + } + Entry::Vacant(entry) => { + entry.insert_vec(v.to_vec()); + } + } + } + + /// Returns true if the map contains a value for the specified key. + /// + /// The key may be any borrowed form of the map's key type, but Hash and Eq + /// on the borrowed form must match those for the key type. + /// + /// # Examples + /// + /// ``` + /// use multimap::MultiMap; + /// + /// let mut map = MultiMap::new(); + /// map.insert(1, 42); + /// assert_eq!(map.contains_key(&1), true); + /// assert_eq!(map.contains_key(&2), false); + /// ``` + pub fn contains_key<Q>(&self, k: &Q) -> bool + where + K: Borrow<Q>, + Q: Eq + Hash + ?Sized, + { + self.inner.contains_key(k) + } + + /// Returns the number of unique keys in the map. + /// + /// # Examples + /// + /// ``` + /// use multimap::MultiMap; + /// + /// let mut map = MultiMap::new(); + /// map.insert(1, 42); + /// map.insert(2, 1337); + /// map.insert(2, 31337); + /// assert_eq!(map.len(), 2); + /// ``` + pub fn len(&self) -> usize { + self.inner.len() + } + + /// Removes a key from the map, returning the vector of values at + /// the key if the key was previously in the map. + /// + /// The key may be any borrowed form of the map's key type, but Hash and Eq + /// on the borrowed form must match those for the key type. + /// + /// # Examples + /// + /// ``` + /// use multimap::MultiMap; + /// + /// let mut map = MultiMap::new(); + /// map.insert(1, 42); + /// map.insert(1, 1337); + /// assert_eq!(map.remove(&1), Some(vec![42, 1337])); + /// assert_eq!(map.remove(&1), None); + /// ``` + pub fn remove<Q>(&mut self, k: &Q) -> Option<Vec<V>> + where + K: Borrow<Q>, + Q: Eq + Hash + ?Sized, + { + self.inner.remove(k) + } + + /// Returns a reference to the first item in the vector corresponding to + /// the key. + /// + /// The key may be any borrowed form of the map's key type, but Hash and Eq + /// on the borrowed form must match those for the key type. + /// + /// # Examples + /// + /// ``` + /// use multimap::MultiMap; + /// + /// let mut map = MultiMap::new(); + /// map.insert(1, 42); + /// map.insert(1, 1337); + /// assert_eq!(map.get(&1), Some(&42)); + /// ``` + pub fn get<Q>(&self, k: &Q) -> Option<&V> + where + K: Borrow<Q>, + Q: Eq + Hash + ?Sized, + { + self.inner.get(k)?.first() + } + + /// Returns a mutable reference to the first item in the vector corresponding to + /// the key. + /// + /// The key may be any borrowed form of the map's key type, but Hash and Eq + /// on the borrowed form must match those for the key type. + /// + /// # Examples + /// + /// ``` + /// use multimap::MultiMap; + /// + /// let mut map = MultiMap::new(); + /// map.insert(1, 42); + /// map.insert(1, 1337); + /// if let Some(v) = map.get_mut(&1) { + /// *v = 99; + /// } + /// assert_eq!(map[&1], 99); + /// ``` + pub fn get_mut<Q>(&mut self, k: &Q) -> Option<&mut V> + where + K: Borrow<Q>, + Q: Eq + Hash + ?Sized, + { + self.inner.get_mut(k)?.get_mut(0) + } + + /// Returns a reference to the vector corresponding to the key. + /// + /// The key may be any borrowed form of the map's key type, but Hash and Eq + /// on the borrowed form must match those for the key type. + /// + /// # Examples + /// + /// ``` + /// use multimap::MultiMap; + /// + /// let mut map = MultiMap::new(); + /// map.insert(1, 42); + /// map.insert(1, 1337); + /// assert_eq!(map.get_vec(&1), Some(&vec![42, 1337])); + /// ``` + pub fn get_vec<Q>(&self, k: &Q) -> Option<&Vec<V>> + where + K: Borrow<Q>, + Q: Eq + Hash + ?Sized, + { + self.inner.get(k) + } + + /// Returns a mutable reference to the vector corresponding to the key. + /// + /// The key may be any borrowed form of the map's key type, but Hash and Eq + /// on the borrowed form must match those for the key type. + /// + /// # Examples + /// + /// ``` + /// use multimap::MultiMap; + /// + /// let mut map = MultiMap::new(); + /// map.insert(1, 42); + /// map.insert(1, 1337); + /// if let Some(v) = map.get_vec_mut(&1) { + /// (*v)[0] = 1991; + /// (*v)[1] = 2332; + /// } + /// assert_eq!(map.get_vec(&1), Some(&vec![1991, 2332])); + /// ``` + pub fn get_vec_mut<Q>(&mut self, k: &Q) -> Option<&mut Vec<V>> + where + K: Borrow<Q>, + Q: Eq + Hash + ?Sized, + { + self.inner.get_mut(k) + } + + /// Returns true if the key is multi-valued. + /// + /// The key may be any borrowed form of the map's key type, but Hash and Eq + /// on the borrowed form must match those for the key type. + /// + /// # Examples + /// + /// ``` + /// use multimap::MultiMap; + /// + /// let mut map = MultiMap::new(); + /// map.insert(1, 42); + /// map.insert(1, 1337); + /// map.insert(2, 2332); + /// + /// assert_eq!(map.is_vec(&1), true); // key is multi-valued + /// assert_eq!(map.is_vec(&2), false); // key is single-valued + /// assert_eq!(map.is_vec(&3), false); // key not in map + /// ``` + pub fn is_vec<Q>(&self, k: &Q) -> bool + where + K: Borrow<Q>, + Q: Eq + Hash + ?Sized, + { + match self.get_vec(k) { + Some(val) => val.len() > 1, + None => false, + } + } + + /// Returns the number of elements the map can hold without reallocating. + /// + /// # Examples + /// + /// ``` + /// use multimap::MultiMap; + /// + /// let map: MultiMap<usize, usize> = MultiMap::new(); + /// assert!(map.capacity() >= 0); + /// ``` + pub fn capacity(&self) -> usize { + self.inner.capacity() + } + + /// Returns true if the map contains no elements. + /// + /// # Examples + /// + /// ``` + /// use multimap::MultiMap; + /// + /// let mut map = MultiMap::new(); + /// assert!(map.is_empty()); + /// map.insert(1,42); + /// assert!(!map.is_empty()); + /// ``` + pub fn is_empty(&self) -> bool { + self.inner.is_empty() + } + + /// Clears the map, removing all key-value pairs. + /// Keeps the allocated memory for reuse. + /// + /// # Examples + /// + /// ``` + /// use multimap::MultiMap; + /// + /// let mut map = MultiMap::new(); + /// map.insert(1,42); + /// map.clear(); + /// assert!(map.is_empty()); + /// ``` + pub fn clear(&mut self) { + self.inner.clear(); + } + + /// An iterator visiting all keys in arbitrary order. + /// Iterator element type is &'a K. + /// + /// # Examples + /// + /// ``` + /// use multimap::MultiMap; + /// + /// let mut map = MultiMap::new(); + /// map.insert(1,42); + /// map.insert(1,1337); + /// map.insert(2,1337); + /// map.insert(4,1991); + /// + /// let mut keys: Vec<_> = map.keys().collect(); + /// keys.sort(); + /// assert_eq!(keys, [&1, &2, &4]); + /// ``` + pub fn keys(&'_ self) -> Keys<'_, K, Vec<V>> { + self.inner.keys() + } + + /// An iterator visiting pairs of each key and its first value in arbitrary order. + /// The iterator returns + /// a reference to the key and the first element in the corresponding key's vector. + /// Iterator element type is (&'a K, &'a V). + /// + /// See [`flat_iter`](Self::flat_iter) + /// for visiting all key-value pairs, + /// or [`iter_all`](Self::iter_all) + /// for visiting each key and its vector of values. + /// + /// # Examples + /// + /// ``` + /// use multimap::MultiMap; + /// + /// let mut map = MultiMap::new(); + /// map.insert(1,42); + /// map.insert(1,1337); + /// map.insert(3,2332); + /// map.insert(4,1991); + /// + /// let mut pairs: Vec<_> = map.iter().collect(); + /// pairs.sort_by_key(|p| p.0); + /// assert_eq!(pairs, [(&1, &42), (&3, &2332), (&4, &1991)]); + /// ``` + pub fn iter(&self) -> Iter<K, V> { + Iter { + inner: self.inner.iter(), + } + } + + /// A mutable iterator visiting pairs of each key and its first value + /// in arbitrary order. The iterator returns + /// a reference to the key and a mutable reference to the first element in the + /// corresponding key's vector. Iterator element type is (&'a K, &'a mut V). + /// + /// See [`flat_iter_mut`](Self::flat_iter_mut) + /// for visiting all key-value pairs, + /// or [`iter_all_mut`](Self::iter_all_mut) + /// for visiting each key and its vector of values. + /// + /// # Examples + /// + /// ``` + /// use multimap::MultiMap; + /// + /// let mut map = MultiMap::new(); + /// map.insert(1,42); + /// map.insert(1,1337); + /// map.insert(3,2332); + /// map.insert(4,1991); + /// + /// for (_, value) in map.iter_mut() { + /// *value *= *value; + /// } + /// + /// let mut pairs: Vec<_> = map.iter_mut().collect(); + /// pairs.sort_by_key(|p| p.0); + /// assert_eq!(pairs, [(&1, &mut 1764), (&3, &mut 5438224), (&4, &mut 3964081)]); + /// ``` + pub fn iter_mut(&mut self) -> IterMut<K, V> { + IterMut { + inner: self.inner.iter_mut(), + } + } + + /// An iterator visiting all key-value pairs in arbitrary order. The iterator returns + /// a reference to the key and the corresponding key's vector. + /// Iterator element type is (&'a K, &'a V). + /// + /// # Examples + /// + /// ``` + /// use multimap::MultiMap; + /// + /// let mut map = MultiMap::new(); + /// map.insert(1,42); + /// map.insert(1,1337); + /// map.insert(3,2332); + /// map.insert(4,1991); + /// + /// let mut pairs: Vec<_> = map.iter_all().collect(); + /// pairs.sort_by_key(|p| p.0); + /// assert_eq!(pairs, [(&1, &vec![42, 1337]), (&3, &vec![2332]), (&4, &vec![1991])]); + /// ``` + pub fn iter_all(&self) -> IterAll<K, Vec<V>> { + self.inner.iter() + } + + /// An iterator visiting all key-value pairs in arbitrary order. The iterator returns + /// a reference to the key and the corresponding key's vector. + /// Iterator element type is (&'a K, &'a V). + /// + /// # Examples + /// + /// ``` + /// use multimap::MultiMap; + /// + /// let mut map = MultiMap::new(); + /// map.insert(1,42); + /// map.insert(1,1337); + /// map.insert(3,2332); + /// map.insert(4,1991); + /// + /// for (key, values) in map.iter_all_mut() { + /// for value in values.iter_mut() { + /// *value = 99; + /// } + /// } + /// + /// let mut pairs: Vec<_> = map.iter_all_mut().collect(); + /// pairs.sort_by_key(|p| p.0); + /// assert_eq!(pairs, [(&1, &mut vec![99, 99]), (&3, &mut vec![99]), (&4, &mut vec![99])]); + /// ``` + pub fn iter_all_mut(&mut self) -> IterAllMut<K, Vec<V>> { + self.inner.iter_mut() + } + + /// An iterator visiting all key-value pairs in arbitrary order. + /// + /// # Examples + /// + /// ``` + /// use multimap::MultiMap; + /// + /// let mut map = MultiMap::new(); + /// map.insert(1,42); + /// map.insert(1,1337); + /// map.insert(3,2332); + /// map.insert(4,1991); + /// + /// let mut pairs: Vec<_> = map.flat_iter().collect(); + /// pairs.sort(); + /// assert_eq!(pairs, [(&1, &42), (&1, &1337), (&3, &2332), (&4, &1991)]); + /// ``` + pub fn flat_iter(&self) -> impl Iterator<Item = (&K, &V)> { + self.iter_all() + .flat_map(|(k, v)| v.iter().map(move |i| (k, i))) + } + + /// A mutable iterator visiting all key-value pairs in arbitrary order. + /// + /// # Examples + /// + /// ``` + /// use multimap::MultiMap; + /// + /// let mut map = MultiMap::new(); + /// map.insert(1,42); + /// map.insert(1,1337); + /// map.insert(3,2332); + /// map.insert(4,1991); + /// + /// for (key, value) in map.flat_iter_mut() { + /// *value *= key; + /// } + /// + /// let mut pairs: Vec<_> = map.flat_iter().collect(); + /// pairs.sort(); + /// assert_eq!(pairs, [(&1, &42), (&1, &1337), (&3, &6996), (&4, &7964)]); + /// ``` + pub fn flat_iter_mut(&mut self) -> impl Iterator<Item = (&K, &mut V)> { + self.iter_all_mut() + .flat_map(|(k, v)| v.iter_mut().map(move |i| (k, i))) + } + + /// Gets the specified key's corresponding entry in the map for in-place manipulation. + /// It's possible to both manipulate the vector and the 'value' (the first value in the + /// vector). + /// + /// # Examples + /// + /// ``` + /// use multimap::MultiMap; + /// + /// let mut m = MultiMap::new(); + /// m.insert(1, 42); + /// + /// { + /// let mut v = m.entry(1).or_insert(43); + /// assert_eq!(v, &42); + /// *v = 44; + /// } + /// assert_eq!(m.entry(2).or_insert(666), &666); + /// + /// { + /// let mut v = m.entry(1).or_insert_vec(vec![43]); + /// assert_eq!(v, &vec![44]); + /// v.push(50); + /// } + /// assert_eq!(m.entry(2).or_insert_vec(vec![667]), &vec![666]); + /// + /// assert_eq!(m.get_vec(&1), Some(&vec![44, 50])); + /// ``` + pub fn entry(&mut self, k: K) -> Entry<K, V> { + use std::collections::hash_map::Entry as HashMapEntry; + match self.inner.entry(k) { + HashMapEntry::Occupied(entry) => Entry::Occupied(OccupiedEntry { inner: entry }), + HashMapEntry::Vacant(entry) => Entry::Vacant(VacantEntry { inner: entry }), + } + } + + /// Retains only the elements specified by the predicate. + /// + /// In other words, remove all pairs `(k, v)` such that `f(&k,&mut v)` returns `false`. + /// + /// # Examples + /// + /// ``` + /// use multimap::MultiMap; + /// + /// let mut m = MultiMap::new(); + /// m.insert(1, 42); + /// m.insert(1, 99); + /// m.insert(2, 42); + /// m.retain(|&k, &v| { k == 1 && v == 42 }); + /// assert_eq!(1, m.len()); + /// assert_eq!(Some(&42), m.get(&1)); + /// ``` + pub fn retain<F>(&mut self, mut f: F) + where + F: FnMut(&K, &V) -> bool, + { + for (key, vector) in &mut self.inner { + vector.retain(|value| f(key, value)); + } + self.inner.retain(|_, v| !v.is_empty()); + } +} + +impl<K, V, S, Q> Index<&Q> for MultiMap<K, V, S> +where + K: Eq + Hash + Borrow<Q>, + Q: Eq + Hash + ?Sized, + S: BuildHasher, +{ + type Output = V; + + fn index(&self, index: &Q) -> &V { + self.inner + .get(index) + .expect("no entry found for key") + .first() + .expect("no value found for key") + } +} + +impl<K, V, S> Debug for MultiMap<K, V, S> +where + K: Eq + Hash + Debug, + V: Debug, + S: BuildHasher, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_map().entries(self.iter_all()).finish() + } +} + +impl<K, V, S> PartialEq for MultiMap<K, V, S> +where + K: Eq + Hash, + V: PartialEq, + S: BuildHasher, +{ + fn eq(&self, other: &MultiMap<K, V, S>) -> bool { + if self.len() != other.len() { + return false; + } + + self.iter_all() + .all(|(key, value)| other.get_vec(key).is_some_and(|v| *value == *v)) + } +} + +impl<K, V, S> Eq for MultiMap<K, V, S> +where + K: Eq + Hash, + V: Eq, + S: BuildHasher, +{ +} + +impl<K, V, S> Default for MultiMap<K, V, S> +where + K: Eq + Hash, + S: BuildHasher + Default, +{ + fn default() -> MultiMap<K, V, S> { + MultiMap { + inner: Default::default(), + } + } +} + +impl<K, V, S> FromIterator<(K, V)> for MultiMap<K, V, S> +where + K: Eq + Hash, + S: BuildHasher + Default, +{ + fn from_iter<T: IntoIterator<Item = (K, V)>>(iterable: T) -> MultiMap<K, V, S> { + let iter = iterable.into_iter(); + let hint = iter.size_hint().0; + + let mut multimap = MultiMap::with_capacity_and_hasher(hint, S::default()); + for (k, v) in iter { + multimap.insert(k, v); + } + + multimap + } +} + +impl<K, V, S> FromIterator<(K, Vec<V>)> for MultiMap<K, V, S> +where + K: Eq + Hash, + V: Clone, + S: BuildHasher + Default, +{ + fn from_iter<T: IntoIterator<Item = (K, Vec<V>)>>(iterable: T) -> MultiMap<K, V, S> { + let iter = iterable.into_iter(); + let hint = iter.size_hint().0; + + let mut multimap = MultiMap::with_capacity_and_hasher(hint, S::default()); + for (k, v) in iter { + multimap.insert_many_from_slice(k, &v[..]) + } + + multimap + } +} + +impl<'a, K, V, S> IntoIterator for &'a MultiMap<K, V, S> +where + K: Eq + Hash, + S: BuildHasher, +{ + type Item = (&'a K, &'a Vec<V>); + type IntoIter = IterAll<'a, K, Vec<V>>; + + fn into_iter(self) -> IterAll<'a, K, Vec<V>> { + self.iter_all() + } +} + +impl<'a, K, V, S> IntoIterator for &'a mut MultiMap<K, V, S> +where + K: Eq + Hash, + S: BuildHasher, +{ + type Item = (&'a K, &'a mut Vec<V>); + type IntoIter = IterAllMut<'a, K, Vec<V>>; + + fn into_iter(self) -> IterAllMut<'a, K, Vec<V>> { + self.inner.iter_mut() + } +} + +impl<K, V, S> IntoIterator for MultiMap<K, V, S> +where + K: Eq + Hash, + S: BuildHasher, +{ + type Item = (K, Vec<V>); + type IntoIter = IntoIter<K, Vec<V>>; + + fn into_iter(self) -> IntoIter<K, Vec<V>> { + self.inner.into_iter() + } +} + +impl<K, V, S> Extend<(K, V)> for MultiMap<K, V, S> +where + K: Eq + Hash, + S: BuildHasher, +{ + fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) { + for (k, v) in iter { + self.insert(k, v); + } + } +} + +impl<'a, K, V, S> Extend<(&'a K, &'a V)> for MultiMap<K, V, S> +where + K: Eq + Hash + Copy, + V: Copy, + S: BuildHasher, +{ + fn extend<T: IntoIterator<Item = (&'a K, &'a V)>>(&mut self, iter: T) { + self.extend(iter.into_iter().map(|(&key, &value)| (key, value))); + } +} + +impl<K, V, S> Extend<(K, Vec<V>)> for MultiMap<K, V, S> +where + K: Eq + Hash, + S: BuildHasher, +{ + fn extend<T: IntoIterator<Item = (K, Vec<V>)>>(&mut self, iter: T) { + for (k, values) in iter { + match self.entry(k) { + Entry::Occupied(mut entry) => { + entry.get_vec_mut().extend(values); + } + Entry::Vacant(entry) => { + entry.insert_vec(values); + } + } + } + } +} + +impl<'a, K, V, S> Extend<(&'a K, &'a Vec<V>)> for MultiMap<K, V, S> +where + K: Eq + Hash + Copy, + V: Copy, + S: BuildHasher, +{ + fn extend<T: IntoIterator<Item = (&'a K, &'a Vec<V>)>>(&mut self, iter: T) { + self.extend( + iter.into_iter() + .map(|(&key, values)| (key, values.to_owned())), + ); + } +} + +#[derive(Clone)] +pub struct Iter<'a, K: 'a, V: 'a> { + inner: IterAll<'a, K, Vec<V>>, +} + +impl<'a, K, V> Iterator for Iter<'a, K, V> { + type Item = (&'a K, &'a V); + + fn next(&mut self) -> Option<(&'a K, &'a V)> { + let (k, v) = self.inner.next()?; + let v = v.first()?; + Some((k, v)) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + self.inner.size_hint() + } +} + +impl<K, V> ExactSizeIterator for Iter<'_, K, V> { + fn len(&self) -> usize { + self.inner.len() + } +} + +pub struct IterMut<'a, K: 'a, V: 'a> { + inner: IterAllMut<'a, K, Vec<V>>, +} + +impl<'a, K, V> Iterator for IterMut<'a, K, V> { + type Item = (&'a K, &'a mut V); + + fn next(&mut self) -> Option<(&'a K, &'a mut V)> { + let (k, v) = self.inner.next()?; + let v = v.first_mut()?; + Some((k, v)) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + self.inner.size_hint() + } +} + +impl<K, V> ExactSizeIterator for IterMut<'_, K, V> { + fn len(&self) -> usize { + self.inner.len() + } +} + +#[macro_export] +/// Create a `MultiMap` from a list of key value pairs +/// +/// ## Example +/// +/// ``` +/// # use multimap::MultiMap; +/// #[macro_use] extern crate multimap; +/// # fn main(){ +/// +/// let map = multimap!( +/// "dog" => "husky", +/// "dog" => "retreaver", +/// "dog" => "shiba inu", +/// "cat" => "cat" +/// ); +/// # } +/// +/// ``` +macro_rules! multimap{ + (@replace_with_unit $_t:tt) => { () }; + (@count $($key:expr),*) => { <[()]>::len(&[$($crate::multimap! { @replace_with_unit $key }),*]) }; + + ($($key:expr => $value:expr),* $(,)?)=>{ + { + let mut map = $crate::MultiMap::with_capacity($crate::multimap! { @count $($key),* }); + $( + map.insert($key,$value); + )* + map + } + } +} + +#[cfg(test)] +mod tests { + use std::collections::HashMap; + use std::iter::FromIterator; + + use super::*; + + #[test] + fn create() { + let _: MultiMap<usize, usize> = MultiMap { + inner: HashMap::new(), + }; + } + + #[test] + fn new() { + let _: MultiMap<usize, usize> = MultiMap::new(); + } + + #[test] + fn with_capacity() { + let _: MultiMap<usize, usize> = MultiMap::with_capacity(20); + } + + #[test] + fn insert() { + let mut m: MultiMap<usize, usize> = MultiMap::new(); + m.insert(1, 3); + } + + #[test] + fn insert_identical() { + let mut m = MultiMap::new(); + m.insert(1, 42); + m.insert(1, 42); + assert_eq!(m.get_vec(&1), Some(&vec![42, 42])); + } + + #[test] + fn insert_many() { + let mut m: MultiMap<usize, usize> = MultiMap::new(); + m.insert_many(1, vec![3, 4]); + assert_eq!(Some(&vec![3, 4]), m.get_vec(&1)); + } + + #[test] + fn insert_many_again() { + let mut m: MultiMap<usize, usize> = MultiMap::new(); + m.insert(1, 2); + m.insert_many(1, vec![3, 4]); + assert_eq!(Some(&vec![2, 3, 4]), m.get_vec(&1)); + } + + #[test] + fn insert_many_overlap() { + let mut m: MultiMap<usize, usize> = MultiMap::new(); + m.insert_many(1, vec![2, 3]); + m.insert_many(1, vec![3, 4]); + assert_eq!(Some(&vec![2, 3, 3, 4]), m.get_vec(&1)); + } + + #[test] + fn insert_many_from_slice() { + let mut m: MultiMap<usize, usize> = MultiMap::new(); + m.insert_many_from_slice(1, &[3, 4]); + assert_eq!(Some(&vec![3, 4]), m.get_vec(&1)); + } + + #[test] + fn insert_many_from_slice_again() { + let mut m: MultiMap<usize, usize> = MultiMap::new(); + m.insert(1, 2); + m.insert_many_from_slice(1, &[3, 4]); + assert_eq!(Some(&vec![2, 3, 4]), m.get_vec(&1)); + } + + #[test] + fn insert_existing() { + let mut m: MultiMap<usize, usize> = MultiMap::new(); + m.insert(1, 3); + m.insert(1, 4); + assert_eq!(Some(&vec![3, 4]), m.get_vec(&1)); + } + + #[test] + #[should_panic(expected = "no entry found for key")] + fn index_no_entry() { + let m: MultiMap<usize, usize> = MultiMap::new(); + let _ = &m[&1]; + } + + #[test] + fn index() { + let mut m: MultiMap<usize, usize> = MultiMap::new(); + m.insert(1, 41); + m.insert(2, 42); + m.insert(3, 43); + let values = m[&2]; + assert_eq!(values, 42); + } + + #[test] + #[should_panic(expected = "no value found for key")] + fn index_empty_vec() { + let mut m: MultiMap<usize, usize> = MultiMap::new(); + m.insert(1, 42); + m.get_vec_mut(&1).unwrap().clear(); + let values = m[&1]; + assert_eq!(values, 42); + } + + #[test] + fn contains_key_true() { + let mut m: MultiMap<usize, usize> = MultiMap::new(); + m.insert(1, 42); + assert!(m.contains_key(&1)); + } + + #[test] + fn contains_key_false() { + let m: MultiMap<usize, usize> = MultiMap::new(); + assert!(!m.contains_key(&1)); + } + + #[test] + fn len() { + let mut m: MultiMap<usize, usize> = MultiMap::new(); + m.insert(1, 42); + m.insert(2, 1337); + m.insert(3, 99); + assert_eq!(m.len(), 3); + } + + #[test] + fn remove_not_present() { + let mut m: MultiMap<usize, usize> = MultiMap::new(); + let v = m.remove(&1); + assert_eq!(v, None); + } + + #[test] + fn remove_present() { + let mut m: MultiMap<usize, usize> = MultiMap::new(); + m.insert(1, 42); + let v = m.remove(&1); + assert_eq!(v, Some(vec![42])); + } + + #[test] + fn get_not_present() { + let m: MultiMap<usize, usize> = MultiMap::new(); + assert_eq!(m.get(&1), None); + } + + #[test] + fn get_present() { + let mut m: MultiMap<usize, usize> = MultiMap::new(); + m.insert(1, 42); + assert_eq!(m.get(&1), Some(&42)); + } + + #[test] + fn get_empty() { + let mut m: MultiMap<usize, usize> = MultiMap::new(); + m.insert(1, 42); + m.get_vec_mut(&1).and_then(Vec::pop); + assert_eq!(m.get(&1), None); + } + + #[test] + fn get_vec_not_present() { + let m: MultiMap<usize, usize> = MultiMap::new(); + assert_eq!(m.get_vec(&1), None); + } + + #[test] + fn get_vec_present() { + let mut m: MultiMap<usize, usize> = MultiMap::new(); + m.insert(1, 42); + m.insert(1, 1337); + assert_eq!(m.get_vec(&1), Some(&vec![42, 1337])); + } + + #[test] + fn capacity() { + let m: MultiMap<usize, usize> = MultiMap::with_capacity(20); + assert!(m.capacity() >= 20); + } + + #[test] + fn is_empty_true() { + let m: MultiMap<usize, usize> = MultiMap::new(); + assert!(m.is_empty()); + } + + #[test] + fn is_empty_false() { + let mut m: MultiMap<usize, usize> = MultiMap::new(); + m.insert(1, 42); + assert!(!m.is_empty()); + } + + #[test] + fn clear() { + let mut m: MultiMap<usize, usize> = MultiMap::new(); + m.insert(1, 42); + m.clear(); + assert!(m.is_empty()); + } + + #[test] + fn get_mut() { + let mut m: MultiMap<usize, usize> = MultiMap::new(); + m.insert(1, 42); + if let Some(v) = m.get_mut(&1) { + *v = 1337; + } + assert_eq!(m[&1], 1337) + } + + #[test] + fn get_vec_mut() { + let mut m: MultiMap<usize, usize> = MultiMap::new(); + m.insert(1, 42); + m.insert(1, 1337); + if let Some(v) = m.get_vec_mut(&1) { + (*v)[0] = 5; + (*v)[1] = 10; + } + assert_eq!(m.get_vec(&1), Some(&vec![5, 10])) + } + + #[test] + fn get_mut_empty() { + let mut m: MultiMap<usize, usize> = MultiMap::new(); + m.insert(1, 42); + m.get_vec_mut(&1).and_then(Vec::pop); + assert_eq!(m.get_mut(&1), None); + } + + #[test] + fn keys() { + let mut m: MultiMap<usize, usize> = MultiMap::new(); + m.insert(1, 42); + m.insert(2, 42); + m.insert(4, 42); + m.insert(8, 42); + + let keys: Vec<_> = m.keys().cloned().collect(); + assert_eq!(keys.len(), 4); + assert!(keys.contains(&1)); + assert!(keys.contains(&2)); + assert!(keys.contains(&4)); + assert!(keys.contains(&8)); + } + + #[test] + fn iter() { + let mut m: MultiMap<usize, usize> = MultiMap::new(); + m.insert(1, 42); + m.insert(1, 42); + m.insert(4, 42); + m.insert(8, 42); + + assert!(m.iter().all(|(_, &v)| v == 42)); + + let mut iter = m.iter(); + + for _ in iter.by_ref().take(2) {} + + assert_eq!(iter.len(), 1); + } + + #[test] + fn iter_empty_vec() { + let mut m: MultiMap<usize, usize> = MultiMap::new(); + m.insert(42, 42); + m.get_vec_mut(&42).unwrap().clear(); + + assert!(m.iter().next().is_none()); + } + + #[test] + fn flat_iter() { + let mut m: MultiMap<usize, usize> = MultiMap::new(); + m.insert(1, 42); + m.insert(1, 43); + m.insert(4, 42); + m.insert(8, 42); + + let keys = [1, 4, 8]; + + for (key, value) in m.flat_iter() { + assert!(keys.contains(key)); + + if key == &1 { + assert!(value == &42 || value == &43); + } else { + assert_eq!(value, &42); + } + } + } + + #[test] + fn flat_iter_mut() { + let mut m: MultiMap<usize, usize> = MultiMap::new(); + m.insert(1, 42); + m.insert(1, 43); + m.insert(4, 42); + m.insert(8, 42); + + let keys = [1, 4, 8]; + + for (key, value) in m.flat_iter_mut() { + assert!(keys.contains(key)); + + if key == &1 { + assert!(value == &42 || value == &43); + + *value = 55; + assert_eq!(value, &55); + } else { + assert_eq!(value, &42); + + *value = 76; + assert_eq!(value, &76); + } + } + } + + #[test] + fn intoiterator_for_reference_type() { + let mut m: MultiMap<usize, usize> = MultiMap::new(); + m.insert(1, 42); + m.insert(1, 43); + m.insert(4, 42); + m.insert(8, 42); + + let keys = [1, 4, 8]; + + for (key, value) in &m { + assert!(keys.contains(key)); + + if key == &1 { + assert_eq!(value, &vec![42, 43]); + } else { + assert_eq!(value, &vec![42]); + } + } + } + + #[test] + fn intoiterator_for_mutable_reference_type() { + let mut m: MultiMap<usize, usize> = MultiMap::new(); + m.insert(1, 42); + m.insert(1, 43); + m.insert(4, 42); + m.insert(8, 42); + + let keys = [1, 4, 8]; + + for (key, value) in &mut m { + assert!(keys.contains(key)); + + if key == &1 { + assert_eq!(value, &vec![42, 43]); + value.push(666); + } else { + assert_eq!(value, &vec![42]); + } + } + + assert_eq!(m.get_vec(&1), Some(&vec![42, 43, 666])); + } + + #[test] + fn intoiterator_consuming() { + let mut m: MultiMap<usize, usize> = MultiMap::new(); + m.insert(1, 42); + m.insert(1, 43); + m.insert(4, 42); + m.insert(8, 42); + + let keys = [1, 4, 8]; + + for (key, value) in m { + assert!(keys.contains(&key)); + + if key == 1 { + assert_eq!(value, vec![42, 43]); + } else { + assert_eq!(value, vec![42]); + } + } + } + + #[test] + fn test_fmt_debug() { + let mut map = MultiMap::new(); + let empty: MultiMap<i32, i32> = MultiMap::new(); + + map.insert(1, 2); + map.insert(1, 5); + map.insert(1, -1); + map.insert(3, 4); + + let map_str = format!("{:?}", map); + + assert!(map_str == "{1: [2, 5, -1], 3: [4]}" || map_str == "{3: [4], 1: [2, 5, -1]}"); + assert_eq!(format!("{:?}", empty), "{}"); + } + + #[test] + fn test_eq() { + let mut m1 = MultiMap::new(); + m1.insert(1, 2); + m1.insert(2, 3); + m1.insert(3, 4); + let mut m2 = MultiMap::new(); + m2.insert(1, 2); + m2.insert(2, 3); + assert_ne!(m1, m2); + m2.insert(3, 4); + assert_eq!(m1, m2); + m2.insert(3, 4); + assert_ne!(m1, m2); + m1.insert(3, 4); + assert_eq!(m1, m2); + } + + #[test] + fn test_eq_empty_key() { + let mut m1 = MultiMap::new(); + m1.insert(1, 2); + m1.insert(2, 3); + let mut m2 = MultiMap::new(); + m2.insert(1, 2); + m2.insert_many(2, []); + assert_ne!(m1, m2); + m2.insert_many(2, [3]); + assert_eq!(m1, m2); + } + + #[test] + fn test_default() { + let _: MultiMap<u8, u8> = Default::default(); + } + + #[test] + fn test_from_iterator() { + let vals: Vec<(&str, i64)> = vec![("foo", 123), ("bar", 456), ("foo", 789)]; + let multimap: MultiMap<&str, i64> = MultiMap::from_iter(vals); + + let foo_vals: &Vec<i64> = multimap.get_vec("foo").unwrap(); + assert!(foo_vals.contains(&123)); + assert!(foo_vals.contains(&789)); + + let bar_vals: &Vec<i64> = multimap.get_vec("bar").unwrap(); + assert!(bar_vals.contains(&456)); + } + + #[test] + fn test_from_vec_iterator() { + let vals: Vec<(&str, Vec<i64>)> = vec![ + ("foo", vec![123, 456]), + ("bar", vec![234]), + ("foobar", vec![567, 678, 789]), + ("bar", vec![12, 23, 34]), + ]; + + let multimap: MultiMap<&str, i64> = MultiMap::from_iter(vals); + + let foo_vals: &Vec<i64> = multimap.get_vec("foo").unwrap(); + assert!(foo_vals.contains(&123)); + assert!(foo_vals.contains(&456)); + + let bar_vals: &Vec<i64> = multimap.get_vec("bar").unwrap(); + assert!(bar_vals.contains(&234)); + assert!(bar_vals.contains(&12)); + assert!(bar_vals.contains(&23)); + assert!(bar_vals.contains(&34)); + + let foobar_vals: &Vec<i64> = multimap.get_vec("foobar").unwrap(); + assert!(foobar_vals.contains(&567)); + assert!(foobar_vals.contains(&678)); + assert!(foobar_vals.contains(&789)); + } + + #[test] + fn test_extend_consuming_hashmap() { + let mut a = MultiMap::new(); + a.insert(1, 42); + + let mut b = HashMap::new(); + b.insert(1, 43); + b.insert(2, 666); + + a.extend(b); + + assert_eq!(a.len(), 2); + assert_eq!(a.get_vec(&1), Some(&vec![42, 43])); + } + + #[test] + fn test_extend_ref_hashmap() { + let mut a = MultiMap::new(); + a.insert(1, 42); + + let mut b = HashMap::new(); + b.insert(1, 43); + b.insert(2, 666); + + a.extend(&b); + + assert_eq!(a.len(), 2); + assert_eq!(a.get_vec(&1), Some(&vec![42, 43])); + assert_eq!(b.len(), 2); + assert_eq!(b[&1], 43); + } + + #[test] + fn test_extend_consuming_multimap() { + let mut a = MultiMap::new(); + a.insert(1, 42); + + let mut b = MultiMap::new(); + b.insert(1, 43); + b.insert(1, 44); + b.insert(2, 666); + + a.extend(b); + + assert_eq!(a.len(), 2); + assert_eq!(a.get_vec(&1), Some(&vec![42, 43, 44])); + } + + #[test] + fn test_extend_ref_multimap() { + let mut a = MultiMap::new(); + a.insert(1, 42); + + let mut b = MultiMap::new(); + b.insert(1, 43); + b.insert(1, 44); + b.insert(2, 666); + + a.extend(&b); + + assert_eq!(a.len(), 2); + assert_eq!(a.get_vec(&1), Some(&vec![42, 43, 44])); + assert_eq!(b.len(), 2); + assert_eq!(b.get_vec(&1), Some(&vec![43, 44])); + } + + #[test] + fn test_entry() { + let mut m = MultiMap::new(); + m.insert(1, 42); + + { + let v = m.entry(1).or_insert(43); + assert_eq!(v, &42); + *v = 44; + } + assert_eq!(m.entry(2).or_insert(666), &666); + + assert_eq!(m[&1], 44); + assert_eq!(m[&2], 666); + } + + #[test] + fn test_entry_vec() { + let mut m = MultiMap::new(); + m.insert(1, 42); + + { + let v = m.entry(1).or_insert_vec(vec![43]); + assert_eq!(v, &vec![42]); + *v.first_mut().unwrap() = 44; + } + assert_eq!(m.entry(2).or_insert_vec(vec![666]), &vec![666]); + + assert_eq!(m[&1], 44); + assert_eq!(m[&2], 666); + } + + #[test] + fn test_is_vec() { + let mut m = MultiMap::new(); + m.insert(1, 42); + m.insert(1, 1337); + m.insert(2, 2332); + + assert!(m.is_vec(&1)); + assert!(!m.is_vec(&2)); + assert!(!m.is_vec(&3)); + } + + #[test] + fn test_macro() { + let mut manual_map = MultiMap::new(); + manual_map.insert("key1", 42); + assert_eq!(manual_map, multimap!("key1" => 42)); + + manual_map.insert("key1", 1337); + manual_map.insert("key2", 2332); + let macro_map = multimap! { + "key1" => 42, + "key1" => 1337, + "key2" => 2332 + }; + assert_eq!(manual_map, macro_map); + } + + #[test] + fn retain_removes_element() { + let mut m = MultiMap::new(); + m.insert(1, 42); + m.insert(1, 99); + m.retain(|&k, &v| k == 1 && v == 42); + assert_eq!(1, m.len()); + assert_eq!(Some(&42), m.get(&1)); + } + + #[test] + fn retain_also_removes_empty_vector() { + let mut m = MultiMap::new(); + m.insert(1, 42); + m.insert(1, 99); + m.insert(2, 42); + m.retain(|&k, &v| k == 1 && v == 42); + assert_eq!(1, m.len()); + assert_eq!(Some(&42), m.get(&1)); + } +} diff --git a/vendor/multimap/src/serde.rs b/vendor/multimap/src/serde.rs new file mode 100644 index 00000000..51ccae66 --- /dev/null +++ b/vendor/multimap/src/serde.rs @@ -0,0 +1,149 @@ +// Copyright (c) 2016 multimap developers +// +// Licensed under the Apache License, Version 2.0 +// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0> or the MIT +// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your +// option. All files in the project carrying such notice may not be copied, +// modified, or distributed except according to those terms. + +//! Serde trait implementations for MultiMap + +extern crate serde; + +use std::fmt; +use std::hash::{BuildHasher, Hash}; +use std::marker::PhantomData; + +use self::serde::de::{MapAccess, Visitor}; +use self::serde::{Deserialize, Deserializer, Serialize, Serializer}; + +use MultiMap; + +impl<K, V, BS> Serialize for MultiMap<K, V, BS> +where + K: Serialize + Eq + Hash, + V: Serialize, + BS: BuildHasher, +{ + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + self.inner.serialize(serializer) + } +} + +impl<K, V, S> MultiMapVisitor<K, V, S> +where + K: Hash + Eq, +{ + fn new() -> Self { + MultiMapVisitor { + marker: PhantomData, + } + } +} + +struct MultiMapVisitor<K, V, S> { + marker: PhantomData<MultiMap<K, V, S>>, +} + +impl<'a, K, V, S> Visitor<'a> for MultiMapVisitor<K, V, S> +where + K: Deserialize<'a> + Eq + Hash, + V: Deserialize<'a>, + S: BuildHasher + Default, +{ + type Value = MultiMap<K, V, S>; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("expected a map") + } + + fn visit_map<M>(self, mut visitor: M) -> Result<Self::Value, M::Error> + where + M: MapAccess<'a>, + { + let mut values = + MultiMap::with_capacity_and_hasher(visitor.size_hint().unwrap_or(0), S::default()); + + while let Some((key, value)) = visitor.next_entry()? { + values.inner.insert(key, value); + } + + Ok(values) + } +} + +impl<'a, K, V, S> Deserialize<'a> for MultiMap<K, V, S> +where + K: Deserialize<'a> + Eq + Hash, + V: Deserialize<'a>, + S: BuildHasher + Default, +{ + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'a>, + { + deserializer.deserialize_map(MultiMapVisitor::<K, V, S>::new()) + } +} + +#[cfg(test)] +mod tests { + + extern crate serde_test; + + use self::serde_test::{assert_tokens, Token}; + + use super::*; + + #[test] + fn test_empty() { + let map = MultiMap::<char, u8>::new(); + + assert_tokens(&map, &[Token::Map { len: Some(0) }, Token::MapEnd]); + } + + #[test] + fn test_single() { + let mut map = MultiMap::<char, u8>::new(); + map.insert('x', 1); + + assert_tokens( + &map, + &[ + Token::Map { len: Some(1) }, + Token::Char('x'), + Token::Seq { len: Some(1) }, + Token::U8(1), + Token::SeqEnd, + Token::MapEnd, + ], + ); + } + + #[test] + fn test_multiple() { + let mut map = MultiMap::<char, u8>::new(); + map.insert('x', 1); + map.insert('x', 3); + map.insert('x', 1); + map.insert('x', 5); + + assert_tokens( + &map, + &[ + Token::Map { len: Some(1) }, + Token::Char('x'), + Token::Seq { len: Some(4) }, + Token::U8(1), + Token::U8(3), + Token::U8(1), + Token::U8(5), + Token::SeqEnd, + Token::MapEnd, + ], + ); + } +} |
