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