xsd_types/value/
hex_binary.rs1use std::{
2 borrow::Borrow,
3 fmt,
4 ops::{Deref, DerefMut},
5 str::FromStr,
6};
7
8use crate::{
9 lexical::{self, LexicalFormOf},
10 Datatype, ParseXsd, XsdValue,
11};
12
13const CHARS: [char; 16] = [
14 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
15];
16
17#[derive(Debug, thiserror::Error)]
18#[error("invalid hexadecimal")]
19pub struct InvalidHex;
20
21#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
22pub struct HexBinaryBuf(Vec<u8>);
23
24impl HexBinaryBuf {
25 pub fn new() -> Self {
26 Self::default()
27 }
28
29 pub fn from_bytes(bytes: Vec<u8>) -> Self {
30 Self(bytes)
31 }
32
33 pub fn decode(input: impl AsRef<[u8]>) -> Result<Self, InvalidHex> {
34 let input = input.as_ref();
35 let mut bytes = Vec::with_capacity(input.len() / 2);
36
37 let mut iter = input.iter();
38 while let Some(&a) = iter.next() {
39 let a = decode_char(a)?;
40
41 match iter.next() {
42 Some(&b) => {
43 let b = decode_char(b)?;
44 bytes.push(a << 4 | b)
45 }
46 None => return Err(InvalidHex),
47 }
48 }
49
50 Ok(Self(bytes))
51 }
52
53 pub fn into_bytes(self) -> Vec<u8> {
54 self.0
55 }
56
57 pub fn as_bytes(&self) -> &[u8] {
58 &self.0
59 }
60
61 pub fn as_hex_binary(&self) -> &HexBinary {
62 HexBinary::new(&self.0)
63 }
64
65 pub fn as_hex_binary_mut(&mut self) -> &mut HexBinary {
66 HexBinary::new_mut(&mut self.0)
67 }
68}
69
70fn decode_char(c: u8) -> Result<u8, InvalidHex> {
71 match c {
72 b'0'..=b'9' => Ok(c - b'0'),
73 b'A'..=b'F' => Ok(0xa + (c - b'A')),
74 b'a'..=b'f' => Ok(0xa + (c - b'a')),
75 _ => Err(InvalidHex),
76 }
77}
78
79impl fmt::Display for HexBinaryBuf {
80 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81 self.as_hex_binary().fmt(f)
82 }
83}
84
85impl From<Vec<u8>> for HexBinaryBuf {
86 fn from(value: Vec<u8>) -> Self {
87 HexBinaryBuf::from_bytes(value)
88 }
89}
90
91impl FromStr for HexBinaryBuf {
92 type Err = InvalidHex;
93
94 fn from_str(s: &str) -> Result<Self, Self::Err> {
95 Self::decode(s)
96 }
97}
98
99impl AsRef<[u8]> for HexBinaryBuf {
100 fn as_ref(&self) -> &[u8] {
101 self.as_bytes()
102 }
103}
104
105impl AsRef<HexBinary> for HexBinaryBuf {
106 fn as_ref(&self) -> &HexBinary {
107 self.as_hex_binary()
108 }
109}
110
111impl Borrow<HexBinary> for HexBinaryBuf {
112 fn borrow(&self) -> &HexBinary {
113 self.as_hex_binary()
114 }
115}
116
117impl Deref for HexBinaryBuf {
118 type Target = HexBinary;
119
120 fn deref(&self) -> &Self::Target {
121 self.as_hex_binary()
122 }
123}
124
125impl DerefMut for HexBinaryBuf {
126 fn deref_mut(&mut self) -> &mut Self::Target {
127 self.as_hex_binary_mut()
128 }
129}
130
131impl XsdValue for HexBinaryBuf {
132 fn datatype(&self) -> Datatype {
133 Datatype::HexBinary
134 }
135}
136
137impl ParseXsd for HexBinaryBuf {
138 type LexicalForm = lexical::HexBinary;
139}
140
141impl LexicalFormOf<HexBinaryBuf> for lexical::HexBinary {
142 type ValueError = std::convert::Infallible;
143
144 fn try_as_value(&self) -> Result<HexBinaryBuf, Self::ValueError> {
145 Ok(self.value())
146 }
147}
148
149#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
150pub struct HexBinary([u8]);
151
152impl HexBinary {
153 pub fn new(bytes: &[u8]) -> &Self {
154 unsafe { std::mem::transmute(bytes) }
155 }
156
157 pub fn new_mut(bytes: &mut [u8]) -> &mut Self {
158 unsafe { std::mem::transmute(bytes) }
159 }
160
161 pub fn chars(&self) -> Chars {
162 Chars {
163 pending: None,
164 bytes: self.0.iter(),
165 }
166 }
167
168 pub fn as_bytes(&self) -> &[u8] {
169 &self.0
170 }
171}
172
173impl<'a> From<&'a [u8]> for &'a HexBinary {
174 fn from(value: &'a [u8]) -> Self {
175 HexBinary::new(value)
176 }
177}
178
179impl<'a> From<&'a mut [u8]> for &'a HexBinary {
180 fn from(value: &'a mut [u8]) -> Self {
181 HexBinary::new(value)
182 }
183}
184
185impl<'a> From<&'a mut [u8]> for &'a mut HexBinary {
186 fn from(value: &'a mut [u8]) -> Self {
187 HexBinary::new_mut(value)
188 }
189}
190
191impl fmt::Display for HexBinary {
192 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
193 for c in self.chars() {
194 c.fmt(f)?
195 }
196
197 Ok(())
198 }
199}
200
201impl ToOwned for HexBinary {
202 type Owned = HexBinaryBuf;
203
204 fn to_owned(&self) -> Self::Owned {
205 HexBinaryBuf::from_bytes(self.as_bytes().to_vec())
206 }
207}
208
209impl XsdValue for HexBinary {
210 fn datatype(&self) -> Datatype {
211 Datatype::HexBinary
212 }
213}
214
215pub struct Chars<'a> {
216 pending: Option<char>,
217 bytes: std::slice::Iter<'a, u8>,
218}
219
220impl<'a> Iterator for Chars<'a> {
221 type Item = char;
222
223 fn next(&mut self) -> Option<Self::Item> {
224 self.pending.take().or_else(|| {
225 self.bytes.next().map(|v| {
226 let a = v >> 4;
227 let b = v & 0x0f;
228
229 self.pending = Some(CHARS[b as usize]);
230 CHARS[a as usize]
231 })
232 })
233 }
234}
235
236#[cfg(test)]
237mod tests {
238 use super::*;
239
240 const TESTS: [(&'static [u8], &'static str); 9] = [
241 (b"M", "4D"),
242 (b"Ma", "4D61"),
243 (b"Man", "4D616E"),
244 (b"light w", "6C696768742077"),
245 (b"light wo", "6C6967687420776F"),
246 (b"light wor", "6C6967687420776F72"),
247 (b"light work", "6C6967687420776F726B"),
248 (b"light work.", "6C6967687420776F726B2E"),
249 (
250 b"Many hands make light work.",
251 "4D616E792068616E6473206D616B65206C6967687420776F726B2E",
252 ),
253 ];
254
255 #[test]
256 fn encoding() {
257 for (input, expected) in TESTS {
258 let output = HexBinary::new(input).to_string();
259 assert_eq!(output, expected)
260 }
261 }
262
263 #[test]
264 fn decoding() {
265 for (expected, input) in TESTS {
266 let output = HexBinaryBuf::decode(input).unwrap();
267 assert_eq!(output.as_bytes(), expected)
268 }
269 }
270}