1use crate::object::macros::object;
4use crate::object::r#ref::{MaybeRef, ObjRef};
5use crate::object::{Name, ObjectIdentifier};
6use crate::object::{Object, ObjectLike};
7use crate::reader::Reader;
8use crate::reader::{Readable, ReaderContext, ReaderExt, Skippable};
9use crate::sync::Arc;
10use crate::sync::FxHashMap;
11use alloc::format;
12use alloc::vec::Vec;
13use core::fmt::{Debug, Display, Formatter};
14use core::ops::Deref;
15
16#[derive(Clone)]
19pub struct Dict<'a>(Inner<'a>);
20
21#[derive(Clone)]
22enum Inner<'a> {
23 Empty,
24 Some(Arc<Repr<'a>>),
25}
26
27impl Default for Dict<'_> {
28 fn default() -> Self {
29 Self::empty()
30 }
31}
32
33impl PartialEq for Dict<'_> {
36 fn eq(&self, other: &Self) -> bool {
37 self.data() == other.data()
38 }
39}
40
41impl<'a> Dict<'a> {
42 pub fn empty() -> Self {
44 Self(Inner::Empty)
45 }
46
47 pub fn data(&self) -> &'a [u8] {
49 match &self.0 {
50 Inner::Empty => &[],
51 Inner::Some(repr) => repr.data,
52 }
53 }
54
55 pub fn len(&self) -> usize {
57 self.offsets().map_or(0, FxHashMap::len)
58 }
59
60 pub fn is_empty(&self) -> bool {
62 self.offsets().is_none_or(FxHashMap::is_empty)
63 }
64
65 pub fn contains_key(&self, key: impl AsRef<[u8]>) -> bool {
67 self.offsets()
68 .is_some_and(|offsets| offsets.contains_key(key.as_ref()))
69 }
70
71 #[allow(
74 private_bounds,
75 reason = "users shouldn't be able to implement `ObjectLike` for custom objects."
76 )]
77 pub fn get<T>(&self, key: impl AsRef<[u8]>) -> Option<T>
78 where
79 T: ObjectLike<'a>,
80 {
81 self.get_raw::<T>(key.as_ref())?.resolve(self.ctx())
82 }
83
84 pub fn get_ref(&self, key: impl AsRef<[u8]>) -> Option<ObjRef> {
86 let offset = *self.offsets()?.get(key.as_ref())?;
87
88 Reader::new(&self.data()[offset..]).read_with_context::<ObjRef>(self.ctx())
89 }
90
91 pub fn keys(&self) -> impl Iterator<Item = Name<'a>> + '_ {
93 self.offsets()
94 .into_iter()
95 .flat_map(|offsets| offsets.keys().cloned())
96 }
97
98 pub fn entries(&self) -> impl Iterator<Item = (Name<'a>, MaybeRef<Object<'a>>)> + '_ {
100 let mut sorted_keys = self.keys().collect::<Vec<_>>();
101 sorted_keys.sort_by(|n1, n2| n1.as_ref().cmp(n2.as_ref()));
102 sorted_keys
103 .into_iter()
104 .filter_map(|k| self.get_raw(k.deref()).map(|obj| (k, obj)))
105 }
106
107 pub fn obj_id(&self) -> Option<ObjectIdentifier> {
109 self.ctx().obj_number()
110 }
111
112 #[allow(private_bounds)]
114 pub fn get_raw<T>(&self, key: impl AsRef<[u8]>) -> Option<MaybeRef<T>>
115 where
116 T: Readable<'a>,
117 {
118 let offset = *self.offsets()?.get(key.as_ref())?;
119
120 Reader::new(&self.data()[offset..]).read_with_context::<MaybeRef<T>>(self.ctx())
121 }
122
123 pub(crate) fn ctx(&self) -> &ReaderContext<'a> {
124 match &self.0 {
125 Inner::Empty => ReaderContext::dummy_ref(),
126 Inner::Some(repr) => &repr.ctx,
127 }
128 }
129
130 fn offsets(&self) -> Option<&FxHashMap<Name<'a>, usize>> {
131 match &self.0 {
132 Inner::Empty => None,
133 Inner::Some(repr) => Some(&repr.offsets),
134 }
135 }
136}
137
138impl Debug for Dict<'_> {
139 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
140 let mut debug_struct = f.debug_struct("Dict");
141
142 for (key, value) in self.entries() {
143 debug_struct.field(&format!("{:?}", key.as_str()), &value);
144 }
145
146 debug_struct.finish()
147 }
148}
149
150impl Display for Dict<'_> {
151 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
152 f.write_str("<<")?;
153 for (key, value) in self.entries() {
154 f.write_str(" ")?;
155 Display::fmt(&key, f)?;
156 f.write_str(" ")?;
157 Display::fmt(&value, f)?;
158 }
159 if !self.is_empty() {
160 f.write_str(" ")?;
161 }
162 f.write_str(">>")
163 }
164}
165
166impl Skippable for Dict<'_> {
167 fn skip(r: &mut Reader<'_>, is_content_stream: bool) -> Option<()> {
168 Self::skip_with_depth(r, is_content_stream, 0)
169 }
170
171 fn skip_with_depth(r: &mut Reader<'_>, is_content_stream: bool, depth: usize) -> Option<()> {
172 if depth >= super::MAX_OBJECT_NESTING_DEPTH {
173 return None;
174 }
175
176 r.forward_tag(b"<<")?;
177
178 loop {
179 r.skip_white_spaces_and_comments();
180
181 if let Some(()) = r.forward_tag(b">>") {
182 break Some(());
183 } else {
184 let Some(_) = r.skip::<Name<'_>>(is_content_stream) else {
185 r.skip_with_depth::<Object<'_>>(is_content_stream, depth + 1)?;
187 continue;
188 };
189
190 r.skip_white_spaces_and_comments();
191
192 if is_content_stream {
193 r.skip_with_depth::<Object<'_>>(is_content_stream, depth + 1)?;
194 } else {
195 r.skip_with_depth::<MaybeRef<Object<'_>>>(is_content_stream, depth + 1)?;
196 }
197 }
198 }
199 }
200}
201
202impl<'a> Readable<'a> for Dict<'a> {
203 fn read(r: &mut Reader<'a>, ctx: &ReaderContext<'a>) -> Option<Self> {
204 read_inner(r, ctx, Some(b"<<"), b">>")
205 }
206}
207
208fn read_inner<'a>(
209 r: &mut Reader<'a>,
210 ctx: &ReaderContext<'a>,
211 start_tag: Option<&[u8]>,
212 end_tag: &[u8],
213) -> Option<Dict<'a>> {
214 #[cfg(feature = "std")]
219 let mut offsets = FxHashMap::with_capacity_and_hasher(8, rustc_hash::FxBuildHasher);
220 #[cfg(not(feature = "std"))]
221 let mut offsets = FxHashMap::new();
222
223 let data = parse_dict_with(
224 r,
225 ctx,
226 start_tag,
227 end_tag,
228 #[inline]
229 |name, offset, _| {
230 offsets.insert(name, offset);
231 Some(())
232 },
233 )?;
234
235 Some(Dict(Inner::Some(Arc::new(Repr {
236 data,
237 offsets,
238 ctx: ctx.clone(),
239 }))))
240}
241
242pub(crate) struct DictProbe<'a> {
243 pub(crate) data: &'a [u8],
244 pub(crate) has_root: bool,
245 pub(crate) has_type: bool,
246}
247
248pub(crate) fn probe_dict<'a>(
252 r: &mut Reader<'a>,
253 ctx: &ReaderContext<'a>,
254 start_tag: Option<&[u8]>,
255 end_tag: &[u8],
256) -> Option<DictProbe<'a>> {
257 let mut has_root = false;
258 let mut has_type = false;
259
260 let data = parse_dict_with(
261 r,
262 ctx,
263 start_tag,
264 end_tag,
265 #[inline]
266 |name, _, _value_reader| {
267 if name.as_ref() == keys::ROOT {
268 has_root = true;
269 } else if name.as_ref() == keys::TYPE {
270 has_type = true;
271 }
272
273 Some(())
274 },
275 )?;
276
277 Some(DictProbe {
278 data,
279 has_root,
280 has_type,
281 })
282}
283
284fn parse_dict_with<'a, F>(
285 r: &mut Reader<'a>,
286 ctx: &ReaderContext<'a>,
287 start_tag: Option<&[u8]>,
288 end_tag: &[u8],
289 mut on_entry: F,
290) -> Option<&'a [u8]>
291where
292 F: FnMut(Name<'a>, usize, &Reader<'a>) -> Option<()>,
293{
294 let depth = usize::from(start_tag.is_some());
295 let dict_data = r.tail()?;
296 let start_offset = r.offset();
297
298 if let Some(start_tag) = start_tag {
300 r.forward_tag(start_tag)?;
301 }
302
303 loop {
304 r.skip_white_spaces_and_comments();
305
306 if let Some(()) = r.peek_tag(end_tag) {
308 r.forward_tag(end_tag)?;
309 let end_offset = r.offset() - start_offset;
310
311 break Some(&dict_data[..end_offset]);
312 } else {
313 let Some(name) = r.read_without_context::<Name<'_>>() else {
314 if start_tag.is_some() {
315 r.skip_with_depth::<Object<'_>>(ctx.in_content_stream(), depth)?;
319 continue;
320 } else {
321 return None;
322 }
323 };
324 r.skip_white_spaces_and_comments();
325
326 let offset = r.offset() - start_offset;
327 on_entry(name, offset, r)?;
335
336 if ctx.in_content_stream() {
337 r.skip_with_depth::<Object<'_>>(ctx.in_content_stream(), depth)?;
338 } else {
339 r.skip_with_depth::<MaybeRef<Object<'_>>>(ctx.in_content_stream(), depth)?;
340 }
341 }
342 }
343}
344
345object!(Dict<'a>, Dict);
346
347struct Repr<'a> {
348 data: &'a [u8],
349 offsets: FxHashMap<Name<'a>, usize>,
350 ctx: ReaderContext<'a>,
351}
352
353pub(crate) struct InlineImageDict<'a>(Dict<'a>);
354
355impl<'a> InlineImageDict<'a> {
356 pub(crate) fn get_dict(&self) -> &Dict<'a> {
357 &self.0
358 }
359}
360
361impl<'a> Readable<'a> for InlineImageDict<'a> {
362 fn read(r: &mut Reader<'a>, ctx: &ReaderContext<'a>) -> Option<Self> {
363 Some(Self(read_inner(r, ctx, None, b"ID")?))
364 }
365}
366
367#[allow(missing_docs)]
369pub mod keys {
370 macro_rules! key {
371 ($i:ident, $e:expr) => {
372 pub const $i: &'static [u8] = $e;
373 };
374 }
375
376 key!(A, b"A");
378 key!(AA, b"AA");
379 key!(ABSOLUTE_COLORIMETRIC, b"AbsoluteColorimetric");
380 key!(AC, b"AC");
381 key!(ACRO_FORM, b"AcroForm");
382 key!(ACTUAL_TEXT, b"ActualText");
383 key!(ADBE, b"ADBE");
384 key!(ADBE_PKCS7_DETACHED, b"adbe.pkcs7.detached");
385 key!(ADBE_PKCS7_SHA1, b"adbe.pkcs7.sha1");
386 key!(ADBE_X509_RSA_SHA1, b"adbe.x509.rsa_sha1");
387 key!(ADOBE_PPKLITE, b"Adobe.PPKLite");
388 key!(AESV2, b"AESV2");
389 key!(AESV3, b"AESV3");
390 key!(AF, b"AF");
391 key!(AF_RELATIONSHIP, b"AFRelationship");
392 key!(AFTER, b"After");
393 key!(AI_META_DATA, b"AIMetaData");
394 key!(AIS, b"AIS");
395 key!(ALL_OFF, b"AllOff");
396 key!(ALL_ON, b"AllOn");
397 key!(ALT, b"Alt");
398 key!(ALPHA, b"Alpha");
399 key!(ALTERNATE, b"Alternate");
400 key!(ANNOT, b"Annot");
401 key!(ANNOTS, b"Annots");
402 key!(ANTI_ALIAS, b"AntiAlias");
403 key!(ANY_OFF, b"AnyOff");
404 key!(ANY_ON, b"AnyOn");
405 key!(AP, b"AP");
406 key!(AP_REF, b"APRef");
407 key!(APP, b"App");
408 key!(ART_BOX, b"ArtBox");
409 key!(ARTIFACT, b"Artifact");
410 key!(AS, b"AS");
411 key!(ASCENT, b"Ascent");
412 key!(ASCII_HEX_DECODE, b"ASCIIHexDecode");
413 key!(ASCII_HEX_DECODE_ABBREVIATION, b"AHx");
414 key!(ASCII85_DECODE, b"ASCII85Decode");
415 key!(ASCII85_DECODE_ABBREVIATION, b"A85");
416 key!(ATTACHED, b"Attached");
417 key!(AUTHOR, b"Author");
418 key!(AVG_WIDTH, b"AvgWidth");
419
420 key!(B, b"B");
422 key!(BACKGROUND, b"Background");
423 key!(BASE_ENCODING, b"BaseEncoding");
424 key!(BASE_FONT, b"BaseFont");
425 key!(BASE_STATE, b"BaseState");
426 key!(BASE_VERSION, b"BaseVersion");
427 key!(BBOX, b"BBox");
428 key!(BC, b"BC");
429 key!(BE, b"BE");
430 key!(BEAD, b"BEAD");
431 key!(BEFORE, b"Before");
432 key!(BG, b"BG");
433 key!(BITS_PER_COMPONENT, b"BitsPerComponent");
434 key!(BITS_PER_COORDINATE, b"BitsPerCoordinate");
435 key!(BITS_PER_FLAG, b"BitsPerFlag");
436 key!(BITS_PER_SAMPLE, b"BitsPerSample");
437 key!(BL, b"Bl");
438 key!(BLACK_IS_1, b"BlackIs1");
439 key!(BLACK_POINT, b"BlackPoint");
440 key!(BLEED_BOX, b"BleedBox");
441 key!(BM, b"BM");
442 key!(BORDER, b"Border");
443 key!(BOUNDS, b"Bounds");
444 key!(BPC, b"BPC");
445 key!(BS, b"BS");
446 key!(BTN, b"Btn");
447 key!(BYTERANGE, b"ByteRange");
448
449 key!(C, b"C");
451 key!(C0, b"C0");
452 key!(C1, b"C1");
453 key!(CA, b"CA");
454 key!(CA_NS, b"ca");
455 key!(CALGRAY, b"CalGray");
456 key!(CALRGB, b"CalRGB");
457 key!(CALCMYK, b"CalCMYK");
458 key!(CAP, b"Cap");
459 key!(CAP_HEIGHT, b"CapHeight");
460 key!(CATALOG, b"Catalog");
461 key!(CCITTFAX_DECODE, b"CCITTFaxDecode");
462 key!(CCITTFAX_DECODE_ABBREVIATION, b"CCF");
463 key!(CENTER_WINDOW, b"CenterWindow");
464 key!(CERT, b"Cert");
465 key!(CERTS, b"Certs");
466 key!(CF, b"CF");
467 key!(CFM, b"CFM");
468 key!(CH, b"Ch");
469 key!(CHAR_PROCS, b"CharProcs");
470 key!(CHAR_SET, b"CharSet");
471 key!(CHECK_SUM, b"CheckSum");
472 key!(CI, b"CI");
473 key!(CICI_SIGNIT, b"CICI.SignIt");
474 key!(CID_FONT_TYPE0, b"CIDFontType0");
475 key!(CID_FONT_TYPE0C, b"CIDFontType0C");
476 key!(CID_FONT_TYPE2, b"CIDFontType2");
477 key!(CID_TO_GID_MAP, b"CIDToGIDMap");
478 key!(CID_SET, b"CIDSet");
479 key!(CIDSYSTEMINFO, b"CIDSystemInfo");
480 key!(CL, b"CL");
481 key!(CLASS_MAP, b"ClassMap");
482 key!(CLR_F, b"ClrF");
483 key!(CLR_FF, b"ClrFf");
484 key!(CMAP, b"CMap");
485 key!(CMAPNAME, b"CMapName");
486 key!(CMYK, b"CMYK");
487 key!(CO, b"CO");
488 key!(COLOR, b"Color");
489 key!(COLLECTION, b"Collection");
490 key!(COLLECTION_ITEM, b"CollectionItem");
491 key!(COLLECTION_FIELD, b"CollectionField");
492 key!(COLLECTION_SCHEMA, b"CollectionSchema");
493 key!(COLLECTION_SORT, b"CollectionSort");
494 key!(COLLECTION_SUBITEM, b"CollectionSubitem");
495 key!(COLOR_BURN, b"ColorBurn");
496 key!(COLOR_DODGE, b"ColorDodge");
497 key!(COLORANTS, b"Colorants");
498 key!(COLORS, b"Colors");
499 key!(COLORSPACE, b"ColorSpace");
500 key!(COLOR_TRANSFORM, b"ColorTransform");
501 key!(COLUMNS, b"Columns");
502 key!(COMPATIBLE, b"Compatible");
503 key!(COMPONENTS, b"Components");
504 key!(CONTACT_INFO, b"ContactInfo");
505 key!(CONTENTS, b"Contents");
506 key!(COORDS, b"Coords");
507 key!(COUNT, b"Count");
508 key!(CP, b"CP");
509 key!(CREATION_DATE, b"CreationDate");
510 key!(CREATOR, b"Creator");
511 key!(CRL, b"CRL");
512 key!(CRLS, b"CRLS");
513 key!(CROP_BOX, b"CropBox");
514 key!(CRYPT, b"Crypt");
515 key!(CS, b"CS");
516 key!(CYX, b"CYX");
517
518 key!(D, b"D");
520 key!(DA, b"DA");
521 key!(DARKEN, b"Darken");
522 key!(DATE, b"Date");
523 key!(DCT_DECODE, b"DCTDecode");
524 key!(DCT_DECODE_ABBREVIATION, b"DCT");
525 key!(DECODE, b"Decode");
526 key!(DECODE_PARMS, b"DecodeParms");
527 key!(DEFAULT, b"default");
528 key!(DEFAULT_CMYK, b"DefaultCMYK");
529 key!(DEFAULT_CRYPT_FILTER, b"DefaultCryptFilter");
530 key!(DEFAULT_GRAY, b"DefaultGray");
531 key!(DEFAULT_RGB, b"DefaultRGB");
532 key!(DESC, b"Desc");
533 key!(DESCENDANT_FONTS, b"DescendantFonts");
534 key!(DESCENT, b"Descent");
535 key!(DEST, b"Dest");
536 key!(DEST_OUTPUT_PROFILE, b"DestOutputProfile");
537 key!(DESTS, b"Dests");
538 key!(DEVICE_CMYK, b"DeviceCMYK");
539 key!(DEVICE_GRAY, b"DeviceGray");
540 key!(DEVICE_N, b"DeviceN");
541 key!(DEVICE_RGB, b"DeviceRGB");
542 key!(DI, b"Di");
543 key!(DIFFERENCE, b"Difference");
544 key!(DIFFERENCES, b"Differences");
545 key!(DIGEST_METHOD, b"DigestMethod");
546 key!(DIGEST_RIPEMD160, b"RIPEMD160");
547 key!(DIGEST_SHA1, b"SHA1");
548 key!(DIGEST_SHA256, b"SHA256");
549 key!(DIGEST_SHA384, b"SHA384");
550 key!(DIGEST_SHA512, b"SHA512");
551 key!(DIRECTION, b"Direction");
552 key!(DISPLAY_DOC_TITLE, b"DisplayDocTitle");
553 key!(DL, b"DL");
554 key!(DM, b"Dm");
555 key!(DOC, b"Doc");
556 key!(DOC_CHECKSUM, b"DocChecksum");
557 key!(DOC_TIME_STAMP, b"DocTimeStamp");
558 key!(DOCMDP, b"DocMDP");
559 key!(DOCUMENT, b"Document");
560 key!(DOMAIN, b"Domain");
561 key!(DOS, b"DOS");
562 key!(DP, b"DP");
563 key!(DR, b"DR");
564 key!(DS, b"DS");
565 key!(DSS, b"DSS");
566 key!(DUPLEX, b"Duplex");
567 key!(DUR, b"Dur");
568 key!(DV, b"DV");
569 key!(DW, b"DW");
570 key!(DW2, b"DW2");
571
572 key!(E, b"E");
574 key!(EARLY_CHANGE, b"EarlyChange");
575 key!(EF, b"EF");
576 key!(EMBEDDED_FDFS, b"EmbeddedFDFs");
577 key!(EMBEDDED_FILE, b"EmbeddedFile");
578 key!(EMBEDDED_FILES, b"EmbeddedFiles");
579 key!(EMPTY, b"");
580 key!(ENCODE, b"Encode");
581 key!(ENCODED_BYTE_ALIGN, b"EncodedByteAlign");
582 key!(ENCODING, b"Encoding");
583 key!(ENCODING_90MS_RKSJ_H, b"90ms-RKSJ-H");
584 key!(ENCODING_90MS_RKSJ_V, b"90ms-RKSJ-V");
585 key!(ENCODING_ETEN_B5_H, b"ETen-B5-H");
586 key!(ENCODING_ETEN_B5_V, b"ETen-B5-V");
587 key!(ENCRYPT, b"Encrypt");
588 key!(ENCRYPT_META_DATA, b"EncryptMetadata");
589 key!(ENCRYPTED_PAYLOAD, b"EncryptedPayload");
590 key!(END_OF_BLOCK, b"EndOfBlock");
591 key!(END_OF_LINE, b"EndOfLine");
592 key!(ENTRUST_PPKEF, b"Entrust.PPKEF");
593 key!(EXCLUSION, b"Exclusion");
594 key!(EXTENSIONS, b"Extensions");
595 key!(EXTENSION_LEVEL, b"ExtensionLevel");
596 key!(EX_DATA, b"ExData");
597 key!(EXPORT, b"Export");
598 key!(EXPORT_STATE, b"ExportState");
599 key!(EXT_G_STATE, b"ExtGState");
600 key!(EXTEND, b"Extend");
601 key!(EXTENDS, b"Extends");
602
603 key!(F, b"F");
605 key!(F_DECODE_PARMS, b"FDecodeParms");
606 key!(F_FILTER, b"FFilter");
607 key!(FB, b"FB");
608 key!(FDF, b"FDF");
609 key!(FF, b"Ff");
610 key!(FIELDS, b"Fields");
611 key!(FILESPEC, b"Filespec");
612 key!(FILTER, b"Filter");
613 key!(FIRST, b"First");
614 key!(FIRST_CHAR, b"FirstChar");
615 key!(FIT_WINDOW, b"FitWindow");
616 key!(FL, b"FL");
617 key!(FLAGS, b"Flags");
618 key!(FLATE_DECODE, b"FlateDecode");
619 key!(FLATE_DECODE_ABBREVIATION, b"Fl");
620 key!(FO, b"Fo");
621 key!(FOLDERS, b"Folders");
622 key!(FONT, b"Font");
623 key!(FONT_BBOX, b"FontBBox");
624 key!(FONT_DESC, b"FontDescriptor");
625 key!(FONT_FAMILY, b"FontFamily");
626 key!(FONT_FILE, b"FontFile");
627 key!(FONT_FILE2, b"FontFile2");
628 key!(FONT_FILE3, b"FontFile3");
629 key!(FONT_MATRIX, b"FontMatrix");
630 key!(FONT_NAME, b"FontName");
631 key!(FONT_STRETCH, b"FontStretch");
632 key!(FONT_WEIGHT, b"FontWeight");
633 key!(FORM, b"Form");
634 key!(FORMTYPE, b"FormType");
635 key!(FRM, b"FRM");
636 key!(FS, b"FS");
637 key!(FT, b"FT");
638 key!(FUNCTION, b"Function");
639 key!(FUNCTION_TYPE, b"FunctionType");
640 key!(FUNCTIONS, b"Functions");
641
642 key!(G, b"G");
644 key!(GAMMA, b"Gamma");
645 key!(GROUP, b"Group");
646 key!(GTS_PDFA1, b"GTS_PDFA1");
647
648 key!(H, b"H");
650 key!(HARD_LIGHT, b"HardLight");
651 key!(HEIGHT, b"Height");
652 key!(HELV, b"Helv");
653 key!(HIDE_MENUBAR, b"HideMenubar");
654 key!(HIDE_TOOLBAR, b"HideToolbar");
655 key!(HIDE_WINDOWUI, b"HideWindowUI");
656 key!(HUE, b"Hue");
657
658 key!(I, b"I");
660 key!(IC, b"IC");
661 key!(ICC_BASED, b"ICCBased");
662 key!(ID, b"ID");
663 key!(ID_TREE, b"IDTree");
664 key!(IDENTITY, b"Identity");
665 key!(IDENTITY_H, b"Identity-H");
666 key!(IDENTITY_V, b"Identity-V");
667 key!(IF, b"IF");
668 key!(ILLUSTRATOR, b"Illustrator");
669 key!(IM, b"IM");
670 key!(IMAGE, b"Image");
671 key!(IMAGE_MASK, b"ImageMask");
672 key!(INDEX, b"Index");
673 key!(INDEXED, b"Indexed");
674 key!(INFO, b"Info");
675 key!(INKLIST, b"InkList");
676 key!(INTENT, b"Intent");
677 key!(INTERPOLATE, b"Interpolate");
678 key!(IRT, b"IRT");
679 key!(IT, b"IT");
680 key!(ITALIC_ANGLE, b"ItalicAngle");
681 key!(ISSUER, b"Issuer");
682 key!(IX, b"IX");
683
684 key!(JAVA_SCRIPT, b"JavaScript");
686 key!(JBIG2_DECODE, b"JBIG2Decode");
687 key!(JBIG2_GLOBALS, b"JBIG2Globals");
688 key!(JPX_DECODE, b"JPXDecode");
689 key!(JS, b"JS");
690
691 key!(K, b"K");
693 key!(KEYWORDS, b"Keywords");
694 key!(KEY_USAGE, b"KeyUsage");
695 key!(KIDS, b"Kids");
696
697 key!(L, b"L");
699 key!(LAB, b"Lab");
700 key!(LANG, b"Lang");
701 key!(LAST, b"Last");
702 key!(LAST_CHAR, b"LastChar");
703 key!(LAST_MODIFIED, b"LastModified");
704 key!(LC, b"LC");
705 key!(LE, b"LE");
706 key!(LEADING, b"Leading");
707 key!(LEGAL_ATTESTATION, b"LegalAttestation");
708 key!(LENGTH, b"Length");
709 key!(LENGTH1, b"Length1");
710 key!(LENGTH2, b"Length2");
711 key!(LENGTH3, b"Length3");
712 key!(LIGHTEN, b"Lighten");
713 key!(LIMITS, b"Limits");
714 key!(LINEARIZED, b"Linearized");
715 key!(LJ, b"LJ");
716 key!(LL, b"LL");
717 key!(LLE, b"LLE");
718 key!(LLO, b"LLO");
719 key!(LOCATION, b"Location");
720 key!(LUMINOSITY, b"Luminosity");
721 key!(LW, b"LW");
722 key!(LZW_DECODE, b"LZWDecode");
723 key!(LZW_DECODE_ABBREVIATION, b"LZW");
724
725 key!(M, b"M");
727 key!(MAC, b"Mac");
728 key!(MAC_EXPERT_ENCODING, b"MacExpertEncoding");
729 key!(MAC_ROMAN_ENCODING, b"MacRomanEncoding");
730 key!(MARK_INFO, b"MarkInfo");
731 key!(MASK, b"Mask");
732 key!(MATRIX, b"Matrix");
733 key!(MATTE, b"Matte");
734 key!(MAX_LEN, b"MaxLen");
735 key!(MAX_WIDTH, b"MaxWidth");
736 key!(MCID, b"MCID");
737 key!(MDP, b"MDP");
738 key!(MEDIA_BOX, b"MediaBox");
739 key!(MEASURE, b"Measure");
740 key!(METADATA, b"Metadata");
741 key!(MISSING_WIDTH, b"MissingWidth");
742 key!(MIX, b"Mix");
743 key!(MK, b"MK");
744 key!(ML, b"ML");
745 key!(MM_TYPE1, b"MMType1");
746 key!(MOD_DATE, b"ModDate");
747 key!(MULTIPLY, b"Multiply");
748
749 key!(N, b"N");
751 key!(NAME, b"Name");
752 key!(NAMES, b"Names");
753 key!(NAVIGATOR, b"Navigator");
754 key!(NEED_APPEARANCES, b"NeedAppearances");
755 key!(NEW_WINDOW, b"NewWindow");
756 key!(NEXT, b"Next");
757 key!(NM, b"NM");
758 key!(NON_EFONT_NO_WARN, b"NonEFontNoWarn");
759 key!(NON_FULL_SCREEN_PAGE_MODE, b"NonFullScreenPageMode");
760 key!(NONE, b"None");
761 key!(NORMAL, b"Normal");
762 key!(NUMS, b"Nums");
763
764 key!(O, b"O");
766 key!(OBJ, b"Obj");
767 key!(OBJR, b"OBJR");
768 key!(OBJ_STM, b"ObjStm");
769 key!(OC, b"OC");
770 key!(OCG, b"OCG");
771 key!(OCGS, b"OCGs");
772 key!(OCMD, b"OCMD");
773 key!(OCPROPERTIES, b"OCProperties");
774 key!(OCSP, b"OCSP");
775 key!(OCSPS, b"OCSPs");
776 key!(OE, b"OE");
777 key!(OID, b"OID");
778 key!(OFF, b"OFF");
779 key!(ON, b"ON");
780 key!(OP, b"OP");
781 key!(OP_NS, b"op");
782 key!(OPEN_ACTION, b"OpenAction");
783 key!(OPEN_TYPE, b"OpenType");
784 key!(OPI, b"OPI");
785 key!(OPM, b"OPM");
786 key!(OPT, b"Opt");
787 key!(ORDER, b"Order");
788 key!(ORDERING, b"Ordering");
789 key!(OS, b"OS");
790 key!(OUTLINES, b"Outlines");
791 key!(OUTPUT_CONDITION, b"OutputCondition");
792 key!(OUTPUT_CONDITION_IDENTIFIER, b"OutputConditionIdentifier");
793 key!(OUTPUT_INTENT, b"OutputIntent");
794 key!(OUTPUT_INTENTS, b"OutputIntents");
795 key!(OVERLAY, b"Overlay");
796
797 key!(P, b"P");
799 key!(PA, b"PA");
800 key!(PAGE, b"Page");
801 key!(PAGE_LABELS, b"PageLabels");
802 key!(PAGE_LAYOUT, b"PageLayout");
803 key!(PAGE_MODE, b"PageMode");
804 key!(PAGES, b"Pages");
805 key!(PAINT_TYPE, b"PaintType");
806 key!(PANOSE, b"Panose");
807 key!(PARAMS, b"Params");
808 key!(PARENT, b"Parent");
809 key!(PARENT_TREE, b"ParentTree");
810 key!(PARENT_TREE_NEXT_KEY, b"ParentTreeNextKey");
811 key!(PART, b"Part");
812 key!(PATH, b"Path");
813 key!(PATTERN, b"Pattern");
814 key!(PATTERN_TYPE, b"PatternType");
815 key!(PC, b"PC");
816 key!(PDF_DOC_ENCODING, b"PDFDocEncoding");
817 key!(PERMS, b"Perms");
818 key!(PERCEPTUAL, b"Perceptual");
819 key!(PIECE_INFO, b"PieceInfo");
820 key!(PG, b"Pg");
821 key!(PI, b"PI");
822 key!(PO, b"PO");
823 key!(POPUP, b"Popup");
824 key!(PRE_RELEASE, b"PreRelease");
825 key!(PREDICTOR, b"Predictor");
826 key!(PREV, b"Prev");
827 key!(PRINT, b"Print");
828 key!(PRINT_AREA, b"PrintArea");
829 key!(PRINT_CLIP, b"PrintClip");
830 key!(PRINT_SCALING, b"PrintScaling");
831 key!(PRINT_STATE, b"PrintState");
832 key!(PRIVATE, b"Private");
833 key!(PROC_SET, b"ProcSet");
834 key!(PROCESS, b"Process");
835 key!(PRODUCER, b"Producer");
836 key!(PROP_BUILD, b"Prop_Build");
837 key!(PROPERTIES, b"Properties");
838 key!(PS, b"PS");
839 key!(PT_DATA, b"PtData");
840 key!(PUB_SEC, b"PubSec");
841 key!(PV, b"PV");
842
843 key!(Q, b"Q");
845 key!(QUADPOINTS, b"QuadPoints");
846
847 key!(R, b"R");
849 key!(RANGE, b"Range");
850 key!(RC, b"RC");
851 key!(RD, b"RD");
852 key!(REASON, b"Reason");
853 key!(REASONS, b"Reasons");
854 key!(RECIPIENTS, b"Recipients");
855 key!(RECT, b"Rect");
856 key!(REF, b"Ref");
857 key!(REFERENCE, b"Reference");
858 key!(REGISTRY, b"Registry");
859 key!(REGISTRY_NAME, b"RegistryName");
860 key!(RELATIVE_COLORIMETRIC, b"RelativeColorimetric");
861 key!(RENAME, b"Rename");
862 key!(REPEAT, b"Repeat");
863 key!(RES_FORK, b"ResFork");
864 key!(RESOURCES, b"Resources");
865 key!(RGB, b"RGB");
866 key!(RI, b"RI");
867 key!(ROLE_MAP, b"RoleMap");
868 key!(ROOT, b"Root");
869 key!(ROTATE, b"Rotate");
870 key!(ROWS, b"Rows");
871 key!(RT, b"RT");
872 key!(RUN_LENGTH_DECODE, b"RunLengthDecode");
873 key!(RUN_LENGTH_DECODE_ABBREVIATION, b"RL");
874 key!(RV, b"RV");
875
876 key!(S, b"S");
878 key!(SA, b"SA");
879 key!(SATURATION, b"Saturation");
880 key!(SCHEMA, b"Schema");
881 key!(SCREEN, b"Screen");
882 key!(SE, b"SE");
883 key!(SEPARATION, b"Separation");
884 key!(SET_F, b"SetF");
885 key!(SET_FF, b"SetFf");
886 key!(SHADING, b"Shading");
887 key!(SHADING_TYPE, b"ShadingType");
888 key!(SIG, b"Sig");
889 key!(SIG_FLAGS, b"SigFlags");
890 key!(SIG_REF, b"SigRef");
891 key!(SIZE, b"Size");
892 key!(SM, b"SM");
893 key!(SMASK, b"SMask");
894 key!(SMASK_IN_DATA, b"SMaskInData");
895 key!(SOFT_LIGHT, b"SoftLight");
896 key!(SORT, b"Sort");
897 key!(SOUND, b"Sound");
898 key!(SPLIT, b"Split");
899 key!(SS, b"SS");
900 key!(ST, b"St");
901 key!(STANDARD_ENCODING, b"StandardEncoding");
902 key!(STATE, b"State");
903 key!(STATE_MODEL, b"StateModel");
904 key!(STATUS, b"Status");
905 key!(STD_CF, b"StdCF");
906 key!(STEM_H, b"StemH");
907 key!(STEM_V, b"StemV");
908 key!(STM_F, b"StmF");
909 key!(STR_F, b"StrF");
910 key!(STRUCT_ELEM, b"StructElem");
911 key!(STRUCT_PARENT, b"StructParent");
912 key!(STRUCT_PARENTS, b"StructParents");
913 key!(STRUCT_TREE_ROOT, b"StructTreeRoot");
914 key!(STYLE, b"Style");
915 key!(SUB_FILTER, b"SubFilter");
916 key!(SUBJ, b"Subj");
917 key!(SUBJECT, b"Subject");
918 key!(SUBJECT_DN, b"SubjectDN");
919 key!(SUBTYPE, b"Subtype");
920 key!(SUPPLEMENT, b"Supplement");
921 key!(SV, b"SV");
922 key!(SV_CERT, b"SVCert");
923 key!(SW, b"SW");
924 key!(SY, b"Sy");
925 key!(SYNCHRONOUS, b"Synchronous");
926 key!(T, b"T");
927 key!(TARGET, b"Target");
928 key!(TEMPLATES, b"Templates");
929 key!(THREAD, b"Thread");
930 key!(THREADS, b"Threads");
931 key!(THREE_DD, b"3DD");
932 key!(THUMB, b"Thumb");
933 key!(TI, b"TI");
934 key!(TILING_TYPE, b"TilingType");
935 key!(TIME_STAMP, b"TimeStamp");
936 key!(TITLE, b"Title");
937 key!(TK, b"TK");
938 key!(TM, b"TM");
939 key!(TO_UNICODE, b"ToUnicode");
940 key!(TR, b"TR");
941 key!(TR2, b"TR2");
942 key!(TRAPPED, b"Trapped");
943 key!(TRANS, b"Trans");
944 key!(TRANSFORM_METHOD, b"TransformMethod");
945 key!(TRANSFORM_PARAMS, b"TransformParams");
946 key!(TRANSPARENCY, b"Transparency");
947 key!(TREF, b"TRef");
948 key!(TRIM_BOX, b"TrimBox");
949 key!(TRUE_TYPE, b"TrueType");
950 key!(TRUSTED_MODE, b"TrustedMode");
951 key!(TU, b"TU");
952 key!(TX, b"Tx");
953 key!(TYPE, b"Type");
954 key!(TYPE0, b"Type0");
955 key!(TYPE1, b"Type1");
956 key!(TYPE1C, b"Type1C");
957 key!(TYPE3, b"Type3");
958
959 key!(U, b"U");
961 key!(UE, b"UE");
962 key!(UF, b"UF");
963 key!(UNCHANGED, b"Unchanged");
964 key!(UNIX, b"Unix");
965 key!(URI, b"URI");
966 key!(URL, b"URL");
967 key!(URL_TYPE, b"URLType");
968 key!(USAGE, b"Usage");
969 key!(USE_CMAP, b"UseCMap");
970 key!(USER_UNIT, b"UserUnit");
971
972 key!(V, b"V");
974 key!(VE, b"VE");
975 key!(VERISIGN_PPKVS, b"VeriSign.PPKVS");
976 key!(VERSION, b"Version");
977 key!(VERTICES, b"Vertices");
978 key!(VERTICES_PER_ROW, b"VerticesPerRow");
979 key!(VIEW, b"View");
980 key!(VIEW_AREA, b"ViewArea");
981 key!(VIEW_CLIP, b"ViewClip");
982 key!(VIEW_STATE, b"ViewState");
983 key!(VIEWER_PREFERENCES, b"ViewerPreferences");
984 key!(VOLUME, b"Volume");
985 key!(VP, b"VP");
986 key!(VRI, b"VRI");
987
988 key!(W, b"W");
990 key!(W2, b"W2");
991 key!(WC, b"WC");
992 key!(WHITE_POINT, b"WhitePoint");
993 key!(WIDGET, b"Widget");
994 key!(WIDTH, b"Width");
995 key!(WIDTHS, b"Widths");
996 key!(WIN, b"Win");
997 key!(WIN_ANSI_ENCODING, b"WinAnsiEncoding");
998 key!(WMODE, b"WMode");
999 key!(WP, b"WP");
1000 key!(WS, b"WS");
1001
1002 key!(X, b"X");
1004 key!(XFA, b"XFA");
1005 key!(X_STEP, b"XStep");
1006 key!(XHEIGHT, b"XHeight");
1007 key!(XOBJECT, b"XObject");
1008 key!(XREF, b"XRef");
1009 key!(XREF_STM, b"XRefStm");
1010
1011 key!(Y, b"Y");
1013 key!(Y_STEP, b"YStep");
1014 key!(YES, b"Yes");
1015
1016 key!(ZA_DB, b"ZaDb");
1018}
1019
1020#[cfg(test)]
1021mod tests {
1022 use crate::object::dict::keys::{COLORSPACE, EXT_G_STATE, FONT, PROC_SET};
1023 use crate::object::dict::{Dict, InlineImageDict};
1024 use crate::object::string;
1025 use crate::object::{FromBytes, Number};
1026 use crate::object::{Name, ObjRef};
1027 use crate::reader::Reader;
1028 use crate::reader::{ReaderContext, ReaderExt};
1029
1030 fn dict_impl(data: &[u8]) -> Option<Dict<'_>> {
1031 Reader::new(data).read_with_context::<Dict<'_>>(&ReaderContext::dummy())
1032 }
1033
1034 #[test]
1035 fn empty_dict_1() {
1036 let dict_data = b"<<>>";
1037 let dict = dict_impl(dict_data).unwrap();
1038
1039 assert_eq!(dict.len(), 0);
1040 }
1041
1042 #[test]
1043 fn empty_dict_2() {
1044 let dict_data = b"<< \n >>";
1045 let dict = dict_impl(dict_data).unwrap();
1046
1047 assert_eq!(dict.len(), 0);
1048 }
1049
1050 #[test]
1051 fn dict_1() {
1052 let dict_data = b"<< /Hi 34.0 >>";
1053 let dict = dict_impl(dict_data).unwrap();
1054
1055 assert_eq!(dict.len(), 1);
1056 assert!(dict.get::<Number>(Name::new_unescaped(b"Hi")).is_some());
1057 }
1058
1059 #[test]
1060 fn dict_2() {
1061 let dict_data = b"<< /Hi \n 34.0 /Second true >>";
1062 let dict = dict_impl(dict_data).unwrap();
1063
1064 assert_eq!(dict.len(), 2);
1065 assert!(dict.get::<Number>(Name::new_unescaped(b"Hi")).is_some());
1066 assert!(dict.get::<bool>(Name::new_unescaped(b"Second")).is_some());
1067 }
1068
1069 #[test]
1070 fn dict_complex() {
1071 let data = "<< /Type /Example
1072/Subtype /DictionaryExample
1073/Version 0.01
1074/IntegerItem 12
1075/StringItem ( a string )
1076/Subdictionary << /Item1 0.4
1077 /Item2 true
1078 /LastItem ( not ! )
1079 /VeryLastItem ( OK )
1080 >>
1081>>";
1082
1083 let dict = Reader::new(data.as_bytes())
1084 .read_with_context::<Dict<'_>>(&ReaderContext::dummy())
1085 .unwrap();
1086 assert_eq!(dict.len(), 6);
1087 assert!(dict.get::<Name<'_>>(Name::new_unescaped(b"Type")).is_some());
1088 assert!(
1089 dict.get::<Name<'_>>(Name::new_unescaped(b"Subtype"))
1090 .is_some()
1091 );
1092 assert!(
1093 dict.get::<Number>(Name::new_unescaped(b"Version"))
1094 .is_some()
1095 );
1096 assert!(
1097 dict.get::<i32>(Name::new_unescaped(b"IntegerItem"))
1098 .is_some()
1099 );
1100 assert!(
1101 dict.get::<string::String<'_>>(Name::new_unescaped(b"StringItem"))
1102 .is_some()
1103 );
1104 assert!(
1105 dict.get::<Dict<'_>>(Name::new_unescaped(b"Subdictionary"))
1106 .is_some()
1107 );
1108 }
1109
1110 #[test]
1111 fn dict_with_trailing() {
1112 let dict_data = b"<< /Hi 67.0 >>trailing data";
1113 let dict = dict_impl(dict_data).unwrap();
1114
1115 assert_eq!(dict.len(), 1);
1116 }
1117
1118 #[test]
1119 fn dict_with_comment() {
1120 let dict_data = b"<< /Hi % A comment \n 67.0 % Another comment \n >>";
1121 let dict = dict_impl(dict_data).unwrap();
1122
1123 assert_eq!(dict.len(), 1);
1124 }
1125
1126 #[test]
1127 fn inline_dict() {
1128 let dict_data = b"/W 17 /H 17 /CS /RGB /BPC 8 /F [ /A85 /LZW ] ID ";
1129
1130 let dict = Reader::new(&dict_data[..])
1131 .read_with_context::<InlineImageDict<'_>>(&ReaderContext::dummy())
1132 .unwrap();
1133
1134 assert_eq!(dict.get_dict().len(), 5);
1135 }
1136
1137 #[test]
1138 fn dict_with_escaped_name() {
1139 let dict_data = b"<< /PANTONE#20104#20C 234 >>";
1140 let dict = dict_impl(dict_data).unwrap();
1141
1142 assert!(dict.contains_key("PANTONE 104 C"));
1143 }
1144
1145 #[test]
1146 fn garbage_in_between() {
1147 let dict_data = b"<<
1148/ProcSet [ /PDF /Text ]
1149/Font << /F4 31 0 R /F6 23 0 R >>
1150/ExtGState << /GS2 14 0 R
11512000
1152 /GS3 15 0 R >>
1153/ColorSpace << /Cs5 13 0 R >>
1154>> ";
1155 let dict = dict_impl(dict_data).unwrap();
1156
1157 assert!(dict.contains_key(PROC_SET));
1158 assert!(dict.contains_key(FONT));
1159 assert!(dict.contains_key(EXT_G_STATE));
1160 assert!(dict.contains_key(COLORSPACE));
1161
1162 let Some(dict) = dict.get::<Dict<'_>>(EXT_G_STATE) else {
1163 panic!("failed to parse ext g state");
1164 };
1165
1166 assert_eq!(dict.get_ref("GS2"), Some(ObjRef::new(14, 0)));
1167 assert_eq!(dict.get_ref("GS3"), Some(ObjRef::new(15, 0)));
1168 }
1169
1170 #[test]
1171 fn dict_repr() {
1172 let dict = Dict::from_bytes(b"<< /Hi 34 >>").unwrap();
1173
1174 assert_eq!(
1175 format!("{dict:?}"),
1176 "Dict { \"Hi\": Number(Number(Integer(34))) }"
1177 );
1178 }
1179
1180 #[test]
1181 fn display() {
1182 let dict = Dict::from_bytes(b"<< /B [1 2] % comment\n /A << /X true >> >>").unwrap();
1183
1184 assert_eq!(format!("{dict}"), "<< /A << /X true >> /B [1 2] >>");
1185 assert_eq!(format!("{}", Dict::empty()), "<<>>");
1186 }
1187
1188 #[test]
1189 fn dict_with_unreadable_value() {
1190 let dict = Dict::from_bytes(b"<< /A <<>>stream /B true >>").unwrap();
1191 let _ = dict.entries().count();
1192 let _ = format!("{dict:?}");
1193 }
1194}