use std::io::{Read, Write};
use crate::{
common::traits::private::Sealed,
v0::{
config::Config,
expr::{
error::{ComposeError, DefaultComposeError, ExprReadWithComposerError},
Expr, ExprTrueLiteral,
},
raw::VariableLengthEnum,
tokens::ExprToken,
},
};
use super::{
error::{DecomposeError, ExprWriteWithDecomposerError},
ExprAddition, ExprBinaryFloat32Literal, ExprBinaryFloat64Literal, ExprCube, ExprCubeRoot,
ExprDivision, ExprFalseLiteral, ExprIntDivision, ExprIntRoot, ExprModulo, ExprMultiplication,
ExprNegation, ExprPower, ExprReciprocal, ExprRoot, ExprSignedIntLiteral, ExprSquare,
ExprSquareRoot, ExprSubtraction, ExprUnsignedIntLiteral, ExprVariable,
};
pub trait ExprObj<S: Sized>: Sealed + Sized + Into<Expr<S>> + TryFrom<Expr<S>> {
fn token(&self) -> ExprToken;
fn into_expr(self) -> Expr<S> {
self.into()
}
}
pub(crate) trait EnumExpr<S: Sized>:
Sealed + TryFrom<VariableLengthEnum> + Into<VariableLengthEnum>
{
fn variable_length_enum(&self) -> &VariableLengthEnum;
}
pub(crate) trait PureExpr<S: Sized>: Sealed + From<()> {}
pub trait BinaryOperationExpr<S: Sized>: Sealed + Into<(S, S)> + From<(S, S)> {
fn lhs(&self) -> &S;
fn rhs(&self) -> &S;
fn lhs_mut(&mut self) -> &mut S;
fn rhs_mut(&mut self) -> &mut S;
}
pub trait UnaryOperationExpr<S: Sized>: Sealed + From<S> + AsRef<S> + AsMut<S> {
fn inner(&self) -> &S {
self.as_ref()
}
fn inner_mut(&mut self) -> &mut S {
self.as_mut()
}
fn into_inner(self) -> S;
}
macro_rules! compose_expr {
($name:ident, $type:ty) => {
fn $name(&mut self, expr: $type) -> Result<S, ComposeError<Self::Error>> {
self.compose_default(expr)
}
};
}
pub trait Composer<S: Sized> {
type Error: std::error::Error;
#[inline]
#[allow(unused_variables)]
fn compose_default<E: ExprObj<S>>(&mut self, expr: E) -> Result<S, ComposeError<Self::Error>> {
Err(ComposeError::DefaultError(
DefaultComposeError::ComposeNotImplemented,
))
}
compose_expr!(compose_variable, ExprVariable<S>);
compose_expr!(compose_true_literal, ExprTrueLiteral<S>);
compose_expr!(compose_false_literal, ExprFalseLiteral<S>);
compose_expr!(compose_binary_float_32_literal, ExprBinaryFloat32Literal<S>);
compose_expr!(compose_binary_float_64_literal, ExprBinaryFloat64Literal<S>);
compose_expr!(compose_signed_int_literal, ExprSignedIntLiteral<S>);
compose_expr!(compose_unsigned_int_literal, ExprUnsignedIntLiteral<S>);
compose_expr!(compose_addition, ExprAddition<S>);
compose_expr!(compose_subtraction, ExprSubtraction<S>);
compose_expr!(compose_multiplication, ExprMultiplication<S>);
compose_expr!(compose_division, ExprDivision<S>);
compose_expr!(compose_int_division, ExprIntDivision<S>);
compose_expr!(compose_modulo, ExprModulo<S>);
compose_expr!(compose_power, ExprPower<S>);
compose_expr!(compose_negation, ExprNegation<S>);
compose_expr!(compose_root, ExprRoot<S>);
compose_expr!(compose_int_root, ExprIntRoot<S>);
compose_expr!(compose_square, ExprSquare<S>);
compose_expr!(compose_cube, ExprCube<S>);
compose_expr!(compose_square_root, ExprSquareRoot<S>);
compose_expr!(compose_cube_root, ExprCubeRoot<S>);
compose_expr!(compose_reciprocal, ExprReciprocal<S>);
}
pub(crate) trait TryReadFromWithComposer<
R: ?Sized + Read,
S: Sized,
C: ?Sized + Config,
CP: ?Sized + Composer<S>,
>
{
fn try_read_with_composer(
byte_stream: &mut R,
config: &C,
composer: &mut CP,
) -> Result<S, ExprReadWithComposerError<CP::Error>>;
}
pub(crate) trait TryReadFromWithComposerAndLength<
R: ?Sized + Read,
S: Sized,
C: ?Sized + Config,
CP: ?Sized + Composer<S>,
>
{
fn try_read_with_composer(
byte_stream: &mut R,
config: &C,
composer: &mut CP,
byte_length: usize,
) -> Result<S, ExprReadWithComposerError<CP::Error>>;
}
pub trait DecompositionRefContainer<'a, S: Sized> {
fn inner_as_ref(&self) -> &'a Expr<S>;
}
impl<'a, S: Sized> DecompositionRefContainer<'a, S> for &'a Expr<S> {
fn inner_as_ref(&self) -> &'a super::Expr<S> {
self
}
}
pub trait Decomposer<S: Sized> {
type Error: std::error::Error;
fn decompose_as_ref<'a>(
&mut self,
storage_ref: &'a S,
) -> Result<impl DecompositionRefContainer<'a, S>, DecomposeError<Self::Error>>;
}
pub(crate) trait TryWriteToWithDecomposer<
W: ?Sized + Write,
S: Sized,
C: ?Sized + Config,
DP: ?Sized + Decomposer<S>,
>
{
fn try_write_with_decomposer(
&self,
writer: &mut W,
config: &C,
decomposer: &mut DP,
) -> Result<(), ExprWriteWithDecomposerError<DP::Error>>;
}