micropdf 0.17.0

A pure Rust PDF library - A pure Rust PDF library with fz_/pdf_ API compatibility
//! PDF Object Reference Counting FFI Functions

use super::super::Handle;
use super::types::{PDF_OBJECTS, PdfObj, PdfObjHandle};

#[unsafe(no_mangle)]
pub extern "C" fn pdf_keep_obj(_ctx: Handle, obj: PdfObjHandle) -> PdfObjHandle {
    if let Some(arc) = PDF_OBJECTS.get(obj) {
        if let Ok(mut guard) = arc.lock() {
            guard.refs += 1;
        }
    }
    obj
}

#[unsafe(no_mangle)]
pub extern "C" fn pdf_drop_obj(_ctx: Handle, obj: PdfObjHandle) {
    if let Some(arc) = PDF_OBJECTS.get(obj) {
        let should_remove = {
            if let Ok(mut guard) = arc.lock() {
                guard.refs -= 1;
                guard.refs <= 0
            } else {
                false
            }
        };
        if should_remove {
            PDF_OBJECTS.remove(obj);
        }
    }
}

// Helper functions for accessing objects
pub(super) fn with_obj<T, F: FnOnce(&PdfObj) -> T>(obj: PdfObjHandle, default: T, f: F) -> T {
    PDF_OBJECTS
        .get(obj)
        .and_then(|arc| arc.lock().ok().map(|guard| f(&guard)))
        .unwrap_or(default)
}

pub(super) fn with_obj_mut<T, F: FnOnce(&mut PdfObj) -> T>(
    obj: PdfObjHandle,
    default: T,
    f: F,
) -> T {
    PDF_OBJECTS
        .get(obj)
        .and_then(|arc| arc.lock().ok().map(|mut guard| f(&mut guard)))
        .unwrap_or(default)
}

#[cfg(test)]
mod tests {
    use super::super::create::pdf_new_int;
    use super::super::marking::pdf_obj_refs;
    use super::*;

    #[test]
    fn test_pdf_keep_obj() {
        let obj = pdf_new_int(0, 42);
        let kept = pdf_keep_obj(0, obj);
        assert_eq!(kept, obj);
        assert_eq!(pdf_obj_refs(0, obj), 2);
        pdf_drop_obj(0, obj);
        pdf_drop_obj(0, obj);
    }

    #[test]
    fn test_pdf_drop_obj() {
        let obj = pdf_new_int(0, 99);
        pdf_drop_obj(0, obj);
    }

    #[test]
    fn test_pdf_keep_drop_invalid() {
        let result = pdf_keep_obj(0, 99999);
        assert_eq!(result, 99999);
        pdf_drop_obj(0, 99999);
    }
}