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 BincodeEncodeError(bincode::error::EncodeError),
68 BincodeDecodeError(bincode::error::DecodeError),
70 InvalidData(String),
72 NonFiniteFloat(f64),
74}
75
76impl std::fmt::Display for SerializeError {
77 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
78 match self {
79 SerializeError::QuotationNotSerializable => {
80 write!(f, "Quotations cannot be serialized - code is not data")
81 }
82 SerializeError::ClosureNotSerializable => {
83 write!(f, "Closures cannot be serialized - code is not data")
84 }
85 SerializeError::ChannelNotSerializable => {
86 write!(f, "Channels cannot be serialized - runtime state")
87 }
88 SerializeError::BincodeEncodeError(e) => write!(f, "Bincode encode error: {}", e),
89 SerializeError::BincodeDecodeError(e) => write!(f, "Bincode decode error: {}", e),
90 SerializeError::InvalidData(msg) => write!(f, "Invalid data: {}", msg),
91 SerializeError::NonFiniteFloat(v) => {
92 write!(f, "Cannot serialize non-finite float: {}", v)
93 }
94 }
95 }
96}
97
98impl std::error::Error for SerializeError {
99 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
100 match self {
101 SerializeError::BincodeEncodeError(e) => Some(e),
102 SerializeError::BincodeDecodeError(e) => Some(e),
103 _ => None,
104 }
105 }
106}
107
108impl From<bincode::error::EncodeError> for SerializeError {
109 fn from(e: bincode::error::EncodeError) -> Self {
110 SerializeError::BincodeEncodeError(e)
111 }
112}
113
114impl From<bincode::error::DecodeError> for SerializeError {
115 fn from(e: bincode::error::DecodeError) -> Self {
116 SerializeError::BincodeDecodeError(e)
117 }
118}
119
120#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
125pub enum TypedMapKey {
126 Int(i64),
127 Bool(bool),
128 String(String),
129}
130
131impl TypedMapKey {
132 pub fn to_typed_value(&self) -> TypedValue {
134 match self {
135 TypedMapKey::Int(v) => TypedValue::Int(*v),
136 TypedMapKey::Bool(v) => TypedValue::Bool(*v),
137 TypedMapKey::String(v) => TypedValue::String(v.clone()),
138 }
139 }
140
141 pub fn from_runtime(key: &RuntimeMapKey) -> Self {
143 match key {
144 RuntimeMapKey::Int(v) => TypedMapKey::Int(*v),
145 RuntimeMapKey::Bool(v) => TypedMapKey::Bool(*v),
146 RuntimeMapKey::String(s) => TypedMapKey::String(s.as_str_or_empty().to_string()),
147 }
148 }
149
150 pub fn to_runtime(&self) -> RuntimeMapKey {
152 match self {
153 TypedMapKey::Int(v) => RuntimeMapKey::Int(*v),
154 TypedMapKey::Bool(v) => RuntimeMapKey::Bool(*v),
155 TypedMapKey::String(s) => RuntimeMapKey::String(global_string(s.clone())),
156 }
157 }
158}
159
160#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
165pub enum TypedValue {
166 Int(i64),
167 Float(f64),
168 Bool(bool),
169 String(String),
170 Symbol(String),
172 Map(BTreeMap<TypedMapKey, TypedValue>),
174 Variant {
176 tag: String,
177 fields: Vec<TypedValue>,
178 },
179}
180
181impl TypedValue {
182 pub fn from_value(value: &Value) -> Result<Self, SerializeError> {
188 match value {
189 Value::Int(v) => Ok(TypedValue::Int(*v)),
190 Value::Float(v) => {
191 if !v.is_finite() {
192 return Err(SerializeError::NonFiniteFloat(*v));
193 }
194 Ok(TypedValue::Float(*v))
195 }
196 Value::Bool(v) => Ok(TypedValue::Bool(*v)),
197 Value::String(s) => Ok(TypedValue::String(s.as_str_or_empty().to_string())),
198 Value::Symbol(s) => Ok(TypedValue::Symbol(s.as_str_or_empty().to_string())),
199 Value::Map(map) => {
200 let mut typed_map = BTreeMap::new();
201 for (k, v) in map.iter() {
202 let typed_key = TypedMapKey::from_runtime(k);
203 let typed_value = TypedValue::from_value(v)?;
204 typed_map.insert(typed_key, typed_value);
205 }
206 Ok(TypedValue::Map(typed_map))
207 }
208 Value::Variant(data) => {
209 let mut typed_fields = Vec::with_capacity(data.fields.len());
210 for field in data.fields.iter() {
211 typed_fields.push(TypedValue::from_value(field)?);
212 }
213 Ok(TypedValue::Variant {
214 tag: data.tag.as_str_or_empty().to_string(),
215 fields: typed_fields,
216 })
217 }
218 Value::Quotation { .. } => Err(SerializeError::QuotationNotSerializable),
219 Value::Closure { .. } => Err(SerializeError::ClosureNotSerializable),
220 Value::Channel(_) => Err(SerializeError::ChannelNotSerializable),
221 Value::WeaveCtx { .. } => Err(SerializeError::ChannelNotSerializable), }
223 }
224
225 pub fn to_value(&self) -> Value {
230 match self {
231 TypedValue::Int(v) => Value::Int(*v),
232 TypedValue::Float(v) => Value::Float(*v),
233 TypedValue::Bool(v) => Value::Bool(*v),
234 TypedValue::String(s) => Value::String(global_string(s.clone())),
235 TypedValue::Symbol(s) => Value::Symbol(global_string(s.clone())),
236 TypedValue::Map(map) => {
237 let mut runtime_map = HashMap::new();
238 for (k, v) in map.iter() {
239 runtime_map.insert(k.to_runtime(), v.to_value());
240 }
241 Value::Map(Box::new(runtime_map))
242 }
243 TypedValue::Variant { tag, fields } => {
244 let runtime_fields: Vec<Value> = fields.iter().map(|f| f.to_value()).collect();
245 Value::Variant(Arc::new(VariantData::new(
246 global_string(tag.clone()),
247 runtime_fields,
248 )))
249 }
250 }
251 }
252
253 pub fn to_map_key(&self) -> Result<TypedMapKey, SerializeError> {
255 match self {
256 TypedValue::Int(v) => Ok(TypedMapKey::Int(*v)),
257 TypedValue::Bool(v) => Ok(TypedMapKey::Bool(*v)),
258 TypedValue::String(v) => Ok(TypedMapKey::String(v.clone())),
259 TypedValue::Float(_) => Err(SerializeError::InvalidData(
260 "Float cannot be a map key".to_string(),
261 )),
262 TypedValue::Map(_) => Err(SerializeError::InvalidData(
263 "Map cannot be a map key".to_string(),
264 )),
265 TypedValue::Variant { .. } => Err(SerializeError::InvalidData(
266 "Variant cannot be a map key".to_string(),
267 )),
268 TypedValue::Symbol(v) => Ok(TypedMapKey::String(v.clone())),
269 }
270 }
271
272 pub fn to_bytes(&self) -> Result<Vec<u8>, SerializeError> {
274 bincode::serde::encode_to_vec(self, bincode::config::standard())
275 .map_err(SerializeError::from)
276 }
277
278 pub fn from_bytes(bytes: &[u8]) -> Result<Self, SerializeError> {
280 let (value, _read) = bincode::serde::decode_from_slice(bytes, bincode::config::standard())
281 .map_err(SerializeError::from)?;
282 Ok(value)
283 }
284
285 pub fn to_debug_string(&self) -> String {
287 match self {
288 TypedValue::Int(v) => format!("{}", v),
289 TypedValue::Float(v) => format!("{}", v),
290 TypedValue::Bool(v) => format!("{}", v),
291 TypedValue::String(v) => format!("{:?}", v),
292 TypedValue::Symbol(v) => format!(":{}", v),
293 TypedValue::Map(m) => {
294 let entries: Vec<String> = m
295 .iter()
296 .map(|(k, v)| format!("{}: {}", key_to_debug_string(k), v.to_debug_string()))
297 .collect();
298 format!("{{ {} }}", entries.join(", "))
299 }
300 TypedValue::Variant { tag, fields } => {
301 if fields.is_empty() {
302 format!("(Variant#{})", tag)
303 } else {
304 let field_strs: Vec<String> =
305 fields.iter().map(|f| f.to_debug_string()).collect();
306 format!("(Variant#{} {})", tag, field_strs.join(" "))
307 }
308 }
309 }
310 }
311}
312
313fn key_to_debug_string(key: &TypedMapKey) -> String {
314 match key {
315 TypedMapKey::Int(v) => format!("{}", v),
316 TypedMapKey::Bool(v) => format!("{}", v),
317 TypedMapKey::String(v) => format!("{:?}", v),
318 }
319}
320
321pub trait ValueSerialize {
323 fn to_typed(&self) -> Result<TypedValue, SerializeError>;
325
326 fn to_bytes(&self) -> Result<Vec<u8>, SerializeError>;
328}
329
330impl ValueSerialize for Value {
331 fn to_typed(&self) -> Result<TypedValue, SerializeError> {
332 TypedValue::from_value(self)
333 }
334
335 fn to_bytes(&self) -> Result<Vec<u8>, SerializeError> {
336 TypedValue::from_value(self)?.to_bytes()
337 }
338}
339
340#[cfg(test)]
341mod tests;