1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
use std::fmt;
use std::rc::Rc;
use std::str::FromStr;
#[derive(Default, Clone, PartialEq, Eq)]
pub struct Buf {
inner: Rc<Box<[u8]>>,
}
impl Buf {
#[inline]
pub fn from_slice<T: AsRef<[u8]>>(s: T) -> Self {
Self {
inner: Rc::new(s.as_ref().into()),
}
}
#[inline]
pub fn len(&self) -> usize {
self.inner.len()
}
pub fn cow_buffer(self) -> Box<[u8]> {
Rc::unwrap_or_clone(self.inner)
}
}
impl AsRef<[u8]> for Buf {
#[inline]
fn as_ref(&self) -> &[u8] {
&self.inner
}
}
impl From<Vec<u8>> for Buf {
#[inline]
fn from(mut s: Vec<u8>) -> Self {
s.shrink_to_fit();
Self {
inner: Rc::new(s.into()),
}
}
}
impl From<Box<[u8]>> for Buf {
#[inline]
fn from(s: Box<[u8]>) -> Self {
Self { inner: Rc::new(s) }
}
}
// Must take reference here because otherwise trait can be implemented for self
impl<T> From<&T> for Buf
where
T: AsRef<[u8]> + ?Sized,
{
#[inline]
fn from(s: &T) -> Self {
Self {
inner: Rc::new(s.as_ref().into()),
}
}
}
impl fmt::Debug for Buf {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
/* FIXME: allow printing of hex crap, data here does not have to be utf-8, and printing it
* like this could panic.
*/
let s = std::str::from_utf8(self.inner.as_ref()).unwrap();
f.write_fmt(format_args!("Bytes<{:?}>", s))
}
}
#[derive(Debug)]
pub struct StringLiteralParseError {}
fn hex_decode(chr: char) -> u8 {
debug_assert!(chr.is_ascii_hexdigit());
let c = chr as u8;
match c {
b'0'..=b'9' => c - b'0',
b'a'..=b'f' => c - b'a' + 10,
b'A'..=b'F' => c - b'A' + 10,
_ => unreachable!(),
}
}
impl FromStr for Buf {
type Err = StringLiteralParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut hex = false;
let mut v: Vec<u8> = Vec::new();
let mut h: [u8; 2] = [0, 0];
let mut ix: usize = 0;
for chr in s.chars() {
if !hex {
if chr == '|' {
hex = true;
ix = 0;
continue;
}
v.push(chr as u8);
} else {
if chr.is_whitespace() {
continue;
}
/* XXX: Allow a range of separators. For now we're ignoring them as purely
* cosmetic, but in future we probably want to delimit bytes with these?
*/
match chr {
':' => continue,
'.' => continue,
'_' => continue,
'-' => continue,
'\'' => continue,
'`' => continue,
_ => (),
}
if chr == '|' {
if ix != 0 {
/* Odd number of hex digits */
return Err(Self::Err {});
}
hex = false;
continue;
}
if !chr.is_ascii_hexdigit() {
/* Non-hex in hex sequence */
return Err(Self::Err {});
}
h[ix] = hex_decode(chr);
ix += 1;
if ix == 2 {
v.push((h[0] << 4) | h[1]);
ix = 0;
}
}
}
Ok(Buf::from(v))
}
}