use core::fmt::{Debug, Display, Write};
use super::cause::Cause;
use super::exit::Exit;
use crate::runtime::FiberId;
const INDENT: &str = " ";
pub fn pretty_cause<E>(cause: &Cause<E>) -> String
where
E: Debug,
{
let mut out = String::new();
write_pretty_cause(cause, 0, &mut out);
out
}
pub fn pretty_exit<A, E>(exit: &Exit<A, E>) -> String
where
A: Debug,
E: Debug,
{
match exit {
Exit::Success(value) => format!("Success({value:?})"),
Exit::Failure(cause) => format!("Failure(\n{}\n)", pretty_cause(cause)),
}
}
fn write_pretty_cause<E>(cause: &Cause<E>, depth: usize, out: &mut String)
where
E: Debug,
{
let pad = INDENT.repeat(depth);
match cause {
Cause::Fail(error) => {
let _ = writeln!(out, "{pad}Fail({error:?})");
}
Cause::Die(message) => {
let _ = writeln!(out, "{pad}Die({message})");
}
Cause::Interrupt(fiber_id) => {
let _ = writeln!(out, "{pad}Interrupt({fiber_id})");
}
Cause::Both(left, right) => {
let _ = writeln!(out, "{pad}Both(");
write_pretty_cause(left, depth + 1, out);
write_pretty_cause(right, depth + 1, out);
let _ = writeln!(out, "{pad})");
}
Cause::Then(left, right) => {
let _ = writeln!(out, "{pad}Then(");
write_pretty_cause(left, depth + 1, out);
write_pretty_cause(right, depth + 1, out);
let _ = writeln!(out, "{pad})");
}
}
}
#[inline]
pub fn pretty_cause_inline<E>(cause: &Cause<E>) -> String
where
E: Display + Clone + 'static,
{
cause.pretty()
}
#[inline]
pub fn pretty_fiber_id(fiber_id: FiberId) -> String {
format!("{fiber_id}")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn pretty_cause_multiline_both() {
let cause = Cause::both(Cause::fail("boom"), Cause::die("defect"));
let rendered = pretty_cause(&cause);
assert!(rendered.contains("Both("));
assert!(rendered.contains("boom"));
assert!(rendered.contains("Die(defect)"));
}
#[test]
fn pretty_exit_success() {
let exit = Exit::<i32, ()>::succeed(42);
assert_eq!(pretty_exit(&exit), "Success(42)");
}
#[test]
fn pretty_exit_failure_includes_cause_tree() {
let exit = Exit::<(), &str>::fail("err");
let rendered = pretty_exit(&exit);
assert!(rendered.starts_with("Failure("));
assert!(rendered.contains("err"));
}
#[test]
fn pretty_cause_fail_then_interrupt() {
let cause = Cause::then(Cause::fail("a"), Cause::interrupt(FiberId(9)));
let rendered = pretty_cause(&cause);
assert!(rendered.contains("Then("));
assert!(rendered.contains("Interrupt"));
assert_eq!(pretty_fiber_id(FiberId(9)), "fiber-9");
}
#[test]
fn pretty_cause_inline_matches_cause_pretty() {
let cause = Cause::then(Cause::fail("a"), Cause::die("b"));
assert_eq!(pretty_cause_inline(&cause), cause.pretty());
}
}