1use std::convert::TryFrom;
2use std::marker::PhantomData;
3use std::mem::ManuallyDrop;
4use std::num::NonZeroI32;
5
6use super::*;
7use crate::chunk::Settings;
8use crate::object::sealed::Sealed;
9
10mod sealed {
11 use crate::Buf;
12
13 pub trait Sealed {
14 const STARTS_WITH_DELIMITER: bool;
16
17 fn write(self, buf: &mut Buf);
19 }
20}
21
22pub trait Primitive: Sealed {}
24
25impl<T: Sealed> Sealed for &T
26where
27 T: Copy,
28{
29 const STARTS_WITH_DELIMITER: bool = T::STARTS_WITH_DELIMITER;
30
31 #[inline]
32 fn write(self, buf: &mut Buf) {
33 (*self).write(buf);
34 }
35}
36
37impl<T: Primitive> Primitive for &T where T: Copy {}
38
39impl Sealed for bool {
40 const STARTS_WITH_DELIMITER: bool = false;
41
42 #[inline]
43 fn write(self, buf: &mut Buf) {
44 if self {
45 buf.extend(b"true");
46 } else {
47 buf.extend(b"false");
48 }
49 }
50}
51
52impl Primitive for bool {}
53
54impl Sealed for i32 {
55 const STARTS_WITH_DELIMITER: bool = false;
56
57 #[inline]
58 fn write(self, buf: &mut Buf) {
59 buf.push_int(self);
60 }
61}
62
63impl Primitive for i32 {}
64
65impl Sealed for f32 {
66 const STARTS_WITH_DELIMITER: bool = false;
67
68 #[inline]
69 fn write(self, buf: &mut Buf) {
70 buf.push_float(self);
71 }
72}
73
74impl Primitive for f32 {}
75
76#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
80pub struct Str<'a>(pub &'a [u8]);
81
82impl Str<'_> {
83 fn is_balanced(self) -> bool {
85 let mut depth = 0;
86 for &byte in self.0 {
87 match byte {
88 b'(' => depth += 1,
89 b')' if depth > 0 => depth -= 1,
90 b')' => return false,
91 _ => {}
92 }
93 }
94 depth == 0
95 }
96}
97
98impl Sealed for Str<'_> {
99 const STARTS_WITH_DELIMITER: bool = true;
100
101 fn write(self, buf: &mut Buf) {
102 buf.limits.register_str_len(self.0.len());
103
104 if self.0.iter().all(|b| b.is_ascii()) {
110 buf.reserve(self.0.len());
111 buf.inner.push(b'(');
112
113 let mut balanced = None;
114 for &byte in self.0 {
115 match byte {
116 b'(' | b')' => {
117 if !*balanced
118 .get_or_insert_with(|| byte != b')' && self.is_balanced())
119 {
120 buf.push(b'\\');
121 }
122 buf.push(byte);
123 }
124 b'\\' => buf.extend(br"\\"),
125 b' '..=b'~' => buf.push(byte),
126 b'\n' => buf.extend(br"\n"),
127 b'\r' => buf.extend(br"\r"),
128 b'\t' => buf.extend(br"\t"),
129 b'\x08' => buf.extend(br"\b"),
130 b'\x0c' => buf.extend(br"\f"),
131 _ => {
132 buf.push(b'\\');
133 buf.push_octal(byte);
134 }
135 }
136 }
137
138 buf.push(b')');
139 } else {
140 buf.reserve(2 + 2 * self.0.len());
141 buf.push(b'<');
142
143 for &byte in self.0 {
144 buf.push_hex(byte);
145 }
146
147 buf.push(b'>');
148 }
149 }
150}
151
152impl Primitive for Str<'_> {}
153
154#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
164pub struct TextStr<'a>(pub &'a str);
165
166impl Sealed for TextStr<'_> {
167 const STARTS_WITH_DELIMITER: bool = true;
168
169 fn write(self, buf: &mut Buf) {
170 buf.limits.register_str_len(self.0.len());
171
172 if self.0.bytes().all(|b| matches!(b, 32..=126)) {
174 Str(self.0.as_bytes()).write(buf);
175 } else {
176 buf.reserve(6 + 4 * self.0.len());
177 write_utf16be_text_str_header(buf);
178 for value in self.0.encode_utf16() {
179 buf.push_hex_u16(value);
180 }
181 write_utf16be_text_str_footer(buf);
182 }
183 }
184}
185
186impl Primitive for TextStr<'_> {}
187
188#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
191pub struct LanguageIdentifier {
192 lang: [u8; 2],
194 region: Option<[u8; 2]>,
196}
197
198impl LanguageIdentifier {
199 pub fn new(lang: [u8; 2], region: Option<[u8; 2]>) -> Self {
203 Self { lang, region }
204 }
205
206 pub fn from_lang(lang: &str) -> Option<Self> {
211 let lang = Self::str_to_code(lang)?;
212 Some(Self::new(lang, None))
213 }
214
215 pub fn from_lang_region(lang: &str, region: &str) -> Option<Self> {
220 let lang = Self::str_to_code(lang)?;
221 let region = Self::str_to_code(region)?;
222 Some(Self::new(lang, Some(region)))
223 }
224
225 fn len(self) -> usize {
228 if self.region.is_some() {
229 4
230 } else {
231 2
232 }
233 }
234
235 fn str_to_code(string: &str) -> Option<[u8; 2]> {
236 if string.chars().all(|c| c.is_ascii_alphanumeric()) {
237 string.as_bytes().try_into().ok()
238 } else {
239 None
240 }
241 }
242}
243
244#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
253pub struct TextStrWithLang<'a, 'b>(pub &'b [(LanguageIdentifier, &'a str)]);
254
255impl<'a, 'b> Sealed for TextStrWithLang<'a, 'b> {
256 const STARTS_WITH_DELIMITER: bool = true;
257
258 fn write(self, buf: &mut Buf) {
259 let mut len = 0;
260 let mut buf_len = 6;
261
262 for (lang, text) in self.0 {
263 len += text.len() + lang.len() + 2;
266 buf_len += 4 * text.len() + lang.len() * 2 + 4;
270 }
271
272 buf.limits.register_str_len(len);
273
274 buf.reserve(buf_len);
277 write_utf16be_text_str_header(buf);
278
279 for (lang, text) in self.0 {
280 write_utf16be_lang_code(*lang, buf);
281 for value in text.encode_utf16() {
282 buf.push_hex_u16(value);
283 }
284 }
285
286 write_utf16be_text_str_footer(buf);
287 }
288}
289
290impl Primitive for TextStrWithLang<'_, '_> {}
291
292fn write_utf16be_text_str_header(buf: &mut Buf) {
293 buf.push(b'<');
294 buf.push_hex(254);
295 buf.push_hex(255);
296}
297
298fn write_utf16be_text_str_footer(buf: &mut Buf) {
299 buf.push(b'>');
300}
301
302fn write_utf16be_lang_code(lang: LanguageIdentifier, buf: &mut Buf) {
303 buf.push_hex_u16(0x001B);
309 buf.push_hex_u16(u16::from(lang.lang[0]));
310 buf.push_hex_u16(u16::from(lang.lang[1]));
311 if let Some(region) = lang.region {
312 buf.push_hex_u16(u16::from(region[0]));
313 buf.push_hex_u16(u16::from(region[1]));
314 }
315 buf.push_hex_u16(0x001B);
316}
317
318pub trait TextStrLike: Primitive {}
325
326impl<'a> TextStrLike for TextStr<'a> {}
327impl<'a, 'b> TextStrLike for TextStrWithLang<'a, 'b> {}
328
329#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
333pub struct Name<'a>(pub &'a [u8]);
334
335impl Sealed for Name<'_> {
336 const STARTS_WITH_DELIMITER: bool = true;
337
338 fn write(self, buf: &mut Buf) {
339 buf.limits.register_name_len(self.0.len());
340
341 buf.reserve(1 + self.0.len());
342 buf.push(b'/');
343 for &byte in self.0 {
344 if byte != b'#' && matches!(byte, b'!'..=b'~') && is_regular_character(byte) {
348 buf.push(byte);
349 } else {
350 buf.push(b'#');
351 buf.push_hex(byte);
352 }
353 }
354 }
355}
356
357impl Primitive for Name<'_> {}
358
359fn is_regular_character(byte: u8) -> bool {
361 !matches!(
362 byte,
363 b'\0'
364 | b'\t'
365 | b'\n'
366 | b'\x0C'
367 | b'\r'
368 | b' '
369 | b'('
370 | b')'
371 | b'<'
372 | b'>'
373 | b'['
374 | b']'
375 | b'{'
376 | b'}'
377 | b'/'
378 | b'%'
379 )
380}
381
382#[inline]
383pub(crate) fn is_delimiter_character(byte: u8) -> bool {
384 matches!(byte, b'(' | b')' | b'<' | b'>' | b'[' | b']' | b'/' | b'%')
385}
386
387#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
389pub struct Null;
390
391impl Sealed for Null {
392 const STARTS_WITH_DELIMITER: bool = false;
393
394 #[inline]
395 fn write(self, buf: &mut Buf) {
396 buf.extend(b"null");
397 }
398}
399
400impl Primitive for Null {}
401
402#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
404pub struct Ref(NonZeroI32);
405
406impl Ref {
407 #[inline]
413 #[track_caller]
414 pub const fn new(id: i32) -> Ref {
415 let option = if id > 0 { NonZeroI32::new(id) } else { None };
416 match option {
417 Some(val) => Self(val),
418 None => panic!("indirect reference out of valid range"),
419 }
420 }
421
422 #[inline]
424 pub const fn get(self) -> i32 {
425 self.0.get()
426 }
427
428 #[inline]
430 pub const fn next(self) -> Self {
431 Self::new(self.get() + 1)
432 }
433
434 #[inline]
437 pub fn bump(&mut self) -> Self {
438 let prev = *self;
439 *self = self.next();
440 prev
441 }
442}
443
444impl Sealed for Ref {
445 const STARTS_WITH_DELIMITER: bool = false;
446
447 #[inline]
448 fn write(self, buf: &mut Buf) {
449 buf.push_int(self.0.get());
450 buf.extend(b" 0 R");
451 }
452}
453
454impl Primitive for Ref {}
455
456#[derive(Debug, Copy, Clone, PartialEq)]
458pub struct Rect {
459 pub x1: f32,
461 pub y1: f32,
463 pub x2: f32,
465 pub y2: f32,
467}
468
469impl Rect {
470 #[inline]
472 pub fn new(x1: f32, y1: f32, x2: f32, y2: f32) -> Self {
473 Self { x1, y1, x2, y2 }
474 }
475
476 #[inline]
479 pub fn to_quad_points(self) -> [f32; 8] {
480 [self.x1, self.y1, self.x2, self.y1, self.x2, self.y2, self.x1, self.y2]
481 }
482}
483
484impl Sealed for Rect {
485 const STARTS_WITH_DELIMITER: bool = true;
486
487 #[inline]
488 fn write(self, buf: &mut Buf) {
489 buf.push(b'[');
490 buf.push_val(self.x1);
491 buf.push(b' ');
492 buf.push_val(self.y1);
493 buf.push(b' ');
494 buf.push_val(self.x2);
495 buf.push(b' ');
496 buf.push_val(self.y2);
497 buf.push(b']');
498
499 buf.limits.register_array_len(4);
500 }
501}
502
503impl Primitive for Rect {}
504
505#[derive(Debug, Copy, Clone, Eq, PartialEq)]
513pub struct Date {
514 year: u16,
516 month: Option<u8>,
518 day: Option<u8>,
520 hour: Option<u8>,
522 minute: Option<u8>,
524 second: Option<u8>,
526 utc_offset_hour: Option<i8>,
528 utc_offset_minute: u8,
531}
532
533impl Date {
534 #[inline]
537 pub fn new(year: u16) -> Self {
538 Self {
539 year: year.min(9999),
540 month: None,
541 day: None,
542 hour: None,
543 minute: None,
544 second: None,
545 utc_offset_hour: None,
546 utc_offset_minute: 0,
547 }
548 }
549
550 #[inline]
552 pub fn month(mut self, month: u8) -> Self {
553 self.month = Some(month.clamp(1, 12));
554 self
555 }
556
557 #[inline]
559 pub fn day(mut self, day: u8) -> Self {
560 self.day = Some(day.clamp(1, 31));
561 self
562 }
563
564 #[inline]
566 pub fn hour(mut self, hour: u8) -> Self {
567 self.hour = Some(hour.min(23));
568 self
569 }
570
571 #[inline]
573 pub fn minute(mut self, minute: u8) -> Self {
574 self.minute = Some(minute.min(59));
575 self
576 }
577
578 #[inline]
580 pub fn second(mut self, second: u8) -> Self {
581 self.second = Some(second.min(59));
582 self
583 }
584
585 #[inline]
589 pub fn utc_offset_hour(mut self, hour: i8) -> Self {
590 self.utc_offset_hour = Some(hour.clamp(-23, 23));
591 self
592 }
593
594 #[inline]
597 pub fn utc_offset_minute(mut self, minute: u8) -> Self {
598 self.utc_offset_minute = minute.min(59);
599 self
600 }
601}
602
603impl Sealed for Date {
604 const STARTS_WITH_DELIMITER: bool = true;
605
606 fn write(self, buf: &mut Buf) {
607 buf.extend(b"(D:");
608
609 (|| {
610 write!(buf.inner, "{:04}", self.year).unwrap();
611 write!(buf.inner, "{:02}", self.month?).unwrap();
612 write!(buf.inner, "{:02}", self.day?).unwrap();
613 write!(buf.inner, "{:02}", self.hour?).unwrap();
614 write!(buf.inner, "{:02}", self.minute?).unwrap();
615 write!(buf.inner, "{:02}", self.second?).unwrap();
616 let utc_offset_hour = self.utc_offset_hour?;
617 if utc_offset_hour == 0 && self.utc_offset_minute == 0 {
618 buf.push(b'Z');
619 } else {
620 write!(
621 buf.inner,
622 "{:+03}'{:02}",
623 utc_offset_hour, self.utc_offset_minute
624 )
625 .unwrap();
626 }
627 Some(())
628 })();
629
630 buf.push(b')');
631 }
632}
633
634impl Primitive for Date {}
635
636#[must_use = "not consuming this leaves the writer in an inconsistent state"]
638pub struct Obj<'a> {
639 buf: &'a mut Buf,
640 indirect: bool,
641 indent: u8,
642 settings: Settings,
643 needs_padding: bool,
644}
645
646impl<'a> Obj<'a> {
647 #[inline]
649 pub(crate) fn direct(
650 buf: &'a mut Buf,
651 indent: u8,
652 settings: Settings,
653 needs_padding: bool,
654 ) -> Self {
655 Self {
656 buf,
657 indirect: false,
658 indent,
659 settings,
660 needs_padding,
661 }
662 }
663
664 #[inline]
666 pub(crate) fn indirect(buf: &'a mut Buf, id: Ref, settings: Settings) -> Self {
667 buf.push_int(id.get());
668 buf.extend(b" 0 obj\n");
669 Self {
670 buf,
671 indirect: true,
672 indent: 0,
673 settings,
674 needs_padding: false,
675 }
676 }
677
678 #[inline]
680 pub fn primitive<T: Primitive>(self, value: T) {
681 let ends_with_delimiter =
695 self.buf.last().copied().is_some_and(is_delimiter_character);
696
697 if self.needs_padding && !T::STARTS_WITH_DELIMITER && !ends_with_delimiter {
698 self.buf.extend(b" ");
699 }
700
701 value.write(self.buf);
702
703 if self.indirect {
704 self.buf.extend(b"\nendobj\n");
705
706 if self.settings.pretty {
707 self.buf.extend(b"\n");
708 }
709 }
710 }
711
712 #[inline]
717 pub fn array(self) -> Array<'a> {
718 self.start()
719 }
720
721 #[inline]
723 pub fn dict(self) -> Dict<'a> {
724 self.start()
725 }
726
727 #[inline]
743 pub fn start<W: Writer<'a>>(self) -> W {
744 W::start(self)
745 }
746}
747
748pub trait Writer<'a> {
750 fn start(obj: Obj<'a>) -> Self;
752}
753
754pub trait Rewrite<'a> {
760 type Output: Writer<'a>;
762}
763
764pub struct Array<'a> {
766 buf: &'a mut Buf,
767 indirect: bool,
768 indent: u8,
769 settings: Settings,
770 len: i32,
771}
772
773writer!(Array: |obj| {
774 obj.buf.push(b'[');
775 Self {
776 buf: obj.buf,
777 indirect: obj.indirect,
778 indent: obj.indent,
779 settings: obj.settings,
780 len: 0,
781 }
782});
783
784impl<'a> Array<'a> {
785 #[inline]
787 pub fn len(&self) -> i32 {
788 self.len
789 }
790
791 #[inline]
793 pub fn is_empty(&self) -> bool {
794 self.len == 0
795 }
796
797 #[inline]
799 pub fn push(&mut self) -> Obj<'_> {
800 let needs_padding = if self.len != 0 {
801 if self.settings.pretty {
802 self.buf.push(b' ');
803 false
804 } else {
805 true
806 }
807 } else {
808 false
809 };
810
811 self.len += 1;
812
813 Obj::direct(self.buf, self.indent, self.settings, needs_padding)
814 }
815
816 #[inline]
820 pub fn item<T: Primitive>(&mut self, value: T) -> &mut Self {
821 self.push().primitive(value);
822 self
823 }
824
825 #[inline]
827 pub fn items<T: Primitive>(
828 &mut self,
829 values: impl IntoIterator<Item = T>,
830 ) -> &mut Self {
831 for value in values {
832 self.item(value);
833 }
834 self
835 }
836
837 #[inline]
839 pub fn typed<T>(self) -> TypedArray<'a, T> {
840 TypedArray::wrap(self)
841 }
842}
843
844impl Drop for Array<'_> {
845 #[inline]
846 fn drop(&mut self) {
847 self.buf.limits.register_array_len(self.len() as usize);
848 self.buf.push(b']');
849 if self.indirect {
850 self.buf.extend(b"\nendobj\n");
851
852 if self.settings.pretty {
853 self.buf.extend(b"\n");
854 }
855 }
856 }
857}
858
859pub struct TypedArray<'a, T> {
861 array: Array<'a>,
862 phantom: PhantomData<fn() -> T>,
863}
864
865impl<'a, T> Writer<'a> for TypedArray<'a, T> {
866 fn start(obj: Obj<'a>) -> Self {
867 Self { array: obj.array(), phantom: PhantomData }
868 }
869}
870
871impl<'a, T> Rewrite<'a> for TypedArray<'_, T> {
872 type Output = TypedArray<'a, T>;
873}
874
875impl<'a, T> TypedArray<'a, T> {
876 #[inline]
878 pub fn wrap(array: Array<'a>) -> Self {
879 Self { array, phantom: PhantomData }
880 }
881
882 #[inline]
884 pub fn len(&self) -> i32 {
885 self.array.len()
886 }
887
888 #[inline]
890 pub fn is_empty(&self) -> bool {
891 self.len() == 0
892 }
893
894 #[inline]
896 pub fn item(&mut self, value: T) -> &mut Self
897 where
898 T: Primitive,
899 {
900 self.array.item(value);
901 self
902 }
903
904 #[inline]
906 pub fn items(&mut self, values: impl IntoIterator<Item = T>) -> &mut Self
907 where
908 T: Primitive,
909 {
910 self.array.items(values);
911 self
912 }
913
914 #[inline]
918 pub fn push<'b>(&'b mut self) -> <T as Rewrite<'b>>::Output
919 where
920 T: Writer<'a> + Rewrite<'b>,
921 {
922 <T as Rewrite>::Output::start(self.array.push())
923 }
924}
925
926pub struct Dict<'a> {
928 buf: &'a mut Buf,
929 indirect: bool,
930 indent: u8,
931 settings: Settings,
932 len: i32,
933}
934
935writer!(Dict: |obj| {
936 obj.buf.extend(b"<<");
937 Self {
938 buf: obj.buf,
939 indirect: obj.indirect,
940 indent: obj.indent.saturating_add(2),
941 settings: obj.settings,
942 len: 0,
943 }
944});
945
946impl<'a> Dict<'a> {
947 #[inline]
949 pub fn len(&self) -> i32 {
950 self.len
951 }
952
953 #[inline]
955 pub fn is_empty(&self) -> bool {
956 self.len == 0
957 }
958
959 #[inline]
961 pub fn insert(&mut self, key: Name) -> Obj<'_> {
962 self.len += 1;
963
964 if self.settings.pretty {
967 self.buf.push(b'\n');
968
969 for _ in 0..self.indent {
970 self.buf.push(b' ');
971 }
972 }
973
974 self.buf.push_val(key);
975
976 let needs_padding = if self.settings.pretty {
977 self.buf.push(b' ');
978 false
979 } else {
980 true
981 };
982
983 Obj::direct(self.buf, self.indent, self.settings, needs_padding)
984 }
985
986 #[inline]
990 pub fn pair<T: Primitive>(&mut self, key: Name, value: T) -> &mut Self {
991 self.insert(key).primitive(value);
992 self
993 }
994
995 pub fn pairs<'n, T: Primitive>(
997 &mut self,
998 pairs: impl IntoIterator<Item = (Name<'n>, T)>,
999 ) -> &mut Self {
1000 for (key, value) in pairs {
1001 self.pair(key, value);
1002 }
1003 self
1004 }
1005
1006 #[inline]
1008 pub fn typed<T>(self) -> TypedDict<'a, T> {
1009 TypedDict::wrap(self)
1010 }
1011}
1012
1013impl Drop for Dict<'_> {
1014 #[inline]
1015 fn drop(&mut self) {
1016 self.buf.limits.register_dict_entries(self.len as usize);
1017
1018 if self.len != 0 && self.settings.pretty {
1019 self.buf.push(b'\n');
1020 for _ in 0..self.indent - 2 {
1021 self.buf.push(b' ');
1022 }
1023 }
1024
1025 self.buf.extend(b">>");
1026
1027 if self.indirect {
1028 self.buf.extend(b"\nendobj\n");
1029
1030 if self.settings.pretty {
1031 self.buf.extend(b"\n");
1032 }
1033 }
1034 }
1035}
1036
1037pub struct TypedDict<'a, T> {
1039 dict: Dict<'a>,
1040 phantom: PhantomData<fn() -> T>,
1041}
1042
1043impl<'a, T> Writer<'a> for TypedDict<'a, T> {
1044 fn start(obj: Obj<'a>) -> Self {
1045 Self { dict: obj.dict(), phantom: PhantomData }
1046 }
1047}
1048
1049impl<'a, T> Rewrite<'a> for TypedDict<'_, T> {
1050 type Output = TypedDict<'a, T>;
1051}
1052
1053impl<'a, T> TypedDict<'a, T> {
1054 #[inline]
1056 pub fn wrap(dict: Dict<'a>) -> Self {
1057 Self { dict, phantom: PhantomData }
1058 }
1059
1060 #[inline]
1062 pub fn len(&self) -> i32 {
1063 self.dict.len()
1064 }
1065
1066 #[inline]
1068 pub fn is_empty(&self) -> bool {
1069 self.len() == 0
1070 }
1071
1072 #[inline]
1074 pub fn pair(&mut self, key: Name, value: T) -> &mut Self
1075 where
1076 T: Primitive,
1077 {
1078 self.dict.pair(key, value);
1079 self
1080 }
1081
1082 #[inline]
1084 pub fn pairs<'n>(
1085 &mut self,
1086 pairs: impl IntoIterator<Item = (Name<'n>, T)>,
1087 ) -> &mut Self
1088 where
1089 T: Primitive,
1090 {
1091 self.dict.pairs(pairs);
1092 self
1093 }
1094
1095 #[inline]
1099 pub fn insert<'b>(&'b mut self, key: Name) -> <T as Rewrite<'b>>::Output
1100 where
1101 T: Writer<'a> + Rewrite<'b>,
1102 {
1103 <T as Rewrite>::Output::start(self.dict.insert(key))
1104 }
1105}
1106
1107pub struct Stream<'a> {
1109 dict: ManuallyDrop<Dict<'a>>,
1110 data: &'a [u8],
1111}
1112
1113impl<'a> Stream<'a> {
1114 pub(crate) fn start(obj: Obj<'a>, data: &'a [u8]) -> Self {
1119 assert!(obj.indirect);
1120
1121 let mut dict = obj.dict();
1122 dict.pair(
1123 Name(b"Length"),
1124 i32::try_from(data.len()).unwrap_or_else(|_| {
1125 panic!("data length (is `{}`) must be <= i32::MAX", data.len());
1126 }),
1127 );
1128
1129 Self { dict: ManuallyDrop::new(dict), data }
1130 }
1131
1132 pub fn filter(&mut self, filter: Filter) -> &mut Self {
1134 self.pair(Name(b"Filter"), filter.to_name());
1135 self
1136 }
1137
1138 pub fn decode_parms(&mut self) -> DecodeParms<'_> {
1144 self.insert(Name(b"DecodeParms")).start()
1145 }
1146}
1147
1148impl Drop for Stream<'_> {
1149 fn drop(&mut self) {
1150 let dict_len = self.dict.len as usize;
1151 self.dict.buf.limits.register_dict_entries(dict_len);
1152
1153 if self.dict.settings.pretty {
1154 self.dict.buf.extend(b"\n");
1155 }
1156
1157 self.dict.buf.extend(b">>");
1158 self.dict.buf.extend(b"\nstream\n");
1159 self.dict.buf.extend(self.data.as_ref());
1160 self.dict.buf.extend(b"\nendstream");
1161 self.dict.buf.extend(b"\nendobj\n");
1162
1163 if self.dict.settings.pretty {
1164 self.dict.buf.extend(b"\n");
1165 }
1166 }
1167}
1168
1169deref!('a, Stream<'a> => Dict<'a>, dict);
1170
1171#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
1173#[allow(missing_docs)]
1174pub enum Filter {
1175 AsciiHexDecode,
1176 Ascii85Decode,
1177 LzwDecode,
1181 FlateDecode,
1182 RunLengthDecode,
1183 CcittFaxDecode,
1184 Jbig2Decode,
1185 DctDecode,
1189 JpxDecode,
1193 Crypt,
1197}
1198
1199impl Filter {
1200 pub(crate) fn to_name(self) -> Name<'static> {
1201 match self {
1202 Self::AsciiHexDecode => Name(b"ASCIIHexDecode"),
1203 Self::Ascii85Decode => Name(b"ASCII85Decode"),
1204 Self::LzwDecode => Name(b"LZWDecode"),
1205 Self::FlateDecode => Name(b"FlateDecode"),
1206 Self::RunLengthDecode => Name(b"RunLengthDecode"),
1207 Self::CcittFaxDecode => Name(b"CCITTFaxDecode"),
1208 Self::Jbig2Decode => Name(b"JBIG2Decode"),
1209 Self::DctDecode => Name(b"DCTDecode"),
1210 Self::JpxDecode => Name(b"JPXDecode"),
1211 Self::Crypt => Name(b"Crypt"),
1212 }
1213 }
1214}
1215
1216pub struct DecodeParms<'a> {
1220 dict: Dict<'a>,
1221}
1222
1223writer!(DecodeParms: |obj| Self { dict: obj.dict() });
1224
1225impl DecodeParms<'_> {
1227 pub fn predictor(&mut self, predictor: Predictor) -> &mut Self {
1231 self.pair(Name(b"Predictor"), predictor.to_i32());
1232 self
1233 }
1234
1235 pub fn colors(&mut self, colors: i32) -> &mut Self {
1240 if colors <= 0 {
1241 panic!("`Colors` must be greater than 0");
1242 }
1243
1244 self.pair(Name(b"Colors"), colors);
1245 self
1246 }
1247
1248 pub fn bits_per_component(&mut self, bits: i32) -> &mut Self {
1254 if ![1, 2, 4, 8, 16].contains(&bits) {
1255 panic!("`BitsPerComponent` must be one of 1, 2, 4, 8, or 16");
1256 }
1257
1258 self.pair(Name(b"BitsPerComponent"), bits);
1259 self
1260 }
1261
1262 pub fn columns(&mut self, columns: i32) -> &mut Self {
1272 self.pair(Name(b"Columns"), columns);
1273 self
1274 }
1275
1276 pub fn early_change(&mut self, early_change: bool) -> &mut Self {
1283 self.pair(Name(b"EarlyChange"), if early_change { 1 } else { 0 });
1284 self
1285 }
1286}
1287
1288impl DecodeParms<'_> {
1290 pub fn k(&mut self, k: i32) -> &mut Self {
1294 self.pair(Name(b"K"), k);
1295 self
1296 }
1297
1298 pub fn end_of_line(&mut self, eol: bool) -> &mut Self {
1303 self.pair(Name(b"EndOfLine"), eol);
1304 self
1305 }
1306
1307 pub fn encoded_byte_align(&mut self, encoded_byte_align: bool) -> &mut Self {
1312 self.pair(Name(b"EncodedByteAlign"), encoded_byte_align);
1313 self
1314 }
1315
1316 pub fn rows(&mut self, rows: i32) -> &mut Self {
1320 self.pair(Name(b"Rows"), rows);
1321 self
1322 }
1323
1324 pub fn end_of_block(&mut self, end_of_block: bool) -> &mut Self {
1329 self.pair(Name(b"EndOfBlock"), end_of_block);
1330 self
1331 }
1332
1333 pub fn black_is_1(&mut self, black_is_1: bool) -> &mut Self {
1337 self.pair(Name(b"BlackIs1"), black_is_1);
1338 self
1339 }
1340
1341 pub fn damaged_rows_before_error(&mut self, count: i32) -> &mut Self {
1346 self.pair(Name(b"DamagedRowsBeforeError"), count);
1347 self
1348 }
1349}
1350
1351impl DecodeParms<'_> {
1353 pub fn jbig2_globals(&mut self, globals: Ref) -> &mut Self {
1357 self.pair(Name(b"JBIG2Globals"), globals);
1358 self
1359 }
1360}
1361
1362impl DecodeParms<'_> {
1364 pub fn color_transform(&mut self, color_transform: bool) -> &mut Self {
1372 self.pair(Name(b"ColorTransform"), if color_transform { 1 } else { 0 });
1373 self
1374 }
1375}
1376
1377impl DecodeParms<'_> {
1379 pub fn crypt_type(&mut self) -> &mut Self {
1381 self.pair(Name(b"Type"), Name(b"CryptFilterDecodeParms"));
1382 self
1383 }
1384
1385 pub fn name(&mut self, name: Name) -> &mut Self {
1390 self.pair(Name(b"Name"), name);
1391 self
1392 }
1393}
1394
1395deref!('a, DecodeParms<'a> => Dict<'a>, dict);
1396
1397#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Hash)]
1399#[allow(missing_docs)]
1400pub enum Predictor {
1401 #[default]
1403 None,
1404 Tiff,
1406 PngNone,
1407 PngSub,
1408 PngUp,
1409 PngAverage,
1410 PngPaeth,
1411 PngOptimum,
1412}
1413
1414impl Predictor {
1415 fn to_i32(self) -> i32 {
1418 match self {
1419 Self::None => 1,
1420 Self::Tiff => 2,
1421 Self::PngNone => 10,
1422 Self::PngSub => 11,
1423 Self::PngUp => 12,
1424 Self::PngAverage => 13,
1425 Self::PngPaeth => 14,
1426 Self::PngOptimum => 15,
1427 }
1428 }
1429}
1430
1431pub struct NameTree<'a, T> {
1441 dict: Dict<'a>,
1442 phantom: PhantomData<T>,
1443}
1444
1445impl<'a, T> Writer<'a> for NameTree<'a, T> {
1446 fn start(obj: Obj<'a>) -> Self {
1447 Self { dict: obj.dict(), phantom: PhantomData }
1448 }
1449}
1450
1451impl<'a, T> Rewrite<'a> for NameTree<'_, T> {
1452 type Output = NameTree<'a, T>;
1453}
1454
1455impl<T> NameTree<'_, T> {
1456 pub fn kids(&mut self) -> TypedArray<'_, Ref> {
1458 self.dict.insert(Name(b"Kids")).array().typed()
1459 }
1460
1461 pub fn names(&mut self) -> NameTreeEntries<'_, T> {
1464 self.dict.insert(Name(b"Names")).start()
1465 }
1466
1467 pub fn limits(&mut self, min: Name, max: Name) -> &mut Self {
1470 self.dict.insert(Name(b"Limits")).array().typed().items([min, max]);
1471 self
1472 }
1473}
1474
1475pub struct NameTreeEntries<'a, T> {
1481 arr: Array<'a>,
1482 phantom: PhantomData<T>,
1483}
1484
1485impl<'a, T> Writer<'a> for NameTreeEntries<'a, T> {
1486 fn start(obj: Obj<'a>) -> Self {
1487 Self { arr: obj.array(), phantom: PhantomData }
1488 }
1489}
1490
1491impl<'a, T> Rewrite<'a> for NameTreeEntries<'_, T> {
1492 type Output = NameTreeEntries<'a, T>;
1493}
1494
1495impl<T> NameTreeEntries<'_, T>
1496where
1497 T: Primitive,
1498{
1499 pub fn insert(&mut self, key: Str, value: T) -> &mut Self {
1501 self.arr.item(key);
1502 self.arr.item(value);
1503 self
1504 }
1505}
1506
1507pub struct NumberTree<'a, T> {
1517 dict: Dict<'a>,
1518 phantom: PhantomData<T>,
1519}
1520
1521impl<'a, T> Writer<'a> for NumberTree<'a, T> {
1522 fn start(obj: Obj<'a>) -> Self {
1523 Self { dict: obj.dict(), phantom: PhantomData }
1524 }
1525}
1526
1527impl<'a, T> Rewrite<'a> for NumberTree<'_, T> {
1528 type Output = NumberTree<'a, T>;
1529}
1530
1531impl<T> NumberTree<'_, T> {
1532 pub fn kids(&mut self) -> TypedArray<'_, Ref> {
1534 self.dict.insert(Name(b"Kids")).array().typed()
1535 }
1536
1537 pub fn nums(&mut self) -> NumberTreeEntries<'_, T> {
1540 self.dict.insert(Name(b"Nums")).start()
1541 }
1542
1543 pub fn limits(&mut self, min: i32, max: i32) -> &mut Self {
1546 self.dict.insert(Name(b"Limits")).array().typed().items([min, max]);
1547 self
1548 }
1549}
1550
1551pub struct NumberTreeEntries<'a, T> {
1557 arr: Array<'a>,
1558 phantom: PhantomData<T>,
1559}
1560
1561impl<'a, T> Writer<'a> for NumberTreeEntries<'a, T> {
1562 fn start(obj: Obj<'a>) -> Self {
1563 Self { arr: obj.array(), phantom: PhantomData }
1564 }
1565}
1566
1567impl<'a, T> Rewrite<'a> for NumberTreeEntries<'_, T> {
1568 type Output = NumberTreeEntries<'a, T>;
1569}
1570
1571impl<T> NumberTreeEntries<'_, T>
1572where
1573 T: Primitive,
1574{
1575 pub fn insert(&mut self, key: i32, value: T) -> &mut Self {
1577 self.arr.item(key);
1578 self.arr.item(value);
1579 self
1580 }
1581}
1582
1583pub trait Finish: Sized {
1604 #[inline]
1606 fn finish(self) {}
1607}
1608
1609impl<T> Finish for T {}
1610
1611#[cfg(test)]
1612mod tests {
1613 use super::*;
1614
1615 #[test]
1616 fn test_primitive_objects() {
1617 test_primitive!(true, b"true");
1619 test_primitive!(false, b"false");
1620 test_primitive!(78, b"78");
1621 test_primitive!(4.22, b"4.22");
1622 test_primitive!(1.184e-7, b"0.0000001184");
1623 test_primitive!(4.2e13, b"42000000000000");
1624 test_primitive!(Ref::new(7), b"7 0 R");
1625 test_primitive!(Null, b"null");
1626
1627 test_primitive!(Str(b"Hello, World!"), b"(Hello, World!)");
1629 test_primitive!(Str(b"()"), br"(())");
1630 test_primitive!(Str(b")()"), br"(\)\(\))");
1631 test_primitive!(Str(b"()(())"), br"(()(()))");
1632 test_primitive!(Str(b"(()))"), br"(\(\(\)\)\))");
1633 test_primitive!(Str(b"\\"), br"(\\)");
1634 test_primitive!(Str(b"\n\ta"), br"(\n\ta)");
1635 test_primitive!(Str(br"\n"), br"(\\n)");
1636 test_primitive!(Str(b"a\x14b"), br"(a\024b)");
1637 test_primitive!(Str(b"\xFF\xAA"), b"<FFAA>");
1638 test_primitive!(Str(b"\x0A\x7F\x1F"), br"(\n\177\037)");
1639
1640 test_primitive!(TextStr("Hallo"), b"(Hallo)");
1642 test_primitive!(TextStr("😀!"), b"<FEFFD83DDE000021>");
1643
1644 test_primitive!(Name(b"Filter"), b"/Filter");
1646 test_primitive!(Name(b"A B"), br"/A#20B");
1647 test_primitive!(Name(b"~+c"), br"/~+c");
1648 test_primitive!(Name(b"/A-B"), br"/#2FA-B");
1649 test_primitive!(Name(b"<A>"), br"/#3CA#3E");
1650 test_primitive!(Name(b"#"), br"/#23");
1651 test_primitive!(Name(b"\n"), br"/#0A");
1652 }
1653
1654 #[test]
1655 fn test_dates() {
1656 test_primitive!(Date::new(2021), b"(D:2021)");
1657 test_primitive!(Date::new(2021).month(30), b"(D:202112)");
1658
1659 let date = Date::new(2020).month(3).day(17).hour(1).minute(2).second(3);
1660 test_primitive!(date, b"(D:20200317010203)");
1661 test_primitive!(date.utc_offset_hour(0), b"(D:20200317010203Z)");
1662 test_primitive!(date.utc_offset_hour(4), b"(D:20200317010203+04'00)");
1663 test_primitive!(
1664 date.utc_offset_hour(-17).utc_offset_minute(10),
1665 b"(D:20200317010203-17'10)"
1666 );
1667 }
1668
1669 #[test]
1670 fn test_arrays() {
1671 test_obj!(|obj| obj.array(), b"[]");
1672 test_obj!(|obj| obj.array().item(12).item(Null), b"[12 null]");
1673 test_obj!(|obj| obj.array().typed().items(vec![1, 2, 3]), b"[1 2 3]");
1674 test_obj!(
1675 |obj| {
1676 let mut array = obj.array();
1677 array.push().array().typed().items(vec![1, 2]);
1678 array.item(3);
1679 },
1680 b"[[1 2] 3]",
1681 );
1682 }
1683
1684 #[test]
1685 fn test_dicts() {
1686 test_obj!(|obj| obj.dict(), b"<<>>");
1687 test_obj!(
1688 |obj| obj.dict().pair(Name(b"Quality"), Name(b"Good")),
1689 b"<<\n /Quality /Good\n>>",
1690 );
1691 test_obj!(
1692 |obj| {
1693 obj.dict().pair(Name(b"A"), 1).pair(Name(b"B"), 2);
1694 },
1695 b"<<\n /A 1\n /B 2\n>>",
1696 );
1697 }
1698
1699 #[test]
1700 fn test_streams() {
1701 let mut w = Pdf::new();
1702 w.stream(Ref::new(1), &b"Hi there!"[..]).filter(Filter::Crypt);
1703 test!(
1704 w.finish(),
1705 b"%PDF-1.7\n%\x80\x80\x80\x80\n",
1706 b"1 0 obj",
1707 b"<<\n /Length 9\n /Filter /Crypt\n>>",
1708 b"stream",
1709 b"Hi there!",
1710 b"endstream",
1711 b"endobj\n",
1712 b"xref",
1713 b"0 2",
1714 b"0000000000 65535 f\r",
1715 b"0000000016 00000 n\r",
1716 b"trailer",
1717 b"<<\n /Size 2\n>>",
1718 b"startxref\n94\n%%EOF",
1719 )
1720 }
1721
1722 #[test]
1723 fn test_arrays_no_pretty() {
1724 test_obj_no_pretty!(|obj| obj.array(), b"[]");
1725 test_obj_no_pretty!(
1726 |obj| {
1727 let mut arr = obj.array();
1728
1729 arr.item(12)
1730 .item(Name(b"Hi"))
1731 .item(Name(b"Hi2"))
1732 .item(false)
1733 .item(TextStr("A string"));
1734
1735 arr.push().dict().pair(Name(b"Test1"), 23);
1736
1737 arr.item(Null).item(23.40);
1738
1739 arr
1740 },
1741 b"[12/Hi/Hi2 false(A string)<</Test1 23>>null 23.4]"
1742 );
1743 }
1744
1745 #[test]
1746 fn test_dicts_no_pretty() {
1747 test_obj_no_pretty!(|obj| obj.dict(), b"<<>>");
1748 test_obj_no_pretty!(
1749 |obj| {
1750 let mut dict = obj.dict();
1751 dict.pair(Name(b"Key1"), 12)
1752 .pair(Name(b"Key2"), Name(b"Hi"))
1753 .pair(Name(b"Key3"), false)
1754 .pair(Name(b"Key4"), TextStr("A string"));
1755 dict.insert(Name(b"Key5")).array().item(23).item(Name(b"Value"));
1756 dict.pair(Name(b"Key6"), Null)
1757 .pair(Name(b"Key7"), 23.40)
1758 },
1759 b"<</Key1 12/Key2/Hi/Key3 false/Key4(A string)/Key5[23/Value]/Key6 null/Key7 23.4>>"
1760 );
1761 }
1762}