use std::{fmt::Display, marker::PhantomData, ops::Deref, str::FromStr, string::FromUtf8Error};
use serde::{Deserialize, Serialize};
use crate::{ast::*, eval::*};
pub trait ABEValidator
where
Self: TryFrom<ABList>,
{
fn check(b: &[ABE]) -> Result<(), MatchError>;
}
#[derive(Clone, Default, PartialEq)]
pub struct TypedABE<V>(pub Vec<ABE>, PhantomData<V>);
impl<V> Serialize for TypedABE<V> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.0.serialize(serializer)
}
}
impl<'de, V: ABEValidator> Deserialize<'de> for TypedABE<V> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let v = Vec::<ABE>::deserialize(deserializer)?;
V::check(&v).map_err(|e| <D::Error as serde::de::Error>::custom(e.to_string()))?;
Ok(TypedABE(v, PhantomData))
}
}
impl From<Vec<ABE>> for TypedABE<Vec<u8>> {
fn from(value: Vec<ABE>) -> Self {
TypedABE(value, PhantomData)
}
}
impl<A: ABEValidator> TypedABE<A> {
pub fn unwrap(self) -> Vec<ABE>{
self.0
}
pub fn eval_default(
&self,
default: A,
ctx: &EvalCtx<impl Scope>,
) -> Result<A, ABEError<<A as TryFrom<ABList>>::Error>> {
let ablst = eval(ctx, &self.0).map_err(ABEError::Eval)?;
if ablst.is_empty() {
return Ok(default);
}
ablst.try_into().map_err(ABEError::TryFrom)
}
pub fn eval(
&self,
ctx: &EvalCtx<impl Scope>,
) -> Result<A, ABEError<<A as TryFrom<ABList>>::Error>> {
let ablst = eval(ctx, &self.0).map_err(ABEError::Eval)?;
ablst.try_into().map_err(ABEError::TryFrom)
}
pub fn from(value: Vec<ABE>) -> Result<Self, MatchError> {
A::check(&value)?;
Ok(TypedABE(value, PhantomData))
}
pub fn new_unchecked(it: impl IntoIterator<Item = ABE>) -> Self {
TypedABE(it.into_iter().collect(), PhantomData)
}
pub const fn from_unchecked(v: Vec<ABE>) -> Self {
TypedABE(v, PhantomData)
}
}
impl<A> TypedABE<A> {
pub fn try_as<T: ABEValidator>(self) -> Result<TypedABE<T>, MatchError> {
TypedABE::from(self.0)
}
}
impl<A> Deref for TypedABE<A> {
type Target = Vec<ABE>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<O: ABEValidator> TryFrom<&[ABE]> for TypedABE<O> {
type Error = ABEError<<O as TryFrom<ABList>>::Error>;
fn try_from(value: &[ABE]) -> Result<Self, Self::Error> {
O::check(value).map_err(ABEError::MatchError)?;
Ok(TypedABE(value.to_vec(), PhantomData))
}
}
impl<O> From<TypedABE<O>> for Expr {
fn from(val: TypedABE<O>) -> Self {
Expr::Lst(val.0)
}
}
impl<O> From<TypedABE<O>> for Vec<ABE> {
fn from(val: TypedABE<O>) -> Self {
val.0
}
}
impl<O: ABEValidator> TryFrom<&[u8]> for TypedABE<O> {
type Error = ABEError<O::Error>;
fn try_from(s: &[u8]) -> Result<Self, Self::Error> {
let abe = parse_abe_b(s).map_err(ABEError::Parse)?;
O::check(&abe).map_err(ABEError::MatchError)?;
Ok(TypedABE(abe, PhantomData))
}
}
impl<O: ABEValidator> FromStr for TypedABE<O> {
type Err = ABEError<O::Error>;
fn from_str(s: &str) -> Result<Self, Self::Err> {
s.as_bytes().try_into()
}
}
impl<O> Display for TypedABE<O> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.iter().try_for_each(|v| Display::fmt(v, f))?;
Ok(())
}
}
impl<O> std::fmt::Debug for TypedABE<O> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_list().entries(&self.0).finish()
}
}
impl ABEValidator for Vec<u8> {
fn check(_b: &[ABE]) -> Result<(), MatchError> {
Ok(())
}
}
impl ABEValidator for ABList {
fn check(_b: &[ABE]) -> Result<(), MatchError> {
Ok(())
}
}
pub type AnyABE = TypedABE<ABList>;
impl From<Vec<ABE>> for AnyABE {
fn from(value: Vec<ABE>) -> Self {
TypedABE(value,PhantomData)
}
}
impl ABEValidator for String {
fn check(b: &[ABE]) -> Result<(), MatchError> {
let [_] = exact(b)?;
Ok(())
}
}
impl TryFrom<ABList> for String {
type Error = ABEError<FromUtf8Error>;
fn try_from(value: ABList) -> Result<Self, Self::Error> {
let b = value.into_exact_bytes().map_err(|_| {
ABEError::MatchError(MatchError {
at: "".into(),
err: MatchErrorKind::ExpectedExpr,
})
})?;
String::from_utf8(b).map_err(ABEError::TryFrom)
}
}
pub fn eval_vec<A: ABEValidator>(
v: Vec<TypedABE<A>>,
e: &EvalCtx<impl Scope>,
) -> Result<Vec<A>, ABEError<<A as TryFrom<ABList>>::Error>> {
v.into_iter().map(|v| v.eval(e)).try_collect()
}
pub trait ToABE {
fn to_abe_str(&self) -> String {
let mut st = String::new();
self.write_abe(&mut |abe| st.push_str(&abe.to_string()));
st
}
fn to_abe(&self) -> Vec<ABE>{
let mut v = vec![];
self.write_abe(&mut |abe| v.push(abe));
v
}
fn write_abe(&self, out: &mut dyn FnMut(ABE)){
self.to_abe().into_iter().for_each(out)
}
}
#[derive(Clone)]
pub struct CList(pub Vec<Vec<u8>>);
impl ABEValidator for CList {
fn check(b: &[ABE]) -> Result<(), MatchError> {
for i in b{
if matches!(i,ABE::Ctr(_)) { is_fslash(i)?;}
}
Ok(())
}
}
impl TryFrom<ABList> for CList{
type Error = MatchErrorKind;
fn try_from(value: ABList) -> Result<Self, Self::Error> {
value.lst.into_iter()
.map(|(b,c)| if !matches!(c,None | Some(Ctr::Colon)) {Err(MatchErrorKind::ExpectedColon)}else {Ok(b)})
.try_collect()
.map(CList)
}
}