use facet_core::Facet;
use facet_diff::{DiffOptions, DiffReport, diff_new_peek_with_options};
use facet_reflect::Peek;
#[derive(Debug, Clone, Default)]
pub struct SameOptions {
float_tolerance: Option<f64>,
}
impl SameOptions {
pub fn new() -> Self {
Self::default()
}
pub const fn float_tolerance(mut self, tolerance: f64) -> Self {
self.float_tolerance = Some(tolerance);
self
}
}
pub enum Sameness {
Same,
Different(String),
Opaque {
type_name: &'static str,
},
}
pub enum SameReport<'mem, 'facet> {
Same,
Different(Box<DiffReport<'mem, 'facet>>),
Opaque {
type_name: &'static str,
},
}
impl<'mem, 'facet> SameReport<'mem, 'facet> {
pub const fn is_same(&self) -> bool {
matches!(self, Self::Same)
}
pub fn into_sameness(self) -> Sameness {
match self {
SameReport::Same => Sameness::Same,
SameReport::Different(report) => Sameness::Different(report.legacy_string()),
SameReport::Opaque { type_name } => Sameness::Opaque { type_name },
}
}
pub fn diff(&self) -> Option<&DiffReport<'mem, 'facet>> {
match self {
SameReport::Different(report) => Some(report.as_ref()),
_ => None,
}
}
}
pub fn check_same<'f, T: Facet<'f>>(left: &T, right: &T) -> Sameness {
check_same_report(left, right).into_sameness()
}
pub fn check_same_report<'f, 'mem, T: Facet<'f>>(
left: &'mem T,
right: &'mem T,
) -> SameReport<'mem, 'f> {
check_same_with_report(left, right, SameOptions::default())
}
pub fn check_same_with<'f, T: Facet<'f>>(left: &T, right: &T, options: SameOptions) -> Sameness {
check_same_with_report(left, right, options).into_sameness()
}
pub fn check_same_with_report<'f, 'mem, T: Facet<'f>>(
left: &'mem T,
right: &'mem T,
options: SameOptions,
) -> SameReport<'mem, 'f> {
check_sameish_with_report(left, right, options)
}
pub fn check_sameish<'f, T: Facet<'f>, U: Facet<'f>>(left: &T, right: &U) -> Sameness {
check_sameish_report(left, right).into_sameness()
}
pub fn check_sameish_report<'f, 'mem, T: Facet<'f>, U: Facet<'f>>(
left: &'mem T,
right: &'mem U,
) -> SameReport<'mem, 'f> {
check_sameish_with_report(left, right, SameOptions::default())
}
pub fn check_sameish_with<'f, T: Facet<'f>, U: Facet<'f>>(
left: &T,
right: &U,
options: SameOptions,
) -> Sameness {
check_sameish_with_report(left, right, options).into_sameness()
}
pub fn check_sameish_with_report<'f, 'mem, T: Facet<'f>, U: Facet<'f>>(
left: &'mem T,
right: &'mem U,
options: SameOptions,
) -> SameReport<'mem, 'f> {
let left_peek = Peek::new(left);
let right_peek = Peek::new(right);
let mut diff_options = DiffOptions::new();
if let Some(tol) = options.float_tolerance {
diff_options = diff_options.with_float_tolerance(tol);
}
let diff = diff_new_peek_with_options(left_peek, right_peek, &diff_options);
if diff.is_equal() {
SameReport::Same
} else {
let mut report = DiffReport::new(diff, left_peek, right_peek);
if let Some(tol) = options.float_tolerance {
report = report.with_float_tolerance(tol);
}
SameReport::Different(Box::new(report))
}
}