restate_sdk_shared_core/
fmt.rs1use crate::CommandType;
2use std::fmt;
3use std::sync::OnceLock;
4
5pub trait CommandFormatter: Send + Sync + fmt::Debug + 'static {
6 fn ty_display(&self, ty: CommandType) -> &'static str;
7}
8
9static GLOBAL_COMMAND_FORMATTER: OnceLock<Box<dyn CommandFormatter>> = OnceLock::new();
10
11pub fn set_error_formatter(formatter: impl CommandFormatter + 'static) {
13 GLOBAL_COMMAND_FORMATTER
14 .set(Box::new(formatter))
15 .expect("Error formatter already set! It can only be set once.");
16}
17
18#[derive(Debug)]
19struct DefaultCommandFormatter;
20
21impl CommandFormatter for DefaultCommandFormatter {
22 fn ty_display(&self, ty: CommandType) -> &'static str {
23 match ty {
24 CommandType::Input => "handler input",
25 CommandType::Output => "handler return",
26 CommandType::GetState => "get state",
27 CommandType::GetStateKeys => "get state keys",
28 CommandType::SetState => "set state",
29 CommandType::ClearState => "clear state",
30 CommandType::ClearAllState => "clear all state",
31 CommandType::GetPromise => "get promise",
32 CommandType::PeekPromise => "peek promise",
33 CommandType::CompletePromise => "complete promise",
34 CommandType::Sleep => "sleep",
35 CommandType::Call => "call",
36 CommandType::OneWayCall => "one way call/send",
37 CommandType::SendSignal => "send signal",
38 CommandType::Run => "run",
39 CommandType::AttachInvocation => "attach invocation",
40 CommandType::GetInvocationOutput => "get invocation output",
41 CommandType::CompleteAwakeable => "complete awakeable",
42 CommandType::CancelInvocation => "cancel invocation",
43 }
44 }
45}
46
47pub(crate) fn display_command_ty(command_type: CommandType) -> &'static str {
48 if let Some(custom_formatter) = GLOBAL_COMMAND_FORMATTER.get() {
49 custom_formatter.ty_display(command_type)
50 } else {
51 DefaultCommandFormatter.ty_display(command_type)
52 }
53}
54
55pub(crate) struct DiffFormatter<'a, 'b> {
56 fmt: &'a mut fmt::Formatter<'b>,
57 indentation: &'static str,
58}
59
60impl<'a, 'b: 'a> DiffFormatter<'a, 'b> {
61 pub(crate) fn new(fmt: &'a mut fmt::Formatter<'b>, indentation: &'static str) -> Self {
62 Self { fmt, indentation }
63 }
64
65 pub(crate) fn write_diff(
66 &mut self,
67 field_name: &'static str,
68 actual: impl fmt::Display,
69 expected: impl fmt::Display,
70 ) -> fmt::Result {
71 write!(
72 self.fmt,
73 "\n{}{field_name}: {actual} != {expected}",
74 self.indentation
75 )
76 }
77
78 pub(crate) fn write_bytes_diff(
79 &mut self,
80 field_name: &'static str,
81 actual: &[u8],
82 expected: &[u8],
83 ) -> fmt::Result {
84 write!(self.fmt, "\n{}{field_name}: ", self.indentation)?;
85 match (std::str::from_utf8(actual), std::str::from_utf8(expected)) {
86 (Ok(actual), Ok(expected)) => {
87 write!(self.fmt, "'{actual}' != '{expected}'",)
88 }
89 (Ok(actual), Err(_)) => {
90 write!(self.fmt, "'{actual}' != {expected:?}")
91 }
92 (Err(_), Ok(expected)) => {
93 write!(self.fmt, "{actual:?} != '{expected}'")
94 }
95 (Err(_), Err(_)) => {
96 write!(self.fmt, "{actual:?} != {expected:?}")
97 }
98 }
99 }
100}