1use bincode::Encode;
2use platform_serialization::de::Decode;
3use serde::{Deserialize, Serialize};
4
5#[cfg(feature = "json-conversion")]
6use crate::serialization::json_safe_fields;
7use crate::{errors::ProtocolError, prelude::TimestampMillis, util::deserializer::ProtocolVersion};
8
9#[cfg_attr(feature = "json-conversion", json_safe_fields)]
10#[derive(
11 Serialize, Deserialize, Encode, Decode, Debug, Default, Clone, Copy, PartialEq, PartialOrd, Eq,
12)]
13#[serde(rename_all = "camelCase")]
14pub struct Metadata {
15 #[serde(default)]
16 pub block_height: u64,
17 #[serde(default)]
18 pub core_chain_locked_height: u64,
19 #[serde(default)]
20 pub time_ms: TimestampMillis,
21 #[serde(default)]
22 pub protocol_version: ProtocolVersion,
23}
24
25impl std::convert::TryFrom<&str> for Metadata {
26 type Error = ProtocolError;
27
28 fn try_from(d: &str) -> Result<Metadata, Self::Error> {
29 serde_json::from_str(d).map_err(|e| ProtocolError::EncodingError(e.to_string()))
30 }
31}
32
33#[cfg(all(feature = "json-conversion", feature = "serde-conversion"))]
34impl crate::serialization::JsonConvertible for Metadata {}
35
36#[cfg(all(feature = "value-conversion", feature = "serde-conversion"))]
37impl crate::serialization::ValueConvertible for Metadata {}
38
39#[cfg(all(
40 test,
41 feature = "json-conversion",
42 feature = "value-conversion",
43 feature = "serde-conversion"
44))]
45mod json_convertible_tests {
46 use super::*;
47 use crate::serialization::{JsonConvertible, ValueConvertible};
48 use platform_value::platform_value;
49 use serde_json::json;
50
51 fn fixture() -> Metadata {
55 Metadata {
56 block_height: 1_234_567,
57 core_chain_locked_height: 2_222_333,
58 time_ms: 1_700_000_000_000,
59 protocol_version: 9,
60 }
61 }
62
63 #[test]
64 fn json_round_trip_with_full_wire_shape() {
65 let original = fixture();
66 let json = original.to_json().expect("to_json");
67 assert_eq!(
70 json,
71 json!({
72 "blockHeight": 1_234_567,
73 "coreChainLockedHeight": 2_222_333,
74 "timeMs": 1_700_000_000_000u64,
75 "protocolVersion": 9,
76 })
77 );
78 let recovered = Metadata::from_json(json).expect("from_json");
79 assert_eq!(original, recovered);
80 }
81
82 #[test]
83 fn value_round_trip_with_full_wire_shape() {
84 let original = fixture();
85 let value = original.to_object().expect("to_object");
86 assert_eq!(
87 value,
88 platform_value!({
89 "blockHeight": 1_234_567u64,
90 "coreChainLockedHeight": 2_222_333u64,
91 "timeMs": 1_700_000_000_000u64,
92 "protocolVersion": 9u32,
93 })
94 );
95 let recovered = Metadata::from_object(value).expect("from_object");
96 assert_eq!(original, recovered);
97 }
98
99 #[test]
102 fn json_stringifies_unsafe_u64() {
103 let original = Metadata {
104 block_height: u64::MAX,
105 ..fixture()
106 };
107 let json = original.to_json().expect("to_json");
108 assert_eq!(json["blockHeight"], json!(u64::MAX.to_string()));
109 let recovered = Metadata::from_json(json).expect("from_json");
110 assert_eq!(original, recovered);
111 }
112}