use core::{error::Error, fmt, marker::PhantomData};
use crate::{
Format,
indent::{Repeat, indented},
many_errors::{ManyErrors, Node},
with_context::WithContext,
};
use super::{ErrorCount, Label, LeafChain, NO_ERRORS};
pub(super) trait Marker {
const TOP_ROW: usize;
const GROUP_ROW_OFFSET: usize;
fn write_marker(f: &mut fmt::Formatter<'_>, indent: usize, index: usize) -> fmt::Result;
}
pub(super) fn draw_marked_many<M, C, E, GC, F, GF>(
errors: &ManyErrors<C, E, GC, F, GF>,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result
where
M: Marker,
E: Error + 'static,
F: Format<WithContext<C, E, F>>,
GF: Format<GC>,
{
match errors {
ManyErrors::None => f.write_str(NO_ERRORS),
ManyErrors::One(node) => draw_marked_node::<M, C, E, GC, F, GF>(node, 0, f),
ManyErrors::Many(nodes) => {
write!(f, "{}:", ErrorCount(nodes.len()))?;
draw_children::<M, C, E, GC, F, GF>(nodes, M::TOP_ROW, f)
}
}
}
fn draw_children<M, C, E, GC, F, GF>(
nodes: &[Node<C, E, GC, F, GF>],
row: usize,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result
where
M: Marker,
E: Error + 'static,
F: Format<WithContext<C, E, F>>,
GF: Format<GC>,
{
for (index, node) in nodes.iter().enumerate() {
M::write_marker(f, row, index)?;
draw_marked_node::<M, C, E, GC, F, GF>(node, row + 1, f)?;
}
Ok(())
}
fn draw_marked_node<M, C, E, GC, F, GF>(
node: &Node<C, E, GC, F, GF>,
content: usize,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result
where
M: Marker,
E: Error + 'static,
F: Format<WithContext<C, E, F>>,
GF: Format<GC>,
{
match node {
Node::Leaf(w) => indented(f, Repeat(" ", content), LeafChain(w)),
Node::Group(w) => {
indented(
f,
Repeat(" ", content),
Label::<_, GF>(&w.context, PhantomData),
)?;
match w.errors.as_ref() {
ManyErrors::None => write!(f, ": {NO_ERRORS}"),
ManyErrors::One(inner) => {
write!(f, ": ")?;
draw_marked_node::<M, C, E, GC, F, GF>(inner, content, f)
}
ManyErrors::Many(nodes) => {
write!(f, " ({}):", ErrorCount(nodes.len()))?;
draw_children::<M, C, E, GC, F, GF>(nodes, content + M::GROUP_ROW_OFFSET, f)
}
}
}
}
}