Reputation: 147
I am very new to rust. For my first non-trivial project I want to take a pdf and underline every word in it with a red squiggly line. I am using the pdfium-render library for that. Here's my attempt:
use pdfium_render::prelude::*;
fn main() -> Result<(), PdfiumError> {
let pdfium = Pdfium::default();
let mut document = pdfium.load_pdf_from_file("test/pdf-in.pdf", None)?;
for (page_index, mut page) in document.pages_mut().iter().enumerate() {
println!("=============== Page {} ===============", page_index);
for object in page.objects_mut().iter() {
// The following line gives the error:
// "cannot borrow `page` as mutable more than once at a time"
let annotations = page.annotations_mut();
annotations.create_squiggly_annotation_under_object(
&object,
PdfColor::DARK_RED,
Some("This is a squiggly annotation"),
)?;
}
}
document.save_to_file("test/pdf-out.pdf")
}
This code does not compile and the error the compiler gives me is the following:
error[E0499]: cannot borrow `page` as mutable more than once at a time
--> src/main.rs:9:31
|
8 | for object in page.objects_mut().iter() {
| -------------------------
| |
| first mutable borrow occurs here
| first borrow later used here
9 | let annotations = page.annotations_mut();
| ^^^^ second mutable borrow occurs here
I understand I am not supposed to borrow mutable things twice but I can't figure out how to avoid that as I need to loop through every object and that requires a mutable borrow.
I tried different variations of this code, but the compiler won't let me do page.objects()
because apparently that would borrow page as immutable and I need it mutable afterwards.
I am also not sure that the way I am creating the annotation is correct, but I cannot test it as I can't compile. Most of the code is coming from pdfium's example github page, although none of the examples describe how to edit a pdf the way I want.
I've read the docs about ownership and borrowing etc. and I will gladly read more docs if someone could point me to a good resource that would let me understand why my code is not working.
Upvotes: 0
Views: 441
Reputation: 27558
This is an issue with the library you're using, you can't simultaneously borrow objects
and mutably borrow annotations
because both are only accessible with accessors which borrow the whole PdfPage
. Fortunately create_squiggly_annotation_under_object
only requires the bounds of the PdfPageObject
and it doesn't have to be an object on the actual PdfPage
so you can just create duplicates by iterating over the document.pages().iter()
twice:
use pdfium_render::prelude::*;
fn main() -> Result<(), PdfiumError> {
let pdfium = Pdfium::default();
let document = pdfium.load_pdf_from_file("foo.pdf", None)?;
for (page_immut, mut page) in document.pages().iter().zip(document.pages().iter()) {
for object in page_immut.objects().iter() {
page.annotations_mut()
.create_squiggly_annotation_under_object(
&object,
PdfColor::DARK_RED,
Some("this is a squiggly annotation"),
)?;
}
}
document.save_to_file("output.pdf")
}
Note: I've removed mut
wherever they were not necessary (on document
, pages()
, objects()
)
Upvotes: 2