sc_network_types/
multihash.rs1use litep2p::types::multihash::{
23 Code as LiteP2pCode, Error as LiteP2pError, Multihash as LiteP2pMultihash, MultihashDigest as _,
24};
25use std::fmt::{self, Debug};
26
27#[derive(Clone, Copy, Debug, PartialEq, Eq)]
29pub enum Code {
30 Identity,
32 Sha2_256,
34}
35
36impl Code {
37 pub fn digest(&self, input: &[u8]) -> Multihash {
39 LiteP2pCode::from(*self).digest(input).into()
40 }
41}
42
43#[derive(Debug, thiserror::Error)]
45pub enum Error {
46 #[error("invalid multihash size '{0}'")]
48 InvalidSize(u64),
49 #[error("unsupported multihash code '{0:x}'")]
51 UnsupportedCode(u64),
52 #[error("other error: {0}")]
55 Other(Box<dyn std::error::Error + Send + Sync>),
56}
57
58impl From<LiteP2pError> for Error {
59 fn from(error: LiteP2pError) -> Self {
60 match error {
61 LiteP2pError::InvalidSize(s) => Self::InvalidSize(s),
62 LiteP2pError::UnsupportedCode(c) => Self::UnsupportedCode(c),
63 e => Self::Other(Box::new(e)),
64 }
65 }
66}
67
68impl From<Code> for LiteP2pCode {
69 fn from(code: Code) -> Self {
70 match code {
71 Code::Identity => LiteP2pCode::Identity,
72 Code::Sha2_256 => LiteP2pCode::Sha2_256,
73 }
74 }
75}
76
77impl TryFrom<LiteP2pCode> for Code {
78 type Error = Error;
79
80 fn try_from(code: LiteP2pCode) -> Result<Self, Self::Error> {
81 match code {
82 LiteP2pCode::Identity => Ok(Code::Identity),
83 LiteP2pCode::Sha2_256 => Ok(Code::Sha2_256),
84 _ => Err(Error::UnsupportedCode(code.into())),
85 }
86 }
87}
88
89impl TryFrom<u64> for Code {
90 type Error = Error;
91
92 fn try_from(code: u64) -> Result<Self, Self::Error> {
93 match LiteP2pCode::try_from(code) {
94 Ok(code) => code.try_into(),
95 Err(e) => Err(e.into()),
96 }
97 }
98}
99
100impl From<Code> for u64 {
101 fn from(code: Code) -> Self {
102 LiteP2pCode::from(code).into()
103 }
104}
105
106#[derive(Clone, Copy, Hash, PartialEq, Eq, Ord, PartialOrd)]
107pub struct Multihash {
108 multihash: LiteP2pMultihash,
109}
110
111impl Multihash {
112 pub fn code(&self) -> u64 {
114 self.multihash.code()
115 }
116
117 pub fn digest(&self) -> &[u8] {
119 self.multihash.digest()
120 }
121
122 pub fn wrap(code: u64, input_digest: &[u8]) -> Result<Self, Error> {
124 LiteP2pMultihash::wrap(code, input_digest).map(Into::into).map_err(Into::into)
125 }
126
127 pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
131 LiteP2pMultihash::from_bytes(bytes).map(Into::into).map_err(Into::into)
132 }
133
134 pub fn to_bytes(&self) -> Vec<u8> {
136 self.multihash.to_bytes()
137 }
138}
139
140impl Debug for Multihash {
142 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
143 Debug::fmt(&self.multihash, f)
144 }
145}
146
147impl From<LiteP2pMultihash> for Multihash {
148 fn from(multihash: LiteP2pMultihash) -> Self {
149 Multihash { multihash }
150 }
151}
152
153impl From<Multihash> for LiteP2pMultihash {
154 fn from(multihash: Multihash) -> Self {
155 multihash.multihash
156 }
157}
158
159impl From<multihash::Multihash<64>> for Multihash {
160 fn from(generic: multihash::Multihash<64>) -> Self {
161 LiteP2pMultihash::wrap(generic.code(), generic.digest())
162 .expect("both have size 64; qed")
163 .into()
164 }
165}
166
167impl From<Multihash> for multihash::Multihash<64> {
168 fn from(multihash: Multihash) -> Self {
169 multihash::Multihash::<64>::wrap(multihash.code(), multihash.digest())
170 .expect("both have size 64; qed")
171 }
172}
173
174#[cfg(test)]
175mod tests {
176 use super::*;
177
178 #[test]
179 fn code_from_u64() {
180 assert_eq!(Code::try_from(0x00).unwrap(), Code::Identity);
181 assert_eq!(Code::try_from(0x12).unwrap(), Code::Sha2_256);
182 assert!(matches!(Code::try_from(0x01).unwrap_err(), Error::UnsupportedCode(0x01)));
183 }
184
185 #[test]
186 fn code_into_u64() {
187 assert_eq!(u64::from(Code::Identity), 0x00);
188 assert_eq!(u64::from(Code::Sha2_256), 0x12);
189 }
190}