neptune_job_queue/
job_result_wrapper.rs1use std::any::Any;
14use std::fmt::Display;
15use std::ops::Deref;
16use std::ops::DerefMut;
17
18use super::errors::JobHandleError;
19use super::traits::JobResult;
20use super::JobCompletion;
21
22#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
41pub struct JobResultWrapper<T>(T);
42
43impl<T: 'static + Send + Sync> JobResult for JobResultWrapper<T> {
44 fn as_any(&self) -> &dyn Any {
45 self
46 }
47
48 fn into_any(self: Box<Self>) -> Box<dyn Any> {
49 self
50 }
51}
52
53impl<T> Deref for JobResultWrapper<T> {
54 type Target = T;
55
56 fn deref(&self) -> &Self::Target {
57 &self.0
58 }
59}
60
61impl<T> DerefMut for JobResultWrapper<T> {
62 fn deref_mut(&mut self) -> &mut Self::Target {
63 &mut self.0
64 }
65}
66
67impl<T: 'static> TryFrom<JobCompletion> for JobResultWrapper<T> {
68 type Error = JobHandleError;
69
70 fn try_from(job_completion: JobCompletion) -> Result<Self, Self::Error> {
71 JobResultWrapper::try_from_completion(job_completion)
72 }
73}
74
75impl<'a, T: 'static> TryFrom<&'a JobCompletion> for &'a JobResultWrapper<T> {
76 type Error = JobHandleError;
77
78 fn try_from(job_completion: &'a JobCompletion) -> Result<Self, Self::Error> {
79 JobResultWrapper::try_from_completion_ref(job_completion)
80 }
81}
82
83impl<T: 'static> TryFrom<Box<dyn JobResult>> for JobResultWrapper<T> {
84 type Error = JobHandleError;
85
86 fn try_from(job_result: Box<dyn JobResult>) -> Result<Self, Self::Error> {
87 JobResultWrapper::try_from_boxed_job_result(job_result)
88 }
89}
90
91impl<'a, T: 'static> TryFrom<&'a dyn JobResult> for &'a JobResultWrapper<T> {
92 type Error = JobHandleError;
93
94 fn try_from(job_result: &'a dyn JobResult) -> Result<Self, Self::Error> {
95 JobResultWrapper::try_from_boxed_job_result_ref(job_result)
96 }
97}
98
99impl<T: 'static + Send + Sync> From<JobResultWrapper<T>> for Box<dyn JobResult> {
100 fn from(wrapper: JobResultWrapper<T>) -> Self {
101 Box::new(wrapper) as Box<dyn JobResult>
102 }
103}
104
105impl<T: Display> Display for JobResultWrapper<T> {
106 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
107 self.0.fmt(f)
108 }
109}
110
111impl<T> JobResultWrapper<T> {
112 pub fn into_inner(self) -> T {
114 self.0
115 }
116}
117
118impl<T: 'static> JobResultWrapper<T> {
119 pub fn new(job_result: T) -> Self {
121 Self(job_result)
122 }
123
124 fn try_from_completion(job_completion: JobCompletion) -> Result<Self, JobHandleError> {
126 Self::try_from_boxed_job_result(job_completion.result()?)
127 }
128
129 fn try_from_completion_ref(job_completion: &JobCompletion) -> Result<&Self, JobHandleError> {
131 Self::try_from_boxed_job_result_ref(job_completion.result_ref().unwrap())
132 }
133
134 fn try_from_boxed_job_result(
136 boxed_trait_object: Box<dyn JobResult>,
137 ) -> Result<Self, JobHandleError> {
138 let any = boxed_trait_object.into_any(); if let Ok(concrete_wrapper) = any.downcast::<JobResultWrapper<T>>() {
140 Ok(*concrete_wrapper) } else {
142 Err(JobHandleError::JobResultWrapperError {
143 from: std::any::type_name::<dyn JobResult>(),
144 to: std::any::type_name::<JobResultWrapper<T>>(),
145 })
146 }
147 }
148
149 fn try_from_boxed_job_result_ref(
151 boxed_trait_object: &dyn JobResult,
152 ) -> Result<&Self, JobHandleError> {
153 let any = boxed_trait_object.as_any();
154 if let Some(concrete_wrapper) = any.downcast_ref::<JobResultWrapper<T>>() {
155 Ok(concrete_wrapper)
156 } else {
157 Err(JobHandleError::JobResultWrapperError {
158 from: std::any::type_name::<dyn JobResult>(),
159 to: std::any::type_name::<JobResultWrapper<T>>(),
160 })
161 }
162 }
163}
164
165#[cfg(test)]
166mod tests {
167 use super::*;
168
169 #[test]
170 pub fn basic_conversions() {
171 type MyJobResult = u64;
172 type MyJobResultWrapper = JobResultWrapper<MyJobResult>;
173
174 let result: MyJobResult = 5;
175
176 let wrapper = MyJobResultWrapper::new(result);
177
178 let _ = wrapper.as_any();
180 let _ = Box::new(MyJobResultWrapper::new(result)).into_any();
181
182 assert_eq!(&*wrapper, &mut *MyJobResultWrapper::new(result));
184
185 let completion: JobCompletion = wrapper.into();
186
187 let _ = <&MyJobResultWrapper>::try_from(&completion).unwrap();
189
190 let _ = MyJobResultWrapper::try_from(completion).unwrap();
192
193 let boxed: Box<dyn JobResult> = MyJobResultWrapper::new(5).into();
195
196 let _ = <&JobResultWrapper<u64>>::try_from(boxed.as_ref()).unwrap();
198
199 let _ = MyJobResultWrapper::try_from(boxed).unwrap();
201 }
202
203 #[test]
204 pub fn optional_traits() {
205 type MyJobResult = u64;
206
207 let wrapper = JobResultWrapper::<MyJobResult>::new(5);
208
209 let copy = wrapper;
211 assert_eq!(wrapper, copy);
212
213 let _ = format!("{:?}", wrapper);
215
216 assert_eq!(wrapper.to_string(), 5.to_string());
218
219 assert!(wrapper > JobResultWrapper::<MyJobResult>::new(2));
221 }
222}