use std::{any::TypeId, collections::VecDeque, ops::ControlFlow};
use treaty::{
any::{any_trait, static_wrapper::OwnedStatic},
protocol::{
visitor::{Sequence, SequenceScope, Value},
Visitor,
},
Builder, Walk, Walker,
};
#[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 = JsonLike::default();
<Data as Walk>::Walker::from(a).walk(builder.as_visitor()).unwrap();
dbg!(builder.build().unwrap());
todo!()
}
#[derive(Debug)]
enum Data {
Bool(bool),
Sequence(Vec<Data>),
}
const _: () = {
struct Impl(Data);
impl From<Data> for Impl {
fn from(value: Data) -> Self {
Self(value)
}
}
impl<'ctx> Walk<'ctx> for Data {
type Walker = Impl;
}
impl<'ctx> Walker<'ctx> for Impl {
type Error = ();
type Output = ();
fn walk(self, visitor: Visitor<'_, 'ctx>) -> Result<Self::Output, Self::Error> {
match self.0 {
Data::Bool(value) => walk_bool(value, visitor),
Data::Sequence(value) => walk_vec(value, visitor),
}
Ok(())
}
}
};
fn walk_bool(value: bool, visitor: Visitor<'_, '_>) {
visitor
.upcast_mut::<dyn Value<OwnedStatic<bool>>>()
.unwrap()
.visit(OwnedStatic(value));
}
fn walk_vec(value: Vec<Data>, visitor: Visitor<'_, '_>) {
struct Scope(VecDeque<Data>);
impl<'ctx> SequenceScope<'ctx> for Scope {
fn next(
&mut self,
visitor: Visitor<'_, 'ctx>,
) -> treaty::protocol::ControlFlow<(), treaty::protocol::visitor::Status> {
if let Some(value) = self.0.pop_front() {
<<Data as Walk>::Walker>::from(value).walk(visitor).unwrap();
ControlFlow::Continue(treaty::protocol::visitor::Status::Continue)
} else {
ControlFlow::Continue(treaty::protocol::visitor::Status::Done)
}
}
}
let mut scope = Scope(value.into());
visitor
.upcast_mut::<dyn Sequence<'_>>()
.unwrap()
.visit(&mut scope);
}
#[derive(Default)]
struct JsonLike(String);
impl<'ctx> Builder<'ctx> for JsonLike {
type Error = ();
type Value = String;
fn as_visitor(&mut self) -> Visitor<'_, 'ctx> {
self
}
fn build(self) -> Result<Self::Value, Self::Error> {
Ok(self.0)
}
}
any_trait! {
impl['a, 'ctx] JsonLike = [
dyn Value<OwnedStatic<bool>> + 'a,
dyn Sequence<'ctx> + 'a,
];
}
impl Value<OwnedStatic<bool>> for JsonLike {
fn visit(&mut self, value: OwnedStatic<bool>) -> treaty::protocol::ControlFlow {
self.0.push_str(&format!("{}", value.0));
ControlFlow::Continue(())
}
}
impl<'ctx> Sequence<'ctx> for JsonLike {
fn visit(&mut self, scope: &mut dyn SequenceScope<'ctx>) -> treaty::protocol::ControlFlow {
self.0.push_str("[");
while let ControlFlow::Continue(treaty::protocol::visitor::Status::Continue) =
scope.next(self)
{
self.0.push_str(",");
}
self.0.push_str("]");
ControlFlow::Continue(())
}
}