hakuban 0.8.5

Data-object sharing library
Documentation
use std::{
	collections::BTreeMap,
	sync::{Arc, Mutex},
};

use super::{DataBytes, DataVersion};
use crate::connection::diff;

type VersionToFrom = (DataVersion, Option<DataVersion>);

const SCAN_SHIFT: u32 = 16;

#[derive(Default)]
pub(crate) struct DiffCache {
	diffs: Mutex<BTreeMap<VersionToFrom, Arc<Mutex<Option<DataBytes>>>>>,
	diff_states: Mutex<BTreeMap<DataVersion, Arc<Mutex<Option<diff::State>>>>>,
}

impl DiffCache {
	pub(crate) fn get_diff(
		&self,
		old_version: Option<&DataVersion>,
		old_data: Option<&DataBytes>,
		new_version: &[i64],
		new_data: &DataBytes,
	) -> Option<DataBytes> {
		let diff_mutex = {
			let mut diffs = self.diffs.lock().unwrap();
			let ret = diffs.entry((new_version.into(), old_version.cloned())).or_insert_with(|| Arc::new(Mutex::new(None))).clone();
			while diffs.len() > 1 {
				diffs.pop_first();
			}
			ret
		};
		let mut diff_mutex_lock = diff_mutex.lock().unwrap();

		Some(
			diff_mutex_lock
				.get_or_insert_with(|| {
					let (diff, new_state) = if let Some(old_version) = old_version {
						let state_mutex = {
							let mut diff_states = self.diff_states.lock().unwrap();
							let ret = diff_states.entry(old_version.clone()).or_insert_with(|| Arc::new(Mutex::new(None))).clone();
							while diff_states.len() > 2 {
								diff_states.pop_first();
							}
							ret
						};
						let mut state_mutex_lock = state_mutex.lock().unwrap();
						let state = state_mutex_lock.get_or_insert_with(|| diff::State::new().diff(&[], old_data.unwrap(), SCAN_SHIFT, 6).unwrap().1);
						state.diff(old_data.unwrap(), new_data, SCAN_SHIFT, 6).unwrap() //TODO: don't unwrap?
					} else {
						let state = diff::State::new();
						state.diff(&[], new_data, SCAN_SHIFT, 6).unwrap()
					};
					let mut diff_states = self.diff_states.lock().unwrap();
					diff_states.entry(new_version.into()).or_insert_with(|| Arc::new(Mutex::new(Some(new_state))));
					while diff_states.len() > 2 {
						diff_states.pop_first();
					}
					Arc::new(diff)
				})
				.clone(),
		)
	}
}