use std::ops::{Deref, DerefMut};
use crossbeam_channel::Sender;
use serde_diff::{Config, Diff, FieldPathMode};
use crate::{
serialization::{ModificationSerializer, SerializationStrategy},
Identifier, ModificationEvent, TrackableMarker,
};
pub struct Tracker<'borrow, 'notifier, C, S, I>
where
C: TrackableMarker,
S: SerializationStrategy,
I: Identifier,
{
old_copy: C,
borrow: &'borrow mut C,
notifier: &'notifier Sender<ModificationEvent<I>>,
serialization: S,
identifier: I,
}
impl<'borrow, 'notifier, C, S, I> Tracker<'borrow, 'notifier, C, S, I>
where
C: TrackableMarker,
S: SerializationStrategy,
I: Identifier,
{
pub fn new(
borrow: &'borrow mut C,
notifier: &'notifier Sender<ModificationEvent<I>>,
serialization: S,
identifier: I,
) -> Tracker<'borrow, 'notifier, C, S, I> {
Tracker {
old_copy: (borrow.deref()).clone(),
borrow,
notifier,
identifier,
serialization,
}
}
}
impl<'borrow, 'notifier, C, S, I> Deref for Tracker<'borrow, 'notifier, C, S, I>
where
C: TrackableMarker,
S: SerializationStrategy,
I: Identifier,
{
type Target = C;
fn deref(&self) -> &Self::Target {
&self.borrow
}
}
impl<'borrow, 'notifier, C, S, I> DerefMut for Tracker<'borrow, 'notifier, C, S, I>
where
C: TrackableMarker,
S: SerializationStrategy,
I: Identifier,
{
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.borrow
}
}
impl<'borrow, 'notifier, C, S, I> Drop for Tracker<'borrow, 'notifier, C, S, I>
where
C: TrackableMarker,
S: SerializationStrategy,
I: Identifier,
{
fn drop(&mut self) {
let diff = Config::new()
.with_field_path_mode(FieldPathMode::Index)
.serializable_diff(&self.old_copy, &self.borrow);
let serializer = ModificationSerializer::new(self.serialization.clone());
match serializer.serialize::<Diff<C>>(&diff) {
Ok(data) => {
if diff.has_changes() {
self.notifier
.send(ModificationEvent::new(data, self.identifier))
.expect("The sender for modification events panicked. Is the receiver still alive?");
}
}
Err(e) => {
panic!(
"Could not serialize modification information because: {:?}",
e
);
}
};
}
}