import_pages/
import_pages.rs

1// PDFium-rs -- Modern Rust interface to PDFium, the PDF library from Google
2//
3// Copyright (c) 2025 Martin van der Werff <github (at) newinnovations.nl>
4//
5// This file is part of PDFium-rs.
6//
7// PDFium-rs is free software: you can redistribute it and/or modify it under the terms of
8// the GNU General Public License as published by the Free Software Foundation, either version 3
9// of the License, or (at your option) any later version.
10//
11// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
12// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
13// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
14// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
15// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
16// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
17// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
18// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19
20// Import all necessary items from the pdfium crate
21// This gives us access to PdfiumDocument and related functionality
22use pdfium::*;
23
24/// Demonstrates importing PDF pages using string-based page specification.
25///
26/// This function shows how to:
27/// - Create a new empty PDF document
28/// - Load an existing PDF file as a source
29/// - Import specific pages using a human-readable string format
30/// - Save the resulting document to disk
31/// - Verify the operation was successful
32///
33/// The string format supports:
34/// - Individual pages: "5" (imports page 5)
35/// - Multiple pages: "1,3,7" (imports pages 1, 3, and 7)
36/// - Page ranges: "10-15" (imports pages 10 through 15 inclusive)
37/// - Mixed format: "1,5-8,12" (imports page 1, pages 5-8, and page 12)
38///
39/// Note: Page numbers in the string are 1-based (human-readable format)
40pub fn example_import_pages() -> PdfiumResult<()> {
41    // Create a new, empty PDF document that will serve as our destination
42    // This document starts with 0 pages and we'll add pages to it
43    let document = PdfiumDocument::new()?;
44
45    // Load the source PDF document from which we'll extract pages
46    // The second parameter (None) means we're not providing a password
47    let src_doc = PdfiumDocument::new_from_path("resources/pg1342-images-3.pdf", None)?;
48
49    // Import specific pages from the source document into our destination document
50    // Parameters breakdown:
51    // - &src_doc: Reference to the source document to import from
52    // - "12,14,30-34": String specifying which pages to import
53    //   * Page 12 (individual page)
54    //   * Page 14 (individual page)
55    //   * Pages 30-34 (range of 5 pages: 30, 31, 32, 33, 34)
56    //   * Total: 7 pages will be imported
57    // - 0: Index position where imported pages should be inserted
58    //   * 0 means insert at the beginning of the destination document
59    //   * If the destination had existing pages, imported pages would be inserted before them
60    document.pages().import(&src_doc, "12,14,30-34", 0)?;
61
62    // Save the destination document with imported pages to a new file
63    // The second parameter (None) indicates we're not specifying a version
64    document.save_to_path("pride-1.pdf", None)?;
65
66    // Verification step: reload the saved document to confirm the operation
67    let document = PdfiumDocument::new_from_path("pride-1.pdf", None)?;
68
69    // Get the total number of pages in the saved document
70    let page_count = document.page_count();
71
72    // Assert that we have exactly 7 pages as expected
73    // This confirms that all specified pages were imported correctly:
74    // 1 page (12) + 1 page (14) + 5 pages (30-34) = 7 pages total
75    assert_eq!(page_count, 7);
76
77    Ok(())
78}
79
80/// Demonstrates importing PDF pages using index-based page specification.
81///
82/// This function shows an alternative approach to page importing using
83/// explicit page indices rather than string specifications. This method
84/// provides more programmatic control and is useful when:
85/// - You have a dynamically generated list of page numbers
86/// - You need to import non-contiguous pages with complex patterns
87/// - You're working with 0-based indexing in your application logic
88///
89/// Key differences from string-based approach:
90/// - Uses 0-based indexing (first page is index 0)
91/// - Requires explicit specification of each page index
92/// - More verbose but offers precise control
93/// - Better for programmatic generation of page lists
94pub fn example_import_pages_by_index() -> PdfiumResult<()> {
95    // Create a new, empty PDF document to serve as our destination
96    let document = PdfiumDocument::new()?;
97
98    // Load the same source PDF document as in the previous example
99    // We're extracting the same pages but using a different method
100    let src_doc = PdfiumDocument::new_from_path("resources/pg1342-images-3.pdf", None)?;
101
102    // Import pages using explicit 0-based indices
103    // Parameters breakdown:
104    // - &src_doc: Reference to the source document
105    // - Some(&[11, 13, 29, 30, 31, 32, 33]): Vector of 0-based page indices
106    //   * Index 11 = Page 12 in human numbering (11 + 1 = 12)
107    //   * Index 13 = Page 14 in human numbering (13 + 1 = 14)
108    //   * Indices 29-33 = Pages 30-34 in human numbering
109    //   * Note: This matches exactly the same pages as "12,14,30-34" from the previous example
110    //   * The Some() wrapper indicates we're providing a specific list of indices
111    //   * Using None instead would import all pages from the source document
112    // - 0: Insertion position (beginning of destination document)
113    document
114        .pages()
115        .import_by_index(&src_doc, Some(&[11, 13, 29, 30, 31, 32, 33]), 0)?;
116
117    // Save the document with a different filename to distinguish from the first example
118    // Even though the content should be identical, using different names helps with testing
119    document.save_to_path("pride-2.pdf", None)?;
120
121    // Verification: reload the saved document to ensure it was created correctly
122    let document = PdfiumDocument::new_from_path("pride-2.pdf", None)?;
123
124    // Count the pages in the saved document
125    let page_count = document.page_count();
126
127    // Verify that we have the same 7 pages as the string-based method
128    // This confirms both methods produce identical results:
129    // - 1 page at index 11 (page 12)
130    // - 1 page at index 13 (page 14)
131    // - 5 pages at indices 29-33 (pages 30-34)
132    // Total: 7 pages
133    assert_eq!(page_count, 7);
134
135    Ok(())
136}
137
138fn main() -> PdfiumResult<()> {
139    example_import_pages()?;
140    example_import_pages_by_index()?;
141    Ok(())
142}