Skip to main content

rustvello_core/
serializer.rs

1use serde::de::DeserializeOwned;
2use serde::Serialize;
3
4use crate::error::{RustvelloError, RustvelloResult};
5
6/// Serializer interface for converting values to/from strings.
7///
8/// Provides a uniform interface for the system, enabling custom
9/// serialization strategies (e.g., for Python interop via PyO3).
10///
11/// In Rust, the default [`SerdeSerializer`] uses `serde_json` directly.
12/// Python backends can implement this trait with pickle or custom codecs.
13pub trait Serializer: Send + Sync {
14    /// Serialize a value to its string representation.
15    fn serialize<T: Serialize>(&self, value: &T) -> RustvelloResult<String>;
16
17    /// Deserialize a string into the target type.
18    fn deserialize<T: DeserializeOwned>(&self, data: &str) -> RustvelloResult<T>;
19}
20
21/// Default JSON serializer backed by serde_json.
22///
23/// This is the standard serializer for pure-Rust usage. It works with
24/// any type implementing `Serialize`/`Deserialize`.
25#[derive(Debug, Default, Clone, Copy)]
26pub struct SerdeSerializer;
27
28impl Serializer for SerdeSerializer {
29    fn serialize<T: Serialize>(&self, value: &T) -> RustvelloResult<String> {
30        serde_json::to_string(value).map_err(|e| RustvelloError::Serialization {
31            message: e.to_string(),
32        })
33    }
34
35    fn deserialize<T: DeserializeOwned>(&self, data: &str) -> RustvelloResult<T> {
36        serde_json::from_str(data).map_err(|e| RustvelloError::Serialization {
37            message: e.to_string(),
38        })
39    }
40}
41
42/// Type alias preserving backward compatibility.
43pub type JsonSerializer = SerdeSerializer;
44
45#[cfg(test)]
46mod tests {
47    use super::*;
48    use serde::{Deserialize, Serialize};
49
50    #[derive(Debug, Serialize, Deserialize, PartialEq)]
51    struct Point {
52        x: i32,
53        y: i32,
54    }
55
56    #[test]
57    fn serialize_struct() {
58        let s = SerdeSerializer;
59        let val = Point { x: 1, y: 2 };
60        let result = s.serialize(&val).unwrap();
61        assert!(result.contains("\"x\":1"));
62        assert!(result.contains("\"y\":2"));
63    }
64
65    #[test]
66    fn serialize_primitive() {
67        let s = SerdeSerializer;
68        assert_eq!(s.serialize(&42i32).unwrap(), "42");
69        assert_eq!(s.serialize(&"hello").unwrap(), "\"hello\"");
70        assert_eq!(s.serialize(&true).unwrap(), "true");
71    }
72
73    #[test]
74    fn serialize_json_value() {
75        let s = SerdeSerializer;
76        let val = serde_json::json!({"key": "value", "num": 42});
77        let result = s.serialize(&val).unwrap();
78        assert!(result.contains("key"));
79        assert!(result.contains("42"));
80    }
81
82    #[test]
83    fn deserialize_struct() {
84        let s = SerdeSerializer;
85        let data = r#"{"x":10,"y":20}"#;
86        let point: Point = s.deserialize(data).unwrap();
87        assert_eq!(point, Point { x: 10, y: 20 });
88    }
89
90    #[test]
91    fn deserialize_json_value() {
92        let s = SerdeSerializer;
93        let val: serde_json::Value = s.deserialize(r#"{"key":"value"}"#).unwrap();
94        assert_eq!(val["key"], "value");
95    }
96
97    #[test]
98    fn deserialize_invalid_json_errors() {
99        let s = SerdeSerializer;
100        let result: RustvelloResult<serde_json::Value> = s.deserialize("not json {{{");
101        assert!(result.is_err());
102    }
103
104    #[test]
105    fn round_trip_struct() {
106        let s = SerdeSerializer;
107        let original = Point { x: 42, y: -7 };
108        let serialized = s.serialize(&original).unwrap();
109        let back: Point = s.deserialize(&serialized).unwrap();
110        assert_eq!(original, back);
111    }
112
113    #[test]
114    fn round_trip_json_value() {
115        let s = SerdeSerializer;
116        let original = serde_json::json!({"a": [1, 2, 3], "b": true});
117        let serialized = s.serialize(&original).unwrap();
118        let back: serde_json::Value = s.deserialize(&serialized).unwrap();
119        assert_eq!(original, back);
120    }
121}