Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add ByteString type
  • Loading branch information
Evan Shaw committed Sep 13, 2022
commit 843a00c5234684216f993c47eff8db2ad71e2505
5 changes: 4 additions & 1 deletion trunk_lexer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@ version = "0.1.0"
edition = "2021"

[lib]
doctest = false
doctest = false

[dependencies]
serde = { version = "1.0.139", features = ["derive"] }
97 changes: 97 additions & 0 deletions trunk_lexer/src/byte_string.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
use std::cmp::{Eq, PartialEq};
use std::fmt::{Debug, Formatter, Result};
use std::ops::Deref;

use serde::Serialize;

/// A wrapper for Vec<u8> that provides a human-readable Debug impl and
/// a few other conveniences.
///
/// The Trunk lexer and parser work mainly with byte strings because
/// valid PHP code is not required to be valid UTF-8.
#[derive(Clone, Eq, PartialEq, Serialize)]
pub struct ByteString(pub(crate) Vec<u8>);

impl ByteString {
pub fn new(bytes: Vec<u8>) -> Self {
ByteString(bytes)
}
}

impl Debug for ByteString {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
write!(f, "\"")?;
for &b in &self.0 {
match b {
0 => write!(f, "\\0")?,
b'\n' | b'\r' | b'\t' => write!(f, "{}", b.escape_ascii())?,
0x01..=0x19 | 0x7f..=0xff => write!(f, "\\x{:02x}", b)?,
_ => write!(f, "{}", b as char)?,
}
}
write!(f, "\"")?;
Ok(())
}
}

impl<const N: usize> PartialEq<&[u8; N]> for ByteString {
fn eq(&self, other: &&[u8; N]) -> bool {
&self.0 == other
}
}

impl From<Vec<u8>> for ByteString {
fn from(bytes: Vec<u8>) -> Self {
ByteString::new(bytes)
}
}

impl From<&[u8]> for ByteString {
fn from(bytes: &[u8]) -> Self {
ByteString::new(bytes.to_vec())
}
}

impl<const N: usize> From<&[u8; N]> for ByteString {
fn from(bytes: &[u8; N]) -> Self {
ByteString::new(bytes.to_vec())
}
}

impl From<&str> for ByteString {
fn from(bytes: &str) -> Self {
ByteString::new(bytes.as_bytes().to_vec())
}
}

impl From<String> for ByteString {
fn from(bytes: String) -> Self {
ByteString::new(bytes.into_bytes())
}
}

impl Deref for ByteString {
type Target = Vec<u8>;

fn deref(&self) -> &Vec<u8> {
&self.0
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_byte_string_debug() {
assert_eq!(format!("{:?}", ByteString::from("abc")), r#""abc""#);
assert_eq!(
format!("{:?}", ByteString::from("\0\n\r\t")),
r#""\0\n\r\t""#
);
assert_eq!(
format!("{:?}", ByteString::from(b"\x01\x10\x7f\xff")),
r#""\x01\x10\x7f\xff""#
);
}
}
2 changes: 2 additions & 0 deletions trunk_lexer/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
mod byte_string;
mod lexer;
mod token;

pub use byte_string::ByteString;
pub use lexer::{Lexer, LexerError};
pub use token::{OpenTagKind, Span, Token, TokenKind};