1use alloc::vec::Vec;
2
3use crate::error::{Error, Result};
4use crate::reader::{Reader, is_regular};
5use crate::string::ascii_hex::decode_hex_digit;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub struct Name<'a> {
10 data: &'a [u8],
11 literal: bool,
12}
13
14impl<'a> Name<'a> {
15 pub(crate) fn new(data: &'a [u8], literal: bool) -> Self {
16 Self { data, literal }
17 }
18
19 pub fn is_literal(&self) -> bool {
21 self.literal
22 }
23
24 pub fn as_str(&self) -> Option<&'a str> {
27 core::str::from_utf8(self.data).ok()
28 }
29
30 pub fn decode_into(&self, out: &mut Vec<u8>) -> Result<()> {
32 out.clear();
33
34 if !self.data.contains(&b'#') {
36 out.extend_from_slice(self.data);
37 return Ok(());
38 }
39
40 let mut inner = Reader::new(self.data);
42
43 while let Some(b) = inner.read_byte() {
44 if b == b'#' {
45 let hex = inner.read_bytes(2).ok_or(Error::SyntaxError)?;
46 let hi = decode_hex_digit(hex[0]).ok_or(Error::SyntaxError)?;
47 let lo = decode_hex_digit(hex[1]).ok_or(Error::SyntaxError)?;
48 out.push(hi << 4 | lo);
49 } else {
50 out.push(b);
51 }
52 }
53
54 Ok(())
55 }
56
57 pub fn decode(&self) -> Result<Vec<u8>> {
59 let mut out = Vec::new();
60 self.decode_into(&mut out)?;
61 Ok(out)
62 }
63}
64
65pub(crate) fn parse_literal<'a>(r: &mut Reader<'a>) -> Option<&'a [u8]> {
66 r.forward_tag(b"/")?;
67 let start = r.offset();
68 while r.eat(is_regular).is_some() {}
69 r.range(start..r.offset())
70}
71
72pub(crate) fn parse_executable<'a>(r: &mut Reader<'a>) -> Option<&'a [u8]> {
73 let start = r.offset();
74 r.forward_while(is_regular);
75 if r.offset() == start {
76 return None;
77 }
78 r.range(start..r.offset())
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 fn read_literal(input: &[u8]) -> Option<Name<'_>> {
86 let mut r = Reader::new(input);
87 parse_literal(&mut r).map(|d| Name::new(d, true))
88 }
89
90 fn read_executable(input: &[u8]) -> Option<Name<'_>> {
91 let mut r = Reader::new(input);
92 parse_executable(&mut r).map(|d| Name::new(d, false))
93 }
94
95 #[test]
96 fn literal_simple() {
97 let n = read_literal(b"/Name1").unwrap();
98 assert_eq!(n.as_str().unwrap(), "Name1");
99 assert!(n.is_literal());
100 }
101
102 #[test]
103 fn literal_empty_name() {
104 let n = read_literal(b"/").unwrap();
105 assert_eq!(n.as_str().unwrap(), "");
106 assert!(n.is_literal());
107 }
108
109 #[test]
110 fn literal_with_hex_escape() {
111 let n = read_literal(b"/lime#20Green").unwrap();
112 assert_eq!(n.as_str().unwrap(), "lime#20Green");
113 assert_eq!(n.decode().unwrap(), b"lime Green");
114 }
115
116 #[test]
117 fn literal_multiple_hex_escapes() {
118 let n = read_literal(b"/paired#28#29parentheses").unwrap();
119 assert_eq!(n.decode().unwrap(), b"paired()parentheses");
120 }
121
122 #[test]
123 fn literal_special_chars() {
124 let n = read_literal(b"/A;Name_With-Various***Characters?").unwrap();
125 assert_eq!(n.as_str().unwrap(), "A;Name_With-Various***Characters?");
126 }
127
128 #[test]
129 fn literal_stops_at_delimiter() {
130 let mut r = Reader::new(b"/Name(rest");
131 let data = parse_literal(&mut r).unwrap();
132 assert_eq!(data, b"Name");
133 assert_eq!(r.peek_byte(), Some(b'('));
134 }
135
136 #[test]
137 fn literal_stops_at_whitespace() {
138 let mut r = Reader::new(b"/Name rest");
139 let data = parse_literal(&mut r).unwrap();
140 assert_eq!(data, b"Name");
141 assert_eq!(r.peek_byte(), Some(b' '));
142 }
143
144 #[test]
145 fn literal_not_a_name() {
146 assert!(read_literal(b"Name").is_none());
147 }
148
149 #[test]
150 fn executable_simple() {
151 let n = read_executable(b"beginbfchar ").unwrap();
152 assert_eq!(n.as_str().unwrap(), "beginbfchar");
153 assert!(!n.is_literal());
154 }
155
156 #[test]
157 fn executable_stops_at_delimiter() {
158 let mut r = Reader::new(b"def/name");
159 let data = parse_executable(&mut r).unwrap();
160 assert_eq!(data, b"def");
161 assert_eq!(r.peek_byte(), Some(b'/'));
162 }
163
164 #[test]
165 fn executable_at_eof() {
166 let n = read_executable(b"endcmap").unwrap();
167 assert_eq!(n.as_str().unwrap(), "endcmap");
168 }
169
170 #[test]
171 fn executable_empty() {
172 assert!(read_executable(b"").is_none());
173 }
174
175 #[test]
176 fn executable_starts_at_delimiter() {
177 assert!(read_executable(b"(foo)").is_none());
178 }
179
180 #[test]
181 fn decode_no_escapes() {
182 let n = Name::new(b"simple", true);
183 assert_eq!(n.decode().unwrap(), b"simple");
184 }
185
186 #[test]
187 fn decode_with_escapes() {
188 let n = Name::new(b"lime#20Green", true);
189 assert_eq!(n.decode().unwrap(), b"lime Green");
190 }
191}