trellis_core/
output_payload.rs1use core::any::Any;
2use core::fmt;
3
4pub(crate) trait StoredOutput: Any + Send + Sync {
5 fn clone_box(&self) -> Box<dyn StoredOutput>;
6 fn equals(&self, other: &dyn StoredOutput) -> bool;
7 fn as_any(&self) -> &dyn Any;
8 fn type_name(&self) -> &'static str;
9}
10
11impl Clone for Box<dyn StoredOutput> {
12 fn clone(&self) -> Self {
13 self.clone_box()
14 }
15}
16
17#[derive(Clone)]
18pub(crate) struct OutputValue<T> {
19 value: T,
20}
21
22impl<T> OutputValue<T> {
23 pub(crate) fn new(value: T) -> Self {
24 Self { value }
25 }
26
27 pub(crate) fn get(&self) -> &T {
28 &self.value
29 }
30}
31
32impl<T> StoredOutput for OutputValue<T>
33where
34 T: Clone + PartialEq + Send + Sync + 'static,
35{
36 fn clone_box(&self) -> Box<dyn StoredOutput> {
37 Box::new(self.clone())
38 }
39
40 fn equals(&self, other: &dyn StoredOutput) -> bool {
41 other
42 .as_any()
43 .downcast_ref::<OutputValue<T>>()
44 .is_some_and(|other| self.value == other.value)
45 }
46
47 fn as_any(&self) -> &dyn Any {
48 self
49 }
50
51 fn type_name(&self) -> &'static str {
52 core::any::type_name::<T>()
53 }
54}
55
56#[derive(Clone)]
58pub struct OutputPayload {
59 value: Box<dyn StoredOutput>,
60}
61
62impl OutputPayload {
63 pub fn new<T>(value: T) -> Self
65 where
66 T: Clone + PartialEq + Send + Sync + 'static,
67 {
68 Self {
69 value: Box::new(OutputValue::new(value)),
70 }
71 }
72
73 pub(crate) fn from_stored(value: Box<dyn StoredOutput>) -> Self {
74 Self { value }
75 }
76
77 pub fn get<T>(&self) -> Option<&T>
79 where
80 T: Clone + PartialEq + Send + Sync + 'static,
81 {
82 self.value
83 .as_any()
84 .downcast_ref::<OutputValue<T>>()
85 .map(OutputValue::get)
86 }
87
88 pub fn type_name(&self) -> &'static str {
90 self.value.type_name()
91 }
92}
93
94impl fmt::Debug for OutputPayload {
95 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
96 f.debug_struct("OutputPayload")
97 .field("type_name", &self.type_name())
98 .finish_non_exhaustive()
99 }
100}
101
102impl PartialEq for OutputPayload {
103 fn eq(&self, other: &Self) -> bool {
104 self.value.equals(other.value.as_ref())
105 }
106}
107
108pub(crate) fn boxed_output<T>(value: T) -> Box<dyn StoredOutput>
109where
110 T: Clone + PartialEq + Send + Sync + 'static,
111{
112 Box::new(OutputValue::new(value))
113}