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 { erased: ErasedResponse { owner, projection: project::<T, U>, payload: TypeId::of::<T>() }, payload: PhantomData }
65 }
66
67 pub fn ptr_eq(&self, other: &Self) -> bool {
68 Arc::ptr_eq(&self.erased.owner, &other.erased.owner)
69 }
70
71 pub fn try_unwrap(self) -> Result<T, Self> {
72 if !self.erased.owner.is::<T>() {
74 return Err(self);
75 }
76 let owner = match self.erased.owner.downcast::<T>() {
77 Ok(owner) => owner,
78 Err(_) => unreachable!("checked direct response owner type"),
79 };
80 Arc::try_unwrap(owner).map_err(Self::from_owner)
81 }
82
83 pub fn into_owned(self) -> T
85 where
86 T: Clone,
87 {
88 self.try_unwrap().unwrap_or_else(|response| (*response).clone())
89 }
90
91 pub fn into_erased(self) -> ErasedResponse {
92 self.erased
93 }
94}
95
96impl<T: Send + Sync + 'static> From<T> for Response<T> {
97 fn from(value: T) -> Self {
98 Self::new(value)
99 }
100}
101
102impl<T: Send + Sync + 'static> From<Arc<T>> for Response<T> {
103 fn from(value: Arc<T>) -> Self {
104 Self::from_owner(value)
105 }
106}
107
108impl<T: Send + Sync + 'static> Clone for Response<T> {
109 fn clone(&self) -> Self {
110 Self { erased: self.erased.clone(), payload: PhantomData }
111 }
112}
113
114impl<T: Send + Sync + 'static> Deref for Response<T> {
115 type Target = T;
116
117 fn deref(&self) -> &T {
118 self.erased.value::<T>().expect("response retains its declared payload")
119 }
120}
121
122impl<T: Send + Sync + 'static> AsRef<T> for Response<T> {
123 fn as_ref(&self) -> &T {
124 self
125 }
126}
127
128impl<T: Send + Sync + 'static> Borrow<T> for Response<T> {
129 fn borrow(&self) -> &T {
130 self
131 }
132}
133
134impl<T: fmt::Debug + Send + Sync + 'static> fmt::Debug for Response<T> {
135 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
136 self.deref().fmt(formatter)
137 }
138}
139
140impl<T: fmt::Display + Send + Sync + 'static> fmt::Display for Response<T> {
141 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
142 self.deref().fmt(formatter)
143 }
144}
145
146impl<T: PartialEq + Send + Sync + 'static> PartialEq for Response<T> {
147 fn eq(&self, other: &Self) -> bool {
148 self.deref() == other.deref()
149 }
150}
151
152impl<T: Eq + Send + Sync + 'static> Eq for Response<T> {}
153
154impl ErasedResponse {
155 pub fn restore<T: Send + Sync + 'static>(self) -> Option<Response<T>> {
156 if self.payload != TypeId::of::<T>() {
158 return None;
159 }
160 Some(Response { erased: self, payload: PhantomData })
161 }
162
163 pub(super) fn value<T: Send + Sync + 'static>(&self) -> Option<&T> {
164 if self.payload != TypeId::of::<T>() {
165 return None;
166 }
167 (self.projection)(&*self.owner)?.downcast_ref::<T>()
168 }
169}
170
171fn project<T: Send + Sync + 'static, U: Borrow<T> + Send + Sync + 'static>(owner: &dyn Any) -> Option<&dyn Any> {
176 let owner = owner.downcast_ref::<U>()?;
177 Some(owner.borrow())
178}
179
180