//! # Design
//!
#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
#![deny(elided_lifetimes_in_paths)]
#![deny(unsafe_code)]
#[cfg(feature = "alloc")]
extern crate alloc;
pub mod any;
pub mod build;
mod doc_macro;
pub mod hkt;
pub mod macros;
pub mod mode;
pub mod protocol;
pub mod symbol;
pub mod transform;
pub mod walk;
use core::ops::ControlFlow;
use effectful::{short::ConvertShort, SendSync};
#[doc(inline)]
pub use build::{Build, Builder};
#[doc(inline)]
pub use walk::{Walk, Walker};
pub enum DefaultMode {}
#[must_use]
#[derive(Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Copy, Clone, SendSync)]
pub enum Status {
Ok,
Err,
}
#[derive(Clone, Copy, PartialEq, Debug, SendSync)]
#[must_use]
pub enum Flow {
Continue,
Err,
Done,
}
type Never = std::convert::Infallible;
impl ConvertShort<Flow> for Option<Never> {
fn convert_short(short: Self) -> Flow {
match short {
None => Flow::Done,
Some(_) => unreachable!(),
}
}
}
impl Flow {
pub fn to_status(self) -> Status {
match self {
Flow::Continue | Flow::Done => Status::Ok,
Flow::Err => Status::Err,
}
}
pub fn to_done(self) -> Self {
match self {
Flow::Continue | Flow::Done => Flow::Done,
Flow::Err => Flow::Err,
}
}
pub fn to_continue(self) -> Self {
match self {
Flow::Continue | Flow::Done => Flow::Continue,
Flow::Err => Flow::Err,
}
}
pub fn to_control_flow(self) -> ControlFlow<Self> {
match self {
Flow::Continue => ControlFlow::Continue(()),
flow => ControlFlow::Break(flow),
}
}
}
#[macro_export]
macro_rules! Walk {
{
$(#[$($attr:tt)*])*
$vis:vis struct $name:ident {$(
$fvis:vis $field:ident: $type:ty
),* $(,)?}
} => {
const _: () = {
impl<'ctx, M: 'ctx, E: effectful::environment::Environment> $crate::Walk<'ctx, M, E> for &'ctx $name
where
$name: effectful::bound::IsSync<E::NeedSend> + effectful::environment::DynBind<E>
{
type Walker = $crate::walkers::core::r#struct::StructWalker<'ctx, Info, $crate::any::StaticType, M, E>;
fn into_walker<'e>(self) -> effectful::environment::NativeForm<'e, Self::Walker, E> {
E::value($crate::walkers::core::r#struct::StructWalker::new(self)).cast()
}
}
// impl<'ctx> $crate::WalkerTypes for &'ctx $name {
// type Error = $crate::walkers::core::r#struct::StructWalkError<FieldError<'ctx>>;
// type Output = ();
// }
$vis enum Info {}
#[allow(non_camel_case_types, unused)]
enum FieldErrorKind<'ctx, M, E: effectful::environment::Environment> {$(
$field($crate::walkers::core::key_value::KeyValueError<$crate::never::Never, <<&'ctx $type as $crate::Walk<'ctx, M, E>>::Walker as $crate::Walker<'ctx, E>>::Error>)
),*}
#[allow(unused)]
$vis struct FieldError<'ctx, M, E: effectful::environment::Environment>(FieldErrorKind<'ctx, M, E>);
unsafe impl<'ctx, M, E: effectful::environment::Environment> effectful::bound::IsSend<E::NeedSend> for FieldError<'ctx, M, E> {}
unsafe impl<'ctx, M, E: effectful::environment::Environment> effectful::bound::IsSync<E::NeedSync> for FieldError<'ctx, M, E> {}
impl<'ctx, M, E: effectful::environment::Environment> ::core::fmt::Debug for FieldError<'ctx, M, E> {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
todo!()
}
}
impl<'ctx, M: 'ctx, E: effectful::environment::Environment> $crate::walkers::core::r#struct::StructTypeInfo<'ctx, M, E> for Info
where
$name: effectful::bound::IsSync<E::NeedSend> + effectful::environment::DynBind<E>
{
const NAME: &'static str = stringify!($name);
const FIELDS: &'static [&'static str] = &[$(stringify!($field)),*];
type FieldError = FieldError<'ctx, M, E>;
type T = $name;
type S = $crate::any::StaticType;
#[allow(unreachable_code, non_snake_case, non_upper_case_globals, non_camel_case_types)]
fn walk_field<'a>(
index: usize,
value: &'ctx Self::T,
visitor: $crate::protocol::DynVisitor<'a, 'ctx, E>,
) -> effectful::environment::NativeForm<'a, Result<$crate::Flow, Self::FieldError>, E> {
mod fields {
enum Fields {$($field),*}
$(pub const $field: usize = Fields::$field as usize;)*
}
match index {
$(fields::$field => {
let key_walker = $crate::walkers::core::value::ValueWalker::new(stringify!($field));
<&'ctx $type as $crate::Walk::<'ctx, M, E>>::into_walker(&value.$field)
.then(|value_walker| {
let walker = $crate::walkers::core::key_value::KeyValueWalker::<$crate::protocol::visitor::TagConst<{ $crate::TAG_FIELD.to_int() }>, _, _>::new($crate::protocol::visitor::TagConst, key_walker, value_walker);
$crate::Walker::<'ctx, E>::walk(walker, visitor)
})
.map(|result| match result {
Ok(_) => {
Ok($crate::Flow::Continue)
}
Err(err) => {
Err(FieldError(FieldErrorKind::$field(err)))
}
})
// E::map($crate::Walker::<'ctx, E>::walk(walker, visitor), |result| match result {
// Ok(_) => {
// Ok($crate::Flow::Continue)
// }
// Err(err) => {
// Err(FieldError(FieldErrorKind::$field(err)))
// }
// })
})*
_ => E::ready(Ok($crate::Flow::Done))
}
}
}
};
};
}
// #[cfg(test)]
// mod test {
// use crate::effect::{BlockOn, Blocking, Spin};
//
// use super::*;
// use macro_rules_attribute::derive;
//
// #[derive(Walk!)]
// struct Demo {
// a: bool,
// b: bool,
// other: Other,
// }
//
// #[derive(Walk!)]
// struct Other {
// value: bool,
// }
//
// #[test]
// fn demo() {
// let value = Demo {
// a: true,
// b: false,
// other: Other { value: true },
// };
//
// let walker = Walk::<DefaultMode, Blocking>::into_walker(&value);
// let mut visitor = builders::debug::Visitor::<Blocking>::new();
//
// dbg!(Spin::block_on(Walker::<Blocking>::walk(
// walker,
// &mut visitor
// )));
//
// todo!();
// }
// }
// pub mod demo {
// use crate::{Build, BuildExt as _};
// use crate::{Walk, WalkExt as _};
// use macro_rules_attribute::derive;
//
// #[derive(Walk!)]
// pub struct X {
// pub a: bool,
// pub b: bool,
// }
//
// #[derive(Build!, PartialEq, Debug)]
// pub struct Y {
// pub b: bool,
// pub a: bool,
// }
//
// #[inline(never)]
// pub fn ident(x: X) -> Y {
// Y::build(x.as_walker()).unwrap()
// // x.walk(Y::new_builder()).unwrap()
// }
//
// #[test]
// fn demo() {
// assert_eq!(ident(X { a: true, b: false }), Y { a: true, b: false });
//
// crate::effect::blocking::Spin::block_on(async {
// let x = X { a: false, b: true };
//
// let y = Y::build_async(x.as_async_walker().await).await.unwrap();
//
// assert_eq!(y, Y { a: false, b: true });
// });
//
// let x = X { a: false, b: true };
//
// let y = Y::build(x.as_walker()).unwrap();
//
// assert_eq!(y, Y { a: false, b: true });
// }
// }