use core::{fmt::Debug, ops::Range};
use crate::IntervalTree;
#[derive(Debug)]
pub enum Entry<'a, R, V>
where
R: Ord + Clone + Debug,
{
Vacant(VacantEntry<'a, R, V>),
Occupied(OccupiedEntry<'a, R, V>),
}
#[derive(Debug)]
pub struct VacantEntry<'a, R, V>
where
R: Ord + Clone + Debug,
{
key: Range<R>,
tree: &'a mut IntervalTree<R, V>,
}
#[derive(Debug)]
pub struct OccupiedEntry<'a, R, V>
where
R: Ord + Clone + Debug,
{
key: Range<R>,
tree: &'a mut IntervalTree<R, V>,
}
impl<'a, R, V> VacantEntry<'a, R, V>
where
R: Ord + Clone + Debug,
{
#[inline]
pub fn key(&self) -> &Range<R> {
&self.key
}
#[inline]
pub fn into_key(self) -> Range<R> {
self.key
}
#[inline]
pub fn insert(self, value: V) -> &'a mut V {
self.tree.insert(self.key.clone(), value);
self.tree.get_mut(&self.key).unwrap()
}
}
impl<'a, R, V> OccupiedEntry<'a, R, V>
where
R: Ord + Clone + Debug,
{
#[inline]
pub fn key(&self) -> &Range<R> {
&self.key
}
#[inline]
pub fn get(&self) -> &V {
self.tree.get(&self.key).unwrap()
}
#[inline]
pub fn get_mut(&mut self) -> &mut V {
self.tree.get_mut(&self.key).unwrap()
}
#[inline]
pub fn into_mut(self) -> &'a mut V {
self.tree.get_mut(&self.key).unwrap()
}
#[inline]
pub fn insert(&mut self, value: V) -> V {
self.tree.insert(self.key.clone(), value).unwrap()
}
#[inline]
pub fn remove(self) -> V {
self.tree.remove(&self.key).unwrap()
}
}
impl<'a, R, V> Entry<'a, R, V>
where
R: Ord + Clone + Debug,
{
pub(crate) fn new(key: Range<R>, tree: &'a mut IntervalTree<R, V>) -> Self {
if tree.contains_key(&key) {
Entry::Occupied(OccupiedEntry { key, tree })
} else {
Entry::Vacant(VacantEntry { key, tree })
}
}
#[inline]
pub fn key(&self) -> &Range<R> {
match self {
Entry::Vacant(entry) => entry.key(),
Entry::Occupied(entry) => entry.key(),
}
}
#[inline]
pub fn or_insert(self, default: V) -> &'a mut V {
match self {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => entry.insert(default),
}
}
#[inline]
pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
match self {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => entry.insert(default()),
}
}
#[inline]
pub fn or_insert_with_key<F: FnOnce(&Range<R>) -> V>(self, default: F) -> &'a mut V {
match self {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => {
let value = default(entry.key());
entry.insert(value)
}
}
}
#[inline]
pub fn and_modify<F: FnOnce(&mut V)>(mut self, f: F) -> Self {
match &mut self {
Entry::Occupied(entry) => {
f(entry.get_mut());
}
Entry::Vacant(_) => {}
}
self
}
#[inline]
pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, R, V> {
match self {
Entry::Occupied(mut entry) => {
entry.insert(value);
entry
}
Entry::Vacant(entry) => {
let key = entry.key.clone();
entry.tree.insert(key.clone(), value);
OccupiedEntry {
key,
tree: entry.tree,
}
}
}
}
}
impl<'a, R, V> Entry<'a, R, V>
where
R: Ord + Clone + Debug,
V: Default,
{
#[inline]
pub fn or_default(self) -> &'a mut V {
match self {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => entry.insert(V::default()),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::{
assert, assert_eq,
prelude::v1::{test, Default, None, Option, Some, String, ToString},
};
#[test]
fn test_entry_or_insert() {
let mut tree: IntervalTree<i32, i32> = IntervalTree::default();
tree.entry(0..10).or_insert(42);
assert_eq!(tree.get(&(0..10)), Some(&42));
tree.entry(0..10).or_insert(100);
assert_eq!(tree.get(&(0..10)), Some(&42));
}
#[test]
fn test_entry_or_insert_with() {
let mut tree: IntervalTree<i32, String> = IntervalTree::default();
tree.entry(0..10).or_insert_with(|| "hello".to_string());
assert_eq!(tree.get(&(0..10)), Some(&"hello".to_string()));
tree.entry(0..10).or_insert_with(|| "world".to_string());
assert_eq!(tree.get(&(0..10)), Some(&"hello".to_string()));
}
#[test]
fn test_entry_or_insert_with_key() {
let mut tree: IntervalTree<i32, i32> = IntervalTree::default();
tree.entry(0..10)
.or_insert_with_key(|key| key.start + key.end);
assert_eq!(tree.get(&(0..10)), Some(&10));
}
#[test]
fn test_entry_and_modify() {
let mut tree: IntervalTree<i32, u32> = IntervalTree::default();
tree.entry(0..10).and_modify(|v| *v += 1).or_insert(42);
assert_eq!(tree.get(&(0..10)), Some(&42));
tree.entry(0..10).and_modify(|v| *v += 1).or_insert(100);
assert_eq!(tree.get(&(0..10)), Some(&43));
}
#[test]
fn test_entry_insert_entry() {
let mut tree: IntervalTree<i32, &str> = IntervalTree::default();
let entry = tree.entry(0..10).insert_entry("hello");
assert_eq!(entry.key(), &(0..10));
assert_eq!(entry.get(), &"hello");
let entry = tree.entry(0..10).insert_entry("world");
assert_eq!(entry.key(), &(0..10));
assert_eq!(entry.get(), &"world");
}
#[test]
fn test_entry_or_default() {
let mut tree: IntervalTree<i32, Option<u32>> = IntervalTree::default();
tree.entry(0..10).or_default();
assert_eq!(tree.get(&(0..10)), Some(&None));
}
#[test]
fn test_entry_key() {
let mut tree: IntervalTree<i32, i32> = IntervalTree::default();
let entry = tree.entry(0..10);
assert_eq!(entry.key(), &(0..10));
}
#[test]
fn test_vacant_entry_into_key() {
let mut tree: IntervalTree<i32, i32> = IntervalTree::default();
let entry = tree.entry(0..10);
match entry {
Entry::Vacant(vacant) => {
let key = vacant.into_key();
assert_eq!(key, 0..10);
}
Entry::Occupied(_) => panic!("Expected vacant entry"),
}
}
#[test]
fn test_occupied_entry_remove() {
let mut tree: IntervalTree<i32, i32> = IntervalTree::default();
tree.insert(0..10, 42);
let entry = tree.entry(0..10);
match entry {
Entry::Occupied(occupied) => {
let value = occupied.remove();
assert_eq!(value, 42);
}
Entry::Vacant(_) => panic!("Expected occupied entry"),
}
assert!(!tree.contains_key(&(0..10)));
}
#[test]
fn test_occupied_entry_insert() {
let mut tree: IntervalTree<i32, i32> = IntervalTree::default();
tree.insert(0..10, 42);
let entry = tree.entry(0..10);
match entry {
Entry::Occupied(mut occupied) => {
let old = occupied.insert(100);
assert_eq!(old, 42);
assert_eq!(occupied.get(), &100);
}
Entry::Vacant(_) => panic!("Expected occupied entry"),
}
}
}