Skip to main content

dpp/document/v0/
platform_value_conversion.rs

1use crate::document::serialization_traits::DocumentPlatformValueMethodsV0;
2use crate::document::DocumentV0;
3use crate::ProtocolError;
4use platform_value::Value;
5use std::collections::BTreeMap;
6
7impl DocumentPlatformValueMethodsV0<'_> for DocumentV0 {
8    fn to_map_value(&self) -> Result<BTreeMap<String, Value>, ProtocolError> {
9        Ok(platform_value::to_value(self)?.into_btree_string_map()?)
10    }
11
12    fn into_map_value(self) -> Result<BTreeMap<String, Value>, ProtocolError> {
13        Ok(platform_value::to_value(self)?.into_btree_string_map()?)
14    }
15}
16
17#[cfg(test)]
18mod tests {
19    use super::*;
20    use crate::document::property_names;
21    use platform_value::Identifier;
22
23    fn minimal_doc() -> DocumentV0 {
24        DocumentV0 {
25            contract_version: None,
26            id: Identifier::new([1u8; 32]),
27            owner_id: Identifier::new([2u8; 32]),
28            properties: BTreeMap::new(),
29            revision: None,
30            created_at: None,
31            updated_at: None,
32            transferred_at: None,
33            created_at_block_height: None,
34            updated_at_block_height: None,
35            transferred_at_block_height: None,
36            created_at_core_block_height: None,
37            updated_at_core_block_height: None,
38            transferred_at_core_block_height: None,
39            creator_id: None,
40            moderated_at: None,
41            moderated_by: None,
42        }
43    }
44
45    fn full_doc() -> DocumentV0 {
46        let mut props = BTreeMap::new();
47        props.insert("name".into(), Value::Text("Eve".into()));
48        props.insert("score".into(), Value::U64(42));
49        DocumentV0 {
50            contract_version: None,
51            id: Identifier::new([7u8; 32]),
52            owner_id: Identifier::new([8u8; 32]),
53            properties: props,
54            revision: Some(3),
55            created_at: Some(1_700_000_000_000),
56            updated_at: Some(1_700_000_100_000),
57            transferred_at: Some(1_700_000_200_000),
58            created_at_block_height: Some(10),
59            updated_at_block_height: Some(20),
60            transferred_at_block_height: Some(30),
61            created_at_core_block_height: Some(1),
62            updated_at_core_block_height: Some(2),
63            transferred_at_core_block_height: Some(3),
64            creator_id: Some(Identifier::new([9u8; 32])),
65            moderated_at: None,
66            moderated_by: None,
67        }
68    }
69
70    // ================================================================
71    //  to_map_value: produces a BTreeMap<String, Value> keyed by the
72    //  documented serde field names (with the $-prefixed renames).
73    // ================================================================
74
75    #[test]
76    fn to_map_value_contains_id_and_owner_id_keys() {
77        let doc = minimal_doc();
78        let map = doc.to_map_value().expect("to_map_value should succeed");
79        assert!(map.contains_key(property_names::ID));
80        assert!(map.contains_key(property_names::OWNER_ID));
81    }
82
83    #[test]
84    fn to_map_value_contains_all_set_optional_fields() {
85        let doc = full_doc();
86        let map = doc.to_map_value().expect("to_map_value should succeed");
87        assert!(map.contains_key(property_names::REVISION));
88        assert!(map.contains_key(property_names::CREATED_AT));
89        assert!(map.contains_key(property_names::UPDATED_AT));
90        assert!(map.contains_key(property_names::TRANSFERRED_AT));
91        assert!(map.contains_key(property_names::CREATED_AT_BLOCK_HEIGHT));
92        assert!(map.contains_key(property_names::UPDATED_AT_BLOCK_HEIGHT));
93        assert!(map.contains_key(property_names::TRANSFERRED_AT_BLOCK_HEIGHT));
94        assert!(map.contains_key(property_names::CREATED_AT_CORE_BLOCK_HEIGHT));
95        assert!(map.contains_key(property_names::UPDATED_AT_CORE_BLOCK_HEIGHT));
96        assert!(map.contains_key(property_names::TRANSFERRED_AT_CORE_BLOCK_HEIGHT));
97        assert!(map.contains_key(property_names::CREATOR_ID));
98        // User-defined properties are flattened into the map
99        assert!(map.contains_key("name"));
100        assert!(map.contains_key("score"));
101    }
102
103    // ================================================================
104    //  into_map_value: same shape as to_map_value, consumes self
105    // ================================================================
106
107    #[test]
108    fn into_map_value_consumes_and_returns_same_shape_as_to_map_value() {
109        let doc = full_doc();
110        let from_ref = doc.to_map_value().expect("to_map_value");
111        let from_owned = doc.into_map_value().expect("into_map_value");
112        assert_eq!(from_ref, from_owned);
113    }
114
115    // After Phase D step 8 slice A, the `to_object` / `into_value` /
116    // `from_platform_value` tests on this V0 inner moved to the outer
117    // `Document` enum's canonical-trait round-trip tests in
118    // `serialization_traits/platform_value_conversion/mod.rs`. The
119    // `to_map_value` / `into_map_value` tests stay because those are
120    // the methods this trait still defines.
121}