Iterate over every annotation on every page. Read annotation type, author, contents, bounding box, colour, and creation date.
use pdfluent::PdfDocument;
fn main() -> pdfluent::Result<()> {
let doc = PdfDocument::open("reviewed.pdf")?;
for page in 0..doc.page_count() {
for a in doc.annotations(page)? {
println!("{}: {:?}", a.subtype, a.contents);
}
}
Ok(())
}Add the pdfluent crate to Cargo.toml.
[dependencies]
pdfluent = "1.0.0-beta.8"Open the file as a read-only document. You do not need a mutable reference just to read annotations.
use pdfluent::PdfDocument;
let doc = PdfDocument::open("reviewed_contract.pdf")?;Call annotations() on each page to get a slice of Annotation objects. Each object exposes its type, position, and metadata.
for page_idx in 0..doc.page_count() {
let annotations = doc.annotations(page_idx)?;
println!("Page {} has {} annotations", page_idx + 1, annotations.len());
for ann in &annotations {
println!(" Type: {}", ann.subtype);
println!(" Rect: {:?}", ann.rect);
println!(" Contents: {:?}", ann.contents);
}
}Use annotation_type() to select only the types you care about. AnnotationType is an enum with variants for each standard PDF annotation type.
for page_idx in 0..doc.page_count() {
for ann in doc.annotations(page_idx)? {
if ann.subtype == "Highlight" {
println!("Highlight at {:?}: {}", ann.rect, ann.contents.unwrap_or_default());
}
}
}Collect all annotations into a serialisable struct. This is useful for syncing review comments to an external system.
// AnnotationInfo exposes: subtype, rect (Option<[f64;4]>), contents (Option<String>)
let mut records = Vec::new();
for page_idx in 0..doc.page_count() {
for ann in doc.annotations(page_idx)? {
records.push(format!(
"{{\"page\":{},\"type\":\"{}\",\"contents\":{:?}}}",
page_idx + 1, ann.subtype, ann.contents.unwrap_or_default()
));
}
}
println!("[{}]", records.join(","));No JVM, no runtime, no DLL dependencies. Ships as a single native binary or WASM module.
Rust's ownership model prevents buffer overflows and use-after-free. No segfaults in PDF parsing.
Same code runs server-side, in Docker, on AWS Lambda, on Cloudflare Workers, or in the browser via WASM.