use std::fmt;
use crate::migration::fields::Role;
use amethystate_core::path::StorePath;
pub struct FieldView<'a> {
pub declared: &'static str,
pub stored: &'static str,
pub at: StorePath,
pub type_name: &'static str,
pub described: &'static str,
pub role: Role,
pub volatile: bool,
pub shown: String,
pub disagreement: Option<Disagreement>,
pub inside: Option<&'a dyn Inspect>,
}
#[derive(Debug, Clone)]
pub struct Disagreement {
pub at: StorePath,
pub reason: Reason,
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub enum Reason {
WillNotRead(std::sync::Arc<str>),
Occupied(std::sync::Arc<str>),
Closed,
NotWrittenBack(std::sync::Arc<str>),
}
impl fmt::Display for Reason {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Reason::WillNotRead(why) => write!(f, "will not read: {why}"),
Reason::Occupied(why) => write!(f, "already held something else: {why}"),
Reason::Closed => f.write_str("the store was closed, so this is the last it heard"),
Reason::NotWrittenBack(why) => {
write!(
f,
"put right by its rule, and the store would not take it back: {why}"
)
}
}
}
}
impl fmt::Display for Disagreement {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self { at, reason } = self;
write!(f, "{at} {reason}")
}
}
impl std::error::Error for Disagreement {}
pub trait Inspect {
fn at(&self) -> StorePath;
fn field_count(&self) -> usize;
fn field_at(&self, index: usize) -> Option<FieldView<'_>>;
fn fields(&self) -> Fields<'_>
where
Self: Sized,
{
Fields {
of: self,
next: 0,
left: self.field_count(),
}
}
fn field(&self, declared: &str) -> Option<FieldView<'_>>
where
Self: Sized,
{
(0..self.field_count())
.filter_map(|i| self.field_at(i))
.find(|view| view.declared == declared)
}
}
pub struct Fields<'a> {
of: &'a dyn Inspect,
next: usize,
left: usize,
}
impl<'a> Iterator for Fields<'a> {
type Item = FieldView<'a>;
fn next(&mut self) -> Option<Self::Item> {
let view = self.of.field_at(self.next)?;
self.next += 1;
self.left -= 1;
Some(view)
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.left, Some(self.left))
}
}
impl ExactSizeIterator for Fields<'_> {}