use std::collections::HashMap;
use uuid::Uuid;
#[derive(Debug)]
pub struct WorkingSet {
by_index: Vec<Option<Uuid>>,
by_uuid: HashMap<Uuid, usize>,
}
impl WorkingSet {
pub(crate) fn new(by_index: Vec<Option<Uuid>>) -> Self {
let mut by_uuid = HashMap::new();
assert!(by_index.is_empty() || by_index[0].is_none());
for (index, uuid) in by_index.iter().enumerate() {
if let Some(uuid) = uuid {
by_uuid.insert(*uuid, index);
}
}
Self { by_index, by_uuid }
}
pub fn len(&self) -> usize {
self.by_index.iter().filter(|e| e.is_some()).count()
}
pub fn largest_index(&self) -> usize {
self.by_index.len().saturating_sub(1)
}
pub fn is_empty(&self) -> bool {
self.by_index.iter().all(|e| e.is_none())
}
pub fn by_index(&self, index: usize) -> Option<Uuid> {
if let Some(Some(uuid)) = self.by_index.get(index) {
Some(*uuid)
} else {
None
}
}
pub fn by_uuid(&self, uuid: Uuid) -> Option<usize> {
self.by_uuid.get(&uuid).copied()
}
pub fn iter(&self) -> impl Iterator<Item = (usize, Uuid)> + '_ {
self.by_index
.iter()
.enumerate()
.filter_map(|(index, uuid)| uuid.as_ref().map(|uuid| (index, *uuid)))
}
}
#[cfg(test)]
mod test {
use super::*;
use pretty_assertions::assert_eq;
fn make() -> (Uuid, Uuid, WorkingSet) {
let uuid1 = Uuid::new_v4();
let uuid2 = Uuid::new_v4();
(
uuid1,
uuid2,
WorkingSet::new(vec![None, Some(uuid1), None, Some(uuid2), None]),
)
}
#[test]
fn test_new() {
let (_, uuid2, ws) = make();
assert_eq!(ws.by_index[3], Some(uuid2));
assert_eq!(ws.by_uuid.get(&uuid2), Some(&3));
}
#[test]
fn test_len_and_is_empty() {
let (_, _, ws) = make();
assert_eq!(ws.len(), 2);
assert_eq!(ws.is_empty(), false);
let ws = WorkingSet::new(vec![]);
assert_eq!(ws.len(), 0);
assert_eq!(ws.is_empty(), true);
let ws = WorkingSet::new(vec![None, None, None]);
assert_eq!(ws.len(), 0);
assert_eq!(ws.is_empty(), true);
}
#[test]
fn test_largest_index() {
let uuid1 = Uuid::new_v4();
let uuid2 = Uuid::new_v4();
let ws = WorkingSet::new(vec![]);
assert_eq!(ws.largest_index(), 0);
let ws = WorkingSet::new(vec![None, Some(uuid1)]);
assert_eq!(ws.largest_index(), 1);
let ws = WorkingSet::new(vec![None, Some(uuid1), None, Some(uuid2)]);
assert_eq!(ws.largest_index(), 3);
let ws = WorkingSet::new(vec![None, Some(uuid1), None, Some(uuid2), None]);
assert_eq!(ws.largest_index(), 4);
}
#[test]
fn test_by_index() {
let (uuid1, uuid2, ws) = make();
assert_eq!(ws.by_index(0), None);
assert_eq!(ws.by_index(1), Some(uuid1));
assert_eq!(ws.by_index(2), None);
assert_eq!(ws.by_index(3), Some(uuid2));
assert_eq!(ws.by_index(4), None);
assert_eq!(ws.by_index(100), None); }
#[test]
fn test_by_uuid() {
let (uuid1, uuid2, ws) = make();
let nosuch = Uuid::new_v4();
assert_eq!(ws.by_uuid(uuid1), Some(1));
assert_eq!(ws.by_uuid(uuid2), Some(3));
assert_eq!(ws.by_uuid(nosuch), None);
}
#[test]
fn test_iter() {
let (uuid1, uuid2, ws) = make();
assert_eq!(ws.iter().collect::<Vec<_>>(), vec![(1, uuid1), (3, uuid2),]);
}
}