1// This file is part of Frontier.
23// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
56// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
1011// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
1516// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <https://www.gnu.org/licenses/>.
1819use ethereum_types::U64;
20use serde::{de, Deserialize, Serialize};
2122/// The syncing status of client.
23#[derive(Copy, Clone, Debug, Eq, PartialEq)]
24pub enum SyncingStatus {
25/// Progress when syncing.
26IsSyncing(SyncingProgress),
27/// Not syncing.
28NotSyncing,
29}
3031impl serde::Serialize for SyncingStatus {
32fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
33where
34S: serde::Serializer,
35 {
36match self {
37Self::IsSyncing(progress) => progress.serialize(serializer),
38Self::NotSyncing => serializer.serialize_bool(false),
39 }
40 }
41}
4243impl<'de> serde::Deserialize<'de> for SyncingStatus {
44fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
45where
46D: serde::Deserializer<'de>,
47 {
48#[derive(Deserialize)]
49 #[serde(untagged)]
50enum Syncing {
51 IsSyncing(SyncingProgress),
52 NotSyncing(bool),
53 }
5455match Syncing::deserialize(deserializer)? {
56 Syncing::IsSyncing(sync) => Ok(Self::IsSyncing(sync)),
57 Syncing::NotSyncing(false) => Ok(Self::NotSyncing),
58 Syncing::NotSyncing(true) => Err(de::Error::custom(
59"eth_syncing should always return false if not syncing.",
60 )),
61 }
62 }
63}
6465/// The syncing progress.
66#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
67#[serde(rename_all = "camelCase")]
68pub struct SyncingProgress {
69/// Block number this node started to synchronize from.
70pub starting_block: U64,
71/// Block number this node is currently importing.
72pub current_block: U64,
73/// Block number of the highest block header this node has received from peers.
74pub highest_block: U64,
75}
7677#[cfg(test)]
78mod tests {
79use super::*;
8081#[test]
82fn syncing_status_serde_impl() {
83let valid_cases = [
84 (
85r#"{"startingBlock":"0x64","currentBlock":"0xc8","highestBlock":"0x12c"}"#,
86 SyncingStatus::IsSyncing(SyncingProgress {
87 starting_block: 100.into(),
88 current_block: 200.into(),
89 highest_block: 300.into(),
90 }),
91 ),
92 ("false", SyncingStatus::NotSyncing),
93 ];
94for (raw, typed) in valid_cases {
95let deserialized = serde_json::from_str::<SyncingStatus>(raw).unwrap();
96assert_eq!(deserialized, typed);
9798let serialized = serde_json::to_string(&typed).unwrap();
99assert_eq!(serialized, raw);
100 }
101102let invalid_cases = ["true"];
103for raw in invalid_cases {
104let status: Result<SyncingStatus, _> = serde_json::from_str(raw);
105assert!(status.is_err());
106 }
107 }
108}