qubit_codec/value/
value_codec_descriptor.rs1use std::any::Any;
10use std::any::TypeId;
11
12use crate::ValueCodecExecutionError;
13use crate::ValueDecoder;
14use crate::ValueEncoder;
15
16type EncodeFn = fn(&dyn Any) -> Result<String, ValueCodecExecutionError>;
17type DecodeFn = fn(&str) -> Result<Box<dyn Any>, ValueCodecExecutionError>;
18
19#[derive(Clone, Copy)]
21pub struct ValueCodecDescriptor {
22 codec_type_id: fn() -> TypeId,
23 codec_type_name: fn() -> &'static str,
24 value_type_id: fn() -> TypeId,
25 value_type_name: fn() -> &'static str,
26 encode: EncodeFn,
27 decode: DecodeFn,
28}
29
30impl ValueCodecDescriptor {
31 #[must_use]
33 pub const fn of<C, V>() -> Self
34 where
35 C: Default + ValueEncoder<V, Output = String> + ValueDecoder<str, Output = V> + 'static,
36 <C as ValueEncoder<V>>::Error: std::error::Error + 'static,
37 <C as ValueDecoder<str>>::Error: std::error::Error + 'static,
38 V: 'static,
39 {
40 Self {
41 codec_type_id: TypeId::of::<C>,
42 codec_type_name: core::any::type_name::<C>,
43 value_type_id: TypeId::of::<V>,
44 value_type_name: core::any::type_name::<V>,
45 encode: encode::<C, V>,
46 decode: decode::<C, V>,
47 }
48 }
49
50 #[must_use]
52 pub fn codec_type_id(&self) -> TypeId {
53 (self.codec_type_id)()
54 }
55
56 #[must_use]
58 pub fn codec_type_name(&self) -> &'static str {
59 (self.codec_type_name)()
60 }
61
62 #[must_use]
64 pub fn value_type_id(&self) -> TypeId {
65 (self.value_type_id)()
66 }
67
68 #[must_use]
70 pub fn value_type_name(&self) -> &'static str {
71 (self.value_type_name)()
72 }
73
74 pub fn encode(&self, value: &dyn Any) -> Result<String, ValueCodecExecutionError> {
80 (self.encode)(value)
81 }
82
83 pub fn decode(&self, input: &str) -> Result<Box<dyn Any>, ValueCodecExecutionError> {
89 (self.decode)(input)
90 }
91}
92
93impl core::fmt::Debug for ValueCodecDescriptor {
94 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
96 formatter
97 .debug_struct("ValueCodecDescriptor")
98 .field("codec_type_name", &self.codec_type_name())
99 .field("value_type_name", &self.value_type_name())
100 .finish_non_exhaustive()
101 }
102}
103
104fn encode<C, V>(value: &dyn Any) -> Result<String, ValueCodecExecutionError>
106where
107 C: Default + ValueEncoder<V, Output = String> + ValueDecoder<str, Output = V> + 'static,
108 <C as ValueEncoder<V>>::Error: std::error::Error + 'static,
109 <C as ValueDecoder<str>>::Error: std::error::Error + 'static,
110 V: 'static,
111{
112 let value = value
113 .downcast_ref::<V>()
114 .ok_or_else(|| ValueCodecExecutionError::TypeMismatch {
115 expected_type: core::any::type_name::<V>(),
116 actual_type: value.type_id(),
117 })?;
118 C::default()
119 .encode(value)
120 .map_err(|source| ValueCodecExecutionError::EncodeFailed {
121 codec_type: core::any::type_name::<C>(),
122 source: Box::new(source),
123 })
124}
125
126fn decode<C, V>(input: &str) -> Result<Box<dyn Any>, ValueCodecExecutionError>
128where
129 C: Default + ValueEncoder<V, Output = String> + ValueDecoder<str, Output = V> + 'static,
130 <C as ValueEncoder<V>>::Error: std::error::Error + 'static,
131 <C as ValueDecoder<str>>::Error: std::error::Error + 'static,
132 V: 'static,
133{
134 C::default()
135 .decode(input)
136 .map(|value| Box::new(value) as Box<dyn Any>)
137 .map_err(|source| ValueCodecExecutionError::DecodeFailed {
138 codec_type: core::any::type_name::<C>(),
139 source: Box::new(source),
140 })
141}