Skip to main content

serde_extensions/
lib.rs

1use serde::Deserialize;
2pub use serde_extensions_derive::*;
3pub use serde_value;
4
5/// A trait for selectively overwriting fields in a struct from a deserializer.
6///
7/// The `Overwrite` trait provides a mechanism to update existing values in a struct
8/// by deserializing only the fields present in the input data, leaving other fields
9/// unchanged. This is particularly useful for configuration merging, partial updates,
10/// and layered settings where you want to apply defaults first and then override
11/// specific values.
12///
13/// # Behavior
14///
15/// - For primitive types and most standard library types, `overwrite` completely
16///   replaces the existing value with the deserialized value.
17/// - For structs that derive `Overwrite` (using `#[derive(Overwrite)]`), only the
18///   fields present in the input are updated, while absent fields retain their
19///   current values.
20///
21/// # Examples
22///
23/// ```rust
24/// use serde::Deserialize;
25/// use serde_extensions::Overwrite;
26///
27/// #[derive(Deserialize, Overwrite)]
28/// struct Config {
29///     host: String,
30///     port: u16,
31///     debug: bool,
32/// }
33///
34/// let mut config = Config {
35///     host: "localhost".to_string(),
36///     port: 8080,
37///     debug: false,
38/// };
39///
40/// // Overwrite only the port, leaving host and debug unchanged
41/// let partial = r#"port=3000"#;
42/// config.overwrite(toml::from_str::<toml::Value>(partial).unwrap()).unwrap();
43///
44/// assert_eq!(config.host, "localhost");
45/// assert_eq!(config.port, 3000);
46/// assert_eq!(config.debug, false);
47/// ```
48///
49/// # Implementing for Custom Types
50///
51/// For structs, you can derive `Overwrite` automatically:
52///
53/// ```rust
54/// use serde_extensions::Overwrite;
55///
56/// #[derive(Overwrite)]
57/// struct MyStruct {
58///     field1: String,
59///     field2: i32,
60/// }
61/// ```
62///
63/// For other types, implement the trait manually. Types that should be completely
64/// replaced (rather than merged) should deserialize a new value and assign it:
65///
66/// ```rust
67/// use serde::{Deserialize, Deserializer};
68/// use serde_extensions::Overwrite;
69///
70/// #[derive(Deserialize)]
71/// struct CustomType(i32);
72///
73/// impl Overwrite for CustomType {
74///     fn overwrite<'de, D>(&mut self, d: D) -> Result<(), D::Error>
75///     where
76///         D: Deserializer<'de>,
77///     {
78///         *self = CustomType::deserialize(d)?;
79///         Ok(())
80///     }
81/// }
82/// ```
83pub trait Overwrite {
84    /// Overwrites the current value with data from a deserializer.
85    ///
86    /// For primitive types and collections, this completely replaces the value.
87    /// For structs with derived `Overwrite`, only fields present in the deserializer
88    /// are updated.
89    ///
90    /// # Arguments
91    ///
92    /// * `d` - A deserializer containing the data to overwrite with
93    ///
94    /// # Errors
95    ///
96    /// Returns a deserialization error if the input data is invalid for the type.
97    ///
98    /// # Examples
99    ///
100    /// ```rust
101    /// use serde_extensions::Overwrite;
102    ///
103    /// let mut value = 42;
104    /// let parsed_value = toml::Value::Integer(100);
105    /// value.overwrite(parsed_value).unwrap();
106    /// assert_eq!(value, 100);
107    /// ```
108    fn overwrite<'de, D>(&mut self, d: D) -> Result<(), D::Error>
109    where
110        D: serde::Deserializer<'de>;
111}
112
113// Blanket implementations for common types that should just be replaced, not merged
114macro_rules! impl_overwrite_replace {
115    ($($t:ty),*) => {
116        $(
117            impl Overwrite for $t {
118                fn overwrite<'de, D>(&mut self, d: D) -> Result<(), D::Error>
119                where
120                    D: serde::Deserializer<'de>,
121                {
122                    *self = Deserialize::deserialize(d)?;
123                    Ok(())
124                }
125            }
126        )*
127    };
128}
129
130// Implement Overwrite for common primitive and standard library types
131impl_overwrite_replace!(
132    bool, i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, f32, f64, String, char, usize, isize
133);
134
135// Implement for Option<T> where T: Overwrite
136impl<T> Overwrite for Option<T>
137where
138    T: for<'de> Deserialize<'de>,
139{
140    fn overwrite<'de, D>(&mut self, d: D) -> Result<(), D::Error>
141    where
142        D: serde::Deserializer<'de>,
143    {
144        *self = Deserialize::deserialize(d)?;
145        Ok(())
146    }
147}
148
149// Implement for Vec<T> where T: Overwrite
150impl<T> Overwrite for Vec<T>
151where
152    T: for<'de> Deserialize<'de>,
153{
154    fn overwrite<'de, D>(&mut self, d: D) -> Result<(), D::Error>
155    where
156        D: serde::Deserializer<'de>,
157    {
158        *self = Deserialize::deserialize(d)?;
159        Ok(())
160    }
161}
162
163// Implement for types from common crates
164impl Overwrite for std::path::PathBuf {
165    fn overwrite<'de, D>(&mut self, d: D) -> Result<(), D::Error>
166    where
167        D: serde::Deserializer<'de>,
168    {
169        *self = Deserialize::deserialize(d)?;
170        Ok(())
171    }
172}
173
174impl<K, V> Overwrite for std::collections::HashMap<K, V>
175where
176    K: for<'de> Deserialize<'de> + std::hash::Hash + Eq,
177    V: for<'de> Deserialize<'de>,
178{
179    fn overwrite<'de, D>(&mut self, d: D) -> Result<(), D::Error>
180    where
181        D: serde::Deserializer<'de>,
182    {
183        *self = Deserialize::deserialize(d)?;
184        Ok(())
185    }
186}