1use std::{any::Any, error::Error, fmt};
2
3use schemars::{JsonSchema, Schema, SchemaGenerator};
4use serde::{Deserializer, Serialize, Serializer};
5
6use crate::{AnyArray, AnyArrayView, AnyArrayViewMut, AnyCowArray, Codec, DynCodec, DynCodecType};
7
8pub struct ErasedError {
10 error: Box<dyn 'static + Error + Send + Sync>,
11}
12
13impl ErasedError {
14 pub fn new<T: 'static + Error + Send + Sync>(err: T) -> Self {
16 let err: Box<dyn 'static + Error + Send + Sync> = Box::new(err);
17
18 match err.downcast::<Self>() {
20 Ok(err) => *err,
21 Err(err) => Self { error: err },
22 }
23 }
24}
25
26impl fmt::Debug for ErasedError {
27 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
28 fmt::Debug::fmt(&self.error, fmt)
29 }
30}
31
32impl fmt::Display for ErasedError {
33 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
34 fmt::Display::fmt(&self.error, fmt)
35 }
36}
37
38impl Error for ErasedError {
39 fn source(&self) -> Option<&(dyn Error + 'static)> {
40 self.error.source()
41 }
42}
43
44pub struct ErasedDynCodec {
46 codec: Box<dyn ErasedDynCodecDispatch>,
47}
48
49impl ErasedDynCodec {
50 pub fn new<T: DynCodec>(codec: T) -> Self {
52 let codec: Box<dyn ErasedDynCodecDispatch> = Box::new(codec);
53
54 if codec.erased_as_any().is::<Self>() {
56 let raw = Box::into_raw(codec);
57 #[expect(unsafe_code, clippy::cast_ptr_alignment)]
58 let codec = unsafe { Box::from_raw(raw.cast::<Self>()) };
60 return *codec;
61 }
62
63 Self { codec }
64 }
65
66 pub fn downcast<T: DynCodec>(self) -> Result<T, Self> {
72 if self.codec.erased_as_any().is::<T>() {
73 let raw = Box::into_raw(self.codec);
74 #[expect(unsafe_code)]
75 let codec = unsafe { Box::from_raw(raw.cast::<T>()) };
77 Ok(*codec)
78 } else {
79 Err(self)
80 }
81 }
82
83 #[must_use]
85 pub fn downcast_ref<T: DynCodec>(&self) -> Option<&T> {
86 self.codec.erased_as_any().downcast_ref()
87 }
88
89 #[must_use]
91 pub fn downcast_mut<T: DynCodec>(&mut self) -> Option<&mut T> {
92 self.codec.erased_as_any_mut().downcast_mut()
93 }
94
95 pub fn codec_config_schema(generator: &mut SchemaGenerator) -> Schema {
97 #[derive(JsonSchema)]
98 #[schemars(extend("additionalProperties" = {"type": "object"}))]
99 struct Codec {
101 #[expect(dead_code)]
104 id: String,
105 }
106
107 Codec::json_schema(generator)
108 }
109}
110
111impl Clone for ErasedDynCodec {
112 fn clone(&self) -> Self {
113 Self {
114 codec: self.codec.erased_clone(),
115 }
116 }
117}
118
119impl Codec for ErasedDynCodec {
120 type Error = ErasedError;
121
122 fn encode(&self, data: AnyCowArray) -> Result<AnyArray, Self::Error> {
123 self.codec.erased_encode(data)
124 }
125
126 fn decode(&self, encoded: AnyCowArray) -> Result<AnyArray, Self::Error> {
127 self.codec.erased_decode(encoded)
128 }
129
130 fn decode_into(
131 &self,
132 encoded: AnyArrayView,
133 decoded: AnyArrayViewMut,
134 ) -> Result<(), Self::Error> {
135 self.codec.erased_decode_into(encoded, decoded)
136 }
137}
138
139impl DynCodec for ErasedDynCodec {
140 type Type = ErasedDynCodecType;
141
142 fn ty(&self) -> Self::Type {
143 ErasedDynCodecType {
144 ty: self.codec.erased_ty(),
145 }
146 }
147
148 fn get_config<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
149 erased_serde::serialize(self.codec.erased_as_serialize(), serializer)
150 }
151}
152
153pub struct ErasedDynCodecType {
155 ty: Box<dyn ErasedDynCodecTypeDispatch>,
156}
157
158impl ErasedDynCodecType {
159 pub fn new<T: DynCodecType>(ty: T) -> Self {
161 let ty: Box<dyn ErasedDynCodecTypeDispatch> = Box::new(ty);
162
163 if ty.erased_as_any().is::<Self>() {
165 let raw = Box::into_raw(ty);
166 #[expect(unsafe_code, clippy::cast_ptr_alignment)]
167 let ty = unsafe { Box::from_raw(raw.cast::<Self>()) };
169 return *ty;
170 }
171
172 Self { ty }
173 }
174
175 pub fn downcast<T: DynCodecType>(self) -> Result<T, Self> {
182 if self.ty.erased_as_any().is::<T>() {
183 let raw = Box::into_raw(self.ty);
184 #[expect(unsafe_code)]
185 let ty = unsafe { Box::from_raw(raw.cast::<T>()) };
187 Ok(*ty)
188 } else {
189 Err(self)
190 }
191 }
192
193 #[must_use]
195 pub fn downcast_ref<T: DynCodecType>(&self) -> Option<&T> {
196 self.ty.erased_as_any().downcast_ref()
197 }
198
199 #[must_use]
201 pub fn downcast_mut<T: DynCodecType>(&mut self) -> Option<&mut T> {
202 self.ty.erased_as_any_mut().downcast_mut()
203 }
204}
205
206impl DynCodecType for ErasedDynCodecType {
207 type Codec = ErasedDynCodec;
208
209 fn codec_id(&self) -> &str {
210 self.ty.erased_codec_id()
211 }
212
213 fn codec_config_schema(&self) -> Schema {
214 self.ty.erased_codec_config_schema()
215 }
216
217 fn codec_from_config<'de, D: Deserializer<'de>>(
218 &self,
219 config: D,
220 ) -> Result<Self::Codec, D::Error> {
221 match self
222 .ty
223 .erased_codec_from_config(&mut <dyn erased_serde::Deserializer>::erase(config))
224 {
225 Ok(codec) => Ok(ErasedDynCodec { codec }),
226 Err(err) => Err(serde::de::Error::custom(err)), }
228 }
229}
230
231trait ErasedDynCodecDispatch: 'static + Send + Sync {
232 fn erased_encode(&self, data: AnyCowArray) -> Result<AnyArray, ErasedError>;
233 fn erased_decode(&self, encoded: AnyCowArray) -> Result<AnyArray, ErasedError>;
234 fn erased_decode_into(
235 &self,
236 encoded: AnyArrayView,
237 decoded: AnyArrayViewMut,
238 ) -> Result<(), ErasedError>;
239
240 fn erased_clone(&self) -> Box<dyn ErasedDynCodecDispatch>;
241
242 fn erased_ty(&self) -> Box<dyn ErasedDynCodecTypeDispatch>;
243
244 fn erased_as_any(&self) -> &dyn Any;
245 fn erased_as_any_mut(&mut self) -> &mut dyn Any;
246
247 fn erased_as_serialize(&self) -> &dyn erased_serde::Serialize;
248}
249
250trait ErasedDynCodecTypeDispatch: 'static + Send + Sync {
251 fn erased_codec_id(&self) -> &str;
252 fn erased_codec_config_schema(&self) -> Schema;
253 fn erased_codec_from_config(
254 &self,
255 config: &mut dyn erased_serde::Deserializer,
256 ) -> Result<Box<dyn ErasedDynCodecDispatch>, erased_serde::Error>;
257
258 fn erased_as_any(&self) -> &dyn Any;
259 fn erased_as_any_mut(&mut self) -> &mut dyn Any;
260}
261
262impl<T: DynCodec> ErasedDynCodecDispatch for T {
263 fn erased_encode(&self, data: AnyCowArray) -> Result<AnyArray, ErasedError> {
264 Codec::encode(self, data).map_err(ErasedError::new)
265 }
266
267 fn erased_decode(&self, encoded: AnyCowArray) -> Result<AnyArray, ErasedError> {
268 Codec::decode(self, encoded).map_err(ErasedError::new)
269 }
270
271 fn erased_decode_into(
272 &self,
273 encoded: AnyArrayView,
274 decoded: AnyArrayViewMut,
275 ) -> Result<(), ErasedError> {
276 Codec::decode_into(self, encoded, decoded).map_err(ErasedError::new)
277 }
278
279 fn erased_clone(&self) -> Box<dyn ErasedDynCodecDispatch> {
280 Box::new(Clone::clone(self))
281 }
282
283 fn erased_ty(&self) -> Box<dyn ErasedDynCodecTypeDispatch> {
284 Box::new(DynCodec::ty(self))
285 }
286
287 fn erased_as_any(&self) -> &dyn Any {
288 self
289 }
290
291 fn erased_as_any_mut(&mut self) -> &mut dyn Any {
292 self
293 }
294
295 fn erased_as_serialize(&self) -> &dyn erased_serde::Serialize {
296 #[repr(transparent)]
297 struct SerializeDynCodec<T: DynCodec>(T);
298
299 impl<T: DynCodec> Serialize for SerializeDynCodec<T> {
300 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
301 DynCodec::get_config(&self.0, serializer)
302 }
303 }
304
305 #[expect(unsafe_code)]
306 unsafe {
308 &*std::ptr::from_ref(self).cast::<SerializeDynCodec<Self>>()
309 }
310 }
311}
312
313impl<T: DynCodecType> ErasedDynCodecTypeDispatch for T {
314 fn erased_codec_id(&self) -> &str {
315 DynCodecType::codec_id(self)
316 }
317
318 fn erased_codec_config_schema(&self) -> Schema {
319 DynCodecType::codec_config_schema(self)
320 }
321
322 fn erased_codec_from_config(
323 &self,
324 config: &mut dyn erased_serde::Deserializer,
325 ) -> Result<Box<dyn ErasedDynCodecDispatch>, erased_serde::Error> {
326 match DynCodecType::codec_from_config(self, config) {
327 Ok(codec) => Ok(Box::new(codec)),
328 Err(err) => Err(err),
329 }
330 }
331
332 fn erased_as_any(&self) -> &dyn Any {
333 self
334 }
335
336 fn erased_as_any_mut(&mut self) -> &mut dyn Any {
337 self
338 }
339}