php_parser_rs/lexer/
byte_string.rs1use schemars::JsonSchema;
2use serde::Deserialize;
3use serde::Serialize;
4
5use std::ops::Deref;
6use std::ops::DerefMut;
7use std::str::from_utf8;
8
9#[derive(PartialOrd, PartialEq, Eq, Clone, Hash)]
15pub struct ByteString {
16 pub bytes: Vec<u8>,
17}
18
19impl ByteString {
20 pub fn new(bytes: Vec<u8>) -> Self {
21 ByteString { bytes }
22 }
23}
24
25impl Default for ByteString {
26 fn default() -> Self {
27 ByteString::new(Vec::new())
28 }
29}
30
31impl std::fmt::Display for ByteString {
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 for &b in &self.bytes {
34 match b {
35 0 => write!(f, "\\0")?,
36 b'\n' | b'\r' | b'\t' => write!(f, "{}", b as char)?,
37 0x01..=0x19 | 0x7f..=0xff => write!(f, "\\x{:02x}", b)?,
38 _ => write!(f, "{}", b as char)?,
39 }
40 }
41
42 Ok(())
43 }
44}
45
46impl std::str::FromStr for ByteString {
47 type Err = ();
48
49 fn from_str(s: &str) -> Result<Self, Self::Err> {
50 Ok(ByteString::new(s.as_bytes().to_vec()))
51 }
52}
53
54impl std::fmt::Debug for ByteString {
55 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56 write!(f, "\"")?;
57 for &b in &self.bytes {
58 match b {
59 0 => write!(f, "\\0")?,
60 b'\n' | b'\r' | b'\t' => write!(f, "{}", b.escape_ascii())?,
61 0x01..=0x19 | 0x7f..=0xff => write!(f, "\\x{:02x}", b)?,
62 _ => write!(f, "{}", b as char)?,
63 }
64 }
65 write!(f, "\"")?;
66 Ok(())
67 }
68}
69
70impl Serialize for ByteString {
71 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
72 where
73 S: serde::Serializer,
74 {
75 serializer.serialize_str(&self.to_string())
76 }
77}
78
79impl<'de> Deserialize<'de> for ByteString {
80 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
81 where
82 D: serde::Deserializer<'de>,
83 {
84 let s = String::deserialize(deserializer)?;
85 Ok(ByteString::new(s.into_bytes()))
86 }
87}
88
89impl JsonSchema for ByteString {
90 fn schema_name() -> String {
91 "ByteString".to_string()
92 }
93
94 fn json_schema(_: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
95 schemars::schema::SchemaObject {
96 instance_type: Some(schemars::schema::InstanceType::String.into()),
97 format: Some("byte-string".to_string()),
98 ..Default::default()
99 }
100 .into()
101 }
102}
103
104impl<const N: usize> PartialEq<&[u8; N]> for ByteString {
105 fn eq(&self, other: &&[u8; N]) -> bool {
106 &self.bytes == other
107 }
108}
109
110impl<const N: usize> PartialEq<&[u8; N]> for &ByteString {
111 fn eq(&self, other: &&[u8; N]) -> bool {
112 &self.bytes == other
113 }
114}
115
116impl From<u8> for ByteString {
117 fn from(byte: u8) -> Self {
118 ByteString::new(vec![byte])
119 }
120}
121
122impl From<Vec<u8>> for ByteString {
123 fn from(bytes: Vec<u8>) -> Self {
124 ByteString::new(bytes)
125 }
126}
127
128impl From<&[u8]> for ByteString {
129 fn from(bytes: &[u8]) -> Self {
130 ByteString::new(bytes.to_vec())
131 }
132}
133
134impl<const N: usize> From<&[u8; N]> for ByteString {
135 fn from(bytes: &[u8; N]) -> Self {
136 ByteString::new(bytes.to_vec())
137 }
138}
139
140impl From<&str> for ByteString {
141 fn from(bytes: &str) -> Self {
142 ByteString::new(bytes.as_bytes().to_vec())
143 }
144}
145
146impl From<String> for ByteString {
147 fn from(bytes: String) -> Self {
148 ByteString::new(bytes.into_bytes())
149 }
150}
151
152impl From<ByteString> for String {
153 fn from(bytes: ByteString) -> Self {
154 String::from(from_utf8(&bytes.bytes).unwrap())
155 }
156}
157
158impl Deref for ByteString {
159 type Target = Vec<u8>;
160
161 fn deref(&self) -> &Vec<u8> {
162 &self.bytes
163 }
164}
165
166impl DerefMut for ByteString {
167 fn deref_mut(&mut self) -> &mut Self::Target {
168 &mut self.bytes
169 }
170}
171
172#[cfg(test)]
173mod tests {
174 use super::*;
175
176 #[test]
177 fn test_byte_string_debug() {
178 assert_eq!(format!("{:?}", ByteString::from("abc")), r#""abc""#);
179 assert_eq!(
180 format!("{:?}", ByteString::from("\0\n\r\t")),
181 r#""\0\n\r\t""#
182 );
183 assert_eq!(
184 format!("{:?}", ByteString::from(b"\x01\x10\x7f\xff")),
185 r#""\x01\x10\x7f\xff""#
186 );
187 }
188}