fc_rpc_v2_types/
index.rs

1// This file is part of Frontier.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5
6// 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.
10
11// 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.
15
16// 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/>.
18
19use std::fmt;
20
21#[derive(Copy, Clone, PartialEq, Eq, Default, Hash)]
22pub struct Index(usize);
23
24impl fmt::Debug for Index {
25	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26		fmt::LowerHex::fmt(&self.0, f)
27	}
28}
29
30impl fmt::Display for Index {
31	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32		fmt::LowerHex::fmt(&self.0, f)
33	}
34}
35
36impl From<Index> for usize {
37	fn from(idx: Index) -> Self {
38		idx.0
39	}
40}
41
42impl From<usize> for Index {
43	fn from(value: usize) -> Self {
44		Self(value)
45	}
46}
47
48impl serde::Serialize for Index {
49	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
50	where
51		S: serde::Serializer,
52	{
53		serializer.serialize_str(&format!("0x{:x}", self.0))
54	}
55}
56
57impl<'de> serde::Deserialize<'de> for Index {
58	fn deserialize<D>(deserializer: D) -> Result<Index, D::Error>
59	where
60		D: serde::Deserializer<'de>,
61	{
62		use serde::de;
63
64		struct IndexVisitor;
65
66		impl de::Visitor<'_> for IndexVisitor {
67			type Value = Index;
68
69			fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
70				formatter.write_str("hex-encoded or decimal index")
71			}
72
73			fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
74			where
75				E: de::Error,
76			{
77				Ok(Index(value as usize))
78			}
79
80			fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
81			where
82				E: de::Error,
83			{
84				if let Some(val) = value.strip_prefix("0x") {
85					usize::from_str_radix(val, 16)
86						.map(Index)
87						.map_err(de::Error::custom)
88				} else {
89					value.parse::<usize>().map(Index).map_err(de::Error::custom)
90				}
91			}
92
93			fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
94			where
95				E: de::Error,
96			{
97				self.visit_str(value.as_ref())
98			}
99		}
100
101		deserializer.deserialize_any(IndexVisitor)
102	}
103}
104
105#[cfg(test)]
106mod tests {
107	use super::*;
108
109	#[test]
110	fn index_serialize() {
111		let indexes = vec![Index(10), Index(10), Index(u32::MAX as usize)];
112		let serialized = serde_json::to_string(&indexes).unwrap();
113		let expected = r#"["0xa","0xa","0xffffffff"]"#;
114		assert_eq!(serialized, expected);
115	}
116
117	#[test]
118	fn index_deserialize() {
119		let s = r#"["0xa", "10", "0xffffffff"]"#;
120		let deserialized: Vec<Index> = serde_json::from_str(s).unwrap();
121		let expected = vec![Index(10), Index(10), Index(u32::MAX as usize)];
122		assert_eq!(deserialized, expected);
123	}
124}