1use alloc::collections::BTreeMap;
19use alloc::string::String;
20use alloc::vec::Vec;
21
22use pith_digest::{Error, Result};
23
24use crate::lex::{Lexer, Tok};
25
26#[derive(Clone, Debug)]
29pub struct CMap {
30 map: BTreeMap<u64, String>,
32 lens: Vec<usize>,
36 wmode: u8,
38}
39
40fn key(code: u64, len: usize) -> u64 {
41 ((len as u64) << 56) | (code & ((1u64 << 56) - 1))
42}
43
44pub(crate) fn code_of_pub(bytes: &[u8]) -> u64 {
45 let mut v = 0u64;
46 for &b in bytes {
47 v = (v << 8) | u64::from(b);
48 }
49 v
50}
51
52fn utf16be(raw: &[u8]) -> Result<String> {
54 if raw.len() % 2 != 0 {
55 return Err(Error::BadValue("ToUnicode destination bytes"));
56 }
57 let units: Vec<u16> = raw
58 .chunks_exact(2)
59 .map(|p| u16::from_be_bytes([p[0], p[1]]))
60 .collect();
61 Ok(char::decode_utf16(units)
62 .map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER))
63 .collect())
64}
65
66impl CMap {
67 pub fn parse(data: &[u8]) -> Result<CMap> {
69 let mut lx = Lexer::new(data);
70 let mut map = BTreeMap::new();
71 let mut spaces: Vec<(u64, u64, usize)> = Vec::new();
72 let mut wmode: u8 = 0;
73 let mut stack: Vec<Tok> = Vec::new();
75 while let Some(t) = lx.next()? {
76 match t {
77 Tok::Str(_) | Tok::Num(_) | Tok::Name(_) | Tok::ArrOpen | Tok::ArrClose => {
78 if matches!(t, Tok::ArrOpen) {
81 let mut arr: Vec<Vec<u8>> = Vec::new();
82 loop {
83 match lx.next()? {
84 Some(Tok::ArrClose) => break,
85 Some(Tok::Str(s)) => arr.push(s.into_owned()),
86 Some(_) => return Err(Error::BadValue("bfrange array")),
87 None => {
88 return Err(Error::Truncated {
89 what: "bfrange array",
90 needed: 1,
91 found: 0,
92 });
93 }
94 }
95 }
96 stack.push(Tok::ArrOpen);
97 for s in arr {
98 stack.push(Tok::Str(alloc::borrow::Cow::Owned(s)));
99 }
100 stack.push(Tok::ArrClose);
101 } else {
102 stack.push(t);
103 }
104 if stack.len() > 4096 {
105 return Err(Error::BadValue("cmap operand stack"));
106 }
107 }
108 Tok::DictOpen | Tok::DictClose => {}
109 Tok::Kw(k) => {
110 match &*k {
111 b"begincodespacerange" => {
112 let n = pop_count(&mut stack)?;
113 for _ in 0..n {
114 let (lo, hi) = take2(&mut lx, "codespacerange")?;
115 if lo.len() != hi.len() || lo.len() > 7 {
116 return Err(Error::BadValue("codespacerange"));
117 }
118 spaces.push((code_of_pub(&lo), code_of_pub(&hi), lo.len()));
119 }
120 }
121 b"beginbfchar" => {
122 let n = pop_count(&mut stack)?;
123 for _ in 0..n {
124 let (src, dst) = take2(&mut lx, "bfchar")?;
125 add_bfchar(&mut map, &src, &dst)?;
126 }
127 }
128 b"beginbfrange" => {
129 let n = pop_count(&mut stack)?;
130 for _ in 0..n {
131 read_bfrange(&mut lx, &mut map)?;
132 }
133 }
134 b"begincidchar" | b"begincidrange" | b"beginnotdefchar"
135 | b"beginnotdefrange" => {
136 let n = pop_count(&mut stack)?;
139 skip_cid_pairs(&mut lx, n)?;
140 }
141 b"def" => {
142 if stack.len() >= 2 {
144 if let (Tok::Name(name), Tok::Num(v)) =
145 (&stack[stack.len() - 2], &stack[stack.len() - 1])
146 {
147 if name.as_ref() == b"WMode"
148 && crate::lex::is_int(*v)
149 && *v >= 0.0
150 && *v <= 1.0
151 {
152 wmode = *v as u8;
153 }
154 }
155 }
156 stack.clear();
157 }
158 _ => stack.clear(),
159 }
160 }
161 }
162 }
163 if map.is_empty() && spaces.is_empty() {
164 return Err(Error::BadValue("CMap has no mappings"));
165 }
166 let mut lens: Vec<usize> = spaces.iter().map(|&(_, _, l)| l).collect();
167 for &k in map.keys() {
169 let l = (k >> 56) as usize;
170 if !lens.contains(&l) {
171 lens.push(l);
172 }
173 }
174 lens.sort_unstable_by(|a, b| b.cmp(a));
175 Ok(CMap { map, lens, wmode })
176 }
177
178 pub fn is_vertical(&self) -> bool {
180 self.wmode == 1
181 }
182
183 pub(crate) fn get(&self, code: u64, len: usize) -> Option<&str> {
185 self.map.get(&key(code, len)).map(String::as_str)
186 }
187
188 pub(crate) fn lens(&self) -> &[usize] {
190 &self.lens
191 }
192
193 pub fn lookup(&self, bytes: &[u8]) -> (Option<&str>, usize) {
198 for &l in &self.lens {
199 if l <= bytes.len() {
200 let c = code_of_pub(&bytes[..l]);
201 if let Some(s) = self.map.get(&key(c, l)) {
202 return (Some(s.as_str()), l);
203 }
204 }
205 }
206 (None, *self.lens.last().unwrap_or(&1))
208 }
209}
210
211fn pop_count(stack: &mut Vec<Tok>) -> Result<i64> {
212 match stack.pop() {
213 Some(Tok::Num(v)) => crate::lex::f64_as_i64(v)
214 .filter(|&n| (0..=1_000_000).contains(&n))
215 .ok_or(Error::BadValue("cmap section count")),
216 _ => Err(Error::BadValue("cmap section count")),
217 }
218}
219
220fn take2(lx: &mut Lexer, what: &'static str) -> Result<(Vec<u8>, Vec<u8>)> {
221 let a = take_str(lx, what)?;
222 let b = take_str(lx, what)?;
223 Ok((a, b))
224}
225
226fn take_str(lx: &mut Lexer, what: &'static str) -> Result<Vec<u8>> {
227 match lx.next()? {
228 Some(Tok::Str(s)) => Ok(s.into_owned()),
229 Some(Tok::Name(n)) => Ok(n.into_owned()),
230 _ => Err(Error::BadValue(what)),
231 }
232}
233
234fn add_bfchar(map: &mut BTreeMap<u64, String>, src: &[u8], dst: &[u8]) -> Result<()> {
235 if src.is_empty() || src.len() > 7 {
236 return Err(Error::BadValue("bfchar source"));
237 }
238 if dst.is_empty() {
239 return Err(Error::BadValue("bfchar destination"));
240 }
241 map.insert(key(code_of_pub(src), src.len()), utf16be(dst)?);
242 Ok(())
243}
244
245fn read_bfrange(lx: &mut Lexer, map: &mut BTreeMap<u64, String>) -> Result<()> {
246 let lo = take_str(lx, "bfrange lo")?;
247 let hi = take_str(lx, "bfrange hi")?;
248 if lo.len() != hi.len() || lo.is_empty() || lo.len() > 7 {
249 return Err(Error::BadValue("bfrange source"));
250 }
251 let lo_v = code_of_pub(&lo);
252 let hi_v = code_of_pub(&hi);
253 if hi_v < lo_v {
254 return Err(Error::BadValue("bfrange range"));
255 }
256 let span = hi_v - lo_v;
257 if span > 65536 {
258 return Err(Error::TooLarge {
259 what: "bfrange span",
260 limit: 65536,
261 });
262 }
263 match lx.next()? {
264 Some(Tok::Str(dst0)) => {
265 let units = utf16_units(&dst0)?;
266 for i in 0..=span {
267 let dst = inc_units(&units, i);
268 let s: String = char::decode_utf16(dst)
269 .map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER))
270 .collect();
271 map.insert(key(lo_v + i, lo.len()), s);
272 }
273 Ok(())
274 }
275 Some(Tok::ArrOpen) => {
276 let mut i = 0u64;
277 loop {
278 match lx.next()? {
279 Some(Tok::ArrClose) => break,
280 Some(Tok::Str(d)) => {
281 if i > span {
282 return Err(Error::BadValue("bfrange array length"));
283 }
284 map.insert(key(lo_v + i, lo.len()), utf16be(&d)?);
285 i += 1;
286 }
287 Some(_) => return Err(Error::BadValue("bfrange array")),
288 None => {
289 return Err(Error::Truncated {
290 what: "bfrange array",
291 needed: 1,
292 found: 0,
293 });
294 }
295 }
296 }
297 if i != span + 1 {
298 return Err(Error::BadValue("bfrange array length"));
299 }
300 Ok(())
301 }
302 _ => Err(Error::BadValue("bfrange destination")),
303 }
304}
305
306fn utf16_units(raw: &[u8]) -> Result<Vec<u16>> {
307 if raw.len() % 2 != 0 || raw.is_empty() {
308 return Err(Error::BadValue("bfrange destination bytes"));
309 }
310 Ok(raw
311 .chunks_exact(2)
312 .map(|p| u16::from_be_bytes([p[0], p[1]]))
313 .collect())
314}
315
316fn inc_units(dst: &[u16], i: u64) -> Vec<u16> {
321 let mut out = dst.to_vec();
322 let mut carry = i;
323 for u in out.iter_mut().rev() {
324 if carry == 0 {
325 break;
326 }
327 let v = u64::from(*u) + carry;
328 *u = (v & 0xFFFF) as u16;
329 carry = v >> 16;
330 }
331 out
332}
333
334fn skip_cid_pairs(lx: &mut Lexer, n: i64) -> Result<()> {
335 for _ in 0..n {
336 let _ = lx.next()?.ok_or(Error::Truncated {
339 what: "cid section",
340 needed: 1,
341 found: 0,
342 })?;
343 match lx.next()? {
344 Some(Tok::ArrOpen) => loop {
345 match lx.next()? {
346 Some(Tok::ArrClose) => break,
347 Some(_) => {}
348 None => {
349 return Err(Error::Truncated {
350 what: "cidrange array",
351 needed: 1,
352 found: 0,
353 });
354 }
355 }
356 },
357 Some(_) => {}
358 None => {
359 return Err(Error::Truncated {
360 what: "cid section",
361 needed: 1,
362 found: 0,
363 });
364 }
365 }
366 }
367 Ok(())
368}