```rust title="Rust"
use kreuzberg::plugins::{Plugin, PostProcessor, ProcessingStage, register_post_processor};
use kreuzberg::{Result, ExtractionResult, ExtractionConfig};
use async_trait::async_trait;
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use serde_json::json;

struct PdfMetadataExtractor {
    processed_count: AtomicUsize,
}

impl Plugin for PdfMetadataExtractor {
    fn name(&self) -> &str { "pdf-metadata-extractor" }
    fn version(&self) -> String { "1.0.0".to_string() }
    fn initialize(&self) -> Result<()> {
        self.processed_count.store(0, Ordering::Release);
        Ok(())
    }
    fn shutdown(&self) -> Result<()> { Ok(()) }
}

#[async_trait]
impl PostProcessor for PdfMetadataExtractor {
    async fn process(
        &self,
        result: &mut ExtractionResult,
        _config: &ExtractionConfig,
    ) -> Result<()> {
        if result.mime_type != "application/pdf" {
            return Ok(());
        }

        let order = self.processed_count.fetch_add(1, Ordering::AcqRel) + 1;

        result.metadata.additional.insert("pdf_processed".to_string(), json!(true));
        result.metadata.additional.insert("pdf_order".to_string(), json!(order));
        result.metadata.additional.insert(
            "content_length".to_string(),
            json!(result.content.len()),
        );
        result.metadata.additional.insert(
            "pdf_processor_version".to_string(),
            json!("1.0.0"),
        );

        Ok(())
    }

    fn processing_stage(&self) -> ProcessingStage {
        ProcessingStage::Early
    }

    fn should_process(
        &self,
        result: &ExtractionResult,
        _config: &ExtractionConfig,
    ) -> bool {
        result.mime_type == "application/pdf"
    }
}

fn main() -> Result<()> {
    register_post_processor(Arc::new(PdfMetadataExtractor {
        processed_count: AtomicUsize::new(0),
    }))?;
    Ok(())
}
```
