1use crate::seqstring::global_string;
52use crate::value::{MapKey as RuntimeMapKey, Value, VariantData};
53use serde::{Deserialize, Serialize};
54use std::collections::{BTreeMap, HashMap};
55use std::sync::Arc;
56
57#[derive(Debug)]
59pub enum SerializeError {
60 QuotationNotSerializable,
62 ClosureNotSerializable,
64 ChannelNotSerializable,
66 BincodeError(Box<bincode::Error>),
68 InvalidData(String),
70 NonFiniteFloat(f64),
72}
73
74impl std::fmt::Display for SerializeError {
75 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76 match self {
77 SerializeError::QuotationNotSerializable => {
78 write!(f, "Quotations cannot be serialized - code is not data")
79 }
80 SerializeError::ClosureNotSerializable => {
81 write!(f, "Closures cannot be serialized - code is not data")
82 }
83 SerializeError::ChannelNotSerializable => {
84 write!(f, "Channels cannot be serialized - runtime state")
85 }
86 SerializeError::BincodeError(e) => write!(f, "Bincode error: {}", e),
87 SerializeError::InvalidData(msg) => write!(f, "Invalid data: {}", msg),
88 SerializeError::NonFiniteFloat(v) => {
89 write!(f, "Cannot serialize non-finite float: {}", v)
90 }
91 }
92 }
93}
94
95impl std::error::Error for SerializeError {
96 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
97 match self {
98 SerializeError::BincodeError(e) => Some(e.as_ref()),
99 _ => None,
100 }
101 }
102}
103
104impl From<bincode::Error> for SerializeError {
105 fn from(e: bincode::Error) -> Self {
106 SerializeError::BincodeError(Box::new(e))
107 }
108}
109
110#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
115pub enum TypedMapKey {
116 Int(i64),
117 Bool(bool),
118 String(String),
119}
120
121impl TypedMapKey {
122 pub fn to_typed_value(&self) -> TypedValue {
124 match self {
125 TypedMapKey::Int(v) => TypedValue::Int(*v),
126 TypedMapKey::Bool(v) => TypedValue::Bool(*v),
127 TypedMapKey::String(v) => TypedValue::String(v.clone()),
128 }
129 }
130
131 pub fn from_runtime(key: &RuntimeMapKey) -> Self {
133 match key {
134 RuntimeMapKey::Int(v) => TypedMapKey::Int(*v),
135 RuntimeMapKey::Bool(v) => TypedMapKey::Bool(*v),
136 RuntimeMapKey::String(s) => TypedMapKey::String(s.as_str_or_empty().to_string()),
137 }
138 }
139
140 pub fn to_runtime(&self) -> RuntimeMapKey {
142 match self {
143 TypedMapKey::Int(v) => RuntimeMapKey::Int(*v),
144 TypedMapKey::Bool(v) => RuntimeMapKey::Bool(*v),
145 TypedMapKey::String(s) => RuntimeMapKey::String(global_string(s.clone())),
146 }
147 }
148}
149
150#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
155pub enum TypedValue {
156 Int(i64),
157 Float(f64),
158 Bool(bool),
159 String(String),
160 Symbol(String),
162 Map(BTreeMap<TypedMapKey, TypedValue>),
164 Variant {
166 tag: String,
167 fields: Vec<TypedValue>,
168 },
169}
170
171impl TypedValue {
172 pub fn from_value(value: &Value) -> Result<Self, SerializeError> {
178 match value {
179 Value::Int(v) => Ok(TypedValue::Int(*v)),
180 Value::Float(v) => {
181 if !v.is_finite() {
182 return Err(SerializeError::NonFiniteFloat(*v));
183 }
184 Ok(TypedValue::Float(*v))
185 }
186 Value::Bool(v) => Ok(TypedValue::Bool(*v)),
187 Value::String(s) => Ok(TypedValue::String(s.as_str_or_empty().to_string())),
188 Value::Symbol(s) => Ok(TypedValue::Symbol(s.as_str_or_empty().to_string())),
189 Value::Map(map) => {
190 let mut typed_map = BTreeMap::new();
191 for (k, v) in map.iter() {
192 let typed_key = TypedMapKey::from_runtime(k);
193 let typed_value = TypedValue::from_value(v)?;
194 typed_map.insert(typed_key, typed_value);
195 }
196 Ok(TypedValue::Map(typed_map))
197 }
198 Value::Variant(data) => {
199 let mut typed_fields = Vec::with_capacity(data.fields.len());
200 for field in data.fields.iter() {
201 typed_fields.push(TypedValue::from_value(field)?);
202 }
203 Ok(TypedValue::Variant {
204 tag: data.tag.as_str_or_empty().to_string(),
205 fields: typed_fields,
206 })
207 }
208 Value::Quotation { .. } => Err(SerializeError::QuotationNotSerializable),
209 Value::Closure { .. } => Err(SerializeError::ClosureNotSerializable),
210 Value::Channel(_) => Err(SerializeError::ChannelNotSerializable),
211 Value::WeaveCtx { .. } => Err(SerializeError::ChannelNotSerializable), }
213 }
214
215 pub fn to_value(&self) -> Value {
220 match self {
221 TypedValue::Int(v) => Value::Int(*v),
222 TypedValue::Float(v) => Value::Float(*v),
223 TypedValue::Bool(v) => Value::Bool(*v),
224 TypedValue::String(s) => Value::String(global_string(s.clone())),
225 TypedValue::Symbol(s) => Value::Symbol(global_string(s.clone())),
226 TypedValue::Map(map) => {
227 let mut runtime_map = HashMap::new();
228 for (k, v) in map.iter() {
229 runtime_map.insert(k.to_runtime(), v.to_value());
230 }
231 Value::Map(Box::new(runtime_map))
232 }
233 TypedValue::Variant { tag, fields } => {
234 let runtime_fields: Vec<Value> = fields.iter().map(|f| f.to_value()).collect();
235 Value::Variant(Arc::new(VariantData::new(
236 global_string(tag.clone()),
237 runtime_fields,
238 )))
239 }
240 }
241 }
242
243 pub fn to_map_key(&self) -> Result<TypedMapKey, SerializeError> {
245 match self {
246 TypedValue::Int(v) => Ok(TypedMapKey::Int(*v)),
247 TypedValue::Bool(v) => Ok(TypedMapKey::Bool(*v)),
248 TypedValue::String(v) => Ok(TypedMapKey::String(v.clone())),
249 TypedValue::Float(_) => Err(SerializeError::InvalidData(
250 "Float cannot be a map key".to_string(),
251 )),
252 TypedValue::Map(_) => Err(SerializeError::InvalidData(
253 "Map cannot be a map key".to_string(),
254 )),
255 TypedValue::Variant { .. } => Err(SerializeError::InvalidData(
256 "Variant cannot be a map key".to_string(),
257 )),
258 TypedValue::Symbol(v) => Ok(TypedMapKey::String(v.clone())),
259 }
260 }
261
262 pub fn to_bytes(&self) -> Result<Vec<u8>, SerializeError> {
264 bincode::serialize(self).map_err(SerializeError::from)
265 }
266
267 pub fn from_bytes(bytes: &[u8]) -> Result<Self, SerializeError> {
269 bincode::deserialize(bytes).map_err(SerializeError::from)
270 }
271
272 pub fn to_debug_string(&self) -> String {
274 match self {
275 TypedValue::Int(v) => format!("{}", v),
276 TypedValue::Float(v) => format!("{}", v),
277 TypedValue::Bool(v) => format!("{}", v),
278 TypedValue::String(v) => format!("{:?}", v),
279 TypedValue::Symbol(v) => format!(":{}", v),
280 TypedValue::Map(m) => {
281 let entries: Vec<String> = m
282 .iter()
283 .map(|(k, v)| format!("{}: {}", key_to_debug_string(k), v.to_debug_string()))
284 .collect();
285 format!("{{ {} }}", entries.join(", "))
286 }
287 TypedValue::Variant { tag, fields } => {
288 if fields.is_empty() {
289 format!("(Variant#{})", tag)
290 } else {
291 let field_strs: Vec<String> =
292 fields.iter().map(|f| f.to_debug_string()).collect();
293 format!("(Variant#{} {})", tag, field_strs.join(" "))
294 }
295 }
296 }
297 }
298}
299
300fn key_to_debug_string(key: &TypedMapKey) -> String {
301 match key {
302 TypedMapKey::Int(v) => format!("{}", v),
303 TypedMapKey::Bool(v) => format!("{}", v),
304 TypedMapKey::String(v) => format!("{:?}", v),
305 }
306}
307
308pub trait ValueSerialize {
310 fn to_typed(&self) -> Result<TypedValue, SerializeError>;
312
313 fn to_bytes(&self) -> Result<Vec<u8>, SerializeError>;
315}
316
317impl ValueSerialize for Value {
318 fn to_typed(&self) -> Result<TypedValue, SerializeError> {
319 TypedValue::from_value(self)
320 }
321
322 fn to_bytes(&self) -> Result<Vec<u8>, SerializeError> {
323 TypedValue::from_value(self)?.to_bytes()
324 }
325}
326
327#[cfg(test)]
328mod tests;