# take-some
A simple library that provides a way to obtain *some* value from various collections.
[![pipeline status](https://gitlab.com/mexus/take-some-rs/badges/master/pipeline.svg)](https://gitlab.com/mexus/take-some-rs/commits/master)
[![crates.io](https://img.shields.io/crates/v/take-some.svg)](https://crates.io/crates/take-some)
[![docs.rs](https://docs.rs/take-some/badge.svg)](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.
License: MIT/Apache-2.0