idmap 0.2.21

Efficient maps of integer id keys to values, backed by an underlying `Vec`
Documentation
#[macro_use]
extern crate idmap;
#[macro_use]
extern crate idmap_derive;
#[allow(unused_extern_crates)]
extern crate serde;
extern crate serde_test;
#[macro_use]
extern crate serde_derive;

use serde_test::{Token, assert_tokens};

use idmap::IdMap;
use KnownState::*;

#[test]
fn test_remove() {
    let mut m = important_cities();
    assert_eq!(m.remove(NewMexico), None);
    for state in IMPORTANT_STATES {
        assert_eq!(Some(state.city()), m.remove(state), "{:#?}", m.raw_debug());
    }
    assert_eq!(m.len(), 0);
    assert_eq!(m.remove(NewMexico), None);
    assert_eq!(m.remove(NorthDakota), None);
}

#[test]
fn test_eq() {
    let first = important_cities();
    let second = important_cities().into_iter().rev().collect::<IdMap<_, _>>();

    assert_eq!(first, second);
}

#[test]
fn test_from_iter() {
    let xs = [(California, "San Diego"), (NewYork, "New York"), (Arizona, "Phoenix")];

    let map: IdMap<_, _> = xs.iter().cloned().collect();

    for &(k, v) in &xs {
        assert_eq!(map.get(k), Some(&v));
    }
    check_missing(TINY_STATES, &map);
}

#[test]
fn test_index() {
    let map = important_cities();

    for state in IMPORTANT_STATES {
        assert_eq!(map[state], state.city());
    }
}

#[test]
fn test_clone() {
    let original = important_cities();
    let cloned = original.clone();
    assert_eq!(original, cloned);
}

#[test]
fn test_insertion_order() {
    let entries = IMPORTANT_STATES.iter()
        .map(|state| (*state, state.city()))
        .collect::<Vec<_>>();
    let reversed_entries = entries.iter().rev().cloned().collect::<Vec<_>>();
    let map = entries.iter()
        .cloned()
        .collect::<IdMap<KnownState, &'static str>>();
    let actual_entries = map.iter()
        .map(|(&state, &city)| (state, city))
        .collect::<Vec<_>>();
    assert_eq!(actual_entries, entries);
    let reversed_map = reversed_entries.iter()
        .cloned()
        .collect::<IdMap<KnownState, &'static str>>();
    let actually_reversed = reversed_map.iter()
        .map(|(&state, &city)| (state, city))
        .collect::<Vec<_>>();
    assert_eq!(actually_reversed, reversed_entries);
}

#[test]
#[should_panic]
#[cfg_attr(feature = "cargo-clippy", allow(no_effect))] // It's supposed to panic
fn test_index_nonexistent() {
    let map = important_cities();

    map[NorthDakota];
}

#[test]
fn test_entry_insert() {
    let mut map = important_cities();

    for &state in ALL_STATES {
        let value = *map.entry(state).or_insert_with(|| state.city());
        assert_eq!(value, state.city());
    }
    check_cities(ALL_STATES, &map);
}

#[test]
fn test_extend_ref() {
    let important = important_cities();
    let mut all = IdMap::new();
    all.insert(NewMexico, "Albuquerque");
    all.insert(California, "Cake");
    all.insert(NorthDakota, "Fargo");

    all.extend(&important);

    assert_eq!(all.len(), 5);
    // Updates must preserve order
    assert_eq!(all.iter().nth(1).unwrap(), (&California, &California.city()));
    // Order of original, unchanged values must be preserved
    assert_eq!(all.iter().nth(2).unwrap(), (&NorthDakota, &"Fargo"));
    check_cities(ALL_STATES, &all);
}

#[test]
fn test_retain() {
    let mut map = important_cities();
    map.retain(|&state, _| match state {
        NewYork => false, // New york city is too big!
        California | Arizona => true,
        _ => unreachable!(),
    });
    assert_eq!(map.len(), 2);
    check_cities(&[Arizona, California], &map);
    check_missing(TINY_STATES, &map);
}


/// List the biggest cities in each state except for `NewMexico` and `NorthDakota`,
/// intentionally excluding them to provide a better test case.
fn important_cities() -> IdMap<KnownState, &'static str> {
    // NOTE: Intentionally out of declared order to try and mess things up
    idmap! {
        Arizona => "Phoenix",
        NewYork => "New York City",
        California => "Los Angeles"
    }
}

#[derive(IntegerId, Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
enum KnownState {
    Arizona,
    California,
    NewMexico,
    NewYork,
    NorthDakota
}
fn check_missing(states: &[KnownState], target: &IdMap<KnownState, &'static str>) {
    for state in states {
        state.check_missing(target);
    }
}
fn check_cities(states: &[KnownState], target: &IdMap<KnownState, &'static str>) {
    for state in states {
        state.check_city(target);
    }
}
static ALL_STATES: &[KnownState] = &[Arizona, California, NewMexico, NewYork, NorthDakota];
// NOTE: Intentionally out of declared order to try and mess things up

static IMPORTANT_STATES: &[KnownState] = &[Arizona, NewYork, California];
static TINY_STATES: &[KnownState] = &[NorthDakota, NewMexico];
impl KnownState {
    fn city(&self) -> &'static str {
        match *self {
            Arizona => "Phoenix",
            California => "Los Angeles",
            NewMexico => "Albuquerque",
            NewYork => "New York City",
            NorthDakota => "Fargo"
        }
    }
    fn check_missing(self, target: &IdMap<KnownState, &'static str>) {
        assert_eq!(target.get(self), None, "Expected no city for {:?}", self);
    }
    fn check_city(self, target: &IdMap<KnownState, &'static str>) {
        assert_eq!(target.get(self), Some(&self.city()), "Unexpected city for {:?}", self);
    }
}

#[test]
fn test_wrapper() {
    let data = idmap! {
        ExampleWrapper(32) => "abc",
        ExampleWrapper(42) => "life",
    };
    assert_eq!(data[ExampleWrapper(32)], "abc");
    assert_eq!(data[ExampleWrapper(42)], "life");
    assert_eq!(data.get(ExampleWrapper(76)), None)
}

#[test]
fn test_struct_wrapper() {
    let data = idmap! {
        ExampleStructWrapper::new(32) => "abc",
        ExampleStructWrapper::new(42) => "life"
    };
    assert_eq!(data[ExampleStructWrapper::new(32)], "abc");
    assert_eq!(data[ExampleStructWrapper::new(42)], "life");
    assert_eq!(data.get(ExampleStructWrapper::new(76)), None)
}

#[derive(IntegerId, Debug, PartialEq)]
struct ExampleWrapper(u16);
#[derive(IntegerId, Debug, PartialEq)]
struct ExampleStructWrapper {
    value: u16
}
impl ExampleStructWrapper {
    #[inline]
    fn new(value: u16) -> Self {
        ExampleStructWrapper { value }
    }
}

#[test]
fn test_serde() {
    macro_rules! state_tokens {
        ($len:expr, $($state:expr => $city:expr),*) => (&[
            Token::Map { len: Some($len) },
            $(
                Token::Enum { name: "KnownState" },
                Token::Str(stringify!($state)),
                Token::Unit,
                Token::BorrowedStr($city),
            )*
            Token::MapEnd
        ]);
    }
    const EXPECTED_TOKENS: &[Token] = state_tokens!(3,
        Arizona => "Phoenix",
        NewYork => "New York City",
        California => "Los Angeles"
    );
    assert_tokens(&important_cities(), EXPECTED_TOKENS);
}