Files
fomo-reducer/src/one_to_many_with_data.rs
2026-03-20 15:10:28 -04:00

72 lines
2.1 KiB
Rust

use std::collections::BTreeMap;
#[derive(Debug, Clone)]
pub struct OneToManyUniqueBTreeMapWithData<Left, Right, RightData> {
left_to_rights: BTreeMap<Left, BTreeMap<Right, RightData>>,
right_to_left: BTreeMap<Right, Left>,
}
impl<Left, Right, RightData> Default for OneToManyUniqueBTreeMapWithData<Left, Right, RightData> {
fn default() -> Self {
Self {
left_to_rights: Default::default(),
right_to_left: Default::default(),
}
}
}
impl<Left, Right, RightData> OneToManyUniqueBTreeMapWithData<Left, Right, RightData>
where
Left: Ord + Clone,
Right: Ord + Clone,
{
/// Clones `left` and `right` so make sure it's cheap to do so
/// Returns whatever `Left` that `right` was already pointing to
pub fn insert(
&mut self,
left: Left,
right: Right,
right_data: RightData,
) -> Option<(Left, Right, RightData)> {
let old = self.remove_right(&right);
self.left_to_rights
.entry(left.clone())
.or_default()
.insert(right.clone(), right_data);
self.right_to_left.insert(right, left);
old
}
pub fn get_rights_for(&self, left: &Left) -> Option<&BTreeMap<Right, RightData>> {
self.left_to_rights.get(left)
}
pub fn get_left_for(&self, right: &Right) -> Option<&Left> {
self.right_to_left.get(right)
}
pub fn remove_left(&mut self, left: &Left) -> Option<(Left, BTreeMap<Right, RightData>)> {
let (left, rights) = self.left_to_rights.remove_entry(left)?;
for (right, _right_data) in &rights {
self.right_to_left.remove(right);
}
Some((left, rights))
}
pub fn remove_right(&mut self, right: &Right) -> Option<(Left, Right, RightData)> {
let left = self.right_to_left.remove(right)?;
let rights = self.left_to_rights.get_mut(&left)?;
let (right, right_data) = rights.remove_entry(right)?;
if rights.is_empty() {
self.left_to_rights.remove(&left);
}
Some((left, right, right_data))
}
}