native_theme/model/
spacing.rs1use serde::{Deserialize, Serialize};
4
5#[serde_with::skip_serializing_none]
10#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
11#[serde(default)]
12#[non_exhaustive]
13pub struct ThemeSpacing {
14 pub xxs: Option<f32>,
16
17 pub xs: Option<f32>,
19
20 pub s: Option<f32>,
22
23 pub m: Option<f32>,
25
26 pub l: Option<f32>,
28
29 pub xl: Option<f32>,
31
32 pub xxl: Option<f32>,
34}
35
36impl_merge!(ThemeSpacing {
37 option { xxs, xs, s, m, l, xl, xxl }
38});
39
40#[cfg(test)]
41#[allow(clippy::unwrap_used, clippy::expect_used)]
42mod tests {
43 use super::*;
44
45 #[test]
46 fn default_is_empty() {
47 assert!(ThemeSpacing::default().is_empty());
48 }
49
50 #[test]
51 fn not_empty_when_field_set() {
52 let s = ThemeSpacing {
53 m: Some(12.0),
54 ..Default::default()
55 };
56 assert!(!s.is_empty());
57 }
58
59 #[test]
60 fn merge_some_replaces_none() {
61 let mut base = ThemeSpacing::default();
62 let overlay = ThemeSpacing {
63 s: Some(8.0),
64 m: Some(12.0),
65 l: Some(16.0),
66 ..Default::default()
67 };
68 base.merge(&overlay);
69 assert_eq!(base.s, Some(8.0));
70 assert_eq!(base.m, Some(12.0));
71 assert_eq!(base.l, Some(16.0));
72 }
73
74 #[test]
75 fn merge_none_preserves_base() {
76 let mut base = ThemeSpacing {
77 xxs: Some(2.0),
78 xs: Some(4.0),
79 ..Default::default()
80 };
81 let overlay = ThemeSpacing::default();
82 base.merge(&overlay);
83 assert_eq!(base.xxs, Some(2.0));
84 assert_eq!(base.xs, Some(4.0));
85 }
86
87 #[test]
88 fn serde_toml_round_trip() {
89 let spacing = ThemeSpacing {
90 xxs: Some(2.0),
91 xs: Some(4.0),
92 s: Some(8.0),
93 m: Some(12.0),
94 l: Some(16.0),
95 xl: Some(24.0),
96 xxl: Some(32.0),
97 };
98 let toml_str = toml::to_string(&spacing).unwrap();
99 let deserialized: ThemeSpacing = toml::from_str(&toml_str).unwrap();
100 assert_eq!(deserialized, spacing);
101 }
102}