ffizz_string/
macros.rs

1/// Re-export a `fz_string_t` utility function in your own crate.
2///
3/// For each utility function, this can be written either as
4///
5/// ```ignore
6/// ffizz_string::reexport!(fz_string_free);
7/// ```
8/// or, to rename the function,
9/// ```ignore
10/// ffizz_string::reexport!(fz_string_free as my_crate_string_free);
11/// ```
12///
13/// It is still up to you to include project-specific documentation and declaration, typically
14/// using `#ffizz_header::snippet!`, due to limitations in the Rust parser around docstrings and
15/// macros. For example:
16///
17/// ```ignore
18/// ffizz_snippet!{
19///     #[ffizz(name="my_crate_string_free")]
20///     /// Free a string ...
21///     /// ```c
22///     /// EXTERN_C void my_crate_string_free(*my_crate_string);
23///     /// ```
24/// }
25/// ffizz_string::reexport!(fz_string_free as my_crate_string_free);
26/// ```
27#[macro_export]
28macro_rules! reexport(
29    // all functions in src/string/utilfns.rs should be reflected here.
30    { fz_string_borrow } => { reexport!(fz_string_borrow as fz_string_borrow); };
31    { fz_string_borrow as $name:ident } => {
32        #[no_mangle]
33        #[allow(unsafe_op_in_unsafe_fn)]
34        pub unsafe extern "C" fn $name(cstr: *const $crate::c_char) -> $crate::fz_string_t {
35            $crate::fz_string_borrow(cstr)
36        }
37    };
38    { fz_string_null } => { reexport!(fz_string_null as fz_string_null); };
39    { fz_string_null as $name:ident } => {
40        #[no_mangle]
41        #[allow(unsafe_op_in_unsafe_fn)]
42        pub unsafe extern "C" fn $name() -> $crate::fz_string_t {
43            $crate::fz_string_null()
44        }
45    };
46    { fz_string_clone } => { reexport!(fz_string_clone as fz_string_clone); };
47    { fz_string_clone as $name:ident } => {
48        #[no_mangle]
49        #[allow(unsafe_op_in_unsafe_fn)]
50        pub unsafe extern "C" fn $name(cstr: *const $crate::c_char) -> $crate::fz_string_t {
51            $crate::fz_string_clone(cstr)
52        }
53    };
54    { fz_string_clone_with_len } => { reexport!(fz_string_clone_with_len as fz_string_clone_with_len); };
55    { fz_string_clone_with_len as $name:ident } => {
56        #[no_mangle]
57        #[allow(unsafe_op_in_unsafe_fn)]
58        pub unsafe extern "C" fn $name(cstr: *const $crate::c_char, len: usize) -> $crate::fz_string_t {
59            $crate::fz_string_clone_with_len(cstr, len)
60        }
61    };
62    { fz_string_content } => { reexport!(fz_string_content as fz_string_content); };
63    { fz_string_content as $name:ident } => {
64        #[no_mangle]
65        #[allow(unsafe_op_in_unsafe_fn)]
66        pub unsafe extern "C" fn $name(fzstr: *mut $crate::fz_string_t) -> *const $crate::c_char {
67            $crate::fz_string_content(fzstr)
68        }
69    };
70    { fz_string_content_with_len } => { reexport!(fz_string_content_with_len as fz_string_content_with_len); };
71    { fz_string_content_with_len as $name:ident } => {
72        #[no_mangle]
73        #[allow(unsafe_op_in_unsafe_fn)]
74        pub unsafe extern "C" fn $name(fzstr: *mut $crate::fz_string_t, len_out: *mut usize) -> *const $crate::c_char {
75            $crate::fz_string_content_with_len(fzstr, len_out)
76        }
77    };
78    { fz_string_is_null } => { reexport!(fz_string_is_null as fz_string_is_null); };
79    { fz_string_is_null as $name:ident } => {
80        #[no_mangle]
81        #[allow(unsafe_op_in_unsafe_fn)]
82        pub unsafe extern "C" fn $name(fzstr: *const $crate::fz_string_t) -> bool {
83            $crate::fz_string_is_null(fzstr)
84        }
85    };
86    { fz_string_free } => { reexport!(fz_string_free as fz_string_free); };
87    { fz_string_free as $name:ident } => {
88        #[no_mangle]
89        #[allow(unsafe_op_in_unsafe_fn)]
90        pub unsafe extern "C" fn $name(fzstr: *mut $crate::fz_string_t) {
91            $crate::fz_string_free(fzstr)
92        }
93    };
94);
95
96#[cfg(test)]
97mod test {
98    use std::mem::MaybeUninit;
99
100    reexport!(fz_string_borrow);
101    reexport!(fz_string_null);
102    reexport!(fz_string_clone);
103    reexport!(fz_string_clone_with_len);
104    reexport!(fz_string_content);
105    reexport!(fz_string_content_with_len);
106    reexport!(fz_string_is_null as is_null);
107    reexport!(fz_string_free as free_willy);
108
109    #[test]
110    fn test() {
111        // This doesn't test all of the variants, as they are formulaic and the macro invocations
112        // above will catch any differences in the function signatures.
113
114        // SAFETY: we will free this value eventually
115        let mut s = MaybeUninit::new(unsafe { fz_string_null() });
116        // SAFETY: s contains a valid fz_string_t.
117        assert!(unsafe { is_null(s.as_ptr()) });
118        // SAFETY: s contains a valid fz_string_t. It is uninitialized
119        // after this call and not used again.
120        unsafe { free_willy(s.as_mut_ptr()) }
121    }
122}