7 releases
0.2.0 | Nov 30, 2023 |
---|---|
0.1.22 | Apr 29, 2021 |
0.1.21 | Jan 28, 2021 |
0.1.20 | Aug 23, 2020 |
0.1.15 | Jun 10, 2017 |
#188 in #pdf
16,746 downloads per month
Used in 14 crates
(via pdf)
32KB
629 lines
pdf_derive
provides a proc macro to derive the Object trait from the pdf
crate.
Usage
There are several ways to derive Object on a struct or enum:
1. Struct from PDF Dictionary
A lot of dictionary types defined in the PDF 1.7 reference have a finite amount of possible
fields. Each of these are usually either required or optional. The latter is achieved by using
a Option<T>
or Vec<T>
as type of a field.
Usually, dictionary types
require that the entry /Type
is some specific string. By default, pdf_derive
assumes that
this should equal the name of the input struct. This can be overridden by setting the Type
attribute equal to either the expected value of the /Type
entry, or to false
in order to
omit the type check completly.
Check similar to that of /Type
can also be specified in the same manner. (but the Type
attribute is special because it accepts a bool).
Examples:
#[derive(Object)]
#[pdf(Type="XObject", Subtype="Image")]
/// A variant of XObject
pub struct ImageDictionary {
#[pdf(key="Width")]
width: i32,
#[pdf(key="Height")]
height: i32,
// [...]
}
This enforces that the dictionary's /Type
entry is present and equals /XObject
, and that the
/Subtype
entry is present and equals /Image
.
Each field in the struct needs to implement Object
. Implementation is provided already for
common types like i32, f32, usize, bool, String (from Primitive::Name), Option and Vec.
The two latter are initialized to default if the entry isn't found in the input dictionary.
Option is therefore frequently used for fields that are optional according to the PDF
reference. Vec can also be used for optional fields that can also be arrays (there are quite
a few of those in the PDF specs - one or many). However, as stated, it accepts absense of the
entry, so required fields of type array aren't yet facilitated for.
Lastly, for each field, it's possible to define a default value by setting the default
attribute to a string that can parse as Rust code.
Example:
#[derive(Object)]
#[pdf(Type = "XRef")]
pub struct XRefInfo {
#[pdf(key = "Filter")]
filter: Vec<StreamFilter>,
#[pdf(key = "Size")]
pub size: i32,
#[pdf(key = "Index", default = "vec![0, size]")]
pub index: Vec<i32>,
// [...]
}
2. Struct from PDF Stream
PDF Streams consist of a stream dictionary along with the stream itself. It is assumed that all
structs that want to derive Object where the primitive it converts from is a stream,
have a field info: T
, where T: Object
, and a field data: Vec<u8>
.
Deriving an Object that converts from Primitive::Stream, the flag is_stream
is required in
the proc macro attributes.
3. Enum from PDF Name
Example:
#[derive(Object, Debug)]
pub enum StreamFilter {
ASCIIHexDecode,
ASCII85Decode,
LZWDecode,
FlateDecode,
JPXDecode,
DCTDecode,
}
In this case, StreamFilter::from_primitive(primitive)
will return Ok(_) only if the primitive
is Primitive::Name
and matches one of the enum variants
Dependencies
~1.5MB
~37K SLoC