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