php_parser_rs/lexer/
byte_string.rs

1use schemars::JsonSchema;
2use serde::Deserialize;
3use serde::Serialize;
4
5use std::ops::Deref;
6use std::ops::DerefMut;
7use std::str::from_utf8;
8
9/// A wrapper for Vec<u8> that provides a human-readable Debug impl and
10/// a few other conveniences.
11///
12/// The Trunk lexer and parser work mainly with byte strings because
13/// valid PHP code is not required to be valid UTF-8.
14#[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}