blitz-pdf 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +300 -10
- package/THIRD_PARTY_NOTICES.md +4 -2
- package/dist/browser.d.ts +1 -1
- package/dist/browser.d.ts.map +1 -1
- package/dist/document-options.d.ts +36 -0
- package/dist/document-options.d.ts.map +1 -0
- package/dist/document-options.js +236 -0
- package/dist/document-options.js.map +1 -0
- package/dist/node.d.ts +1 -1
- package/dist/node.d.ts.map +1 -1
- package/dist/options.d.ts +35 -1
- package/dist/options.d.ts.map +1 -1
- package/dist/options.js +21 -14
- package/dist/options.js.map +1 -1
- package/dist/types.d.ts +71 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/validation.d.ts +2 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +7 -0
- package/dist/validation.js.map +1 -0
- package/examples/zugferd.mjs +41 -0
- package/licenses/RUST_DEPENDENCIES.txt +27 -0
- package/package.json +3 -2
- package/src/browser.ts +1 -1
- package/src/document-options.ts +218 -0
- package/src/node.ts +1 -1
- package/src/options.ts +18 -13
- package/src/types.ts +76 -1
- package/src/validation.ts +6 -0
- package/vendor/README.md +27 -2
- package/vendor/krilla/.cargo-ok +1 -0
- package/vendor/krilla/.cargo_vcs_info.json +6 -0
- package/vendor/krilla/Cargo.lock +1357 -0
- package/vendor/krilla/Cargo.toml +165 -0
- package/vendor/krilla/LICENSE_APACHE +202 -0
- package/vendor/krilla/LICENSE_MIT +21 -0
- package/vendor/krilla/README.md +156 -0
- package/vendor/krilla/examples/basic.rs +117 -0
- package/vendor/krilla/examples/empty_document.rs +25 -0
- package/vendor/krilla/examples/parley.rs +174 -0
- package/vendor/krilla/examples/simple_text.rs +118 -0
- package/vendor/krilla/examples/stream_builder.rs +93 -0
- package/vendor/krilla/icc/LICENSE +116 -0
- package/vendor/krilla/icc/README.md +1 -0
- package/vendor/krilla/icc/sGrey-v2-magic.icc +0 -0
- package/vendor/krilla/icc/sGrey-v4.icc +0 -0
- package/vendor/krilla/icc/sRGB-v2-magic.icc +0 -0
- package/vendor/krilla/icc/sRGB-v4.icc +0 -0
- package/vendor/krilla/src/chunk_container.rs +503 -0
- package/vendor/krilla/src/configure/PDF_A1.md +227 -0
- package/vendor/krilla/src/configure/PDF_A2.md +269 -0
- package/vendor/krilla/src/configure/PDF_A3.md +31 -0
- package/vendor/krilla/src/configure/PDF_A4.md +211 -0
- package/vendor/krilla/src/configure/PDF_UA1.md +202 -0
- package/vendor/krilla/src/configure/README.md +23 -0
- package/vendor/krilla/src/configure/mod.rs +197 -0
- package/vendor/krilla/src/configure/validate.rs +1244 -0
- package/vendor/krilla/src/configure/version.rs +134 -0
- package/vendor/krilla/src/content.rs +1352 -0
- package/vendor/krilla/src/data.rs +49 -0
- package/vendor/krilla/src/document.rs +156 -0
- package/vendor/krilla/src/error.rs +170 -0
- package/vendor/krilla/src/geom.rs +341 -0
- package/vendor/krilla/src/graphics/blend.rs +46 -0
- package/vendor/krilla/src/graphics/color.rs +552 -0
- package/vendor/krilla/src/graphics/graphic.rs +30 -0
- package/vendor/krilla/src/graphics/graphics_state.rs +251 -0
- package/vendor/krilla/src/graphics/icc.rs +218 -0
- package/vendor/krilla/src/graphics/image.rs +835 -0
- package/vendor/krilla/src/graphics/mask.rs +128 -0
- package/vendor/krilla/src/graphics/mod.rs +14 -0
- package/vendor/krilla/src/graphics/paint.rs +434 -0
- package/vendor/krilla/src/graphics/separation.rs +86 -0
- package/vendor/krilla/src/graphics/shading_function.rs +865 -0
- package/vendor/krilla/src/graphics/shading_pattern.rs +60 -0
- package/vendor/krilla/src/graphics/tiling_pattern.rs +119 -0
- package/vendor/krilla/src/graphics/xobject.rs +150 -0
- package/vendor/krilla/src/interactive/action.rs +68 -0
- package/vendor/krilla/src/interactive/annotation.rs +283 -0
- package/vendor/krilla/src/interactive/destination.rs +289 -0
- package/vendor/krilla/src/interactive/mod.rs +3 -0
- package/vendor/krilla/src/interchange/embed.rs +240 -0
- package/vendor/krilla/src/interchange/metadata.rs +564 -0
- package/vendor/krilla/src/interchange/mod.rs +4 -0
- package/vendor/krilla/src/interchange/outline.rs +263 -0
- package/vendor/krilla/src/interchange/tagging/fmt.rs +733 -0
- package/vendor/krilla/src/interchange/tagging/generate.toml +474 -0
- package/vendor/krilla/src/interchange/tagging/generated.rs +4754 -0
- package/vendor/krilla/src/interchange/tagging/mod.rs +1324 -0
- package/vendor/krilla/src/interchange/tagging/tag.rs +686 -0
- package/vendor/krilla/src/lib.rs +179 -0
- package/vendor/krilla/src/num.rs +26 -0
- package/vendor/krilla/src/page.rs +612 -0
- package/vendor/krilla/src/pdf.rs +313 -0
- package/vendor/krilla/src/resource.rs +436 -0
- package/vendor/krilla/src/serialize.rs +1101 -0
- package/vendor/krilla/src/stream.rs +368 -0
- package/vendor/krilla/src/surface.rs +664 -0
- package/vendor/krilla/src/text/cid.rs +488 -0
- package/vendor/krilla/src/text/font.rs +351 -0
- package/vendor/krilla/src/text/glyph/bitmap.rs +81 -0
- package/vendor/krilla/src/text/glyph/colr.rs +581 -0
- package/vendor/krilla/src/text/glyph/mod.rs +205 -0
- package/vendor/krilla/src/text/glyph/outline.rs +72 -0
- package/vendor/krilla/src/text/glyph/svg.rs +34 -0
- package/vendor/krilla/src/text/group.rs +463 -0
- package/vendor/krilla/src/text/mod.rs +232 -0
- package/vendor/krilla/src/text/shape.rs +102 -0
- package/vendor/krilla/src/text/type3.rs +514 -0
- package/vendor/krilla/src/util.rs +286 -0
- package/vendor/stylo/properties/longhands.toml +0 -1
- package/vendor/stylo/stylesheets/rule_parser.rs +1 -1
- package/wasm/blitz_pdf.js +10 -5
- package/wasm/blitz_pdf_bg.wasm +0 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
use std::fmt::{Debug, Formatter};
|
|
2
|
+
use std::hash::{Hash, Hasher};
|
|
3
|
+
use std::sync::Arc;
|
|
4
|
+
|
|
5
|
+
/// A type that holds some bytes.
|
|
6
|
+
#[derive(Clone)]
|
|
7
|
+
pub struct Data(pub(crate) Arc<dyn AsRef<[u8]> + Send + Sync>);
|
|
8
|
+
|
|
9
|
+
impl AsRef<[u8]> for Data {
|
|
10
|
+
fn as_ref(&self) -> &[u8] {
|
|
11
|
+
self.0.as_ref().as_ref()
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
impl Hash for Data {
|
|
16
|
+
fn hash<H: Hasher>(&self, state: &mut H) {
|
|
17
|
+
self.as_ref().hash(state);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
impl From<Arc<dyn AsRef<[u8]> + Send + Sync>> for Data {
|
|
22
|
+
fn from(value: Arc<dyn AsRef<[u8]> + Send + Sync>) -> Self {
|
|
23
|
+
Self(value)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
impl From<&'static [u8]> for Data {
|
|
28
|
+
fn from(value: &'static [u8]) -> Self {
|
|
29
|
+
Self(Arc::new(value))
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
impl From<Vec<u8>> for Data {
|
|
34
|
+
fn from(value: Vec<u8>) -> Self {
|
|
35
|
+
Self(Arc::new(value))
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
impl From<Arc<Vec<u8>>> for Data {
|
|
40
|
+
fn from(value: Arc<Vec<u8>>) -> Self {
|
|
41
|
+
Self(value)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
impl Debug for Data {
|
|
46
|
+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
47
|
+
write!(f, "Data {{..}}")
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
//! Creating new PDF documents.
|
|
2
|
+
//!
|
|
3
|
+
//! When using krilla, the starting point is always the creation of a [`Document`]. A document
|
|
4
|
+
//! represents _one_ PDF document, to which you can add pages or configure them in any
|
|
5
|
+
//! other way you want.
|
|
6
|
+
//!
|
|
7
|
+
//! Unfortunately, creating PDFs always requires some kind of global state to keep track
|
|
8
|
+
//! of different aspects in the creation process, meaning that it is not possible to
|
|
9
|
+
//! generate multiple pages at the same time. Instead, you need to add pages separately
|
|
10
|
+
//! by calling the [`Document::start_page`] method, which returns a new [`Page`] object that mutably
|
|
11
|
+
//! borrows the global state from the document. Once the page is dropped, the global
|
|
12
|
+
//! state is passed back to the original document, which you can then use to add even
|
|
13
|
+
//! more pages.
|
|
14
|
+
//!
|
|
15
|
+
//! [`Page`]: Page
|
|
16
|
+
|
|
17
|
+
use crate::chunk_container::ChunkContainer;
|
|
18
|
+
use crate::destination::NamedDestination;
|
|
19
|
+
use crate::error::KrillaResult;
|
|
20
|
+
use crate::interchange::embed::EmbeddedFile;
|
|
21
|
+
use crate::interchange::metadata::Metadata;
|
|
22
|
+
use crate::interchange::outline::Outline;
|
|
23
|
+
use crate::interchange::tagging::TagTree;
|
|
24
|
+
use crate::page::{Page, PageSettings};
|
|
25
|
+
#[cfg(feature = "pdf")]
|
|
26
|
+
use crate::pdf::PdfDocument;
|
|
27
|
+
use crate::serialize::{SerializeContext, SerializeSettings};
|
|
28
|
+
use crate::surface::Location;
|
|
29
|
+
|
|
30
|
+
/// A PDF document.
|
|
31
|
+
pub struct Document {
|
|
32
|
+
pub(crate) serializer_context: SerializeContext,
|
|
33
|
+
pub(crate) chunk_container: ChunkContainer,
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
impl Default for Document {
|
|
37
|
+
fn default() -> Self {
|
|
38
|
+
Self::new()
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
impl Document {
|
|
43
|
+
/// Create a new document with default serialize settings.
|
|
44
|
+
pub fn new() -> Self {
|
|
45
|
+
let serializer_context = SerializeContext::new(SerializeSettings::default());
|
|
46
|
+
let chunk_container = ChunkContainer::new(&serializer_context);
|
|
47
|
+
|
|
48
|
+
Self {
|
|
49
|
+
serializer_context,
|
|
50
|
+
chunk_container,
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/// Create a new document with custom serialize settings.
|
|
55
|
+
pub fn new_with(serialize_settings: SerializeSettings) -> Self {
|
|
56
|
+
let serializer_context = SerializeContext::new(serialize_settings);
|
|
57
|
+
let chunk_container = ChunkContainer::new(&serializer_context);
|
|
58
|
+
|
|
59
|
+
Self {
|
|
60
|
+
serializer_context,
|
|
61
|
+
chunk_container,
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/// Start a new page with default settings.
|
|
66
|
+
pub fn start_page(&mut self) -> Page<'_> {
|
|
67
|
+
let page_index = self.serializer_context.page_infos().iter().len();
|
|
68
|
+
Page::new(
|
|
69
|
+
&mut self.serializer_context,
|
|
70
|
+
&mut self.chunk_container,
|
|
71
|
+
page_index,
|
|
72
|
+
PageSettings::default(),
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/// Start a new page with specific page settings.
|
|
77
|
+
pub fn start_page_with(&mut self, page_settings: PageSettings) -> Page<'_> {
|
|
78
|
+
let page_index = self.serializer_context.page_infos().iter().len();
|
|
79
|
+
Page::new(
|
|
80
|
+
&mut self.serializer_context,
|
|
81
|
+
&mut self.chunk_container,
|
|
82
|
+
page_index,
|
|
83
|
+
page_settings,
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/// Embed the pages (0-indexed) from the given
|
|
88
|
+
/// PDF document.
|
|
89
|
+
#[cfg(feature = "pdf")]
|
|
90
|
+
pub fn embed_pdf_pages(&mut self, pdf: &PdfDocument, page_indices: &[usize]) {
|
|
91
|
+
self.serializer_context.embed_pdf_pages(pdf, page_indices);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/// Set the location that should be assumed for subsequent operations.
|
|
95
|
+
pub fn set_location(&mut self, location: Location) {
|
|
96
|
+
self.serializer_context.set_location(location);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/// Reset the location that should be assumed for subsequent operations.
|
|
100
|
+
pub fn reset_location(&mut self) {
|
|
101
|
+
self.serializer_context.reset_location();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/// Set the outline of the document.
|
|
105
|
+
pub fn set_outline(&mut self, outline: Outline) {
|
|
106
|
+
self.serializer_context.set_outline(outline);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/// Set the metadata of the document.
|
|
110
|
+
pub fn set_metadata(&mut self, metadata: Metadata) {
|
|
111
|
+
self.chunk_container.metadata = Some(metadata);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/// Set the tag tree of the document.
|
|
115
|
+
pub fn set_tag_tree(&mut self, tag_tree: TagTree) {
|
|
116
|
+
self.serializer_context.set_tag_tree(tag_tree);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/// Embed a new file in the PDF document.
|
|
120
|
+
///
|
|
121
|
+
/// Returns `None` if the file couldn't be embedded because a file
|
|
122
|
+
/// with the same name has already been embedded.
|
|
123
|
+
pub fn embed_file(&mut self, file: EmbeddedFile) -> Option<()> {
|
|
124
|
+
self.serializer_context
|
|
125
|
+
.embed_file(&mut self.chunk_container, file)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/// Manually register a global named destination.
|
|
129
|
+
///
|
|
130
|
+
/// Named destinations used in link annotations are automatically registered, so you don't need
|
|
131
|
+
/// to call this function for them.
|
|
132
|
+
///
|
|
133
|
+
/// Returns `None` if a named destination with the same name and a different destination has
|
|
134
|
+
/// already been registered, and therefore could not be registered again.
|
|
135
|
+
#[must_use]
|
|
136
|
+
pub fn register_named_destination(&mut self, dest: NamedDestination) -> Option<()> {
|
|
137
|
+
self.serializer_context
|
|
138
|
+
.register_named_destination(dest)
|
|
139
|
+
.map(|_| ())
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/// Attempt to export the document to a PDF file.
|
|
143
|
+
pub fn finish(mut self) -> KrillaResult<Vec<u8>> {
|
|
144
|
+
// Write empty page if none has been created yet.
|
|
145
|
+
if self.serializer_context.page_infos().is_empty() {
|
|
146
|
+
self.start_page();
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
let Self {
|
|
150
|
+
serializer_context,
|
|
151
|
+
chunk_container,
|
|
152
|
+
} = self;
|
|
153
|
+
|
|
154
|
+
Ok(serializer_context.finish(chunk_container)?.finish())
|
|
155
|
+
}
|
|
156
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
//! Error handling.
|
|
2
|
+
//!
|
|
3
|
+
//! There are a lot of things that can go wrong when writing a PDF, like for example when
|
|
4
|
+
//! invalid fonts are provided. This module provides the basic error types krilla uses.
|
|
5
|
+
|
|
6
|
+
use std::error::Error;
|
|
7
|
+
use std::fmt::{self, Display, Formatter};
|
|
8
|
+
use std::sync::Arc;
|
|
9
|
+
|
|
10
|
+
use crate::configure::{ValidationError, Validators};
|
|
11
|
+
#[cfg(feature = "raster-images")]
|
|
12
|
+
use crate::graphics::image::Image;
|
|
13
|
+
#[cfg(feature = "pdf")]
|
|
14
|
+
use crate::pdf::{PdfDocument, PdfError};
|
|
15
|
+
use crate::surface::Location;
|
|
16
|
+
use crate::tagging::TagId;
|
|
17
|
+
use crate::text::Font;
|
|
18
|
+
|
|
19
|
+
/// A wrapper type for krilla errors.
|
|
20
|
+
pub type KrillaResult<T> = Result<T, KrillaError>;
|
|
21
|
+
|
|
22
|
+
/// An error in krilla.
|
|
23
|
+
#[derive(Debug, PartialEq, Eq, Clone)]
|
|
24
|
+
pub enum KrillaError {
|
|
25
|
+
/// An error while attempting to embed a font.
|
|
26
|
+
Font(Font, String),
|
|
27
|
+
/// A list of validation errors. Can only occur if you set the `validator` in
|
|
28
|
+
/// the [`SerializeSettings`] to something else than the dummy validator.
|
|
29
|
+
///
|
|
30
|
+
/// [`SerializeSettings`]: crate::SerializeSettings
|
|
31
|
+
Validation(Vec<(ValidationError, Validators)>),
|
|
32
|
+
/// A hard limit of the selected PDF version was exceeded.
|
|
33
|
+
Limit(LimitError),
|
|
34
|
+
/// The same destination name has been associated with two different destinations,
|
|
35
|
+
/// which is prohibited.
|
|
36
|
+
DuplicateNamedDestination(Arc<String>),
|
|
37
|
+
/// A duplicate [`Tag::id`] was provided.
|
|
38
|
+
///
|
|
39
|
+
/// [`Tag::id`]: crate::interchange::tagging::Tag::id
|
|
40
|
+
DuplicateTagId(TagId, Option<Location>),
|
|
41
|
+
/// A [`TagId`] was not found in the [`TagTree`].
|
|
42
|
+
///
|
|
43
|
+
/// [`TagTree`]: crate::interchange::tagging::TagTree
|
|
44
|
+
UnknownTagId(TagId, Option<Location>),
|
|
45
|
+
/// An image couldn't be processed properly.
|
|
46
|
+
///
|
|
47
|
+
/// The third argument contains the error message.
|
|
48
|
+
#[cfg(feature = "raster-images")]
|
|
49
|
+
Image(Image, Option<Location>, String),
|
|
50
|
+
/// An embedded PDF document couldn't be processed properly.
|
|
51
|
+
#[cfg(feature = "pdf")]
|
|
52
|
+
Pdf(PdfDocument, PdfError, Option<Location>),
|
|
53
|
+
/// A sixteen bit image was used, even though it isn't
|
|
54
|
+
/// supported by the used PDF version (only available in PDF 1.5+).
|
|
55
|
+
#[cfg(feature = "raster-images")]
|
|
56
|
+
SixteenBitImage(Image, Option<Location>),
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
impl Display for KrillaError {
|
|
60
|
+
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
|
61
|
+
match self {
|
|
62
|
+
KrillaError::Font(_, message) => write!(f, "failed to embed font: {message}"),
|
|
63
|
+
KrillaError::Validation(errors) => {
|
|
64
|
+
let count = errors.len();
|
|
65
|
+
write!(
|
|
66
|
+
f,
|
|
67
|
+
"validation failed with {count} {}",
|
|
68
|
+
if count == 1 { "error" } else { "errors" }
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
KrillaError::Limit(error) => write!(f, "PDF version limit exceeded: {error}"),
|
|
72
|
+
KrillaError::DuplicateNamedDestination(name) => {
|
|
73
|
+
write!(f, "duplicate named destination: {name}")
|
|
74
|
+
}
|
|
75
|
+
KrillaError::DuplicateTagId(id, location) => {
|
|
76
|
+
write!(f, "duplicate tag id {id:?}")?;
|
|
77
|
+
write_location(f, *location)
|
|
78
|
+
}
|
|
79
|
+
KrillaError::UnknownTagId(id, location) => {
|
|
80
|
+
write!(f, "unknown tag id {id:?}")?;
|
|
81
|
+
write_location(f, *location)
|
|
82
|
+
}
|
|
83
|
+
#[cfg(feature = "raster-images")]
|
|
84
|
+
KrillaError::Image(_, location, message) => {
|
|
85
|
+
write!(f, "failed to process image")?;
|
|
86
|
+
write_location(f, *location)?;
|
|
87
|
+
write!(f, ": {message}")
|
|
88
|
+
}
|
|
89
|
+
#[cfg(feature = "pdf")]
|
|
90
|
+
KrillaError::Pdf(_, error, location) => {
|
|
91
|
+
write!(f, "failed to process embedded PDF")?;
|
|
92
|
+
write_location(f, *location)?;
|
|
93
|
+
write!(f, ": {error}")
|
|
94
|
+
}
|
|
95
|
+
#[cfg(feature = "raster-images")]
|
|
96
|
+
KrillaError::SixteenBitImage(_, location) => {
|
|
97
|
+
write!(
|
|
98
|
+
f,
|
|
99
|
+
"sixteen bit images require PDF 1.5 or newer, but the selected PDF version does not support them"
|
|
100
|
+
)?;
|
|
101
|
+
write_location(f, *location)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
impl Error for KrillaError {
|
|
108
|
+
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
|
109
|
+
match self {
|
|
110
|
+
KrillaError::Limit(error) => Some(error),
|
|
111
|
+
#[cfg(feature = "pdf")]
|
|
112
|
+
KrillaError::Pdf(_, error, _) => Some(error),
|
|
113
|
+
_ => None,
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/// A limit imposed by the selected PDF version.
|
|
119
|
+
#[derive(Debug, PartialEq, Eq, Clone)]
|
|
120
|
+
pub enum LimitError {
|
|
121
|
+
/// A float exceeded the maximum allowed size for the PDF version.
|
|
122
|
+
TooLargeFloat,
|
|
123
|
+
/// An array exceeded the maximum allowed length for the PDF version.
|
|
124
|
+
TooLongArray,
|
|
125
|
+
/// A dictionary exceeded the maximum allowed number of entries for the PDF version.
|
|
126
|
+
TooLongDictionary,
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
impl Display for LimitError {
|
|
130
|
+
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
|
131
|
+
match self {
|
|
132
|
+
LimitError::TooLargeFloat => write!(f, "a float exceeded the maximum allowed size"),
|
|
133
|
+
LimitError::TooLongArray => write!(f, "an array exceeded the maximum allowed length"),
|
|
134
|
+
LimitError::TooLongDictionary => {
|
|
135
|
+
write!(
|
|
136
|
+
f,
|
|
137
|
+
"a dictionary exceeded the maximum allowed number of entries"
|
|
138
|
+
)
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
impl Error for LimitError {}
|
|
145
|
+
|
|
146
|
+
fn write_location(f: &mut Formatter<'_>, location: Option<Location>) -> fmt::Result {
|
|
147
|
+
if let Some(location) = location {
|
|
148
|
+
write!(f, " at location {location}")
|
|
149
|
+
} else {
|
|
150
|
+
Ok(())
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
#[cfg(test)]
|
|
155
|
+
mod tests {
|
|
156
|
+
use std::error::Error as _;
|
|
157
|
+
|
|
158
|
+
use super::{KrillaError, LimitError};
|
|
159
|
+
|
|
160
|
+
#[test]
|
|
161
|
+
fn krilla_error_implements_error() {
|
|
162
|
+
let error = KrillaError::Limit(LimitError::TooLongArray);
|
|
163
|
+
|
|
164
|
+
assert_eq!(
|
|
165
|
+
error.to_string(),
|
|
166
|
+
"PDF version limit exceeded: an array exceeded the maximum allowed length"
|
|
167
|
+
);
|
|
168
|
+
assert!(error.source().is_some());
|
|
169
|
+
}
|
|
170
|
+
}
|