use std::fmt::Debug;
use substrate_data::frame::{self, to_frame};
use substrate_data::{Schema, from_text, read_bytes, to_bytes, to_text};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum Verdict {
Reads,
Rejects,
Garbage,
Lazy,
}
impl Verdict {
pub(crate) fn label(self) -> &'static str {
match self {
Verdict::Reads => "reads",
Verdict::Rejects => "rejects",
Verdict::Garbage => "**garbage**",
Verdict::Lazy => "fails when iterated",
}
}
}
#[derive(Clone, Copy, Debug)]
pub(crate) struct Cells {
pub(crate) frame: Verdict,
pub(crate) binary: Verdict,
pub(crate) text: Verdict,
}
#[derive(Debug)]
pub(crate) struct Row {
pub(crate) group: Group,
pub(crate) change: &'static str,
pub(crate) new_reads_old: Cells,
pub(crate) old_reads_new: Cells,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum Group {
Fields,
Numbers,
Options,
Enums,
Nested,
}
fn judge<R: PartialEq>(got: Option<R>, want: Option<&R>) -> Verdict {
match (got, want) {
(None, _) => Verdict::Rejects,
(Some(got), Some(want)) if got == *want => Verdict::Reads,
_ => Verdict::Garbage,
}
}
pub(crate) fn cells<W: Schema, R: Schema + PartialEq + Debug>(
written: &W,
want: Option<&R>,
) -> Cells {
let frame = judge(frame::read_frame::<R>(&to_frame(written)), want);
let binary = judge(read_bytes::<R>(&to_bytes(written)).ok(), want);
let text = judge(
from_text::<R>(&to_text(written))
.ok()
.map(|read| read.value),
want,
);
Cells {
frame,
binary,
text,
}
}
pub(crate) fn row<O, N>(
group: Group,
change: &'static str,
old: (O, Option<N>),
new: (N, Option<O>),
) -> Row
where
O: Schema + PartialEq + Debug,
N: Schema + PartialEq + Debug,
{
let ((old, old_want), (new, new_want)) = (old, new);
Row {
group,
change,
new_reads_old: cells::<O, N>(&old, old_want.as_ref()),
old_reads_new: cells::<N, O>(&new, new_want.as_ref()),
}
}