1use ethereum_types::U64;
4use serde::{Deserialize, Deserializer, Serialize, Serializer};
5
6#[derive(Clone, Debug, Eq, PartialEq)]
8pub enum SyncingStatus {
9 IsFalse,
11 IsSyncing(Box<SyncProgress>),
13}
14
15impl Serialize for SyncingStatus {
16 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
17 where
18 S: Serializer,
19 {
20 match self {
21 SyncingStatus::IsFalse => serializer.serialize_bool(false),
22 SyncingStatus::IsSyncing(sync) => sync.serialize(serializer),
23 }
24 }
25}
26
27impl<'de> Deserialize<'de> for SyncingStatus {
28 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
29 where
30 D: Deserializer<'de>,
31 {
32 #[derive(Debug, Serialize, Deserialize)]
33 #[serde(untagged)]
34 pub(crate) enum SyncingStatusIntermediate {
35 IsFalse(bool),
37 IsSyncing(Box<SyncProgress>),
39 }
40
41 match SyncingStatusIntermediate::deserialize(deserializer)? {
42 SyncingStatusIntermediate::IsFalse(false) => Ok(SyncingStatus::IsFalse),
43 SyncingStatusIntermediate::IsFalse(true) => Err(serde::de::Error::custom(
44 "neo_syncing returned `true` that is undefined value.",
45 )),
46 SyncingStatusIntermediate::IsSyncing(sync) => Ok(SyncingStatus::IsSyncing(sync)),
47 }
48 }
49}
50
51#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
66#[serde(rename_all = "camelCase")]
67pub struct SyncProgress {
69 pub current_block: U64,
71
72 pub highest_block: U64,
74
75 pub starting_block: U64,
77
78 #[serde(default, skip_serializing_if = "Option::is_none")]
80 pub pulled_states: Option<U64>,
81
82 #[serde(default, skip_serializing_if = "Option::is_none")]
84 pub known_states: Option<U64>,
85
86 #[serde(default, skip_serializing_if = "Option::is_none")]
88 pub healed_bytecode_bytes: Option<U64>,
89
90 #[serde(default, skip_serializing_if = "Option::is_none")]
92 pub healed_bytecodes: Option<U64>,
93
94 #[serde(default, skip_serializing_if = "Option::is_none")]
96 pub healed_trienode_bytes: Option<U64>,
97
98 #[serde(default, skip_serializing_if = "Option::is_none")]
100 pub healed_trienodes: Option<U64>,
101
102 #[serde(default, skip_serializing_if = "Option::is_none")]
104 pub healing_bytecode: Option<U64>,
105
106 #[serde(default, skip_serializing_if = "Option::is_none")]
108 pub healing_trienodes: Option<U64>,
109
110 #[serde(default, skip_serializing_if = "Option::is_none")]
112 pub synced_account_bytes: Option<U64>,
113
114 #[serde(default, skip_serializing_if = "Option::is_none")]
116 pub synced_accounts: Option<U64>,
117
118 #[serde(default, skip_serializing_if = "Option::is_none")]
120 pub synced_bytecode_bytes: Option<U64>,
121
122 #[serde(default, skip_serializing_if = "Option::is_none")]
124 pub synced_bytecodes: Option<U64>,
125
126 #[serde(default, skip_serializing_if = "Option::is_none")]
128 pub synced_storage: Option<U64>,
129
130 #[serde(default, skip_serializing_if = "Option::is_none")]
132 pub synced_storage_bytes: Option<U64>,
133}
134
135#[cfg(test)]
136mod tests {
137 use super::*;
138
139 #[test]
141 fn deserialize_sync_geth() {
142 let s = r#"{
143 "currentBlock": "0xeaa2b4",
144 "healedBytecodeBytes": "0xaad91fe",
145 "healedBytecodes": "0x61d3",
146 "healedTrienodeBytes": "0x156ac02b1",
147 "healedTrienodes": "0x2885aa4",
148 "healingBytecode": "0x0",
149 "healingTrienodes": "0x454",
150 "highestBlock": "0xeaa329",
151 "startingBlock": "0xea97ee",
152 "syncedAccountBytes": "0xa29fec90d",
153 "syncedAccounts": "0xa7ed9ad",
154 "syncedBytecodeBytes": "0xdec39008",
155 "syncedBytecodes": "0x8d407",
156 "syncedStorage": "0x2a517da1",
157 "syncedStorageBytes": "0x23634dbedf"
158 }"#;
159
160 let sync: SyncingStatus = serde_json::from_str(s).unwrap();
161 match sync {
162 SyncingStatus::IsFalse => {
163 assert!(false, "Expected IsSyncing variant, got IsFalse")
164 },
165 SyncingStatus::IsSyncing(_) => {},
166 }
167 }
168
169 #[test]
170 fn deserialize_sync_minimal() {
171 let s = r#"{
172 "currentBlock": "0xeaa2b4",
173 "highestBlock": "0xeaa329",
174 "startingBlock": "0xea97ee"
175 }"#;
176
177 let sync: SyncingStatus = serde_json::from_str(s).unwrap();
178 match sync {
179 SyncingStatus::IsFalse => {
180 assert!(false, "Expected IsSyncing variant, got IsFalse")
181 },
182 SyncingStatus::IsSyncing(_) => {},
183 }
184 }
185
186 #[test]
187 fn deserialize_sync_false() {
188 let s = r"false";
189
190 let sync: SyncingStatus = serde_json::from_str(s).unwrap();
191 match sync {
192 SyncingStatus::IsFalse => {},
193 SyncingStatus::IsSyncing(_) => {
194 assert!(false, "Expected IsFalse variant, got IsSyncing")
195 },
196 }
197 }
198}