1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//! A simple library that provides a way to obtain *some* value from various collections.
//!
//! [](https://gitlab.com/mexus/take-some-rs/commits/master)
//! [](https://crates.io/crates/take-some)
//! [](https://docs.rs/take-some)
//!
//! [[Release docs]](https://docs.rs/take-some/)
//!
//! [[Master docs]](https://mexus.gitlab.io/take-some-rs/take_some/)
//!
//! Sometimes one simply needs to "take" an element from a collection, no matter which element
//! will it be. If you are that one, please feel free to use the crate that aims to make your
//! (yes, yours!) life a tiny bit easier.
//!
//! Now let's see how it works.
//! Let's say you want to implement a hash map that is statically guaranteed by the rust's type
//! system to be non-empy at all the times.
//! The most straightforward way to do so is to declare it as a pair of an item and the rest of the
//! items, like `struct NonEmptyHashMap<K, V, S> (((K, V), ::std::collections::HashMap<K, V,S>))`.
//!
//! So far, so good. You will obviously want to create some nice user API for it, and that will
//! include an instantiation of you type with a normal `HashMap` from the standard library. And
//! here shines the `take-some` crate!
//!
//! ```rust
//! extern crate take_some;
//!
//! use std::collections::HashMap;
//! use std::hash::{BuildHasher, Hash};
//! use take_some::TakeSome;
//!
//! struct NonEmptyHashMap<K, V, S> {
//! first: (K, V),
//! rest: HashMap<K, V, S>,
//! }
//!
//! impl<K, V, S> NonEmptyHashMap<K, V, S>
//! where
//! K: Eq + Hash,
//! S: BuildHasher,
//! {
//! fn from_std_hashmap(mut map: HashMap<K, V, S>) -> Option<Self> {
//! map.take_some()
//! .map(|first| NonEmptyHashMap { first, rest: map })
//! }
//!
//! // An alternative implementation that takes advantage of the `TakeSome::split_at_some`
//! // method.
//! fn from_std_hashmap2(map: HashMap<K, V, S>) -> Option<Self> {
//! map.split_at_some()
//! .map(|(first, rest)| NonEmptyHashMap { first, rest })
//! .ok()
//! }
//! }
//!
//! fn main() {
//! let map: HashMap<String, String> = vec![
//! ("first".into(), "lol".into()),
//! ("second".into(), "lul".into()),
//! ].into_iter()
//! .collect();
//! let non_empty_map = NonEmptyHashMap::from_std_hashmap(map);
//! assert!(non_empty_map.is_some());
//!
//! let empty_map: HashMap<String, String> = HashMap::new();
//! let non_empty_map = NonEmptyHashMap::from_std_hashmap(empty_map);
//! // It is entirely impossible (hail to the type system!) to create an instance of the
//! // `NonEmptyHashMap` with an empty map!
//! assert!(non_empty_map.is_none());
//! }
//! ```
//!
//! And that's it! Yes, it is that simple.
//!
//! If you'd like to implement the trait for your custom collections, have a look at the source
//! code of the crate (`btree_map.rs`, `hash_set.rs`, `vec.rs` and so forth), or take a look at an
//! example in the `examples` directory where we implement the trait for a "foreign" type.
/// A helper trait that allows to take *some* value out of a collection, i.e. remove a single
/// element and return it, while preserving all others.