1use 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}