mupdf_sys/
lib.rs

1#![allow(non_upper_case_globals)]
2#![allow(non_camel_case_types)]
3#![allow(non_snake_case)]
4#![allow(clippy::all)]
5
6include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
7
8use core::ffi::{c_int, CStr};
9
10/// This function allocates a new device and returns a pointer to it if no error occured. For the
11/// required structure of `T` check the example below. If an error occurs the pointer `errptr` points
12/// to will be set to to a pointer pointing to the error and null returned from this function.
13///
14/// # Safety
15///
16/// The caller must ensure `ctx` and `errptr` to be a valid pointers.
17///
18/// It must also ensure `T` to be a type that starts with `fz_device`. Memory will be allocated for
19/// a new instance of `T`, but only the `fz_device` portion will be initialized. The rest is
20/// currently being zero-initialized, but this might change in the future.
21///
22/// # Example
23///
24/// This is how a compliant `T` might look like. The `repr(C)` is necessary as `repr(Rust)` does
25/// not guarantee stable field orderings.
26///
27/// ```rust
28/// use mupdf_sys::fz_device;
29///
30/// #[repr(C)]
31/// struct MyDevice {
32///     base: fz_device,
33///     foo: u32,
34/// }
35/// ```
36pub unsafe fn mupdf_new_derived_device<T>(
37    ctx: *mut fz_context,
38    label: &'static CStr,
39    errptr: *mut *mut mupdf_error_t,
40) -> *mut T {
41    let SIZE: c_int = const {
42        if (c_int::MAX as usize) < size_of::<T>() {
43            panic!("device too big")
44        } else {
45            size_of::<T>() as c_int
46        }
47    };
48
49    let device = mupdf_new_device_of_size(ctx, SIZE, errptr);
50    let label = Memento_label(device.cast(), label.as_ptr());
51    label.cast()
52}