use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use crate::config::{ArithmeticOp, TypeConfig, get_standard_arithmetic_ops};
use crate::generator::generate_arithmetic_for_all_types;
pub fn generate_result_arithmetic_impls(config: &TypeConfig) -> TokenStream2 {
let ops = get_standard_arithmetic_ops();
let pattern1_impls = generate_pattern_lhs_op_result_rhs(config, &ops);
let pattern2_impls = generate_pattern_result_lhs_op_rhs(config, &ops);
quote! {
#pattern1_impls
#pattern2_impls
}
}
fn generate_pattern_lhs_op_result_rhs(
config: &TypeConfig,
ops: &[(ArithmeticOp, &str, &str, TokenStream2)],
) -> TokenStream2 {
generate_arithmetic_for_all_types(
config,
ops,
|lhs_alias,
rhs_alias,
output_alias,
trait_ident,
method_ident,
_op_symbol,
result,
_op,
_| {
if result.is_safe {
quote! {
impl #trait_ident<Result<#rhs_alias, FloatError>> for #lhs_alias {
type Output = Result<#output_alias, FloatError>;
fn #method_ident(self, rhs: Result<#rhs_alias, FloatError>) -> Self::Output {
match rhs {
Ok(b) => Ok(self.#method_ident(b)),
Err(e) => Err(e),
}
}
}
}
} else {
quote! {
impl #trait_ident<Result<#rhs_alias, FloatError>> for #lhs_alias {
type Output = Result<#output_alias, FloatError>;
fn #method_ident(self, rhs: Result<#rhs_alias, FloatError>) -> Self::Output {
match rhs {
Ok(b) => self.#method_ident(b),
Err(e) => Err(e),
}
}
}
}
}
},
)
}
fn generate_pattern_result_lhs_op_rhs(
config: &TypeConfig,
ops: &[(ArithmeticOp, &str, &str, TokenStream2)],
) -> TokenStream2 {
generate_arithmetic_for_all_types(
config,
ops,
|lhs_alias,
rhs_alias,
output_alias,
trait_ident,
method_ident,
_op_symbol,
result,
_op,
_| {
if result.is_safe {
quote! {
impl #trait_ident<#rhs_alias> for Result<#lhs_alias, FloatError> {
type Output = Result<#output_alias, FloatError>;
fn #method_ident(self, rhs: #rhs_alias) -> Self::Output {
match self {
Ok(a) => Ok(a.#method_ident(rhs)),
Err(e) => Err(e),
}
}
}
}
} else {
quote! {
impl #trait_ident<#rhs_alias> for Result<#lhs_alias, FloatError> {
type Output = Result<#output_alias, FloatError>;
fn #method_ident(self, rhs: #rhs_alias) -> Self::Output {
match self {
Ok(a) => a.#method_ident(rhs),
Err(e) => Err(e),
}
}
}
}
}
},
)
}