oasis_core_runtime/common/
bytes.rs1#[macro_export]
11macro_rules! impl_bytes {
12 ($name:ident, $size:expr, $doc:expr) => {
13 #[doc=$doc]
14 #[derive(Clone, Copy, zeroize::Zeroize)]
15 pub struct $name(pub [u8; $size]);
16
17 impl $name {
18 pub const fn len() -> usize {
20 $size
21 }
22 }
23
24 impl AsRef<[u8]> for $name {
25 fn as_ref(&self) -> &[u8] {
26 &self.0
27 }
28 }
29
30 impl Eq for $name {}
31
32 impl PartialOrd for $name {
33 fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> {
34 Some(self.cmp(other))
35 }
36 }
37
38 impl PartialEq for $name {
39 fn eq(&self, other: &Self) -> bool {
40 &self.0[..] == &other.0[..]
41 }
42 }
43
44 impl Ord for $name {
45 fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
46 self.0[..].cmp(&other.0[..])
47 }
48 }
49
50 impl ::core::hash::Hash for $name {
51 fn hash<H>(&self, state: &mut H)
52 where
53 H: ::core::hash::Hasher,
54 {
55 state.write(&self.0);
56 }
57 }
58
59 impl Default for $name {
60 fn default() -> Self {
61 $name([0; $size])
62 }
63 }
64
65 impl From<$name> for [u8; $size] {
66 fn from(b: $name) -> Self {
67 b.0
68 }
69 }
70
71 impl From<&[u8]> for $name {
72 fn from(b: &[u8]) -> $name {
73 let mut data = [0; $size];
74 data.copy_from_slice(b);
75 $name(data)
76 }
77 }
78
79 impl From<&'static str> for $name {
80 fn from(s: &'static str) -> $name {
81 let s = s.strip_prefix("0x").unwrap_or(s);
82
83 if s.len() % 2 == 1 {
84 ("0".to_owned() + s).parse().unwrap()
85 } else {
86 s.parse().unwrap()
87 }
88 }
89 }
90
91 impl From<Vec<u8>> for $name {
92 fn from(v: Vec<u8>) -> $name {
93 Self::from(&v[..])
94 }
95 }
96
97 impl ::std::str::FromStr for $name {
98 type Err = ::rustc_hex::FromHexError;
99
100 fn from_str(s: &str) -> Result<$name, ::rustc_hex::FromHexError> {
101 use ::rustc_hex::FromHex;
102
103 let a: Vec<u8> = s.from_hex()?;
104 if a.len() != $size {
105 return Err(::rustc_hex::FromHexError::InvalidHexLength);
106 }
107
108 let mut ret = [0; $size];
109 ret.copy_from_slice(&a);
110 Ok($name(ret))
111 }
112 }
113
114 impl ::core::fmt::LowerHex for $name {
117 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
118 for i in &self.0[..] {
119 write!(f, "{:02x}", i)?;
120 }
121 Ok(())
122 }
123 }
124
125 impl ::core::fmt::Debug for $name {
126 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
127 ::core::fmt::LowerHex::fmt(self, f)
128 }
129 }
130
131 impl ::core::fmt::Display for $name {
132 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
133 for i in &self.0[0..2] {
134 write!(f, "{:02x}", i)?;
135 }
136 write!(f, "…")?;
137 for i in &self.0[$size - 2..$size] {
138 write!(f, "{:02x}", i)?;
139 }
140 Ok(())
141 }
142 }
143
144 impl $crate::cbor::Encode for $name {
147 fn into_cbor_value(self) -> $crate::cbor::Value {
148 $crate::cbor::Value::ByteString(self.0.into())
149 }
150 }
151
152 impl $crate::cbor::Decode for $name {
155 fn try_default() -> Result<Self, $crate::cbor::DecodeError> {
156 Ok(Default::default())
157 }
158
159 fn try_from_cbor_value(
160 value: $crate::cbor::Value,
161 ) -> Result<Self, $crate::cbor::DecodeError> {
162 use ::std::convert::TryInto;
163
164 match value {
165 $crate::cbor::Value::ByteString(data) => Ok(Self(
166 data.try_into()
167 .map_err(|_| $crate::cbor::DecodeError::UnexpectedType)?,
168 )),
169 _ => Err($crate::cbor::DecodeError::UnexpectedType),
170 }
171 }
172 }
173 };
174}
175
176#[cfg(test)]
177mod tests {
178 const TEST_KEY_BYTES: [u8; 32] = [
180 0xc6, 0x72, 0xb8, 0xd1, 0xef, 0x56, 0xed, 0x28, 0xab, 0x87, 0xc3, 0x62, 0x2c, 0x51, 0x14,
181 0x06, 0x9b, 0xdd, 0x3a, 0xd7, 0xb8, 0xf9, 0x73, 0x74, 0x98, 0xd0, 0xc0, 0x1e, 0xce, 0xf0,
182 0x96, 0x7a,
183 ];
184
185 impl_bytes!(TestKey, 32, "test key");
186
187 #[test]
188 fn test_length() {
189 assert_eq!(TestKey::len(), 32);
190 }
191
192 #[test]
193 fn test_cbor() {
194 let test_key = TestKey(TEST_KEY_BYTES);
196 let test_key_vec = cbor::to_vec(test_key);
197
198 let mut expected_test_key_vec = vec![88, 32];
200 expected_test_key_vec.extend_from_slice(&TEST_KEY_BYTES);
201 assert_eq!(test_key_vec, expected_test_key_vec);
202
203 let new_test_key: TestKey = cbor::from_slice(&test_key_vec).unwrap();
205 assert_eq!(new_test_key, test_key);
206 }
207
208 #[test]
209 fn test_cbor_null() {
210 let test_key: TestKey = cbor::from_slice(&[0xF6]).unwrap();
211 assert_eq!(
212 test_key,
213 "0000000000000000000000000000000000000000000000000000000000000000".into()
214 );
215 }
216}