Skip to main content

dpp/address_funds/serde_helpers/
address_output_singular.rs

1//! `#[serde(with = "address_output_singular")]` helper.
2//!
3//! Reshapes `Option<(PlatformAddress, Credits)>` to/from a single
4//! `{ address, amount }` object (or `null`) on the JSON / Object wire.
5
6use super::AddressOutputEntry;
7use crate::address_funds::PlatformAddress;
8use crate::fee::Credits;
9use serde::{Deserialize, Deserializer, Serializer};
10
11pub fn serialize<S>(
12    value: &Option<(PlatformAddress, Credits)>,
13    serializer: S,
14) -> Result<S::Ok, S::Error>
15where
16    S: Serializer,
17{
18    match value {
19        Some((address, amount)) => serializer.serialize_some(&AddressOutputEntry {
20            address: *address,
21            amount: *amount,
22        }),
23        None => serializer.serialize_none(),
24    }
25}
26
27pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<(PlatformAddress, Credits)>, D::Error>
28where
29    D: Deserializer<'de>,
30{
31    let opt: Option<AddressOutputEntry> = Option::deserialize(deserializer)?;
32    Ok(opt.map(|entry| (entry.address, entry.amount)))
33}
34
35#[cfg(test)]
36mod tests {
37    use super::*;
38    use serde::Serialize;
39
40    fn p2pkh(byte: u8) -> PlatformAddress {
41        PlatformAddress::P2pkh([byte; 20])
42    }
43
44    #[derive(Serialize, Deserialize, PartialEq, Debug)]
45    struct Wrapper(#[serde(with = "super")] Option<(PlatformAddress, Credits)>);
46
47    #[test]
48    fn none_serializes_to_null() {
49        let original = Wrapper(None);
50        let value = serde_json::to_value(&original).expect("serialize None");
51        assert_eq!(value, serde_json::Value::Null);
52
53        let restored: Wrapper = serde_json::from_value(value).expect("deserialize null");
54        assert_eq!(original, restored);
55    }
56
57    #[test]
58    fn some_round_trips_as_object() {
59        let original = Wrapper(Some((p2pkh(7), 42u64)));
60        let value = serde_json::to_value(&original).expect("serialize Some");
61        assert_eq!(value["amount"], serde_json::json!(42));
62        let address_hex = value["address"].as_str().expect("address as hex string");
63        assert!(address_hex.starts_with("00")); // P2pkh discriminant
64        assert_eq!(address_hex.len(), 42); // 21 bytes hex-encoded
65
66        let restored: Wrapper = serde_json::from_value(value).expect("deserialize object");
67        assert_eq!(original, restored);
68    }
69}