take-some 0.1.2

A simple library that provides a way to obtain *some* value from various collections
Documentation
extern crate indexmap;
extern crate take_some;

use indexmap::IndexMap;
use std::fmt;
use std::hash::{BuildHasher, Hash};
use std::ops::{Deref, DerefMut};
use take_some::TakeSome;

// Creating our own wrapper on top of the foreign type `IndexMap`.
struct IndexMapWrapper<K, V, S>(IndexMap<K, V, S>);

// Let's implement `Debug` so we can print out the map.
impl<K, V, S> fmt::Debug for IndexMapWrapper<K, V, S>
where
    K: fmt::Debug + Hash + Eq,
    V: fmt::Debug,
    S: BuildHasher,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self.0)
    }
}

// That's a very important trait that we definitely want to implement.
// For more details see https://doc.rust-lang.org/std/ops/trait.Deref.html
impl<K, V, S> Deref for IndexMapWrapper<K, V, S> {
    type Target = IndexMap<K, V, S>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

// Same story as with `Deref`: https://doc.rust-lang.org/std/ops/trait.DerefMut.html
impl<K, V, S> DerefMut for IndexMapWrapper<K, V, S> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

// An easy converter from an `IndexMap` to our own map.
impl<K, V, S> From<IndexMap<K, V, S>> for IndexMapWrapper<K, V, S> {
    fn from(origin: IndexMap<K, V, S>) -> Self {
        IndexMapWrapper(origin)
    }
}

// And finally, a guest of honour...
impl<K, V, S> TakeSome for IndexMapWrapper<K, V, S>
where
    K: Eq + Hash,
    S: BuildHasher,
{
    type Item = (K, V);

    fn take_some(&mut self) -> Option<Self::Item> {
        // Thank Providence the `IndexMap` provides such a convenient way to pop out an element
        // out of it :)
        self.0.pop()
    }
}

fn main() {
    let mut map: IndexMapWrapper<_, _, _> = IndexMap::new().into();
    // We can call method of `IndexMap` on `IndexMapWrapper` directly thanks to the `DerefMut`
    // trait.
    map.insert("Lol".to_string(), "wut".to_string());
    map.insert("Ahaha".into(), "....".into());
    println!("Originally we had: {:?}", map);

    // Okay, here comes the first test!
    let some_item = map.take_some();
    assert!(some_item.is_some());
    println!("Here's the `some` item: {:?}", some_item.unwrap());

    // And here works the `Deref` trait.
    assert_eq!(1, map.len());
    println!("The remainder: {:?}", map);
    // To see the output run `cargo run --example indexmap`.
}