1use std::convert::TryFrom;
2use std::marker::PhantomData;
3use std::mem::ManuallyDrop;
4use std::num::NonZeroI32;
5
6use super::*;
7
8pub trait Primitive {
10 fn write(self, buf: &mut Buf);
12}
13
14impl<T: Primitive> Primitive for &T
15where
16 T: Copy,
17{
18 #[inline]
19 fn write(self, buf: &mut Buf) {
20 (*self).write(buf);
21 }
22}
23
24impl Primitive for bool {
25 #[inline]
26 fn write(self, buf: &mut Buf) {
27 if self {
28 buf.extend(b"true");
29 } else {
30 buf.extend(b"false");
31 }
32 }
33}
34
35impl Primitive for i32 {
36 #[inline]
37 fn write(self, buf: &mut Buf) {
38 buf.push_int(self);
39 }
40}
41
42impl Primitive for f32 {
43 #[inline]
44 fn write(self, buf: &mut Buf) {
45 buf.push_float(self);
46 }
47}
48
49#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
53pub struct Str<'a>(pub &'a [u8]);
54
55impl Str<'_> {
56 fn is_balanced(self) -> bool {
58 let mut depth = 0;
59 for &byte in self.0 {
60 match byte {
61 b'(' => depth += 1,
62 b')' if depth > 0 => depth -= 1,
63 b')' => return false,
64 _ => {}
65 }
66 }
67 depth == 0
68 }
69}
70
71impl Primitive for Str<'_> {
72 fn write(self, buf: &mut Buf) {
73 buf.limits.register_str_len(self.0.len());
74
75 if self.0.iter().all(|b| b.is_ascii()) {
81 buf.reserve(self.0.len());
82 buf.inner.push(b'(');
83
84 let mut balanced = None;
85 for &byte in self.0 {
86 match byte {
87 b'(' | b')' => {
88 if !*balanced
89 .get_or_insert_with(|| byte != b')' && self.is_balanced())
90 {
91 buf.push(b'\\');
92 }
93 buf.push(byte);
94 }
95 b'\\' => buf.extend(br"\\"),
96 b' '..=b'~' => buf.push(byte),
97 b'\n' => buf.extend(br"\n"),
98 b'\r' => buf.extend(br"\r"),
99 b'\t' => buf.extend(br"\t"),
100 b'\x08' => buf.extend(br"\b"),
101 b'\x0c' => buf.extend(br"\f"),
102 _ => {
103 buf.push(b'\\');
104 buf.push_octal(byte);
105 }
106 }
107 }
108
109 buf.push(b')');
110 } else {
111 buf.reserve(2 + 2 * self.0.len());
112 buf.push(b'<');
113
114 for &byte in self.0 {
115 buf.push_hex(byte);
116 }
117
118 buf.push(b'>');
119 }
120 }
121}
122
123#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
133pub struct TextStr<'a>(pub &'a str);
134
135impl Primitive for TextStr<'_> {
136 fn write(self, buf: &mut Buf) {
137 buf.limits.register_str_len(self.0.len());
138
139 if self.0.bytes().all(|b| matches!(b, 32..=126)) {
141 Str(self.0.as_bytes()).write(buf);
142 } else {
143 buf.reserve(6 + 4 * self.0.len());
144 write_utf16be_text_str_header(buf);
145 for value in self.0.encode_utf16() {
146 buf.push_hex_u16(value);
147 }
148 write_utf16be_text_str_footer(buf);
149 }
150 }
151}
152
153#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
156pub struct LanguageIdentifier {
157 lang: [u8; 2],
159 region: Option<[u8; 2]>,
161}
162
163impl LanguageIdentifier {
164 pub fn new(lang: [u8; 2], region: Option<[u8; 2]>) -> Self {
168 Self { lang, region }
169 }
170
171 pub fn from_lang(lang: &str) -> Option<Self> {
176 let lang = Self::str_to_code(lang)?;
177 Some(Self::new(lang, None))
178 }
179
180 pub fn from_lang_region(lang: &str, region: &str) -> Option<Self> {
185 let lang = Self::str_to_code(lang)?;
186 let region = Self::str_to_code(region)?;
187 Some(Self::new(lang, Some(region)))
188 }
189
190 fn len(self) -> usize {
193 if self.region.is_some() {
194 4
195 } else {
196 2
197 }
198 }
199
200 fn str_to_code(string: &str) -> Option<[u8; 2]> {
201 if string.chars().all(|c| c.is_ascii_alphanumeric()) {
202 string.as_bytes().try_into().ok()
203 } else {
204 None
205 }
206 }
207}
208
209#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
218pub struct TextStrWithLang<'a, 'b>(pub &'b [(LanguageIdentifier, &'a str)]);
219
220impl<'a, 'b> Primitive for TextStrWithLang<'a, 'b> {
221 fn write(self, buf: &mut Buf) {
222 let mut len = 0;
223 let mut buf_len = 6;
224
225 for (lang, text) in self.0 {
226 len += text.len() + lang.len() + 2;
229 buf_len += 4 * text.len() + lang.len() * 2 + 4;
233 }
234
235 buf.limits.register_str_len(len);
236
237 buf.reserve(buf_len);
240 write_utf16be_text_str_header(buf);
241
242 for (lang, text) in self.0 {
243 write_utf16be_lang_code(*lang, buf);
244 for value in text.encode_utf16() {
245 buf.push_hex_u16(value);
246 }
247 }
248
249 write_utf16be_text_str_footer(buf);
250 }
251}
252
253fn write_utf16be_text_str_header(buf: &mut Buf) {
254 buf.push(b'<');
255 buf.push_hex(254);
256 buf.push_hex(255);
257}
258
259fn write_utf16be_text_str_footer(buf: &mut Buf) {
260 buf.push(b'>');
261}
262
263fn write_utf16be_lang_code(lang: LanguageIdentifier, buf: &mut Buf) {
264 buf.push_hex_u16(0x001B);
270 buf.push_hex_u16(u16::from(lang.lang[0]));
271 buf.push_hex_u16(u16::from(lang.lang[1]));
272 if let Some(region) = lang.region {
273 buf.push_hex_u16(u16::from(region[0]));
274 buf.push_hex_u16(u16::from(region[1]));
275 }
276 buf.push_hex_u16(0x001B);
277}
278
279pub trait TextStrLike: Primitive {}
286
287impl<'a> TextStrLike for TextStr<'a> {}
288impl<'a, 'b> TextStrLike for TextStrWithLang<'a, 'b> {}
289
290#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
294pub struct Name<'a>(pub &'a [u8]);
295
296impl Primitive for Name<'_> {
297 fn write(self, buf: &mut Buf) {
298 buf.limits.register_name_len(self.0.len());
299
300 buf.reserve(1 + self.0.len());
301 buf.push(b'/');
302 for &byte in self.0 {
303 if byte != b'#' && matches!(byte, b'!'..=b'~') && is_regular_character(byte) {
307 buf.push(byte);
308 } else {
309 buf.push(b'#');
310 buf.push_hex(byte);
311 }
312 }
313 }
314}
315
316fn is_regular_character(byte: u8) -> bool {
318 !matches!(
319 byte,
320 b'\0'
321 | b'\t'
322 | b'\n'
323 | b'\x0C'
324 | b'\r'
325 | b' '
326 | b'('
327 | b')'
328 | b'<'
329 | b'>'
330 | b'['
331 | b']'
332 | b'{'
333 | b'}'
334 | b'/'
335 | b'%'
336 )
337}
338
339#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
341pub struct Null;
342
343impl Primitive for Null {
344 #[inline]
345 fn write(self, buf: &mut Buf) {
346 buf.extend(b"null");
347 }
348}
349
350#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
352pub struct Ref(NonZeroI32);
353
354impl Ref {
355 #[inline]
361 #[track_caller]
362 pub const fn new(id: i32) -> Ref {
363 let option = if id > 0 { NonZeroI32::new(id) } else { None };
364 match option {
365 Some(val) => Self(val),
366 None => panic!("indirect reference out of valid range"),
367 }
368 }
369
370 #[inline]
372 pub const fn get(self) -> i32 {
373 self.0.get()
374 }
375
376 #[inline]
378 pub const fn next(self) -> Self {
379 Self::new(self.get() + 1)
380 }
381
382 #[inline]
385 pub fn bump(&mut self) -> Self {
386 let prev = *self;
387 *self = self.next();
388 prev
389 }
390}
391
392impl Primitive for Ref {
393 #[inline]
394 fn write(self, buf: &mut Buf) {
395 buf.push_int(self.0.get());
396 buf.extend(b" 0 R");
397 }
398}
399
400#[derive(Debug, Copy, Clone, PartialEq)]
402pub struct Rect {
403 pub x1: f32,
405 pub y1: f32,
407 pub x2: f32,
409 pub y2: f32,
411}
412
413impl Rect {
414 #[inline]
416 pub fn new(x1: f32, y1: f32, x2: f32, y2: f32) -> Self {
417 Self { x1, y1, x2, y2 }
418 }
419
420 #[inline]
423 pub fn to_quad_points(self) -> [f32; 8] {
424 [self.x1, self.y1, self.x2, self.y1, self.x2, self.y2, self.x1, self.y2]
425 }
426}
427
428impl Primitive for Rect {
429 #[inline]
430 fn write(self, buf: &mut Buf) {
431 buf.push(b'[');
432 buf.push_val(self.x1);
433 buf.push(b' ');
434 buf.push_val(self.y1);
435 buf.push(b' ');
436 buf.push_val(self.x2);
437 buf.push(b' ');
438 buf.push_val(self.y2);
439 buf.push(b']');
440
441 buf.limits.register_array_len(4);
442 }
443}
444
445#[derive(Debug, Copy, Clone, Eq, PartialEq)]
453pub struct Date {
454 year: u16,
456 month: Option<u8>,
458 day: Option<u8>,
460 hour: Option<u8>,
462 minute: Option<u8>,
464 second: Option<u8>,
466 utc_offset_hour: Option<i8>,
468 utc_offset_minute: u8,
471}
472
473impl Date {
474 #[inline]
477 pub fn new(year: u16) -> Self {
478 Self {
479 year: year.min(9999),
480 month: None,
481 day: None,
482 hour: None,
483 minute: None,
484 second: None,
485 utc_offset_hour: None,
486 utc_offset_minute: 0,
487 }
488 }
489
490 #[inline]
492 pub fn month(mut self, month: u8) -> Self {
493 self.month = Some(month.clamp(1, 12));
494 self
495 }
496
497 #[inline]
499 pub fn day(mut self, day: u8) -> Self {
500 self.day = Some(day.clamp(1, 31));
501 self
502 }
503
504 #[inline]
506 pub fn hour(mut self, hour: u8) -> Self {
507 self.hour = Some(hour.min(23));
508 self
509 }
510
511 #[inline]
513 pub fn minute(mut self, minute: u8) -> Self {
514 self.minute = Some(minute.min(59));
515 self
516 }
517
518 #[inline]
520 pub fn second(mut self, second: u8) -> Self {
521 self.second = Some(second.min(59));
522 self
523 }
524
525 #[inline]
529 pub fn utc_offset_hour(mut self, hour: i8) -> Self {
530 self.utc_offset_hour = Some(hour.clamp(-23, 23));
531 self
532 }
533
534 #[inline]
537 pub fn utc_offset_minute(mut self, minute: u8) -> Self {
538 self.utc_offset_minute = minute.min(59);
539 self
540 }
541}
542
543impl Primitive for Date {
544 fn write(self, buf: &mut Buf) {
545 buf.extend(b"(D:");
546
547 (|| {
548 write!(buf.inner, "{:04}", self.year).unwrap();
549 write!(buf.inner, "{:02}", self.month?).unwrap();
550 write!(buf.inner, "{:02}", self.day?).unwrap();
551 write!(buf.inner, "{:02}", self.hour?).unwrap();
552 write!(buf.inner, "{:02}", self.minute?).unwrap();
553 write!(buf.inner, "{:02}", self.second?).unwrap();
554 let utc_offset_hour = self.utc_offset_hour?;
555 if utc_offset_hour == 0 && self.utc_offset_minute == 0 {
556 buf.push(b'Z');
557 } else {
558 write!(
559 buf.inner,
560 "{:+03}'{:02}",
561 utc_offset_hour, self.utc_offset_minute
562 )
563 .unwrap();
564 }
565 Some(())
566 })();
567
568 buf.push(b')');
569 }
570}
571
572#[must_use = "not consuming this leaves the writer in an inconsistent state"]
574pub struct Obj<'a> {
575 buf: &'a mut Buf,
576 indirect: bool,
577 indent: u8,
578}
579
580impl<'a> Obj<'a> {
581 #[inline]
583 pub(crate) fn direct(buf: &'a mut Buf, indent: u8) -> Self {
584 Self { buf, indirect: false, indent }
585 }
586
587 #[inline]
589 pub(crate) fn indirect(buf: &'a mut Buf, id: Ref) -> Self {
590 buf.push_int(id.get());
591 buf.extend(b" 0 obj\n");
592 Self { buf, indirect: true, indent: 0 }
593 }
594
595 #[inline]
597 pub fn primitive<T: Primitive>(self, value: T) {
598 value.write(self.buf);
599 if self.indirect {
600 self.buf.extend(b"\nendobj\n\n");
601 }
602 }
603
604 #[inline]
606 pub fn array(self) -> Array<'a> {
607 self.start()
608 }
609
610 #[inline]
612 pub fn dict(self) -> Dict<'a> {
613 self.start()
614 }
615
616 #[inline]
632 pub fn start<W: Writer<'a>>(self) -> W {
633 W::start(self)
634 }
635}
636
637pub trait Writer<'a> {
639 fn start(obj: Obj<'a>) -> Self;
641}
642
643pub trait Rewrite<'a> {
649 type Output: Writer<'a>;
651}
652
653pub struct Array<'a> {
655 buf: &'a mut Buf,
656 indirect: bool,
657 indent: u8,
658 len: i32,
659}
660
661writer!(Array: |obj| {
662 obj.buf.push(b'[');
663 Self {
664 buf: obj.buf,
665 indirect: obj.indirect,
666 indent: obj.indent,
667 len: 0,
668 }
669});
670
671impl<'a> Array<'a> {
672 #[inline]
674 pub fn len(&self) -> i32 {
675 self.len
676 }
677
678 #[inline]
680 pub fn is_empty(&self) -> bool {
681 self.len == 0
682 }
683
684 #[inline]
686 pub fn push(&mut self) -> Obj<'_> {
687 if self.len != 0 {
688 self.buf.push(b' ');
689 }
690 self.len += 1;
691 Obj::direct(self.buf, self.indent)
692 }
693
694 #[inline]
698 pub fn item<T: Primitive>(&mut self, value: T) -> &mut Self {
699 self.push().primitive(value);
700 self
701 }
702
703 #[inline]
705 pub fn items<T: Primitive>(
706 &mut self,
707 values: impl IntoIterator<Item = T>,
708 ) -> &mut Self {
709 for value in values {
710 self.item(value);
711 }
712 self
713 }
714
715 #[inline]
717 pub fn typed<T>(self) -> TypedArray<'a, T> {
718 TypedArray::wrap(self)
719 }
720}
721
722impl Drop for Array<'_> {
723 #[inline]
724 fn drop(&mut self) {
725 self.buf.limits.register_array_len(self.len() as usize);
726 self.buf.push(b']');
727 if self.indirect {
728 self.buf.extend(b"\nendobj\n\n");
729 }
730 }
731}
732
733pub struct TypedArray<'a, T> {
735 array: Array<'a>,
736 phantom: PhantomData<fn() -> T>,
737}
738
739impl<'a, T> Writer<'a> for TypedArray<'a, T> {
740 fn start(obj: Obj<'a>) -> Self {
741 Self { array: obj.array(), phantom: PhantomData }
742 }
743}
744
745impl<'a, T> Rewrite<'a> for TypedArray<'_, T> {
746 type Output = TypedArray<'a, T>;
747}
748
749impl<'a, T> TypedArray<'a, T> {
750 #[inline]
752 pub fn wrap(array: Array<'a>) -> Self {
753 Self { array, phantom: PhantomData }
754 }
755
756 #[inline]
758 pub fn len(&self) -> i32 {
759 self.array.len()
760 }
761
762 #[inline]
764 pub fn is_empty(&self) -> bool {
765 self.len() == 0
766 }
767
768 #[inline]
770 pub fn item(&mut self, value: T) -> &mut Self
771 where
772 T: Primitive,
773 {
774 self.array.item(value);
775 self
776 }
777
778 #[inline]
780 pub fn items(&mut self, values: impl IntoIterator<Item = T>) -> &mut Self
781 where
782 T: Primitive,
783 {
784 self.array.items(values);
785 self
786 }
787
788 #[inline]
792 pub fn push<'b>(&'b mut self) -> <T as Rewrite<'b>>::Output
793 where
794 T: Writer<'a> + Rewrite<'b>,
795 {
796 <T as Rewrite>::Output::start(self.array.push())
797 }
798}
799
800pub struct Dict<'a> {
802 buf: &'a mut Buf,
803 indirect: bool,
804 indent: u8,
805 len: i32,
806}
807
808writer!(Dict: |obj| {
809 obj.buf.extend(b"<<");
810 Self {
811 buf: obj.buf,
812 indirect: obj.indirect,
813 indent: obj.indent.saturating_add(2),
814 len: 0,
815 }
816});
817
818impl<'a> Dict<'a> {
819 #[inline]
821 pub fn len(&self) -> i32 {
822 self.len
823 }
824
825 #[inline]
827 pub fn is_empty(&self) -> bool {
828 self.len == 0
829 }
830
831 #[inline]
833 pub fn insert(&mut self, key: Name) -> Obj<'_> {
834 self.len += 1;
835 self.buf.push(b'\n');
836
837 for _ in 0..self.indent {
838 self.buf.push(b' ');
839 }
840
841 self.buf.push_val(key);
842 self.buf.push(b' ');
843
844 Obj::direct(self.buf, self.indent)
845 }
846
847 #[inline]
851 pub fn pair<T: Primitive>(&mut self, key: Name, value: T) -> &mut Self {
852 self.insert(key).primitive(value);
853 self
854 }
855
856 pub fn pairs<'n, T: Primitive>(
858 &mut self,
859 pairs: impl IntoIterator<Item = (Name<'n>, T)>,
860 ) -> &mut Self {
861 for (key, value) in pairs {
862 self.pair(key, value);
863 }
864 self
865 }
866
867 #[inline]
869 pub fn typed<T>(self) -> TypedDict<'a, T> {
870 TypedDict::wrap(self)
871 }
872}
873
874impl Drop for Dict<'_> {
875 #[inline]
876 fn drop(&mut self) {
877 self.buf.limits.register_dict_entries(self.len as usize);
878
879 if self.len != 0 {
880 self.buf.push(b'\n');
881 for _ in 0..self.indent - 2 {
882 self.buf.push(b' ');
883 }
884 }
885 self.buf.extend(b">>");
886 if self.indirect {
887 self.buf.extend(b"\nendobj\n\n");
888 }
889 }
890}
891
892pub struct TypedDict<'a, T> {
894 dict: Dict<'a>,
895 phantom: PhantomData<fn() -> T>,
896}
897
898impl<'a, T> Writer<'a> for TypedDict<'a, T> {
899 fn start(obj: Obj<'a>) -> Self {
900 Self { dict: obj.dict(), phantom: PhantomData }
901 }
902}
903
904impl<'a, T> Rewrite<'a> for TypedDict<'_, T> {
905 type Output = TypedDict<'a, T>;
906}
907
908impl<'a, T> TypedDict<'a, T> {
909 #[inline]
911 pub fn wrap(dict: Dict<'a>) -> Self {
912 Self { dict, phantom: PhantomData }
913 }
914
915 #[inline]
917 pub fn len(&self) -> i32 {
918 self.dict.len()
919 }
920
921 #[inline]
923 pub fn is_empty(&self) -> bool {
924 self.len() == 0
925 }
926
927 #[inline]
929 pub fn pair(&mut self, key: Name, value: T) -> &mut Self
930 where
931 T: Primitive,
932 {
933 self.dict.pair(key, value);
934 self
935 }
936
937 #[inline]
939 pub fn pairs<'n>(
940 &mut self,
941 pairs: impl IntoIterator<Item = (Name<'n>, T)>,
942 ) -> &mut Self
943 where
944 T: Primitive,
945 {
946 self.dict.pairs(pairs);
947 self
948 }
949
950 #[inline]
954 pub fn insert<'b>(&'b mut self, key: Name) -> <T as Rewrite<'b>>::Output
955 where
956 T: Writer<'a> + Rewrite<'b>,
957 {
958 <T as Rewrite>::Output::start(self.dict.insert(key))
959 }
960}
961
962pub struct Stream<'a> {
964 dict: ManuallyDrop<Dict<'a>>,
965 data: &'a [u8],
966}
967
968impl<'a> Stream<'a> {
969 pub(crate) fn start(obj: Obj<'a>, data: &'a [u8]) -> Self {
974 assert!(obj.indirect);
975
976 let mut dict = obj.dict();
977 dict.pair(
978 Name(b"Length"),
979 i32::try_from(data.len()).unwrap_or_else(|_| {
980 panic!("data length (is `{}`) must be <= i32::MAX", data.len());
981 }),
982 );
983
984 Self { dict: ManuallyDrop::new(dict), data }
985 }
986
987 pub fn filter(&mut self, filter: Filter) -> &mut Self {
989 self.pair(Name(b"Filter"), filter.to_name());
990 self
991 }
992
993 pub fn decode_parms(&mut self) -> DecodeParms<'_> {
999 self.insert(Name(b"DecodeParms")).start()
1000 }
1001}
1002
1003impl Drop for Stream<'_> {
1004 fn drop(&mut self) {
1005 let dict_len = self.dict.len as usize;
1006 self.dict.buf.limits.register_dict_entries(dict_len);
1007
1008 self.dict.buf.extend(b"\n>>");
1009 self.dict.buf.extend(b"\nstream\n");
1010 self.dict.buf.extend(self.data.as_ref());
1011 self.dict.buf.extend(b"\nendstream");
1012 self.dict.buf.extend(b"\nendobj\n\n");
1013 }
1014}
1015
1016deref!('a, Stream<'a> => Dict<'a>, dict);
1017
1018#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
1020#[allow(missing_docs)]
1021pub enum Filter {
1022 AsciiHexDecode,
1023 Ascii85Decode,
1024 LzwDecode,
1028 FlateDecode,
1029 RunLengthDecode,
1030 CcittFaxDecode,
1031 Jbig2Decode,
1032 DctDecode,
1036 JpxDecode,
1040 Crypt,
1044}
1045
1046impl Filter {
1047 pub(crate) fn to_name(self) -> Name<'static> {
1048 match self {
1049 Self::AsciiHexDecode => Name(b"ASCIIHexDecode"),
1050 Self::Ascii85Decode => Name(b"ASCII85Decode"),
1051 Self::LzwDecode => Name(b"LZWDecode"),
1052 Self::FlateDecode => Name(b"FlateDecode"),
1053 Self::RunLengthDecode => Name(b"RunLengthDecode"),
1054 Self::CcittFaxDecode => Name(b"CCITTFaxDecode"),
1055 Self::Jbig2Decode => Name(b"JBIG2Decode"),
1056 Self::DctDecode => Name(b"DCTDecode"),
1057 Self::JpxDecode => Name(b"JPXDecode"),
1058 Self::Crypt => Name(b"Crypt"),
1059 }
1060 }
1061}
1062
1063pub struct DecodeParms<'a> {
1067 dict: Dict<'a>,
1068}
1069
1070writer!(DecodeParms: |obj| Self { dict: obj.dict() });
1071
1072impl DecodeParms<'_> {
1074 pub fn predictor(&mut self, predictor: Predictor) -> &mut Self {
1078 self.pair(Name(b"Predictor"), predictor.to_i32());
1079 self
1080 }
1081
1082 pub fn colors(&mut self, colors: i32) -> &mut Self {
1087 if colors <= 0 {
1088 panic!("`Colors` must be greater than 0");
1089 }
1090
1091 self.pair(Name(b"Colors"), colors);
1092 self
1093 }
1094
1095 pub fn bits_per_component(&mut self, bits: i32) -> &mut Self {
1101 if ![1, 2, 4, 8, 16].contains(&bits) {
1102 panic!("`BitsPerComponent` must be one of 1, 2, 4, 8, or 16");
1103 }
1104
1105 self.pair(Name(b"BitsPerComponent"), bits);
1106 self
1107 }
1108
1109 pub fn columns(&mut self, columns: i32) -> &mut Self {
1119 self.pair(Name(b"Columns"), columns);
1120 self
1121 }
1122
1123 pub fn early_change(&mut self, early_change: bool) -> &mut Self {
1130 self.pair(Name(b"EarlyChange"), if early_change { 1 } else { 0 });
1131 self
1132 }
1133}
1134
1135impl DecodeParms<'_> {
1137 pub fn k(&mut self, k: i32) -> &mut Self {
1141 self.pair(Name(b"K"), k);
1142 self
1143 }
1144
1145 pub fn end_of_line(&mut self, eol: bool) -> &mut Self {
1150 self.pair(Name(b"EndOfLine"), eol);
1151 self
1152 }
1153
1154 pub fn encoded_byte_align(&mut self, encoded_byte_align: bool) -> &mut Self {
1159 self.pair(Name(b"EncodedByteAlign"), encoded_byte_align);
1160 self
1161 }
1162
1163 pub fn rows(&mut self, rows: i32) -> &mut Self {
1167 self.pair(Name(b"Rows"), rows);
1168 self
1169 }
1170
1171 pub fn end_of_block(&mut self, end_of_block: bool) -> &mut Self {
1176 self.pair(Name(b"EndOfBlock"), end_of_block);
1177 self
1178 }
1179
1180 pub fn black_is_1(&mut self, black_is_1: bool) -> &mut Self {
1184 self.pair(Name(b"BlackIs1"), black_is_1);
1185 self
1186 }
1187
1188 pub fn damaged_rows_before_error(&mut self, count: i32) -> &mut Self {
1193 self.pair(Name(b"DamagedRowsBeforeError"), count);
1194 self
1195 }
1196}
1197
1198impl DecodeParms<'_> {
1200 pub fn jbig2_globals(&mut self, globals: Ref) -> &mut Self {
1204 self.pair(Name(b"JBIG2Globals"), globals);
1205 self
1206 }
1207}
1208
1209impl DecodeParms<'_> {
1211 pub fn color_transform(&mut self, color_transform: bool) -> &mut Self {
1219 self.pair(Name(b"ColorTransform"), if color_transform { 1 } else { 0 });
1220 self
1221 }
1222}
1223
1224impl DecodeParms<'_> {
1226 pub fn crypt_type(&mut self) -> &mut Self {
1228 self.pair(Name(b"Type"), Name(b"CryptFilterDecodeParms"));
1229 self
1230 }
1231
1232 pub fn name(&mut self, name: Name) -> &mut Self {
1237 self.pair(Name(b"Name"), name);
1238 self
1239 }
1240}
1241
1242deref!('a, DecodeParms<'a> => Dict<'a>, dict);
1243
1244#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Hash)]
1246#[allow(missing_docs)]
1247pub enum Predictor {
1248 #[default]
1250 None,
1251 Tiff,
1253 PngNone,
1254 PngSub,
1255 PngUp,
1256 PngAverage,
1257 PngPaeth,
1258 PngOptimum,
1259}
1260
1261impl Predictor {
1262 fn to_i32(self) -> i32 {
1265 match self {
1266 Self::None => 1,
1267 Self::Tiff => 2,
1268 Self::PngNone => 10,
1269 Self::PngSub => 11,
1270 Self::PngUp => 12,
1271 Self::PngAverage => 13,
1272 Self::PngPaeth => 14,
1273 Self::PngOptimum => 15,
1274 }
1275 }
1276}
1277
1278pub struct NameTree<'a, T> {
1288 dict: Dict<'a>,
1289 phantom: PhantomData<T>,
1290}
1291
1292impl<'a, T> Writer<'a> for NameTree<'a, T> {
1293 fn start(obj: Obj<'a>) -> Self {
1294 Self { dict: obj.dict(), phantom: PhantomData }
1295 }
1296}
1297
1298impl<'a, T> Rewrite<'a> for NameTree<'_, T> {
1299 type Output = NameTree<'a, T>;
1300}
1301
1302impl<T> NameTree<'_, T> {
1303 pub fn kids(&mut self) -> TypedArray<'_, Ref> {
1305 self.dict.insert(Name(b"Kids")).array().typed()
1306 }
1307
1308 pub fn names(&mut self) -> NameTreeEntries<'_, T> {
1311 self.dict.insert(Name(b"Names")).start()
1312 }
1313
1314 pub fn limits(&mut self, min: Name, max: Name) -> &mut Self {
1317 self.dict.insert(Name(b"Limits")).array().typed().items([min, max]);
1318 self
1319 }
1320}
1321
1322pub struct NameTreeEntries<'a, T> {
1328 arr: Array<'a>,
1329 phantom: PhantomData<T>,
1330}
1331
1332impl<'a, T> Writer<'a> for NameTreeEntries<'a, T> {
1333 fn start(obj: Obj<'a>) -> Self {
1334 Self { arr: obj.array(), phantom: PhantomData }
1335 }
1336}
1337
1338impl<'a, T> Rewrite<'a> for NameTreeEntries<'_, T> {
1339 type Output = NameTreeEntries<'a, T>;
1340}
1341
1342impl<T> NameTreeEntries<'_, T>
1343where
1344 T: Primitive,
1345{
1346 pub fn insert(&mut self, key: Str, value: T) -> &mut Self {
1348 self.arr.item(key);
1349 self.arr.item(value);
1350 self
1351 }
1352}
1353
1354pub struct NumberTree<'a, T> {
1364 dict: Dict<'a>,
1365 phantom: PhantomData<T>,
1366}
1367
1368impl<'a, T> Writer<'a> for NumberTree<'a, T> {
1369 fn start(obj: Obj<'a>) -> Self {
1370 Self { dict: obj.dict(), phantom: PhantomData }
1371 }
1372}
1373
1374impl<'a, T> Rewrite<'a> for NumberTree<'_, T> {
1375 type Output = NumberTree<'a, T>;
1376}
1377
1378impl<T> NumberTree<'_, T> {
1379 pub fn kids(&mut self) -> TypedArray<'_, Ref> {
1381 self.dict.insert(Name(b"Kids")).array().typed()
1382 }
1383
1384 pub fn nums(&mut self) -> NumberTreeEntries<'_, T> {
1387 self.dict.insert(Name(b"Nums")).start()
1388 }
1389
1390 pub fn limits(&mut self, min: i32, max: i32) -> &mut Self {
1393 self.dict.insert(Name(b"Limits")).array().typed().items([min, max]);
1394 self
1395 }
1396}
1397
1398pub struct NumberTreeEntries<'a, T> {
1404 arr: Array<'a>,
1405 phantom: PhantomData<T>,
1406}
1407
1408impl<'a, T> Writer<'a> for NumberTreeEntries<'a, T> {
1409 fn start(obj: Obj<'a>) -> Self {
1410 Self { arr: obj.array(), phantom: PhantomData }
1411 }
1412}
1413
1414impl<'a, T> Rewrite<'a> for NumberTreeEntries<'_, T> {
1415 type Output = NumberTreeEntries<'a, T>;
1416}
1417
1418impl<T> NumberTreeEntries<'_, T>
1419where
1420 T: Primitive,
1421{
1422 pub fn insert(&mut self, key: i32, value: T) -> &mut Self {
1424 self.arr.item(key);
1425 self.arr.item(value);
1426 self
1427 }
1428}
1429
1430pub trait Finish: Sized {
1451 #[inline]
1453 fn finish(self) {}
1454}
1455
1456impl<T> Finish for T {}
1457
1458#[cfg(test)]
1459mod tests {
1460 use super::*;
1461
1462 #[test]
1463 fn test_primitive_objects() {
1464 test_primitive!(true, b"true");
1466 test_primitive!(false, b"false");
1467 test_primitive!(78, b"78");
1468 test_primitive!(4.22, b"4.22");
1469 test_primitive!(1.184e-7, b"0.0000001184");
1470 test_primitive!(4.2e13, b"42000000000000");
1471 test_primitive!(Ref::new(7), b"7 0 R");
1472 test_primitive!(Null, b"null");
1473
1474 test_primitive!(Str(b"Hello, World!"), b"(Hello, World!)");
1476 test_primitive!(Str(b"()"), br"(())");
1477 test_primitive!(Str(b")()"), br"(\)\(\))");
1478 test_primitive!(Str(b"()(())"), br"(()(()))");
1479 test_primitive!(Str(b"(()))"), br"(\(\(\)\)\))");
1480 test_primitive!(Str(b"\\"), br"(\\)");
1481 test_primitive!(Str(b"\n\ta"), br"(\n\ta)");
1482 test_primitive!(Str(br"\n"), br"(\\n)");
1483 test_primitive!(Str(b"a\x14b"), br"(a\024b)");
1484 test_primitive!(Str(b"\xFF\xAA"), b"<FFAA>");
1485 test_primitive!(Str(b"\x0A\x7F\x1F"), br"(\n\177\037)");
1486
1487 test_primitive!(TextStr("Hallo"), b"(Hallo)");
1489 test_primitive!(TextStr("😀!"), b"<FEFFD83DDE000021>");
1490
1491 test_primitive!(Name(b"Filter"), b"/Filter");
1493 test_primitive!(Name(b"A B"), br"/A#20B");
1494 test_primitive!(Name(b"~+c"), br"/~+c");
1495 test_primitive!(Name(b"/A-B"), br"/#2FA-B");
1496 test_primitive!(Name(b"<A>"), br"/#3CA#3E");
1497 test_primitive!(Name(b"#"), br"/#23");
1498 test_primitive!(Name(b"\n"), br"/#0A");
1499 }
1500
1501 #[test]
1502 fn test_dates() {
1503 test_primitive!(Date::new(2021), b"(D:2021)");
1504 test_primitive!(Date::new(2021).month(30), b"(D:202112)");
1505
1506 let date = Date::new(2020).month(3).day(17).hour(1).minute(2).second(3);
1507 test_primitive!(date, b"(D:20200317010203)");
1508 test_primitive!(date.utc_offset_hour(0), b"(D:20200317010203Z)");
1509 test_primitive!(date.utc_offset_hour(4), b"(D:20200317010203+04'00)");
1510 test_primitive!(
1511 date.utc_offset_hour(-17).utc_offset_minute(10),
1512 b"(D:20200317010203-17'10)"
1513 );
1514 }
1515
1516 #[test]
1517 fn test_arrays() {
1518 test_obj!(|obj| obj.array(), b"[]");
1519 test_obj!(|obj| obj.array().item(12).item(Null), b"[12 null]");
1520 test_obj!(|obj| obj.array().typed().items(vec![1, 2, 3]), b"[1 2 3]");
1521 test_obj!(
1522 |obj| {
1523 let mut array = obj.array();
1524 array.push().array().typed().items(vec![1, 2]);
1525 array.item(3);
1526 },
1527 b"[[1 2] 3]",
1528 );
1529 }
1530
1531 #[test]
1532 fn test_dicts() {
1533 test_obj!(|obj| obj.dict(), b"<<>>");
1534 test_obj!(
1535 |obj| obj.dict().pair(Name(b"Quality"), Name(b"Good")),
1536 b"<<\n /Quality /Good\n>>",
1537 );
1538 test_obj!(
1539 |obj| {
1540 obj.dict().pair(Name(b"A"), 1).pair(Name(b"B"), 2);
1541 },
1542 b"<<\n /A 1\n /B 2\n>>",
1543 );
1544 }
1545
1546 #[test]
1547 fn test_streams() {
1548 let mut w = Pdf::new();
1549 w.stream(Ref::new(1), &b"Hi there!"[..]).filter(Filter::Crypt);
1550 test!(
1551 w.finish(),
1552 b"%PDF-1.7\n%\x80\x80\x80\x80\n",
1553 b"1 0 obj",
1554 b"<<\n /Length 9\n /Filter /Crypt\n>>",
1555 b"stream",
1556 b"Hi there!",
1557 b"endstream",
1558 b"endobj\n",
1559 b"xref",
1560 b"0 2",
1561 b"0000000000 65535 f\r",
1562 b"0000000016 00000 n\r",
1563 b"trailer",
1564 b"<<\n /Size 2\n>>",
1565 b"startxref\n94\n%%EOF",
1566 )
1567 }
1568}