use core::{fmt, marker::PhantomData};
use derive_where::derive_where;
use crate::Format;
#[derive_where(Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct Add<L, R>(PhantomData<fn() -> (L, R)>);
impl<L: fmt::Debug + Default, R: fmt::Debug + Default> fmt::Debug for Add<L, R> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("Add")
.field(&L::default())
.field(&R::default())
.finish()
}
}
impl<E, L, R> Format<E> for Add<L, R>
where
E: ?Sized,
L: Format<E>,
R: Format<E>,
{
fn fmt(error: &E, f: &mut fmt::Formatter<'_>) -> fmt::Result {
L::fmt(error, f)?;
R::fmt(error, f)
}
}
pub mod separator;
#[cfg(test)]
mod tests {
use core::error::Error;
use super::*;
use crate::{Chain, Formatted, OneLine, Suggestion, tests::Inner};
use separator::*;
fn _assert_traits() {
fn assert_all<
T: Clone + Copy + Default + PartialEq + Eq + core::hash::Hash + Send + Sync,
>() {
}
assert_all::<Add<OneLine, separator::NewLine>>();
assert_all::<Add<Add<OneLine, separator::NewLine>, Suggestion>>();
assert_all::<separator::NewLine>();
assert_all::<separator::Space>();
fn assert_format<E: ?Sized, F: Format<E>>() {}
assert_format::<crate::tests::Error, Add<OneLine, separator::NewLine>>();
assert_format::<crate::tests::Error, Add<OneLine, Chain>>();
assert_format::<crate::tests::Error, Add<Add<OneLine, separator::NewLine>, Suggestion>>();
fn assert_oneline<E: Error + ?Sized>()
where
OneLine: Format<E>,
{
}
assert_oneline::<crate::tests::Error>();
}
#[test]
fn test_one_line_plus_newline() {
let error = crate::tests::Error::Two(Inner::A);
assert_eq!(
Formatted::<_, Add<OneLine, NewLine>>::new(error).to_string(),
"Two: InnerA\n"
);
}
#[test]
fn test_nested_oneline_newline_suggestion() {
let error = crate::tests::Error::One;
assert_eq!(
Formatted::<_, Add<Add<OneLine, NewLine>, Suggestion>>::new(error).to_string(),
"One\nTry passing --help to see available options."
);
}
#[test]
fn test_empty_rhs_keeps_separator() {
let error = crate::tests::Error::Two(Inner::A);
assert_eq!(
Formatted::<_, Add<Add<OneLine, NewLine>, Suggestion>>::new(error).to_string(),
"Two: InnerA\n"
);
}
#[test]
fn test_right_associated_nesting() {
let error = crate::tests::Error::Two(Inner::A);
assert_eq!(
Formatted::<_, Add<OneLine, Add<NewLine, OneLine>>>::new(error).to_string(),
"Two: InnerA\nTwo: InnerA"
);
}
#[test]
fn test_debug_prints_inner() {
let add = Add::<OneLine, separator::NewLine>::default();
assert_eq!(format!("{add:?}"), "Add(OneLine, NewLine)");
}
}