Я новичок в ржавчине. Для своего первого нетривиального проекта я хочу взять PDF-файл и подчеркнуть в нем каждое слово красной волнистой линией. Для этого я использую библиотеку pdfium-render. Вот моя попытка:
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")
}
Этот код не компилируется, и компилятор выдает следующую ошибку:
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
Я понимаю, что мне не следует заимствовать изменяемые объекты дважды, но я не могу понять, как этого избежать, поскольку мне нужно перебирать каждый объект, а для этого требуется изменяемое заимствование.
Я пробовал разные варианты этого кода, но компилятор не позволил мне это сделать page.objects(), потому что, очевидно, это заимствовало бы страницу как неизменяемую, а потом мне нужно, чтобы она была изменяемой.
Я также не уверен, что способ создания аннотации правильный, но я не могу проверить ее, так как не могу скомпилировать. Большая часть кода взята со страницы примера pdfium на GitHub, хотя ни один из примеров не описывает, как редактировать PDF-файл так, как я хочу.
Я прочитал документацию о владении, заимствовании и т. д. и с удовольствием прочту больше документации, если кто-нибудь укажет мне на хороший ресурс, который позволит мне понять, почему мой код не работает.
Как бы то ни было, библиотека не очень идиоматическая Rust, если вы используете ее для изучения Rust, я бы посоветовал вам переключиться на другую библиотеку. Или, по крайней мере, постарайтесь не привыкать к именованию итераторов из него.

Это проблема с библиотекой, которую вы используете: вы не можете одновременно заимствовать objects и изменять annotations, потому что оба доступны только с помощью аксессоров, которые заимствуют всю PdfPage. К счастью, create_squiggly_annotation_under_object требует только границ PdfPageObject, и это не обязательно должен быть объект на самом PdfPage, поэтому вы можете просто создавать дубликаты, дважды перебирая document.pages().iter():
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")
}
Примечание. Я удалил mut там, где они не были нужны (на document, pages(), objects()).
Вы неверно истолковали ошибки, вы можете использовать
page.objects()для получения неизменяемых объектов, но это не решает проблему, котораяannotations_mutтребует монопольного доступа кPdfPage.