#![deny(unsafe_code)]
use std::borrow::{Borrow, BorrowMut};
use std::fmt;
use std::fmt::{Display, Formatter};
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct OpaqueData {
size: usize,
}
impl OpaqueData {
pub(crate) const fn new(size: usize) -> Self {
Self { size }
}
pub const fn size(self) -> usize {
self.size
}
}
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct ChangeStamp(u32);
impl ChangeStamp {
pub const fn new(value: u32) -> Self {
Self(value)
}
pub const fn initial() -> Self {
Self(0)
}
pub const fn value(self) -> u32 {
self.0
}
pub(crate) fn as_mut_ptr(&mut self) -> *mut u32 {
&mut self.0
}
}
impl From<u32> for ChangeStamp {
fn from(value: u32) -> Self {
Self(value)
}
}
impl From<ChangeStamp> for u32 {
fn from(ChangeStamp(value): ChangeStamp) -> Self {
value
}
}
impl Display for ChangeStamp {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl PartialEq<u32> for ChangeStamp {
fn eq(&self, other: &u32) -> bool {
self.0 == *other
}
}
impl PartialEq<ChangeStamp> for u32 {
fn eq(&self, other: &ChangeStamp) -> bool {
*self == other.0
}
}
impl AsRef<u32> for ChangeStamp {
fn as_ref(&self) -> &u32 {
&self.0
}
}
impl AsMut<u32> for ChangeStamp {
fn as_mut(&mut self) -> &mut u32 {
&mut self.0
}
}
impl Borrow<u32> for ChangeStamp {
fn borrow(&self) -> &u32 {
&self.0
}
}
impl BorrowMut<u32> for ChangeStamp {
fn borrow_mut(&mut self) -> &mut u32 {
&mut self.0
}
}
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
pub struct StampedData<T> {
data: T,
change_stamp: ChangeStamp,
}
impl<T> StampedData<T> {
pub fn from_data_change_stamp(data: T, change_stamp: impl Into<ChangeStamp>) -> Self {
Self {
data,
change_stamp: change_stamp.into(),
}
}
pub fn into_data_change_stamp(self) -> (T, ChangeStamp) {
(self.data, self.change_stamp)
}
pub fn into_data(self) -> T {
self.data
}
pub const fn data(&self) -> &T {
&self.data
}
pub const fn change_stamp(&self) -> ChangeStamp {
self.change_stamp
}
pub fn map<U, F>(self, op: F) -> StampedData<U>
where
F: FnOnce(T) -> U,
{
StampedData {
data: op(self.data),
change_stamp: self.change_stamp,
}
}
}
impl<T> From<(T, ChangeStamp)> for StampedData<T> {
fn from((data, change_stamp): (T, ChangeStamp)) -> Self {
Self { data, change_stamp }
}
}
impl<T> From<StampedData<T>> for (T, ChangeStamp) {
fn from(stamped_data: StampedData<T>) -> Self {
(stamped_data.data, stamped_data.change_stamp)
}
}
impl<T> AsRef<T> for StampedData<T> {
fn as_ref(&self) -> &T {
&self.data
}
}
impl<T> AsMut<T> for StampedData<T> {
fn as_mut(&mut self) -> &mut T {
&mut self.data
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn change_stamp_display() {
assert_eq!(ChangeStamp::from(42).to_string(), "42");
}
#[test]
fn stamped_data_map() {
assert_eq!(
StampedData::from_data_change_stamp(42, 1).map(|x| x.to_string()),
StampedData::from_data_change_stamp(String::from("42"), 1)
);
}
}