use std::fmt;
use peace_item_model::ItemId;
use serde::{Deserialize, Serialize};
use crate::{FieldNameAndType, ValueResolutionMode};
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct ValueResolutionCtx {
value_resolution_mode: ValueResolutionMode,
item_id: ItemId,
params_type_name: String,
resolution_chain: Vec<FieldNameAndType>,
}
impl ValueResolutionCtx {
pub fn new(
value_resolution_mode: ValueResolutionMode,
item_id: ItemId,
params_type_name: String,
) -> Self {
Self {
value_resolution_mode,
item_id,
params_type_name,
resolution_chain: Vec::new(),
}
}
pub fn value_resolution_mode(&self) -> ValueResolutionMode {
self.value_resolution_mode
}
pub fn item_id(&self) -> &ItemId {
&self.item_id
}
pub fn params_type_name(&self) -> &str {
&self.params_type_name
}
pub fn resolution_chain(&self) -> &[FieldNameAndType] {
self.resolution_chain.as_ref()
}
pub fn push(&mut self, field_name_and_type: FieldNameAndType) {
self.resolution_chain.push(field_name_and_type);
}
pub fn pop(&mut self) {
self.resolution_chain.pop();
}
}
impl fmt::Display for ValueResolutionCtx {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let params_type_name = self.params_type_name();
write!(f, "{params_type_name} {{")?;
if let Some((last, chain)) = self.resolution_chain().split_last() {
writeln!(f)?;
chain
.iter()
.enumerate()
.try_for_each(|(indentation, field_name_and_type)| {
let indentation = indentation + 1;
(0..indentation).try_for_each(|_| write!(f, " "))?;
let field_name = field_name_and_type.field_name();
let type_name = field_name_and_type.type_name();
writeln!(f, "{field_name}: {type_name} {{")
})?;
let indentation = self.resolution_chain().len();
(0..indentation).try_for_each(|_| write!(f, " "))?;
let field_name = last.field_name();
let type_name = last.type_name();
writeln!(f, "{field_name}: {type_name},")?;
(0..indentation).try_for_each(|_| write!(f, " "))?;
writeln!(f, "..")?;
}
(0..self.resolution_chain().len())
.rev()
.skip(1)
.try_for_each(|indentation| {
let indentation = indentation + 1;
(0..indentation).try_for_each(|_| write!(f, " "))?;
writeln!(f, "}},")?;
(0..indentation).try_for_each(|_| write!(f, " "))?;
writeln!(f, "..")
})?;
write!(f, "}}")
}
}