use std::collections::BTreeMap;
use crate::{Point, PointKey};
#[derive(Clone, Debug, Default)]
pub(super) struct ForcedEyes {
pub(super) by_point: BTreeMap<PointKey, Point>,
}
impl ForcedEyes {
pub(super) const fn new() -> Self {
Self {
by_point: BTreeMap::new(),
}
}
pub(super) fn insert(&mut self, point: Point) {
self.by_point.insert(point.key(), point);
}
pub(super) fn take(&mut self, point: Point) -> Option<Point> {
self.by_point.remove(&point.key())
}
pub(super) fn contains(&self, point: Point) -> bool {
self.by_point.contains_key(&point.key())
}
pub(super) fn iter(&self) -> impl Iterator<Item = Point> + '_ {
self.by_point.values().copied()
}
pub(super) fn entries(&self) -> impl Iterator<Item = (PointKey, Point)> + '_ {
self.by_point.iter().map(|(key, point)| (*key, *point))
}
pub(super) fn len(&self) -> usize {
self.by_point.len()
}
}
#[cfg(test)]
mod tests {
#![allow(clippy::unwrap_used, clippy::expect_used)]
use super::ForcedEyes;
use crate::Point;
fn p(x: f64, y: f64) -> Point {
Point::new(x, y)
}
#[test]
fn an_eye_is_found_only_at_its_exact_point() {
let mut eyes = ForcedEyes::new();
eyes.insert(p(10.0, 10.0));
assert!(eyes.contains(p(10.0, 10.0)));
let one_bit_up = f64::from_bits(10.0_f64.to_bits() + 1);
assert!(!eyes.contains(p(10.0, one_bit_up)));
}
#[test]
fn the_two_zeroes_are_one_eye() {
let mut eyes = ForcedEyes::new();
eyes.insert(p(-0.0, 0.0));
assert!(eyes.contains(p(0.0, -0.0)));
assert_eq!(eyes.len(), 1);
}
#[test]
fn inserting_the_same_eye_twice_keeps_one() {
let mut eyes = ForcedEyes::new();
eyes.insert(p(4.0, 4.0));
eyes.insert(p(4.0, 4.0));
assert_eq!(eyes.len(), 1);
}
#[test]
fn taking_answers_the_stored_point_and_empties_the_slot() {
let mut eyes = ForcedEyes::new();
eyes.insert(p(4.0, 4.0));
assert_eq!(eyes.take(p(4.0, 4.0)), Some(p(4.0, 4.0)));
assert_eq!(eyes.take(p(4.0, 4.0)), None);
assert_eq!(eyes.len(), 0);
}
#[test]
fn iteration_is_by_key_not_by_insertion() {
let mut eyes = ForcedEyes::new();
for point in [p(9.0, 1.0), p(1.0, 9.0), p(5.0, 5.0)] {
eyes.insert(point);
}
let walked: Vec<Point> = eyes.iter().collect();
let mut sorted = walked.clone();
sorted.sort_by_key(|point| point.key());
assert_eq!(walked, sorted);
}
}