harmos_sdk/operations/
response.rs1use std::any::{Any, TypeId};
20use std::borrow::Borrow;
21use std::fmt;
22use std::marker::PhantomData;
23use std::ops::Deref;
24use std::sync::Arc;
25type Projection = fn(&dyn Any) -> Option<&dyn Any>;
36
37pub struct Response<T: Send + Sync + 'static> {
40 erased: ErasedResponse,
41 payload: PhantomData<fn() -> T>,
42}
43
44#[derive(Clone)]
46pub struct ErasedResponse {
47 owner: Arc<dyn Any + Send + Sync>,
48 projection: Projection,
49 payload: TypeId,
50}
51
52impl<T: Send + Sync + 'static> Response<T> {
59 pub fn new(value: T) -> Self {
60 Self::from_owner(Arc::new(value))
61 }
62
63 pub fn from_owner<U: Borrow<T> + Send + Sync + 'static>(owner: Arc<U>) -> Self {
64 Self {
65 erased: ErasedResponse {
66 owner,
67 projection: project::<T, U>,
68 payload: TypeId::of::<T>(),
69 },
70 payload: PhantomData,
71 }
72 }
73
74 pub fn ptr_eq(&self, other: &Self) -> bool {
75 Arc::ptr_eq(&self.erased.owner, &other.erased.owner)
76 }
77
78 pub fn try_unwrap(self) -> Result<T, Self> {
79 if !self.erased.owner.is::<T>() {
81 return Err(self);
82 }
83 let owner = match self.erased.owner.downcast::<T>() {
84 Ok(owner) => owner,
85 Err(_) => unreachable!("checked direct response owner type"),
86 };
87 Arc::try_unwrap(owner).map_err(Self::from_owner)
88 }
89
90 pub fn into_owned(self) -> T
92 where
93 T: Clone,
94 {
95 self.try_unwrap().unwrap_or_else(|response| (*response).clone())
96 }
97
98 pub fn into_erased(self) -> ErasedResponse {
99 self.erased
100 }
101}
102
103impl<T: Send + Sync + 'static> From<T> for Response<T> {
104 fn from(value: T) -> Self {
105 Self::new(value)
106 }
107}
108
109impl<T: Send + Sync + 'static> From<Arc<T>> for Response<T> {
110 fn from(value: Arc<T>) -> Self {
111 Self::from_owner(value)
112 }
113}
114
115impl<T: Send + Sync + 'static> Clone for Response<T> {
116 fn clone(&self) -> Self {
117 Self {
118 erased: self.erased.clone(),
119 payload: PhantomData,
120 }
121 }
122}
123
124impl<T: Send + Sync + 'static> Deref for Response<T> {
125 type Target = T;
126
127 fn deref(&self) -> &T {
128 self.erased.value::<T>().expect("response retains its declared payload")
129 }
130}
131
132impl<T: Send + Sync + 'static> AsRef<T> for Response<T> {
133 fn as_ref(&self) -> &T {
134 self
135 }
136}
137
138impl<T: Send + Sync + 'static> Borrow<T> for Response<T> {
139 fn borrow(&self) -> &T {
140 self
141 }
142}
143
144impl<T: fmt::Debug + Send + Sync + 'static> fmt::Debug for Response<T> {
145 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
146 self.deref().fmt(formatter)
147 }
148}
149
150impl<T: fmt::Display + Send + Sync + 'static> fmt::Display for Response<T> {
151 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
152 self.deref().fmt(formatter)
153 }
154}
155
156impl<T: PartialEq + Send + Sync + 'static> PartialEq for Response<T> {
157 fn eq(&self, other: &Self) -> bool {
158 self.deref() == other.deref()
159 }
160}
161
162impl<T: Eq + Send + Sync + 'static> Eq for Response<T> {}
163
164impl ErasedResponse {
165 pub fn restore<T: Send + Sync + 'static>(self) -> Option<Response<T>> {
166 if self.payload != TypeId::of::<T>() {
168 return None;
169 }
170 Some(Response { erased: self, payload: PhantomData })
171 }
172
173 pub(super) fn value<T: Send + Sync + 'static>(&self) -> Option<&T> {
174 if self.payload != TypeId::of::<T>() {
175 return None;
176 }
177 (self.projection)(&*self.owner)?.downcast_ref::<T>()
178 }
179}
180
181fn project<T: Send + Sync + 'static, U: Borrow<T> + Send + Sync + 'static>(owner: &dyn Any) -> Option<&dyn Any> {
186 let owner = owner.downcast_ref::<U>()?;
187 Some(owner.borrow())
188}
189
190