Skip to main content

statime_config/tree/
atomic.rs

1//! The leaf types of the tree.
2
3use std::{
4    net::{IpAddr, SocketAddr},
5    path::PathBuf,
6};
7
8use serde::{Deserialize, Serialize, de};
9
10use crate::{
11    ConfigError,
12    tree::{
13        configurable::Configurable, merge::OriginId, partial_value::PartialValue, path::ConfigPath,
14        setting::Setting,
15    },
16};
17
18/// Marks a type as a value the tree does not look inside.
19///
20/// Every traversal (i.e. resolving, applying defaults and attributing)
21/// stops at such a type, so implementing this is all it takes to make a type
22/// usable as a configuration value. It can be derived automatically using
23/// `#[derive(ConfigurableAtomic)]`.
24pub trait ConfigurableAtomic:
25    std::fmt::Debug + Clone + PartialEq + serde::Serialize + for<'a> serde::Deserialize<'a>
26{
27}
28
29/// An atomic value is its own partial representation, and a field holding one
30/// is a setting.
31impl<T> Configurable for T
32where
33    T: ConfigurableAtomic,
34{
35    type Partial = Self;
36    type Node = Setting<Self>;
37}
38
39/// An atomic value has nothing inside for a pass to reach: the setting holding
40/// it records the origin and supplies the default, and resolving it is where
41/// the recursion stops.
42impl<T> PartialValue for T
43where
44    T: ConfigurableAtomic,
45{
46    type Resolved = Self;
47
48    fn attribute(&mut self, _origin: OriginId) {}
49
50    fn apply_defaults(&mut self) {}
51
52    fn resolve(self, _path: &mut ConfigPath) -> Result<Self::Resolved, ConfigError> {
53        Ok(self)
54    }
55}
56
57impl ConfigurableAtomic for bool {}
58impl ConfigurableAtomic for u8 {}
59impl ConfigurableAtomic for i8 {}
60impl ConfigurableAtomic for u16 {}
61impl ConfigurableAtomic for i16 {}
62impl ConfigurableAtomic for u32 {}
63impl ConfigurableAtomic for i32 {}
64impl ConfigurableAtomic for u64 {}
65impl ConfigurableAtomic for i64 {}
66impl ConfigurableAtomic for usize {}
67impl ConfigurableAtomic for isize {}
68impl ConfigurableAtomic for String {}
69impl ConfigurableAtomic for PathBuf {}
70impl ConfigurableAtomic for IpAddr {}
71impl ConfigurableAtomic for SocketAddr {}
72impl<T> ConfigurableAtomic for Option<T> where T: ConfigurableAtomic {}
73
74#[derive(Debug, PartialEq, Clone, Copy)]
75pub struct PartialF32(f32);
76
77impl<'de> Deserialize<'de> for PartialF32 {
78    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
79    where
80        D: serde::Deserializer<'de>,
81    {
82        let value = f32::deserialize(deserializer)?;
83        if value.is_nan() || value.is_infinite() {
84            Err(de::Error::custom(
85                "Invalid float value, should not be NaN or infinite",
86            ))
87        } else {
88            Ok(PartialF32(value))
89        }
90    }
91}
92
93impl Serialize for PartialF32 {
94    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
95    where
96        S: serde::Serializer,
97    {
98        serializer.serialize_f32(self.0)
99    }
100}
101
102impl PartialValue for PartialF32 {
103    type Resolved = f32;
104
105    fn attribute(&mut self, _origin: OriginId) {}
106
107    fn apply_defaults(&mut self) {}
108
109    fn resolve(self, _path: &mut ConfigPath) -> Result<Self::Resolved, ConfigError> {
110        Ok(self.0)
111    }
112}
113
114impl Configurable for f32 {
115    type Partial = PartialF32;
116    type Node = Setting<PartialF32>;
117}
118
119impl ConfigurableAtomic for Option<f32> {}
120
121#[derive(Debug, PartialEq, Clone, Copy)]
122pub struct PartialF64(f64);
123
124impl<'de> Deserialize<'de> for PartialF64 {
125    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
126    where
127        D: serde::Deserializer<'de>,
128    {
129        let value = f64::deserialize(deserializer)?;
130        if value.is_nan() || value.is_infinite() {
131            Err(de::Error::custom(
132                "Invalid float value, should not be NaN or infinite",
133            ))
134        } else {
135            Ok(PartialF64(value))
136        }
137    }
138}
139
140impl Serialize for PartialF64 {
141    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
142    where
143        S: serde::Serializer,
144    {
145        serializer.serialize_f64(self.0)
146    }
147}
148
149impl PartialValue for PartialF64 {
150    type Resolved = f64;
151
152    fn attribute(&mut self, _origin: OriginId) {}
153
154    fn apply_defaults(&mut self) {}
155
156    fn resolve(self, _path: &mut ConfigPath) -> Result<Self::Resolved, ConfigError> {
157        Ok(self.0)
158    }
159}
160
161impl Configurable for f64 {
162    type Partial = PartialF64;
163    type Node = Setting<PartialF64>;
164}
165
166impl ConfigurableAtomic for Option<f64> {}