use std::cell::RefCell;
use std::ffi::{CString, c_char, c_int};
thread_local! {
static LAST_ERROR: RefCell<(i32, String)> = const { RefCell::new((0, String::new())) };
static LAST_ERROR_CSTRING: RefCell<CString> = RefCell::new(CString::new("").unwrap());
}
pub(crate) fn set_error(code: i32, msg: &str) {
LAST_ERROR.with(|e| *e.borrow_mut() = (code, msg.to_owned()));
}
pub(crate) fn clear_error() {
LAST_ERROR.with(|e| *e.borrow_mut() = (0, String::new()));
}
#[unsafe(no_mangle)]
pub extern "C" fn cpdf_lastError() -> c_int {
LAST_ERROR.with(|e| e.borrow().0)
}
#[unsafe(no_mangle)]
pub extern "C" fn cpdf_lastErrorString() -> *const c_char {
LAST_ERROR.with(|e| {
let msg = e.borrow().1.clone();
let cs = CString::new(msg).unwrap_or_else(|_| CString::new("").unwrap());
LAST_ERROR_CSTRING.with(|slot| {
*slot.borrow_mut() = cs;
slot.borrow().as_ptr()
})
})
}
#[unsafe(no_mangle)]
pub extern "C" fn cpdf_clearError() {
clear_error();
}
pub mod annotations;
pub mod attachments;
pub mod bookmarks;
pub mod compression;
pub mod document;
pub mod encryption;
pub mod fonts;
pub mod images;
pub mod metadata;
pub mod ocg;
pub mod page_labels;
pub mod pages;
pub mod stamps;
pub mod text;
pub use document::CPDF_DOCS;
#[cfg(test)]
mod tests {
use super::*;
use std::ffi::CStr;
#[test]
fn test_cpdf_last_error_default() {
cpdf_clearError();
assert_eq!(cpdf_lastError(), 0);
}
#[test]
fn test_cpdf_last_error_string_default() {
cpdf_clearError();
let ptr = cpdf_lastErrorString();
assert!(!ptr.is_null());
let s = unsafe { CStr::from_ptr(ptr).to_str().unwrap() };
assert!(s.is_empty());
}
#[test]
fn test_cpdf_error_from_invalid_handle() {
cpdf_clearError();
let _ = super::bookmarks::cpdf_getBookmarksJSON(0, std::ptr::null_mut());
assert_ne!(cpdf_lastError(), 0);
let ptr = cpdf_lastErrorString();
assert!(!ptr.is_null());
let s = unsafe { CStr::from_ptr(ptr).to_str().unwrap() };
assert!(!s.is_empty());
cpdf_clearError();
assert_eq!(cpdf_lastError(), 0);
}
}