use std::{marker::PhantomData, ops::Deref, sync::Arc};
use crate::{Data, Read, UniqueIdentifier, Update, Write};
pub trait UidTuple {}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Doublet<U1, U2, const ID: usize = 2>(PhantomData<U1>, PhantomData<U2>)
where
U1: UniqueIdentifier,
U2: UniqueIdentifier;
type UID2<U1, U2> = (
Arc<<U1 as UniqueIdentifier>::DataType>,
Arc<<U2 as UniqueIdentifier>::DataType>,
);
impl<U1: UniqueIdentifier, U2: UniqueIdentifier> UidTuple for Doublet<U1, U2> {}
impl<U1, U2> UniqueIdentifier for Doublet<U1, U2, 0>
where
U1: UniqueIdentifier,
U2: UniqueIdentifier,
{
type DataType = <U1 as UniqueIdentifier>::DataType;
const PORT: u16 = <U1 as UniqueIdentifier>::PORT;
}
impl<U1, U2> UniqueIdentifier for Doublet<U1, U2, 1>
where
U1: UniqueIdentifier,
U2: UniqueIdentifier,
{
type DataType = <U2 as UniqueIdentifier>::DataType;
const PORT: u16 = <U2 as UniqueIdentifier>::PORT;
}
impl<U1, U2> UniqueIdentifier for Doublet<U1, U2>
where
U1: UniqueIdentifier,
U2: UniqueIdentifier,
{
type DataType = UID2<U1, U2>;
const PORT: u16 = (U1::PORT - 50_000) + (U2::PORT - 50_000) + 20_000;
}
impl<C, U1, U2> Write<Doublet<U1, U2, 0>> for C
where
C: Update + Write<U1> + Write<U2> + UidTuple,
U1: UniqueIdentifier,
U2: UniqueIdentifier,
Doublet<U1, U2>: UniqueIdentifier<DataType = <U1 as UniqueIdentifier>::DataType>,
{
fn write(&mut self) -> Option<Data<Doublet<U1, U2, 0>>> {
<_ as Write<U1>>::write(self).map(|x| x.transmute())
}
}
impl<C, U1, U2> Write<Doublet<U1, U2, 1>> for C
where
C: Update + Write<U1> + Write<U2> + UidTuple,
U1: UniqueIdentifier,
U2: UniqueIdentifier,
Doublet<U1, U2>: UniqueIdentifier<DataType = <U2 as UniqueIdentifier>::DataType>,
{
fn write(&mut self) -> Option<Data<Doublet<U1, U2, 1>>> {
<_ as Write<U2>>::write(self).map(|x| x.transmute())
}
}
impl<C, U1, U2> Write<Doublet<U1, U2>> for C
where
C: Update + Write<U1> + Write<U2> + UidTuple,
U1: UniqueIdentifier,
U2: UniqueIdentifier,
Doublet<U1, U2>: UniqueIdentifier<DataType = UID2<U1, U2>>,
{
fn write(&mut self) -> Option<Data<Doublet<U1, U2>>> {
let data1 = <_ as Write<U1>>::write(self);
let data2 = <_ as Write<U2>>::write(self);
data1
.map(|data| data.into_arc())
.zip(data2.map(|data| data.into_arc()))
.map(|data| Data::new(data))
}
}
impl<C, U1, U2> Read<Doublet<U1, U2, 0>> for C
where
C: Update + Read<U1> + Read<U2> + UidTuple,
U1: UniqueIdentifier,
U2: UniqueIdentifier,
Doublet<U1, U2>: UniqueIdentifier<DataType = <U1 as UniqueIdentifier>::DataType>,
{
fn read(&mut self, data: Data<Doublet<U1, U2, 0>>) {
<_ as Read<U1>>::read(self, data.transmute());
}
}
impl<C, U1, U2> Read<Doublet<U1, U2, 1>> for C
where
C: Update + Read<U1> + Read<U2> + UidTuple,
U1: UniqueIdentifier,
U2: UniqueIdentifier,
Doublet<U1, U2>: UniqueIdentifier<DataType = <U2 as UniqueIdentifier>::DataType>,
{
fn read(&mut self, data: Data<Doublet<U1, U2, 1>>) {
<_ as Read<U2>>::read(self, data.transmute());
}
}
impl<C, U1, U2> Read<Doublet<U1, U2>> for C
where
C: Update + Read<U1> + Read<U2> + UidTuple,
U1: UniqueIdentifier,
U2: UniqueIdentifier,
Doublet<U1, U2>: UniqueIdentifier<DataType = UID2<U1, U2>>,
{
fn read(&mut self, data: Data<Doublet<U1, U2>>) {
let (data1, data2) = data.into_arc().deref().clone();
<_ as Read<U1>>::read(self, data1.into());
<_ as Read<U2>>::read(self, data2.into());
}
}
pub struct Get<U1, U2, const ID: usize>
where
U1: UniqueIdentifier,
U2: UniqueIdentifier,
{
data: Arc<UID2<U1, U2>>,
}
impl<U1, U2, const ID: usize> Default for Get<U1, U2, ID>
where
U1: UniqueIdentifier,
U2: UniqueIdentifier,
<U1 as UniqueIdentifier>::DataType: Default,
<U2 as UniqueIdentifier>::DataType: Default,
{
fn default() -> Self {
Self {
data: Default::default(),
}
}
}
impl<U1, U2, const ID: usize> Update for Get<U1, U2, ID>
where
U1: UniqueIdentifier,
U2: UniqueIdentifier,
{
}
impl<U1, U2, const ID: usize> Read<Doublet<U1, U2>> for Get<U1, U2, ID>
where
U1: UniqueIdentifier,
U2: UniqueIdentifier,
{
fn read(&mut self, data: Data<Doublet<U1, U2>>) {
self.data = data.into_arc();
}
}
impl<U1, U2> Write<U1> for Get<U1, U2, 0>
where
U1: UniqueIdentifier,
U2: UniqueIdentifier,
{
fn write(&mut self) -> Option<Data<U1>> {
let (data1, _data2) = self.data.deref().clone();
Some(data1.into())
}
}
impl<U1, U2> Write<U2> for Get<U1, U2, 1>
where
U1: UniqueIdentifier,
U2: UniqueIdentifier,
{
fn write(&mut self) -> Option<Data<U2>> {
let (_data1, data2) = self.data.deref().clone();
Some(data2.into())
}
}