rustup_toolchain_manifest/
hash_value.rs1use serde::{Deserialize, Deserializer, Serialize, Serializer};
2use std::str::FromStr;
3use thiserror::Error;
4
5#[derive(Clone, Copy, Debug, Error)]
7pub enum ParseError {
8 #[error("Invalid byte: {0}")]
10 InvalidByte(u8),
11
12 #[error("Not a multiple of 8 bits")]
14 NotOctetSized,
15}
16
17#[derive(Default, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
19pub struct HashValue {
20 bytes: Vec<u8>,
21}
22
23impl HashValue {
24 fn nibble_to_ascii(c: u8) -> u8 {
25 match c {
26 0..=9 => b'0' + c,
27 10..=15 => b'a' + (c - 10),
28 _ => panic!("Value not in range 0-15: {}", c),
29 }
30 }
31
32 fn ascii_to_nibble(c: u8) -> Result<u8, ParseError> {
33 match c {
34 b'0'..=b'9' => Ok(c - b'0'),
35 b'a'..=b'f' => Ok(c - b'a' + 10),
36 b'A'..=b'F' => Ok(c - b'A' + 10),
37 _ => Err(ParseError::InvalidByte(c)),
38 }
39 }
40
41 fn to_ascii(&self) -> Vec<u8> {
43 let mut characters = vec![0u8; self.bytes.len() * 2];
44 for (idx, character) in self.bytes.iter().enumerate() {
45 let high = character >> 4;
46 let low = character & 0xf;
47 characters[idx * 2] = Self::nibble_to_ascii(high);
48 characters[idx * 2 + 1] = Self::nibble_to_ascii(low);
49 }
50 characters
51 }
52
53 #[must_use]
55 pub fn from_bytes(bytes: &[u8]) -> HashValue {
56 HashValue { bytes: bytes.to_vec() }
57 }
58}
59
60impl AsRef<[u8]> for HashValue {
61 fn as_ref(&self) -> &[u8] {
62 self.bytes.as_ref()
63 }
64}
65
66impl std::fmt::Debug for HashValue {
67 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
68 write!(formatter, "\"{}\"", self)
69 }
70}
71
72impl std::fmt::Display for HashValue {
73 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
74 let ascii = self.to_ascii();
75 let ascii = unsafe { std::str::from_utf8_unchecked(&ascii) };
76 formatter.write_str(ascii)
77 }
78}
79
80impl Serialize for HashValue {
81 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
82 where
83 S: Serializer,
84 {
85 if serializer.is_human_readable() {
86 let ascii = self.to_ascii();
87 let ascii = unsafe { std::str::from_utf8_unchecked(&ascii) };
88 serializer.serialize_str(ascii)
89 } else {
90 serializer.serialize_bytes(&self.bytes)
91 }
92 }
93}
94
95impl<'a> Deserialize<'a> for HashValue {
96 fn deserialize<D>(deserializer: D) -> Result<HashValue, D::Error>
97 where
98 D: Deserializer<'a>,
99 {
100 if deserializer.is_human_readable() {
101 let s = String::deserialize(deserializer)?;
102 Ok(HashValue::from_str(s.as_str()).map_err(serde::de::Error::custom)?)
103 } else {
104 let bytes = <Vec<u8>>::deserialize(deserializer)?;
105 Ok(HashValue { bytes })
106 }
107 }
108}
109
110impl std::str::FromStr for HashValue {
111 type Err = ParseError;
112
113 fn from_str(string: &str) -> Result<HashValue, ParseError> {
114 let string = string.as_bytes();
115 let length = string.len();
116 if length % 2 == 0 {
117 let mut bytes = vec![0u8; length / 2];
118 for (idx, byte) in bytes.iter_mut().enumerate() {
119 let high = Self::ascii_to_nibble(string[idx * 2])?;
120 let low = Self::ascii_to_nibble(string[idx * 2 + 1])?;
121 *byte = (high << 4) | low;
122 }
123 Ok(HashValue { bytes })
124 } else {
125 Err(ParseError::NotOctetSized)
126 }
127 }
128}