Skip to main content

wayle_core/property/
serde.rs

1#[cfg(feature = "schema")]
2use std::borrow::Cow;
3use std::fmt::{self, Debug, Formatter};
4
5#[cfg(feature = "schema")]
6use schemars::{JsonSchema, Schema, SchemaGenerator};
7use serde::{Deserialize, Deserializer, Serialize, Serializer};
8
9use super::Property;
10
11impl<T: Clone + Send + Sync + Debug + 'static> Debug for Property<T> {
12    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
13        f.debug_struct("Property")
14            .field("value", &self.get())
15            .finish()
16    }
17}
18
19impl<T: Clone + Send + Sync + Serialize + 'static> Serialize for Property<T> {
20    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
21    where
22        S: Serializer,
23    {
24        self.get().serialize(serializer)
25    }
26}
27
28impl<'de, T: Clone + Send + Sync + Deserialize<'de> + 'static> Deserialize<'de> for Property<T> {
29    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
30    where
31        D: Deserializer<'de>,
32    {
33        let value = T::deserialize(deserializer)?;
34        Ok(Property::new(value))
35    }
36}
37
38#[cfg(feature = "schema")]
39impl<T: Clone + Send + Sync + JsonSchema + 'static> JsonSchema for Property<T> {
40    fn schema_name() -> Cow<'static, str> {
41        T::schema_name()
42    }
43
44    fn json_schema(generator: &mut SchemaGenerator) -> Schema {
45        T::json_schema(generator)
46    }
47}
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52
53    #[test]
54    fn serializes_to_inner_value() {
55        let property = Property::new(42);
56        let json = serde_json::to_string(&property).unwrap();
57
58        assert_eq!(json, "42");
59    }
60
61    #[test]
62    fn deserializes_from_inner_value() {
63        let property: Property<String> = serde_json::from_str("\"hello\"").unwrap();
64
65        assert_eq!(property.get(), "hello");
66    }
67
68    #[test]
69    fn json_roundtrip() {
70        #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
71        struct Config {
72            name: Property<String>,
73            count: Property<i32>,
74            enabled: Property<bool>,
75        }
76
77        let config = Config {
78            name: Property::new(String::from("test")),
79            count: Property::new(42),
80            enabled: Property::new(true),
81        };
82
83        let json = serde_json::to_string(&config).unwrap();
84        let deserialized: Config = serde_json::from_str(&json).unwrap();
85
86        assert_eq!(deserialized.name.get(), "test");
87        assert_eq!(deserialized.count.get(), 42);
88        assert!(deserialized.enabled.get());
89    }
90
91    #[test]
92    fn toml_roundtrip() {
93        #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
94        struct ClockConfig {
95            format: Property<String>,
96            show_seconds: Property<bool>,
97        }
98
99        let config = ClockConfig {
100            format: Property::new(String::from("%H:%M")),
101            show_seconds: Property::new(false),
102        };
103
104        let serialized = toml::to_string(&config).unwrap();
105        assert!(serialized.contains("format = \"%H:%M\""));
106        assert!(serialized.contains("show_seconds = false"));
107
108        let deserialized: ClockConfig = toml::from_str(&serialized).unwrap();
109        assert_eq!(deserialized.format.get(), "%H:%M");
110        assert!(!deserialized.show_seconds.get());
111    }
112
113    #[test]
114    fn deserialized_property_starts_with_no_subscribers() {
115        let property: Property<i32> = serde_json::from_str("42").unwrap();
116
117        assert!(!property.has_subscribers());
118    }
119}