restate_sdk_shared_core/
fmt.rs1use std::fmt;
2use std::sync::OnceLock;
3
4pub trait ErrorFormatter: Send + Sync + fmt::Debug + 'static {
5 fn display_closed_error(&self, f: &mut fmt::Formatter<'_>, event: &str) -> fmt::Result {
6 write!(f, "State machine was closed when invoking '{event}'")
7 }
8}
9
10static GLOBAL_ERROR_FORMATTER: OnceLock<Box<dyn ErrorFormatter>> = OnceLock::new();
11
12pub fn set_error_formatter(formatter: impl ErrorFormatter + 'static) -> bool {
18 GLOBAL_ERROR_FORMATTER.set(Box::new(formatter)).is_ok()
19}
20
21#[derive(Debug)]
22struct DefaultErrorFormatter;
23
24impl ErrorFormatter for DefaultErrorFormatter {}
25
26macro_rules! delegate_to_formatter {
27 ($fn_name:ident($($param_name:ident: $param_type:ty),*) -> $return_type:ty) => {
28 pub(crate) fn $fn_name($($param_name: $param_type),*) -> $return_type {
29 if let Some(custom_formatter) = GLOBAL_ERROR_FORMATTER.get() {
30 custom_formatter.$fn_name($($param_name),*)
31 } else {
32 DefaultErrorFormatter.$fn_name($($param_name),*)
33 }
34 }
35 };
36}
37
38delegate_to_formatter!(display_closed_error(f: &mut fmt::Formatter<'_>, event: &str) -> fmt::Result);
39
40pub(crate) struct DiffFormatter<'a, 'b> {
41 fmt: &'a mut fmt::Formatter<'b>,
42 indentation: &'static str,
43}
44
45impl<'a, 'b: 'a> DiffFormatter<'a, 'b> {
46 pub(crate) fn new(fmt: &'a mut fmt::Formatter<'b>, indentation: &'static str) -> Self {
47 Self { fmt, indentation }
48 }
49
50 pub(crate) fn write_diff(
51 &mut self,
52 field_name: &'static str,
53 actual: impl fmt::Display,
54 expected: impl fmt::Display,
55 ) -> fmt::Result {
56 write!(
57 self.fmt,
58 "\n{}{field_name}: {actual} != {expected}",
59 self.indentation
60 )
61 }
62
63 pub(crate) fn write_bytes_diff(
64 &mut self,
65 field_name: &'static str,
66 actual: &[u8],
67 expected: &[u8],
68 ) -> fmt::Result {
69 write!(self.fmt, "\n{}{field_name}: ", self.indentation)?;
70 match (std::str::from_utf8(actual), std::str::from_utf8(expected)) {
71 (Ok(actual), Ok(expected)) => {
72 write!(self.fmt, "'{actual}' != '{expected}'",)
73 }
74 (Ok(actual), Err(_)) => {
75 write!(self.fmt, "'{actual}' != {expected:?}")
76 }
77 (Err(_), Ok(expected)) => {
78 write!(self.fmt, "{actual:?} != '{expected}'")
79 }
80 (Err(_), Err(_)) => {
81 write!(self.fmt, "{actual:?} != {expected:?}")
82 }
83 }
84 }
85}