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

#1465 in Procedural macros

Download history 1498/week @ 2023-10-20 1407/week @ 2023-10-27 1219/week @ 2023-11-03 1288/week @ 2023-11-10 1480/week @ 2023-11-17 1217/week @ 2023-11-24 1911/week @ 2023-12-01 1089/week @ 2023-12-08 1817/week @ 2023-12-15 1518/week @ 2023-12-22 1195/week @ 2023-12-29 1692/week @ 2024-01-05 1763/week @ 2024-01-12 1528/week @ 2024-01-19 1401/week @ 2024-01-26 1240/week @ 2024-02-02

6,287 downloads per month
Used in 17 crates (via pdf)

MIT license

629 lines

pdf_derive provides a proc macro to derive the Object trait from the pdf crate.


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).


#[pdf(Type="XObject", Subtype="Image")]
/// A variant of XObject
pub struct ImageDictionary {
    width: i32,
    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.


#[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


#[derive(Object, Debug)]
pub enum StreamFilter {

In this case, StreamFilter::from_primitive(primitive) will return Ok(_) only if the primitive is Primitive::Name and matches one of the enum variants


~32K SLoC