hakuban 0.8.5

Data-object sharing library
Documentation
#[cfg(not(target_family = "wasm"))]
use std::time::{Instant, SystemTime, UNIX_EPOCH};
use std::{cmp::max, sync::Arc, time::Duration};

#[cfg(target_family = "wasm")]
use web_time::{Instant, SystemTime, UNIX_EPOCH};

/// Structure holding individual data-object's state
#[derive(Clone, PartialEq, Eq)]
pub struct ObjectState<T> {
	pub data: T,
	pub format: DataFormat,
	pub version: DataVersion,
	pub synchronized: DataSynchronized,
}

//TODO: consider dropping these types. too many new names for the reader.
/// `= Vec<i64>`
pub type DataVersion = Vec<i64>;
/// `= Vec<String>`
pub type DataFormat = Vec<String>;
/// `= Arc<Vec<u8>>`
pub type DataBytes = Arc<Vec<u8>>;

/// Object synchronization state
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum DataSynchronized {
	// some (not necessarily current) data was exposed by currently assigned exposer
	Now,
	// data was exposed by somebody but "Now" conditions were not met
	LastAt(Instant),
}

impl DataSynchronized {
	pub fn micros_ago(&self) -> u64 {
		match self {
			DataSynchronized::LastAt(timestamp) => {
				max(1, (Instant::now().checked_duration_since(*timestamp)).map(|duration| duration.as_micros()).unwrap_or(1) as u64)
			}
			DataSynchronized::Now => 0,
		}
	}

	pub fn from_micros_ago(micros_ago: u64) -> DataSynchronized {
		if micros_ago == 0 {
			DataSynchronized::Now
		} else {
			//FIXME: stupid default, we should saturate
			DataSynchronized::LastAt(Instant::now().checked_sub(Duration::from_micros(micros_ago)).unwrap_or(Instant::now()))
		}
	}
}

impl<T: 'static> ObjectState<T> {
	pub fn new(data: T) -> ObjectState<T> {
		let timestamp = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_nanos();
		ObjectState {
			data,
			format: vec![],
			version: vec![0, (timestamp / 1000000000) as i64, (timestamp % 1000000000) as i64],
			synchronized: DataSynchronized::Now,
		}
	}

	pub fn with_data<U>(self, data: U) -> ObjectState<U> {
		ObjectState { data, version: self.version, format: self.format, synchronized: self.synchronized }
	}

	pub fn with_version(mut self, version: impl Into<DataVersion>) -> ObjectState<T> {
		self.version = version.into();
		self
	}

	pub fn with_format(mut self, format: impl Into<DataFormat>) -> ObjectState<T> {
		self.format = format.into();
		self
	}

	pub fn with_synchronized(mut self, synchronized: impl Into<DataSynchronized>) -> ObjectState<T> {
		self.synchronized = synchronized.into();
		self
	}
}