Модификация pdf с помощью Rust и pdfium

Я новичок в ржавчине. Для своего первого нетривиального проекта я хочу взять 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-файл так, как я хочу.

Я прочитал документацию о владении, заимствовании и т. д. и с удовольствием прочту больше документации, если кто-нибудь укажет мне на хороший ресурс, который позволит мне понять, почему мой код не работает.

Вы неверно истолковали ошибки, вы можете использовать page.objects() для получения неизменяемых объектов, но это не решает проблему, которая annotations_mut требует монопольного доступа к PdfPage.

cafce25 30.05.2024 16:39

Как бы то ни было, библиотека не очень идиоматическая Rust, если вы используете ее для изучения Rust, я бы посоветовал вам переключиться на другую библиотеку. Или, по крайней мере, постарайтесь не привыкать к именованию итераторов из него.

cafce25 30.05.2024 16:49
Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
0
2
110
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это проблема с библиотекой, которую вы используете: вы не можете одновременно заимствовать 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()).

Другие вопросы по теме