use std::any::TypeId;
use uniserde::{
impls::core::iterator::IterWalker,
protocol::{implementer, AnyImpl, Implementation, Implementer, ImplementerExt},
protocols::{sequence, ControlFlow},
transform, Build, Builder, WalkOnce,
};
#[test]
fn demo() {
let a = Data::Sequence(vec![
Data::Bool(true),
Data::Sequence(vec![Data::Bool(false), Data::Bool(true)]),
Data::Bool(false),
]);
// let mut builder = <Data as Build>::Builder::default();
let mut builder = StringBuilder::default();
a.walk_once(builder.as_visitor());
dbg!(builder.build());
todo!()
}
#[derive(Debug)]
enum Data {
Bool(bool),
Sequence(Vec<Data>),
}
impl<'ctx> WalkOnce<'ctx> for Data {
type Error = ();
type Value = ();
fn walk_once(self, visitor: &mut dyn Implementer<'ctx>) -> Result<Self::Value, Self::Error> {
match self {
Data::Bool(value) => value.walk_once(visitor),
Data::Sequence(list) => IterWalker::new(list).walk_once(visitor),
}
}
}
#[derive(Default)]
struct StringBuilder(String);
impl<'ctx> Builder<'ctx> for StringBuilder {
type Error = ();
type Value = String;
fn as_visitor(&mut self) -> &mut dyn Implementer<'ctx> {
self
}
fn build(self) -> Result<Self::Value, Self::Error> {
Ok(self.0)
}
fn accepts(id: TypeId) -> bool {
id == TypeId::of::<uniserde::protocols::sequence::Sequence>()
|| id == TypeId::of::<uniserde::protocols::bool::Bool>()
}
}
implementer! {
impl['ctx] StringBuilder = [sequence::Sequence, uniserde::protocols::bool::Bool];
}
impl<'ctx> uniserde::protocols::sequence::Object<'ctx> for StringBuilder {
fn visit(
&mut self,
accessor: &mut dyn sequence::Accessor<'ctx>,
) -> uniserde::protocols::ControlFlow {
self.0.push('[');
loop {
if accessor.next(self) != uniserde::protocols::sequence::ControlFlow::Continue {
break;
}
self.0.push_str(", ");
}
self.0.push(']');
uniserde::protocols::ControlFlow::Done
}
}
impl<'ctx> uniserde::protocols::bool::Object<'ctx> for StringBuilder {
fn visit(&mut self, value: bool) -> ControlFlow {
self.0.push_str(&value.to_string());
ControlFlow::Done
}
}
#[derive(Default)]
enum DataBuilder {
#[default]
Empty,
Bool(<bool as Build<'static>>::Builder),
Sequence(VecBuilder<Data>),
}
impl<'ctx> Build<'ctx> for Data {
type Builder = DataBuilder;
}
impl<'ctx> Builder<'ctx> for DataBuilder {
type Error = ();
type Value = Data;
fn as_visitor(&mut self) -> &mut dyn Implementer<'ctx> {
self
}
fn build(self) -> Result<Self::Value, Self::Error> {
match self {
DataBuilder::Empty => Err(()),
DataBuilder::Bool(value) => Ok(Data::Bool(value.build().unwrap())),
DataBuilder::Sequence(list) => Ok(Data::Sequence(list.build().unwrap())),
}
}
fn accepts(id: TypeId) -> bool {
<<bool as Build>::Builder as Builder>::accepts(id)
|| <VecBuilder<Data> as Builder>::accepts(id)
}
}
impl<'ctx> Implementer<'ctx> for DataBuilder {
fn interface(&mut self, id: TypeId) -> Option<AnyImpl<'_, 'ctx>> {
if <<bool as Build>::Builder as Builder>::accepts(id) {
let builder = <<bool as Build>::Builder as Default>::default();
*self = Self::Bool(builder);
} else if VecBuilder::<Data>::accepts(id) {
let builder = VecBuilder::<Data>::default();
*self = Self::Sequence(builder);
}
match self {
DataBuilder::Empty => panic!(),
DataBuilder::Bool(builder) => builder.interface(id),
DataBuilder::Sequence(builder) => builder.interface(id),
}
}
}
struct VecBuilder<T>(Vec<T>);
impl<T> Default for VecBuilder<T> {
fn default() -> Self {
Self(Vec::new())
}
}
impl<'ctx, T: Build<'ctx>> Builder<'ctx> for VecBuilder<T> {
type Error = ();
type Value = Vec<T>;
fn as_visitor(&mut self) -> &mut dyn uniserde::protocol::Implementer<'ctx> {
self
}
fn build(self) -> Result<Self::Value, Self::Error> {
Ok(self.0)
}
fn accepts(id: TypeId) -> bool {
id == TypeId::of::<uniserde::protocols::sequence::Sequence>()
}
}
implementer! {
impl['ctx, T: Build<'ctx>] VecBuilder<T> = [sequence::Sequence];
}
impl<'ctx, T: Build<'ctx>> sequence::Object<'ctx> for VecBuilder<T> {
fn visit(
&mut self,
accessor: &mut dyn sequence::Accessor<'ctx>,
) -> uniserde::protocols::ControlFlow {
loop {
let mut builder = <T as Build>::Builder::default();
let flow = accessor.next(builder.as_visitor());
if flow == uniserde::protocols::sequence::ControlFlow::Done {
break;
} else {
let Ok(value) = builder.build() else { panic!() };
self.0.push(value);
}
}
ControlFlow::Done
}
}