use std::marker::PhantomData;
use cotis::element_configuring::{
ConfigureElements, ConfigureLeafElements, OpenElement, OpenLeafElement,
};
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
#[derive(Clone, Copy, Debug)]
pub struct LeafConfigListNil;
#[derive(Debug)]
pub struct LeafConfigList<Head, Tail>(PhantomData<(Head, Tail)>);
impl<Head, Tail> Clone for LeafConfigList<Head, Tail> {
fn clone(&self) -> Self {
*self
}
}
impl<Head, Tail> Copy for LeafConfigList<Head, Tail> {}
impl<Head, Tail> LeafConfigList<Head, Tail> {
pub fn new() -> LeafConfigList<Head, LeafConfigListNil> {
LeafConfigList(PhantomData)
}
pub fn extend<Head2, Tail2>() -> LeafConfigList<Head, LeafConfigList<Head2, Tail2>> {
LeafConfigList(PhantomData)
}
pub fn new_long() -> LeafConfigList<Head, Tail> {
LeafConfigList(PhantomData)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LeafConfigData {
internal: Vec<u8>,
}
impl LeafConfigData {
pub(crate) fn new<Head: Serialize>(config: &Head) -> LeafConfigData {
Self {
internal: serde_json::to_vec(&config).unwrap(),
}
}
fn try_reconstruct<Head: DeserializeOwned>(&self) -> Option<Head> {
serde_json::from_slice(&self.internal).ok()
}
}
pub trait LeafConfigListCompatible<Configurer, ConfigType>
where
Configurer: ConfigureElements<ConfigType>,
{
fn configure(
data: &LeafConfigData,
configurer: &mut OpenLeafElement<'_, Configurer, ConfigType>,
);
fn configure_open(data: &LeafConfigData, configurer: OpenElement<'_, Configurer, ConfigType>);
}
impl<Head, Tail, Configurer, ConfigType> LeafConfigListCompatible<Configurer, ConfigType>
for LeafConfigList<Head, Tail>
where
Configurer: ConfigureLeafElements<Head> + ConfigureElements<ConfigType>,
Tail: LeafConfigListCompatible<Configurer, ConfigType>,
Head: DeserializeOwned,
{
fn configure(
data: &LeafConfigData,
configurer: &mut OpenLeafElement<'_, Configurer, ConfigType>,
) {
let reconstruction: Option<Head> = data.try_reconstruct();
match reconstruction {
Some(reconstruction) => {
configurer.set_leaf_config(reconstruction);
}
None => {
Tail::configure(data, configurer);
}
}
}
fn configure_open(data: &LeafConfigData, configurer: OpenElement<'_, Configurer, ConfigType>) {
let reconstruction: Option<Head> = data.try_reconstruct();
match reconstruction {
Some(reconstruction) => {
configurer.set_leaf_config(reconstruction);
}
None => {
Tail::configure_open(data, configurer);
}
}
}
}
impl<Configurer, ConfigType> LeafConfigListCompatible<Configurer, ConfigType> for LeafConfigListNil
where
Configurer: ConfigureElements<ConfigType>,
{
fn configure(
_data: &LeafConfigData,
_configurer: &mut OpenLeafElement<'_, Configurer, ConfigType>,
) {
}
fn configure_open(_data: &LeafConfigData, configurer: OpenElement<'_, Configurer, ConfigType>) {
drop(configurer);
}
}