Skip to main content

oanda_client/
patch.rs

1//! Distinguishes omitted fields from explicit JSON null in OANDA mutations.
2
3use serde::{Deserialize, Deserializer, Serialize, Serializer};
4
5/// A mutation field that may be left unchanged, cleared, or set.
6#[derive(Debug, Clone, PartialEq, Eq, Default)]
7pub enum Patch<T> {
8    /// Omit the field from the request.
9    #[default]
10    Unchanged,
11    /// Send JSON null to clear the existing value.
12    Clear,
13    /// Send a new value.
14    Set(T),
15}
16
17impl<T> Patch<T> {
18    /// Whether the field should be omitted when serialized as a struct field.
19    pub fn is_unchanged(&self) -> bool {
20        matches!(self, Self::Unchanged)
21    }
22}
23
24impl<T: Serialize> Serialize for Patch<T> {
25    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
26        match self {
27            Self::Unchanged => Err(serde::ser::Error::custom(
28                "unchanged patch must be omitted by the enclosing field",
29            )),
30            Self::Clear => serializer.serialize_none(),
31            Self::Set(value) => value.serialize(serializer),
32        }
33    }
34}
35
36impl<'de, T: Deserialize<'de>> Deserialize<'de> for Patch<T> {
37    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
38        Option::<T>::deserialize(deserializer).map(|value| match value {
39            Some(value) => Self::Set(value),
40            None => Self::Clear,
41        })
42    }
43}