1#[macro_export]
10macro_rules! dyn_newtype_define {
11 ( $(#[$outer:meta])*
12 $vis:vis $name:ident<$lifetime:lifetime>(Box<$trait:ident>)
13 ) => {
14 $crate::_dyn_newtype_define_inner!{
15 $(#[$outer])*
16 $vis $name<$lifetime>(Box<$trait>)
17 }
18 $crate::_dyn_newtype_impl_deref_mut!($name<$lifetime>);
19 };
20 ( $(#[$outer:meta])*
21 $vis:vis $name:ident(Box<$trait:ident>)
22 ) => {
23 $crate::_dyn_newtype_define_inner!{
24 $(#[$outer])*
25 $vis $name(Box<$trait>)
26 }
27 $crate::_dyn_newtype_impl_deref_mut!($name);
28 };
29 ( $(#[$outer:meta])*
30 $vis:vis $name:ident<$lifetime:lifetime>(Arc<$trait:ident>)
31 ) => {
32 $crate::_dyn_newtype_define_inner!{
33 $(#[$outer])*
34 $vis $name<$lifetime>(Arc<$trait>)
35 }
36 };
37 ( $(#[$outer:meta])*
38 $vis:vis $name:ident(Arc<$trait:ident>)
39 ) => {
40 $crate::_dyn_newtype_define_inner!{
41 $(#[$outer])*
42 $vis $name(Arc<$trait>)
43 }
44 };
45}
46
47#[macro_export]
48macro_rules! _dyn_newtype_define_inner {
49 ( $(#[$outer:meta])*
50 $vis:vis $name:ident($container:ident<$trait:ident>)
51 ) => {
52 $(#[$outer])*
53 $vis struct $name { inner: $container<$crate::maybe_add_send_sync!(dyn $trait + 'static)> }
54
55 impl std::ops::Deref for $name {
56 type Target = $crate::maybe_add_send_sync!(dyn $trait + 'static);
57
58 fn deref(&self) -> &<Self as std::ops::Deref>::Target {
59 &*self.inner
60 }
61
62 }
63
64 impl $name {
65 pub fn get_mut(&mut self) -> Option<&mut <Self as std::ops::Deref>::Target> {
66 Arc::get_mut(&mut self.inner)
67 }
68 }
69
70 impl<I> From<I> for $name
71 where
72 I: $trait + $crate::task::MaybeSend + $crate::task::MaybeSync + 'static,
73 {
74 fn from(i: I) -> Self {
75 Self { inner: $container::new(i) }
76 }
77 }
78
79 impl std::fmt::Debug for $name {
80 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
81 std::fmt::Debug::fmt(&self.inner, f)
82 }
83 }
84 };
85 ( $(#[$outer:meta])*
86 $vis:vis $name:ident<$lifetime:lifetime>($container:ident<$trait:ident>)
87 ) => {
88 $(#[$outer])*
89 $vis struct $name<$lifetime> { inner: $container<dyn $trait<$lifetime> + Send + $lifetime> }
90
91 impl<$lifetime> std::ops::Deref for $name<$lifetime> {
92 type Target = $crate::maybe_add_send!(dyn $trait<$lifetime> + $lifetime);
93
94 fn deref(&self) -> &<Self as std::ops::Deref>::Target {
95 &*self.inner
96 }
97 }
98
99 impl<$lifetime, I> From<I> for $name<$lifetime>
100 where
101 I: $trait<$lifetime> + $crate::task::MaybeSend + $lifetime,
102 {
103 fn from(i: I) -> Self {
104 Self($container::new(i))
105 }
106 }
107 };
108}
109
110#[macro_export]
113macro_rules! dyn_newtype_display_passthrough {
114 ($newtype:ty) => {
115 impl std::fmt::Display for $newtype {
116 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
117 std::fmt::Display::fmt(&self.inner, f)
118 }
119 }
120 };
121}
122
123#[macro_export]
126macro_rules! module_plugin_dyn_newtype_define{
127 ( $(#[$outer:meta])*
128 $vis:vis $name:ident<$lifetime:lifetime>(Box<$trait:ident>)
129 ) => {
130 $crate::_dyn_newtype_define_with_instance_id_inner!{
131 $(#[$outer])*
132 $vis $name<$lifetime>(Box<$trait>)
133 }
134 $crate::_dyn_newtype_impl_deref_mut!($name<$lifetime>);
135 };
136 ( $(#[$outer:meta])*
137 $vis:vis $name:ident(Box<$trait:ident>)
138 ) => {
139 $crate::_dyn_newtype_define_with_instance_id_inner!{
140 $(#[$outer])*
141 $vis $name(Box<$trait>)
142 }
143 $crate::_dyn_newtype_impl_deref_mut!($name);
144 };
145 ( $(#[$outer:meta])*
146 $vis:vis $name:ident<$lifetime:lifetime>(Arc<$trait:ident>)
147 ) => {
148 $crate::_dyn_newtype_define_with_instance_id_inner!{
149 $(#[$outer])*
150 $vis $name<$lifetime>(Arc<$trait>)
151 }
152 };
153 ( $(#[$outer:meta])*
154 $vis:vis $name:ident(Arc<$trait:ident>)
155 ) => {
156 $crate::_dyn_newtype_define_with_instance_id_inner!{
157 $(#[$outer])*
158 $vis $name(Arc<$trait>)
159 }
160 };
161}
162
163#[macro_export]
164macro_rules! _dyn_newtype_define_with_instance_id_inner {
165 ( $(#[$outer:meta])*
166 $vis:vis $name:ident($container:ident<$trait:ident>)
167 ) => {
168 $(#[$outer])*
169 $vis struct $name {
170 module_instance_id: $crate::core::ModuleInstanceId,
171 inner: $container<$crate::maybe_add_send_sync!(dyn $trait + 'static)>,
172 }
173
174 impl std::ops::Deref for $name {
175 type Target = $crate::maybe_add_send_sync!(dyn $trait + 'static);
176
177 fn deref(&self) -> &<Self as std::ops::Deref>::Target {
178 &*self.inner
179 }
180
181 }
182
183 impl $name {
184 pub fn module_instance_id(&self) -> ::fedimint_core::core::ModuleInstanceId {
185 self.module_instance_id
186 }
187
188 pub fn from_typed<I>(
189 module_instance_id: ::fedimint_core::core::ModuleInstanceId,
190 typed: I
191 ) -> Self
192 where
193 I: $trait + $crate::task::MaybeSend + $crate::task::MaybeSync + 'static {
194
195 Self { inner: $container::new(typed), module_instance_id }
196 }
197
198 pub fn from_parts(
199 module_instance_id: $crate::core::ModuleInstanceId,
200 dynbox: $container<$crate::maybe_add_send_sync!(dyn $trait + 'static)>
201 ) -> Self {
202 Self { inner: dynbox, module_instance_id }
203 }
204 }
205
206 impl std::fmt::Debug for $name {
207 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
208 let mut d = f.debug_struct(stringify!($name));
209 d.field("id", &self.module_instance_id);
210 if let Some(kind) = self.module_kind() {
211 d.field("kind", &kind);
212 } else {
213 d.field("kind", &"?");
214
215 }
216 d
217 .field("inner", &self.inner)
218 .finish()
219 }
220 }
221 };
222 ( $(#[$outer:meta])*
223 $vis:vis $name:ident<$lifetime:lifetime>($container:ident<$trait:ident>)
224 ) => {
225 $(#[$outer])*
226 $vis struct $name<$lifetime>{ inner: $container<dyn $trait<$lifetime> + Send + $lifetime>, module_instance_id: ModuleInstanceId }
227
228 impl $name {
229 pub fn module_instance_id(&self) -> ::fedimint_core::core::ModuleInstanceId {
230 self.1
231 }
232
233 pub fn from_typed<I>(module_instance_id: ::fedimint_core::core::ModuleInstanceId, typed: I) -> Self
234 where
235 I: $trait + $crate::task::MaybeSend + $crate::task::MaybeSync + 'static {
236
237 Self { inner: $container::new(typed), module_instance_id }
238 }
239 }
240
241 impl<$lifetime> std::ops::Deref for $name<$lifetime> {
242 type Target = $crate::maybe_add_send_sync!(dyn $trait + 'static);
243
244 fn deref(&self) -> &<Self as std::ops::Deref>::Target {
245 &*self.inner
246 }
247 }
248 };
249}
250
251#[macro_export]
252macro_rules! _dyn_newtype_impl_deref_mut {
253 ($name:ident<$lifetime:lifetime>) => {
254 impl<$lifetime> std::ops::DerefMut for $name<$lifetime> {
255 fn deref_mut(&mut self) -> &mut <Self as std::ops::Deref>::Target {
256 &mut *self.inner
257 }
258 }
259 };
260 ($name:ident) => {
261 impl std::ops::DerefMut for $name {
262 fn deref_mut(&mut self) -> &mut <Self as std::ops::Deref>::Target {
263 &mut *self.inner
264 }
265 }
266 };
267}
268
269#[macro_export]
284macro_rules! dyn_newtype_impl_dyn_clone_passthrough {
285 ($name:ident) => {
286 impl Clone for $name {
287 fn clone(&self) -> Self {
288 self.0.clone()
289 }
290 }
291 };
292}
293
294#[macro_export]
295macro_rules! module_plugin_dyn_newtype_clone_passthrough {
296 ($name:ident) => {
297 impl Clone for $name {
298 fn clone(&self) -> Self {
299 self.inner.clone(self.module_instance_id)
300 }
301 }
302 };
303}
304
305#[macro_export]
310macro_rules! module_plugin_dyn_newtype_encode_decode {
311 ($name:ident) => {
312 impl Encodable for $name {
313 fn consensus_encode<W: std::io::Write>(
314 &self,
315 writer: &mut W,
316 ) -> Result<(), std::io::Error> {
317 self.module_instance_id.consensus_encode(writer)?;
318
319 let mut buf = Vec::with_capacity(512);
320 self.inner.consensus_encode_dyn(&mut buf)?;
321
322 buf.consensus_encode(writer)?;
323
324 Ok(())
325 }
326 }
327
328 impl Decodable for $name {
329 fn consensus_decode_partial_from_finite_reader<R: std::io::Read>(
330 reader: &mut R,
331 decoders: &$crate::module::registry::ModuleDecoderRegistry,
332 ) -> Result<Self, fedimint_core::encoding::DecodeError> {
333 let module_instance_id =
334 fedimint_core::core::ModuleInstanceId::consensus_decode_partial_from_finite_reader(
335 reader, decoders,
336 )?;
337 let val = match decoders.get(module_instance_id) {
338 Some(decoder) => {
339 let total_len_u64 =
340 u64::consensus_decode_partial_from_finite_reader(reader, decoders)?;
341 decoder.decode_complete(
342 reader,
343 total_len_u64,
344 module_instance_id,
345 decoders,
346 )?
347 }
348 None => match decoders.decoding_mode() {
349 $crate::module::registry::DecodingMode::Reject => {
350 return Err(fedimint_core::encoding::DecodeError::new_custom(
351 anyhow::anyhow!(
352 "Module decoder not available for module instance: {module_instance_id} when decoding {}", std::any::type_name::<Self>()
353 ),
354 ));
355 }
356 $crate::module::registry::DecodingMode::Fallback => $name::from_typed(
357 module_instance_id,
358 $crate::core::DynUnknown(
359 Vec::<u8>::consensus_decode_partial_from_finite_reader(
360 reader,
361 &Default::default(),
362 )?,
363 ),
364 ),
365 },
366 };
367
368 Ok(val)
369 }
370 }
371 };
372}
373
374#[macro_export]
385macro_rules! module_plugin_static_trait_define{
386 ( $(#[$outer:meta])*
387 $dyn_newtype:ident, $static_trait:ident, $dyn_trait:ident, { $($extra_methods:tt)* }, { $($extra_impls:tt)* }
388 ) => {
389 pub trait $static_trait:
390 std::fmt::Debug + std::fmt::Display + std::cmp::PartialEq + std::hash::Hash + DynEncodable + Decodable + Encodable + Clone + IntoDynInstance<DynType = $dyn_newtype> + Send + Sync + 'static
391 {
392 const KIND : ModuleKind;
393
394 $($extra_methods)*
395 }
396
397 impl $dyn_trait for ::fedimint_core::core::DynUnknown {
398 fn as_any(&self) -> &(dyn Any + Send + Sync) {
399 self
400 }
401
402 fn module_kind(&self) -> Option<ModuleKind> {
403 None
404 }
405
406 fn clone(&self, instance_id: ::fedimint_core::core::ModuleInstanceId) -> $dyn_newtype {
407 $dyn_newtype::from_typed(instance_id, <Self as Clone>::clone(self))
408 }
409
410 fn dyn_hash(&self) -> u64 {
411 use std::hash::Hash;
412 let mut s = std::collections::hash_map::DefaultHasher::new();
413 self.hash(&mut s);
414 std::hash::Hasher::finish(&s)
415 }
416
417 $($extra_impls)*
418 }
419
420 impl<T> $dyn_trait for T
421 where
422 T: $static_trait + DynEncodable + 'static + Send + Sync,
423 {
424 fn as_any(&self) -> &(dyn Any + Send + Sync) {
425 self
426 }
427
428 fn module_kind(&self) -> Option<ModuleKind> {
429 Some(<Self as $static_trait>::KIND)
430 }
431
432 fn clone(&self, instance_id: ::fedimint_core::core::ModuleInstanceId) -> $dyn_newtype {
433 $dyn_newtype::from_typed(instance_id, <Self as Clone>::clone(self))
434 }
435
436 fn dyn_hash(&self) -> u64 {
437 let mut s = std::collections::hash_map::DefaultHasher::new();
438 self.hash(&mut s);
439 std::hash::Hasher::finish(&s)
440 }
441
442 $($extra_impls)*
443 }
444
445 impl std::hash::Hash for $dyn_newtype {
446 fn hash<H>(&self, state: &mut H)
447 where
448 H: std::hash::Hasher
449 {
450 self.module_instance_id.hash(state);
451 self.inner.dyn_hash().hash(state);
452 }
453 }
454 };
455}
456
457#[macro_export]
463macro_rules! module_plugin_static_trait_define_config{
464 ( $(#[$outer:meta])*
465 $dyn_newtype:ident, $static_trait:ident, $dyn_trait:ident, { $($extra_methods:tt)* }, { $($extra_impls:tt)* }, { $($extra_impls_unknown:tt)* }
466 ) => {
467 pub trait $static_trait:
468 std::fmt::Debug + std::fmt::Display + std::cmp::PartialEq + std::hash::Hash + DynEncodable + Decodable + Encodable + Clone + IntoDynInstance<DynType = $dyn_newtype> + Send + Sync + serde::Serialize + serde::de::DeserializeOwned + 'static
469 {
470 const KIND : ::fedimint_core::core::ModuleKind;
471 $($extra_methods)*
472 }
473
474 impl $dyn_trait for ::fedimint_core::core::DynUnknown {
475 fn as_any(&self) -> &(dyn Any + Send + Sync) {
476 self
477 }
478
479 fn module_kind(&self) -> Option<::fedimint_core::core::ModuleKind> {
480 None
481 }
482
483 fn clone(&self, instance_id: ::fedimint_core::core::ModuleInstanceId) -> $dyn_newtype {
484 $dyn_newtype::from_typed(instance_id, <Self as Clone>::clone(self))
485 }
486
487 fn dyn_hash(&self) -> u64 {
488 use std::hash::Hash;
489 let mut s = std::collections::hash_map::DefaultHasher::new();
490 self.hash(&mut s);
491 std::hash::Hasher::finish(&s)
492 }
493
494 $($extra_impls_unknown)*
495 }
496
497 impl<T> $dyn_trait for T
498 where
499 T: $static_trait + DynEncodable + 'static + Send + Sync,
500 {
501 fn as_any(&self) -> &(dyn Any + Send + Sync) {
502 self
503 }
504
505 fn module_kind(&self) -> Option<::fedimint_core::core::ModuleKind> {
506 Some(<T as $static_trait>::KIND)
507 }
508
509 fn clone(&self, instance_id: ::fedimint_core::core::ModuleInstanceId) -> $dyn_newtype {
510 $dyn_newtype::from_typed(instance_id, <Self as Clone>::clone(self))
511 }
512
513 fn dyn_hash(&self) -> u64 {
514 let mut s = std::collections::hash_map::DefaultHasher::new();
515 self.hash(&mut s);
516 std::hash::Hasher::finish(&s)
517 }
518
519 $($extra_impls)*
520 }
521
522 impl std::hash::Hash for $dyn_newtype {
523 fn hash<H>(&self, state: &mut H)
524 where
525 H: std::hash::Hasher
526 {
527 self.module_instance_id.hash(state);
528 self.inner.dyn_hash().hash(state);
529 }
530 }
531 };
532}
533
534#[macro_export]
537macro_rules! plugin_types_trait_impl_config {
538 ($common_gen:ty, $gen:ty, $gen_local:ty, $gen_consensus:ty, $cfg:ty, $cfg_local:ty, $cfg_private:ty, $cfg_consensus:ty, $cfg_client:ty) => {
539 impl fedimint_core::config::ModuleInitParams for $gen {
540 type Local = $gen_local;
541 type Consensus = $gen_consensus;
542
543 fn from_parts(local: Self::Local, consensus: Self::Consensus) -> Self {
544 Self { local, consensus }
545 }
546
547 fn to_parts(self) -> (Self::Local, Self::Consensus) {
548 (self.local, self.consensus)
549 }
550 }
551
552 impl fedimint_core::config::TypedServerModuleConsensusConfig for $cfg_consensus {
553 fn kind(&self) -> fedimint_core::core::ModuleKind {
554 <$common_gen as fedimint_core::module::CommonModuleInit>::KIND
555 }
556
557 fn version(&self) -> fedimint_core::module::ModuleConsensusVersion {
558 <$common_gen as fedimint_core::module::CommonModuleInit>::CONSENSUS_VERSION
559 }
560 }
561
562 impl fedimint_core::config::TypedServerModuleConfig for $cfg {
563 type Local = $cfg_local;
564 type Private = $cfg_private;
565 type Consensus = $cfg_consensus;
566
567 fn from_parts(
568 local: Self::Local,
569 private: Self::Private,
570 consensus: Self::Consensus,
571 ) -> Self {
572 Self {
573 local,
574 private,
575 consensus,
576 }
577 }
578
579 fn to_parts(self) -> (ModuleKind, Self::Local, Self::Private, Self::Consensus) {
580 (
581 <$common_gen as fedimint_core::module::CommonModuleInit>::KIND,
582 self.local,
583 self.private,
584 self.consensus,
585 )
586 }
587 }
588 };
589}
590
591#[macro_export]
594macro_rules! plugin_types_trait_impl_common {
595 ($kind:expr_2021, $types:ty, $client_config:ty, $input:ty, $output:ty, $outcome:ty, $ci:ty, $input_error:ty, $output_error:ty) => {
596 impl fedimint_core::module::ModuleCommon for $types {
597 type ClientConfig = $client_config;
598 type Input = $input;
599 type Output = $output;
600 type OutputOutcome = $outcome;
601 type ConsensusItem = $ci;
602 type InputError = $input_error;
603 type OutputError = $output_error;
604 }
605
606 impl fedimint_core::core::ClientConfig for $client_config {
607 const KIND: ModuleKind = $kind;
608 }
609
610 impl fedimint_core::core::IntoDynInstance for $client_config {
611 type DynType = fedimint_core::core::DynClientConfig;
612
613 fn into_dyn(self, instance_id: ModuleInstanceId) -> Self::DynType {
614 fedimint_core::core::DynClientConfig::from_typed(instance_id, self)
615 }
616 }
617
618 impl fedimint_core::core::Input for $input {
619 const KIND: ModuleKind = $kind;
620 }
621
622 impl fedimint_core::core::IntoDynInstance for $input {
623 type DynType = fedimint_core::core::DynInput;
624
625 fn into_dyn(self, instance_id: ModuleInstanceId) -> Self::DynType {
626 fedimint_core::core::DynInput::from_typed(instance_id, self)
627 }
628 }
629
630 impl fedimint_core::core::Output for $output {
631 const KIND: ModuleKind = $kind;
632 }
633
634 impl fedimint_core::core::IntoDynInstance for $output {
635 type DynType = fedimint_core::core::DynOutput;
636
637 fn into_dyn(self, instance_id: ModuleInstanceId) -> Self::DynType {
638 fedimint_core::core::DynOutput::from_typed(instance_id, self)
639 }
640 }
641
642 impl fedimint_core::core::OutputOutcome for $outcome {
643 const KIND: ModuleKind = $kind;
644 }
645
646 impl fedimint_core::core::IntoDynInstance for $outcome {
647 type DynType = fedimint_core::core::DynOutputOutcome;
648
649 fn into_dyn(self, instance_id: ModuleInstanceId) -> Self::DynType {
650 fedimint_core::core::DynOutputOutcome::from_typed(instance_id, self)
651 }
652 }
653
654 impl fedimint_core::core::ModuleConsensusItem for $ci {
655 const KIND: ModuleKind = $kind;
656 }
657
658 impl fedimint_core::core::IntoDynInstance for $ci {
659 type DynType = fedimint_core::core::DynModuleConsensusItem;
660
661 fn into_dyn(self, instance_id: ModuleInstanceId) -> Self::DynType {
662 fedimint_core::core::DynModuleConsensusItem::from_typed(instance_id, self)
663 }
664 }
665
666 impl fedimint_core::core::InputError for $input_error {
667 const KIND: ModuleKind = $kind;
668 }
669
670 impl fedimint_core::core::IntoDynInstance for $input_error {
671 type DynType = fedimint_core::core::DynInputError;
672
673 fn into_dyn(self, instance_id: ModuleInstanceId) -> Self::DynType {
674 fedimint_core::core::DynInputError::from_typed(instance_id, self)
675 }
676 }
677
678 impl fedimint_core::core::OutputError for $output_error {
679 const KIND: ModuleKind = $kind;
680 }
681
682 impl fedimint_core::core::IntoDynInstance for $output_error {
683 type DynType = fedimint_core::core::DynOutputError;
684
685 fn into_dyn(self, instance_id: ModuleInstanceId) -> Self::DynType {
686 fedimint_core::core::DynOutputError::from_typed(instance_id, self)
687 }
688 }
689 };
690}
691
692#[macro_export]
693macro_rules! erased_eq_no_instance_id {
694 ($newtype:ty) => {
695 fn erased_eq_no_instance_id(&self, other: &$newtype) -> bool {
696 let other: &Self = other
697 .as_any()
698 .downcast_ref()
699 .expect("Type is ensured in previous step");
700
701 self == other
702 }
703 };
704}
705
706#[macro_export]
707macro_rules! module_plugin_dyn_newtype_eq_passthrough {
708 ($newtype:ty) => {
709 impl PartialEq for $newtype {
710 fn eq(&self, other: &Self) -> bool {
711 if self.module_instance_id != other.module_instance_id {
712 return false;
713 }
714 self.erased_eq_no_instance_id(other)
715 }
716 }
717
718 impl Eq for $newtype {}
719 };
720}
721
722#[macro_export]
723macro_rules! module_plugin_dyn_newtype_display_passthrough {
724 ($newtype:ty) => {
725 impl std::fmt::Display for $newtype {
726 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
727 f.write_fmt(format_args!("{}-{}", self.module_instance_id, self.inner))
728 }
729 }
730 };
731}
732
733#[macro_export]
746macro_rules! extensible_associated_module_type {
747 ($name:ident, $name_v0:ident, $error:ident) => {
748 #[derive(
749 Clone,
750 Eq,
751 PartialEq,
752 Hash,
753 serde::Deserialize,
754 serde::Serialize,
755 fedimint_core::encoding::Encodable,
756 fedimint_core::encoding::Decodable,
757 )]
758 pub enum $name {
759 V0($name_v0),
760 #[encodable_default]
761 Default {
762 variant: u64,
763 bytes: Vec<u8>,
764 },
765 }
766
767 impl $name {
768 pub fn maybe_v0_ref(&self) -> Option<&$name_v0> {
769 match self {
770 $name::V0(v0) => Some(v0),
771 $name::Default { .. } => None,
772 }
773 }
774
775 pub fn ensure_v0_ref(&self) -> Result<&$name_v0, $error> {
776 match self {
777 $name::V0(v0) => Ok(v0),
778 $name::Default { variant, .. } => Err($error { variant: *variant }),
779 }
780 }
781 }
782
783 impl std::fmt::Debug for $name {
784 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
785 use $crate::bitcoin::hashes::hex::DisplayHex;
786 match self {
787 $name::V0(v0) => {
788 std::fmt::Debug::fmt(v0, f)?;
789 }
790 $name::Default { variant, bytes } => {
791 f.debug_struct(stringify!($name))
792 .field("variant", variant)
793 .field("bytes", &bytes.as_hex())
794 .finish()?;
795 }
796 }
797 Ok(())
798 }
799 }
800
801 #[derive(
802 Debug,
803 thiserror::Error,
804 Clone,
805 Eq,
806 PartialEq,
807 Hash,
808 serde::Deserialize,
809 serde::Serialize,
810 fedimint_core::encoding::Encodable,
811 fedimint_core::encoding::Decodable,
812 )]
813 #[error("Unknown {} variant {variant}", stringify!($name))]
814 pub struct $error {
815 pub variant: u64,
816 }
817
818 impl std::fmt::Display for $name {
819 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
820 match self {
821 $name::V0(inner) => std::fmt::Display::fmt(inner, f),
822 $name::Default { variant, .. } => {
823 write!(f, "Unknown {} (variant={variant})", stringify!($name))
824 }
825 }
826 }
827 }
828 };
829}