use serde::{Deserialize, Serialize};
use std::{
collections::HashMap,
fmt,
hash::Hash,
iter::FusedIterator,
mem::take,
ops::{Deref, DerefMut},
sync::Arc,
};
use tokio::sync::{RwLock, RwLockReadGuard, oneshot, watch};
use tracing::Instrument;
use super::{ChangeNotifier, ChangeSender, RecvError, SendError, default_on_err, send_event};
use crate::{exec, prelude::*};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum HashMapEvent<K, V> {
Set(K, V),
Remove(K),
Clear,
ShrinkToFit,
Done,
#[serde(skip)]
InitialComplete,
}
pub struct ObservableHashMap<K, V, Codec = crate::codec::Default> {
hm: HashMap<K, V>,
tx: rch::broadcast::Sender<HashMapEvent<K, V>, Codec>,
change: ChangeSender,
on_err: Arc<dyn Fn(SendError) + Send + Sync>,
done: bool,
}
impl<K, V, Codec> fmt::Debug for ObservableHashMap<K, V, Codec>
where
K: fmt::Debug,
V: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.hm.fmt(f)
}
}
impl<K, V, Codec> From<HashMap<K, V>> for ObservableHashMap<K, V, Codec>
where
K: Clone + RemoteSend,
V: Clone + RemoteSend,
Codec: crate::codec::Codec,
{
fn from(hm: HashMap<K, V>) -> Self {
let (tx, _rx) = rch::broadcast::channel::<_, _, { rch::DEFAULT_BUFFER }>(1);
Self { hm, tx, on_err: Arc::new(default_on_err), change: ChangeSender::new(), done: false }
}
}
impl<K, V, Codec> From<ObservableHashMap<K, V, Codec>> for HashMap<K, V> {
fn from(ohm: ObservableHashMap<K, V, Codec>) -> Self {
ohm.hm
}
}
impl<K, V, Codec> Default for ObservableHashMap<K, V, Codec>
where
K: Clone + RemoteSend,
V: Clone + RemoteSend,
Codec: crate::codec::Codec,
{
fn default() -> Self {
Self::from(HashMap::new())
}
}
impl<K, V, Codec> ObservableHashMap<K, V, Codec>
where
K: Eq + Hash + Clone + RemoteSend,
V: Clone + RemoteSend,
Codec: crate::codec::Codec,
{
pub fn new() -> Self {
Self::default()
}
pub fn set_error_handler<E>(&mut self, on_err: E)
where
E: Fn(SendError) + Send + Sync + 'static,
{
self.on_err = Arc::new(on_err);
}
pub fn subscribe(&self, buffer: usize) -> HashMapSubscription<K, V, Codec> {
HashMapSubscription::new(
HashMapInitialValue::new_value(self.hm.clone()),
if self.done { None } else { Some(self.tx.subscribe(buffer)) },
)
}
pub fn subscribe_incremental(&self, buffer: usize) -> HashMapSubscription<K, V, Codec> {
HashMapSubscription::new(
HashMapInitialValue::new_incremental(self.hm.clone(), self.on_err.clone()),
if self.done { None } else { Some(self.tx.subscribe(buffer)) },
)
}
pub fn subscriber_count(&self) -> usize {
self.tx.receiver_count()
}
pub fn notifier(&self) -> ChangeNotifier {
self.change.subscribe()
}
pub fn insert(&mut self, k: K, v: V) -> Option<V> {
self.assert_not_done();
self.change.notify();
send_event(&self.tx, &*self.on_err, HashMapEvent::Set(k.clone(), v.clone()));
self.hm.insert(k, v)
}
pub fn remove<Q>(&mut self, k: &Q) -> Option<V>
where
K: std::borrow::Borrow<Q>,
Q: Hash + Eq,
{
self.assert_not_done();
match self.hm.remove_entry(k) {
Some((k, v)) => {
self.change.notify();
send_event(&self.tx, &*self.on_err, HashMapEvent::Remove(k));
Some(v)
}
None => None,
}
}
pub fn clear(&mut self) {
self.assert_not_done();
if !self.hm.is_empty() {
self.hm.clear();
self.change.notify();
send_event(&self.tx, &*self.on_err, HashMapEvent::Clear);
}
}
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(&K, &mut V) -> bool,
{
self.assert_not_done();
self.hm.retain(|k, v| {
if f(k, v) {
true
} else {
self.change.notify();
send_event(&self.tx, &*self.on_err, HashMapEvent::Remove(k.clone()));
false
}
});
}
pub fn entry(&mut self, key: K) -> Entry<'_, K, V, Codec> {
self.assert_not_done();
match self.hm.entry(key) {
std::collections::hash_map::Entry::Occupied(inner) => Entry::Occupied(OccupiedEntry {
inner,
tx: &self.tx,
change: &self.change,
on_err: &*self.on_err,
}),
std::collections::hash_map::Entry::Vacant(inner) => {
Entry::Vacant(VacantEntry { inner, tx: &self.tx, change: &self.change, on_err: &*self.on_err })
}
}
}
pub fn get_mut<Q>(&mut self, k: &Q) -> Option<RefMut<'_, K, V, Codec>>
where
K: std::borrow::Borrow<Q>,
Q: Hash + Eq,
{
self.assert_not_done();
match self.hm.get_key_value(k) {
Some((key, _)) => {
let key = key.clone();
let value = self.hm.get_mut(k).unwrap();
Some(RefMut {
key,
value,
changed: false,
tx: &self.tx,
change: &self.change,
on_err: &*self.on_err,
})
}
None => None,
}
}
pub fn iter_mut(&mut self) -> IterMut<'_, K, V, Codec> {
self.assert_not_done();
IterMut { inner: self.hm.iter_mut(), tx: &self.tx, change: &self.change, on_err: &*self.on_err }
}
pub fn shrink_to_fit(&mut self) {
self.assert_not_done();
send_event(&self.tx, &*self.on_err, HashMapEvent::ShrinkToFit);
self.hm.shrink_to_fit()
}
fn assert_not_done(&self) {
if self.done {
panic!("observable hash map cannot be changed after done has been called");
}
}
pub fn done(&mut self) {
if !self.done {
send_event(&self.tx, &*self.on_err, HashMapEvent::Done);
self.done = true;
}
}
pub fn is_done(&self) -> bool {
self.done
}
pub fn into_inner(self) -> HashMap<K, V> {
self.into()
}
}
impl<K, V, Codec> Deref for ObservableHashMap<K, V, Codec> {
type Target = HashMap<K, V>;
fn deref(&self) -> &Self::Target {
&self.hm
}
}
impl<K, V, Codec> Extend<(K, V)> for ObservableHashMap<K, V, Codec>
where
K: Eq + Hash + Clone + RemoteSend,
V: Clone + RemoteSend,
Codec: crate::codec::Codec,
{
fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I) {
for (k, v) in iter {
self.insert(k, v);
}
}
}
pub struct RefMut<'a, K, V, Codec>
where
K: Clone + RemoteSend,
V: Clone + RemoteSend,
Codec: crate::codec::Codec,
{
key: K,
value: &'a mut V,
changed: bool,
tx: &'a rch::broadcast::Sender<HashMapEvent<K, V>, Codec>,
change: &'a ChangeSender,
on_err: &'a dyn Fn(SendError),
}
impl<K, V, Codec> Deref for RefMut<'_, K, V, Codec>
where
K: Clone + RemoteSend,
V: Clone + RemoteSend,
Codec: crate::codec::Codec,
{
type Target = V;
fn deref(&self) -> &Self::Target {
self.value
}
}
impl<K, V, Codec> DerefMut for RefMut<'_, K, V, Codec>
where
K: Clone + RemoteSend,
V: Clone + RemoteSend,
Codec: crate::codec::Codec,
{
fn deref_mut(&mut self) -> &mut Self::Target {
self.changed = true;
self.value
}
}
impl<K, V, Codec> Drop for RefMut<'_, K, V, Codec>
where
K: Clone + RemoteSend,
V: Clone + RemoteSend,
Codec: crate::codec::Codec,
{
fn drop(&mut self) {
if self.changed {
self.change.notify();
send_event(self.tx, self.on_err, HashMapEvent::Set(self.key.clone(), self.value.clone()));
}
}
}
pub struct IterMut<'a, K, V, Codec = crate::codec::Default> {
inner: std::collections::hash_map::IterMut<'a, K, V>,
tx: &'a rch::broadcast::Sender<HashMapEvent<K, V>, Codec>,
change: &'a ChangeSender,
on_err: &'a dyn Fn(SendError),
}
impl<'a, K, V, Codec> Iterator for IterMut<'a, K, V, Codec>
where
K: Clone + RemoteSend,
V: Clone + RemoteSend,
Codec: crate::codec::Codec,
{
type Item = RefMut<'a, K, V, Codec>;
fn next(&mut self) -> Option<Self::Item> {
match self.inner.next() {
Some((key, value)) => Some(RefMut {
key: key.clone(),
value,
changed: false,
tx: self.tx,
change: self.change,
on_err: self.on_err,
}),
None => None,
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<K, V, Codec> ExactSizeIterator for IterMut<'_, K, V, Codec>
where
K: Clone + RemoteSend,
V: Clone + RemoteSend,
Codec: crate::codec::Codec,
{
fn len(&self) -> usize {
self.inner.len()
}
}
impl<K, V, Codec> FusedIterator for IterMut<'_, K, V, Codec>
where
K: Clone + RemoteSend,
V: Clone + RemoteSend,
Codec: crate::codec::Codec,
{
}
#[derive(Debug)]
pub enum Entry<'a, K, V, Codec = crate::codec::Default> {
Occupied(OccupiedEntry<'a, K, V, Codec>),
Vacant(VacantEntry<'a, K, V, Codec>),
}
impl<'a, K, V, Codec> Entry<'a, K, V, Codec>
where
K: Clone + RemoteSend,
V: Clone + RemoteSend,
Codec: crate::codec::Codec,
{
pub fn or_insert(self, default: V) -> RefMut<'a, K, V, Codec> {
match self {
Self::Occupied(ocu) => ocu.into_mut(),
Self::Vacant(vac) => vac.insert(default),
}
}
pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> RefMut<'a, K, V, Codec> {
match self {
Self::Occupied(ocu) => ocu.into_mut(),
Self::Vacant(vac) => vac.insert(default()),
}
}
pub fn or_insert_with_key<F: FnOnce(&K) -> V>(self, default: F) -> RefMut<'a, K, V, Codec> {
match self {
Self::Occupied(ocu) => ocu.into_mut(),
Self::Vacant(vac) => {
let value = default(vac.key());
vac.insert(value)
}
}
}
pub fn key(&self) -> &K {
match self {
Self::Occupied(ocu) => ocu.key(),
Self::Vacant(vac) => vac.key(),
}
}
pub fn and_modify<F: FnOnce(&mut V)>(mut self, f: F) -> Self {
if let Self::Occupied(ocu) = &mut self {
let mut value = ocu.get_mut();
f(&mut *value);
}
self
}
}
impl<'a, K, V, Codec> Entry<'a, K, V, Codec>
where
K: Clone + RemoteSend,
V: Clone + RemoteSend + Default,
Codec: crate::codec::Codec,
{
pub fn or_default(self) -> RefMut<'a, K, V, Codec> {
#[allow(clippy::unwrap_or_default)]
self.or_insert_with(V::default)
}
}
pub struct OccupiedEntry<'a, K, V, Codec = crate::codec::Default> {
inner: std::collections::hash_map::OccupiedEntry<'a, K, V>,
tx: &'a rch::broadcast::Sender<HashMapEvent<K, V>, Codec>,
change: &'a ChangeSender,
on_err: &'a dyn Fn(SendError),
}
impl<K, V, Codec> fmt::Debug for OccupiedEntry<'_, K, V, Codec>
where
K: fmt::Debug,
V: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.inner.fmt(f)
}
}
impl<'a, K, V, Codec> OccupiedEntry<'a, K, V, Codec>
where
K: Clone + RemoteSend,
V: Clone + RemoteSend,
Codec: crate::codec::Codec,
{
pub fn key(&self) -> &K {
self.inner.key()
}
pub fn remove_entry(self) -> (K, V) {
let (k, v) = self.inner.remove_entry();
self.change.notify();
send_event(self.tx, self.on_err, HashMapEvent::Remove(k.clone()));
(k, v)
}
pub fn get(&self) -> &V {
self.inner.get()
}
pub fn get_mut(&mut self) -> RefMut<'_, K, V, Codec> {
RefMut {
key: self.inner.key().clone(),
value: self.inner.get_mut(),
changed: false,
tx: self.tx,
change: self.change,
on_err: self.on_err,
}
}
pub fn into_mut(self) -> RefMut<'a, K, V, Codec> {
let key = self.inner.key().clone();
RefMut {
key,
value: self.inner.into_mut(),
changed: false,
tx: self.tx,
change: self.change,
on_err: self.on_err,
}
}
pub fn insert(&mut self, value: V) -> V {
self.change.notify();
send_event(self.tx, self.on_err, HashMapEvent::Set(self.inner.key().clone(), value.clone()));
self.inner.insert(value)
}
pub fn remove(self) -> V {
let (k, v) = self.inner.remove_entry();
self.change.notify();
send_event(self.tx, self.on_err, HashMapEvent::Remove(k));
v
}
}
pub struct VacantEntry<'a, K, V, Codec = crate::codec::Default> {
inner: std::collections::hash_map::VacantEntry<'a, K, V>,
tx: &'a rch::broadcast::Sender<HashMapEvent<K, V>, Codec>,
change: &'a ChangeSender,
on_err: &'a dyn Fn(SendError),
}
impl<K, V, Codec> fmt::Debug for VacantEntry<'_, K, V, Codec>
where
K: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.inner.fmt(f)
}
}
impl<'a, K, V, Codec> VacantEntry<'a, K, V, Codec>
where
K: Clone + RemoteSend,
V: Clone + RemoteSend,
Codec: crate::codec::Codec,
{
pub fn key(&self) -> &K {
self.inner.key()
}
pub fn into_key(self) -> K {
self.inner.into_key()
}
pub fn insert(self, value: V) -> RefMut<'a, K, V, Codec> {
let key = self.inner.key().clone();
self.change.notify();
send_event(self.tx, self.on_err, HashMapEvent::Set(key.clone(), value.clone()));
let value = self.inner.insert(value);
RefMut { key, value, changed: false, tx: self.tx, change: self.change, on_err: self.on_err }
}
}
struct MirroredHashMapInner<K, V> {
hm: HashMap<K, V>,
complete: bool,
done: bool,
error: Option<RecvError>,
max_size: usize,
}
impl<K, V> MirroredHashMapInner<K, V>
where
K: Eq + Hash,
{
fn handle_event(&mut self, event: HashMapEvent<K, V>) -> Result<(), RecvError> {
match event {
HashMapEvent::InitialComplete => {
self.complete = true;
}
HashMapEvent::Set(k, v) => {
self.hm.insert(k, v);
if self.hm.len() > self.max_size {
return Err(RecvError::MaxSizeExceeded(self.max_size));
}
}
HashMapEvent::Remove(k) => {
self.hm.remove(&k);
}
HashMapEvent::Clear => {
self.hm.clear();
}
HashMapEvent::ShrinkToFit => {
self.hm.shrink_to_fit();
}
HashMapEvent::Done => {
self.done = true;
}
}
Ok(())
}
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(bound(serialize = "K: RemoteSend + Eq + Hash, V: RemoteSend, Codec: crate::codec::Codec"))]
#[serde(bound(deserialize = "K: RemoteSend + Eq + Hash, V: RemoteSend, Codec: crate::codec::Codec"))]
enum HashMapInitialValue<K, V, Codec = crate::codec::Default> {
Value(HashMap<K, V>),
Incremental {
len: usize,
rx: rch::mpsc::Receiver<(K, V), Codec>,
},
}
impl<K, V, Codec> HashMapInitialValue<K, V, Codec>
where
K: RemoteSend + Eq + Hash + Clone,
V: RemoteSend + Clone,
Codec: crate::codec::Codec,
{
fn new_value(hm: HashMap<K, V>) -> Self {
Self::Value(hm)
}
fn new_incremental(hm: HashMap<K, V>, on_err: Arc<dyn Fn(SendError) + Send + Sync>) -> Self {
let (tx, rx) = rch::mpsc::channel(128);
let len = hm.len();
exec::spawn(
async move {
for (k, v) in hm.into_iter() {
match tx.send((k, v)).await {
Ok(_) => (),
Err(err) if err.is_disconnected() => break,
Err(err) => match err.try_into() {
Ok(err) => (on_err)(err),
Err(_) => unreachable!(),
},
}
}
}
.in_current_span(),
);
Self::Incremental { len, rx }
}
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(bound(serialize = "K: RemoteSend + Eq + Hash, V: RemoteSend, Codec: crate::codec::Codec"))]
#[serde(bound(deserialize = "K: RemoteSend + Eq + Hash, V: RemoteSend, Codec: crate::codec::Codec"))]
pub struct HashMapSubscription<K, V, Codec = crate::codec::Default> {
initial: HashMapInitialValue<K, V, Codec>,
#[serde(skip, default)]
complete: bool,
events: Option<rch::broadcast::Receiver<HashMapEvent<K, V>, Codec>>,
#[serde(skip, default)]
done: bool,
}
impl<K, V, Codec> HashMapSubscription<K, V, Codec>
where
K: RemoteSend + Eq + Hash + Clone,
V: RemoteSend + Clone,
Codec: crate::codec::Codec,
{
fn new(
initial: HashMapInitialValue<K, V, Codec>,
events: Option<rch::broadcast::Receiver<HashMapEvent<K, V>, Codec>>,
) -> Self {
Self { initial, complete: false, events, done: false }
}
pub fn is_incremental(&self) -> bool {
matches!(self.initial, HashMapInitialValue::Incremental { .. })
}
pub fn is_complete(&self) -> bool {
self.complete
}
pub fn is_done(&self) -> bool {
self.events.is_none() || self.done
}
pub fn take_initial(&mut self) -> Option<HashMap<K, V>> {
match &mut self.initial {
HashMapInitialValue::Value(value) if !self.complete => {
self.complete = true;
Some(take(value))
}
_ => None,
}
}
pub async fn recv(&mut self) -> Result<Option<HashMapEvent<K, V>>, RecvError> {
if !self.complete {
match &mut self.initial {
HashMapInitialValue::Incremental { len, rx } => {
if *len > 0 {
match rx.recv().await? {
Some((k, v)) => {
*len -= 1;
return Ok(Some(HashMapEvent::Set(k, v)));
}
None => return Err(RecvError::Closed),
}
} else {
self.complete = true;
return Ok(Some(HashMapEvent::InitialComplete));
}
}
HashMapInitialValue::Value(_) => {
panic!("take_initial must be called before recv for non-incremental subscription");
}
}
}
if let Some(rx) = &mut self.events {
match rx.recv().await? {
HashMapEvent::Done => self.events = None,
evt => return Ok(Some(evt)),
}
}
if self.done {
Ok(None)
} else {
self.done = true;
Ok(Some(HashMapEvent::Done))
}
}
}
impl<K, V, Codec> HashMapSubscription<K, V, Codec>
where
K: RemoteSend + Eq + Hash + Clone + Sync,
V: RemoteSend + Clone + Sync,
Codec: crate::codec::Codec,
{
pub fn mirror(mut self, max_size: usize) -> MirroredHashMap<K, V, Codec> {
let (tx, _rx) = rch::broadcast::channel::<_, _, { rch::DEFAULT_BUFFER }>(1);
let (changed_tx, changed_rx) = watch::channel(());
let (dropped_tx, mut dropped_rx) = oneshot::channel();
let inner = Arc::new(RwLock::new(Some(MirroredHashMapInner {
hm: self.take_initial().unwrap_or_default(),
complete: self.is_complete(),
done: self.is_done(),
error: None,
max_size,
})));
let inner_task = inner.clone();
let tx_send = tx.clone();
exec::spawn(
async move {
loop {
let event = tokio::select! {
event = self.recv() => event,
_ = &mut dropped_rx => return,
};
let mut inner = inner_task.write().await;
let inner = match inner.as_mut() {
Some(inner) => inner,
None => return,
};
changed_tx.send_replace(());
match event {
Ok(Some(event)) => {
if tx_send.receiver_count() > 0 {
let _ = tx_send.send(event.clone());
}
if let Err(err) = inner.handle_event(event) {
inner.error = Some(err);
return;
}
if inner.done {
break;
}
}
Ok(None) => break,
Err(err) => {
inner.error = Some(err);
return;
}
}
}
}
.in_current_span(),
);
MirroredHashMap { inner, tx, changed_rx, _dropped_tx: dropped_tx }
}
}
pub struct MirroredHashMap<K, V, Codec = crate::codec::Default> {
inner: Arc<RwLock<Option<MirroredHashMapInner<K, V>>>>,
tx: rch::broadcast::Sender<HashMapEvent<K, V>, Codec>,
changed_rx: watch::Receiver<()>,
_dropped_tx: oneshot::Sender<()>,
}
impl<K, V, Codec> fmt::Debug for MirroredHashMap<K, V, Codec> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("MirroredHashMap").finish()
}
}
impl<K, V, Codec> MirroredHashMap<K, V, Codec>
where
K: RemoteSend + Eq + Hash + Clone,
V: RemoteSend + Clone,
Codec: crate::codec::Codec,
{
pub async fn borrow(&self) -> Result<MirroredHashMapRef<'_, K, V>, RecvError> {
let inner = self.inner.read().await;
let inner = RwLockReadGuard::map(inner, |inner| inner.as_ref().unwrap());
match &inner.error {
None => Ok(MirroredHashMapRef(inner)),
Some(err) => Err(err.clone()),
}
}
pub async fn borrow_and_update(&mut self) -> Result<MirroredHashMapRef<'_, K, V>, RecvError> {
let inner = self.inner.read().await;
self.changed_rx.borrow_and_update();
let inner = RwLockReadGuard::map(inner, |inner| inner.as_ref().unwrap());
match &inner.error {
None => Ok(MirroredHashMapRef(inner)),
Some(err) => Err(err.clone()),
}
}
pub async fn detach(self) -> HashMap<K, V> {
let mut inner = self.inner.write().await;
inner.take().unwrap().hm
}
pub async fn changed(&mut self) {
let _ = self.changed_rx.changed().await;
}
pub async fn subscribe(&self, buffer: usize) -> Result<HashMapSubscription<K, V, Codec>, RecvError> {
let view = self.borrow().await?;
let initial = view.clone();
let events = if view.is_done() { None } else { Some(self.tx.subscribe(buffer)) };
Ok(HashMapSubscription::new(HashMapInitialValue::new_value(initial), events))
}
pub async fn subscribe_incremental(
&self, buffer: usize,
) -> Result<HashMapSubscription<K, V, Codec>, RecvError> {
let view = self.borrow().await?;
let initial = view.clone();
let events = if view.is_done() { None } else { Some(self.tx.subscribe(buffer)) };
Ok(HashMapSubscription::new(
HashMapInitialValue::new_incremental(initial, Arc::new(default_on_err)),
events,
))
}
}
impl<K, V, Codec> Drop for MirroredHashMap<K, V, Codec> {
fn drop(&mut self) {
}
}
pub struct MirroredHashMapRef<'a, K, V>(RwLockReadGuard<'a, MirroredHashMapInner<K, V>>);
impl<K, V> MirroredHashMapRef<'_, K, V> {
pub fn is_complete(&self) -> bool {
self.0.complete
}
pub fn is_done(&self) -> bool {
self.0.done
}
}
impl<K, V> fmt::Debug for MirroredHashMapRef<'_, K, V>
where
K: fmt::Debug,
V: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.hm.fmt(f)
}
}
impl<K, V> Deref for MirroredHashMapRef<'_, K, V> {
type Target = HashMap<K, V>;
fn deref(&self) -> &Self::Target {
&self.0.hm
}
}
impl<K, V> Drop for MirroredHashMapRef<'_, K, V> {
fn drop(&mut self) {
}
}