wayle_core/property/
serde.rs1#[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}