rustler_sys/
rustler_sys_api.rs

1#![allow(clippy::missing_safety_doc)]
2#![allow(clippy::upper_case_acronyms)]
3
4#[cfg(windows)]
5use unreachable::UncheckedOptionExt; // unchecked unwrap used in generated Windows code
6
7pub use std::ffi::{c_char, c_double, c_int, c_long, c_uchar, c_uint, c_ulong, c_void};
8
9use std::os;
10
11#[allow(non_camel_case_types)]
12pub type size_t = usize;
13
14//use std::mem::size_of;
15
16#[allow(non_camel_case_types)]
17pub type ERL_NIF_UINT = size_t;
18
19#[allow(non_camel_case_types)]
20pub type ERL_NIF_TERM = ERL_NIF_UINT;
21
22//#[derive(Debug, Copy, Clone)]
23//#[repr(C)]
24//pub struct ERL_NIF_TERM(ERL_NIF_UINT);  // Don't do this, 32 bit calling convention is different for structs and ints.
25
26/// See [ErlNifEnv](http://www.erlang.org/doc/man/erl_nif.html#ErlNifEnv) in the Erlang docs.
27#[derive(Debug)]
28#[allow(missing_copy_implementations)]
29#[repr(C)]
30pub struct ErlNifEnv {
31    dummy: *mut c_void, // block automatic Send and Sync traits.  Ref https://doc.rust-lang.org/beta/nomicon/send-and-sync.html
32}
33
34// Ownership of an env may be safely transfers between threads, therefore ErlNifEnv is Send.
35// This is the common use case for process independent environments created with enif_alloc_env().
36// ErlNifEnv is NOT Sync because it is thread unsafe.
37unsafe impl Send for ErlNifEnv {}
38
39/// See [ErlNifFunc](http://www.erlang.org/doc/man/erl_nif.html#ErlNifFunc) in the Erlang docs.
40// #[allow(missing_copy_implementations)]
41#[derive(Debug)]
42#[repr(C)]
43pub struct ErlNifFunc {
44    pub name: *const c_char,
45    pub arity: c_uint,
46    pub function: unsafe extern "C" fn(
47        env: *mut ErlNifEnv,
48        argc: c_int,
49        argv: *const ERL_NIF_TERM,
50    ) -> ERL_NIF_TERM,
51    pub flags: c_uint,
52}
53
54// #[allow(missing_copy_implementations)]
55#[doc(hidden)]
56#[derive(Debug)]
57#[repr(C)]
58#[allow(non_snake_case)]
59pub struct ErlNifEntry {
60    pub major: c_int,
61    pub minor: c_int,
62    pub name: *const c_char,
63    pub num_of_funcs: c_int,
64    pub funcs: *const ErlNifFunc,
65    pub load: Option<
66        unsafe extern "C" fn(
67            env: *mut ErlNifEnv,
68            priv_data: *mut *mut c_void,
69            load_info: ERL_NIF_TERM,
70        ) -> c_int,
71    >,
72    pub reload: Option<
73        unsafe extern "C" fn(
74            env: *mut ErlNifEnv,
75            priv_data: *mut *mut c_void,
76            load_info: ERL_NIF_TERM,
77        ) -> c_int,
78    >,
79    pub upgrade: Option<
80        unsafe extern "C" fn(
81            env: *mut ErlNifEnv,
82            priv_data: *mut *mut c_void,
83            old_priv_data: *mut *mut c_void,
84            load_info: ERL_NIF_TERM,
85        ) -> c_int,
86    >,
87    pub unload: Option<unsafe extern "C" fn(env: *mut ErlNifEnv, priv_data: *mut c_void) -> ()>,
88    pub vm_variant: *const c_char,
89    pub options: c_uint,                      // added in 2.7
90    pub sizeof_ErlNifResourceTypeInit: usize, // added in 2.12
91}
92
93pub const ERL_NIF_DIRTY_NIF_OPTION: c_uint = 1;
94
95/// See [ErlNifBinary](http://www.erlang.org/doc/man/erl_nif.html#ErlNifBinary) in the Erlang docs.
96#[allow(missing_copy_implementations)]
97#[derive(Debug, Copy, Clone)]
98#[repr(C)]
99pub struct ErlNifBinary {
100    pub size: size_t,
101    pub data: *mut c_uchar,
102    ref_bin: *mut c_void,
103    _spare: [*mut c_void; 2],
104}
105
106#[cfg(windows)]
107pub type ErlNifEvent = os::windows::raw::HANDLE;
108
109#[cfg(unix)]
110pub type ErlNifEvent = os::unix::io::RawFd;
111
112/// See [ErlNifResourceType](http://www.erlang.org/doc/man/erl_nif.html#ErlNifResourceType) in the Erlang docs.
113#[allow(missing_copy_implementations)]
114#[repr(C)]
115pub struct ErlNifResourceType {
116    dummy: c_int,
117}
118
119/// See [ErlNifResourceDtor](http://www.erlang.org/doc/man/erl_nif.html#ErlNifResourceDtor) in the Erlang docs.
120#[allow(missing_copy_implementations)]
121pub type ErlNifResourceDtor = unsafe extern "C" fn(env: *mut ErlNifEnv, obj: *mut c_void) -> ();
122
123/// See [ErlNifResourceStop](http://www.erlang.org/doc/man/erl_nif.html#ErlNifResourceStop) in the Erlang docs.
124#[allow(missing_copy_implementations)]
125pub type ErlNifResourceStop = unsafe extern "C" fn(
126    env: *mut ErlNifEnv,
127    obj: *mut c_void,
128    event: ErlNifEvent,
129    is_direct_call: c_int,
130) -> ();
131
132/// See [ErlNifResourceDown](http://www.erlang.org/doc/man/erl_nif.html#ErlNifResourceDown) in the Erlang docs.
133#[allow(missing_copy_implementations)]
134pub type ErlNifResourceDown = unsafe extern "C" fn(
135    env: *mut ErlNifEnv,
136    obj: *mut c_void,
137    pid: *const ErlNifPid,
138    mon: *const ErlNifMonitor,
139) -> ();
140
141/// See [ErlNifResourceDynCall](http://www.erlang.org/doc/man/erl_nif.html#ErlNifResourceDynCall) in the Erlang Docs.
142pub type ErlNifResourceDynCall =
143    unsafe extern "C" fn(env: *mut ErlNifEnv, obj: *mut c_void, call_data: *const c_void) -> ();
144
145/// See [ErlNifResourceTypeInit](http://www.erlang.org/doc/man/erl_nif.html#ErlNifResourceTypeInit) in the Erlang docs.
146#[derive(Debug, Copy, Clone)]
147#[repr(C)]
148pub struct ErlNifResourceTypeInit {
149    pub dtor: *const ErlNifResourceDtor,
150    pub stop: *const ErlNifResourceStop, // at ERL_NIF_SELECT_STOP event
151    pub down: *const ErlNifResourceDown, // enif_monitor_process
152    pub members: c_int,
153    pub dyncall: *const ErlNifResourceDynCall,
154}
155
156/// See [ErlNifSelectFlags](http://erlang.org/doc/man/erl_nif.html#ErlNifSelectFlags) in the Erlang docs.
157pub type ErlNifSelectFlags = c_int;
158#[allow(clippy::identity_op)]
159pub const ERL_NIF_SELECT_READ: ErlNifSelectFlags = 1 << 0;
160pub const ERL_NIF_SELECT_WRITE: ErlNifSelectFlags = 1 << 1;
161pub const ERL_NIF_SELECT_STOP: ErlNifSelectFlags = 1 << 2;
162pub const ERL_NIF_SELECT_FAILED: ErlNifSelectFlags = 1 << 3;
163pub const ERL_NIF_SELECT_READ_CANCELLED: ErlNifSelectFlags = 1 << 4;
164pub const ERL_NIF_SELECT_WRITE_CANCELLED: ErlNifSelectFlags = 1 << 5;
165pub const ERL_NIF_SELECT_ERROR_CANCELLED: ErlNifSelectFlags = 1 << 6;
166pub const ERL_NIF_SELECT_NOTSUP: ErlNifSelectFlags = 1 << 7;
167
168/// See [ErlNifMonitor](http://www.erlang.org/doc/man/erl_nif.html#ErlNifMonitor) in the Erlang docs.
169#[derive(Debug, Copy, Clone)]
170#[repr(C)]
171pub struct ErlNifMonitor {
172    // from https://github.com/erlang/otp/blob/83e20c62057ebc1d8064bf57b01be560cd244e1d/erts/emulator/beam/erl_drv_nif.h#L64
173    // data: [c_uchar; size_of::<*const c_void>()*4],  size_of is non-const
174    data: [usize; 4],
175}
176
177/// See [ErlNifResourceFlags](http://www.erlang.org/doc/man/erl_nif.html#ErlNifResourceFlags) in the Erlang docs.
178#[derive(Debug, Copy, Clone)]
179#[repr(C)]
180pub enum ErlNifResourceFlags {
181    ERL_NIF_RT_CREATE = 1,
182    ERL_NIF_RT_TAKEOVER = 2,
183}
184
185/// See [ErlNifCharEncoding](http://www.erlang.org/doc/man/erl_nif.html#ErlNifCharEncoding) in the Erlang docs.
186#[derive(Debug, Copy, Clone)]
187#[repr(C)]
188pub enum ErlNifCharEncoding {
189    ERL_NIF_LATIN1 = 1,
190    #[cfg(feature = "nif_version_2_17")]
191    ERL_NIF_UTF8 = 2,
192}
193
194/// See [ErlNifPid](http://www.erlang.org/doc/man/erl_nif.html#ErlNifPid) in the Erlang docs.
195#[derive(Debug, Copy, Clone)]
196#[repr(C)]
197pub struct ErlNifPid {
198    pid: ERL_NIF_TERM,
199}
200
201/// See [enif_make_pid](http://erlang.org/doc/man/erl_nif.html#enif_make_pid) in the Erlang docs
202pub unsafe fn enif_make_pid(_env: *mut ErlNifEnv, pid: ErlNifPid) -> ERL_NIF_TERM {
203    pid.pid
204}
205
206/// See [enif_compare_pids](http://erlang.org/doc/man/erl_nif.html#enif_compare_pids) in the Erlang docs
207pub unsafe fn enif_compare_pids(pid1: *const ErlNifPid, pid2: *const ErlNifPid) -> c_int {
208    // Mimics the implementation of the enif_compare_pids macro
209    enif_compare((*pid1).pid, (*pid2).pid)
210}
211
212/// See [ErlNifSysInfo](http://www.erlang.org/doc/man/erl_nif.html#ErlNifSysInfo) in the Erlang docs.
213#[allow(missing_copy_implementations)]
214#[repr(C)]
215pub struct ErlNifSysInfo {
216    pub driver_major_version: c_int,
217    pub driver_minor_version: c_int,
218    pub erts_version: *mut c_char,
219    pub otp_release: *mut c_char,
220    pub thread_support: c_int,
221    pub smp_support: c_int,
222    pub async_threads: c_int,
223    pub scheduler_threads: c_int,
224    pub nif_major_version: c_int,
225    pub nif_minor_version: c_int,
226    pub dirty_scheduler_support: c_int,
227}
228
229// /// See [ErlNifFunc](http://www.erlang.org/doc/man/erl_nif.html#ErlNifFunc) in the Erlang docs.
230// #[derive(Copy, Clone)]
231// #[repr(C)]
232// pub enum ErlNifDirtyTaskFlags {
233//     ERL_NIF_DIRTY_JOB_CPU_BOUND = 1,
234//     ERL_NIF_DIRTY_JOB_IO_BOUND = 2,
235// }
236
237pub type ErlNifDirtyTaskFlags = c_uint;
238pub const ERL_NIF_DIRTY_JOB_CPU_BOUND: ErlNifDirtyTaskFlags = 1;
239pub const ERL_NIF_DIRTY_JOB_IO_BOUND: ErlNifDirtyTaskFlags = 2;
240
241/// See [ErlNifMapIterator](http://www.erlang.org/doc/man/erl_nif.html#ErlNifMapIterator) in the Erlang docs.
242#[allow(missing_copy_implementations)]
243#[repr(C)]
244pub struct ErlNifMapIterator {
245    map: ERL_NIF_TERM,
246    t_limit: ERL_NIF_UINT,
247    idx: ERL_NIF_UINT,
248    ks: *mut ERL_NIF_TERM,
249    vs: *mut ERL_NIF_TERM,
250    __spare__: [*mut c_void; 2],
251}
252
253/// See [ErlNifMapIteratorEntry](http://www.erlang.org/doc/man/erl_nif.html#ErlNifMapIteratorEntry) in the Erlang docs.
254#[derive(Copy, Clone)]
255#[repr(C)]
256pub enum ErlNifMapIteratorEntry {
257    ERL_NIF_MAP_ITERATOR_HEAD = 1,
258    ERL_NIF_MAP_ITERATOR_TAIL = 2,
259}
260
261/// See [ErlNifTime](http://www.erlang.org/doc/man/erl_nif.html#ErlNifTime) in the Erlang docs.
262pub type ErlNifTime = i64;
263
264/// Error return value for `enif_monotonic_time()`, `enif_time_offset()`, and `enif_convert_time_unit()`.
265pub const ERL_NIF_TIME_ERROR: i64 = -9_223_372_036_854_775_808;
266//const ERL_NIF_TIME_ERROR:i64 = i64::min_value();  "error: const fn's not yet stable"
267
268/// See [ErlNifTimeUnit](http://www.erlang.org/doc/man/erl_nif.html#ErlNifTimeUnit) in the Erlang docs.
269#[derive(Copy, Clone)]
270#[repr(C)]
271pub enum ErlNifTimeUnit {
272    // values yanked from https://github.com/erlang/otp/blob/7cb403e4aa044fd2cc7702dbe8e2d0eea68e81f3/erts/emulator/beam/erl_drv_nif.h#L132
273    ERL_NIF_SEC = 0,
274    ERL_NIF_MSEC = 1,
275    ERL_NIF_USEC = 2,
276    ERL_NIF_NSEC = 3,
277}
278
279/// See [ErlNifUniqueInteger](http://erlang.org/doc/man/erl_nif.html#ErlNifUniqueInteger) in the Erlang docs.
280pub type ErlNifUniqueInteger = c_int;
281#[allow(clippy::identity_op)]
282pub const ERL_NIF_UNIQUE_POSITIVE: ErlNifUniqueInteger = 1 << 0;
283#[allow(clippy::identity_op)]
284pub const ERL_NIF_UNIQUE_MONOTONIC: ErlNifUniqueInteger = 1 << 1;
285// ref https://github.com/erlang/otp/blob/maint/erts/emulator/beam/erl_nif.h#L203
286// FIXME: Should actually be C enum, but repr(C) enums in Rust can't be used as bitfields.
287//        Fix if the right abstraction ever lands in Rust.
288
289/// See [ErlNifPort](http://erlang.org/doc/man/erl_nif.html#ErlNifPort) in the Erlang docs.
290#[derive(Copy, Clone)]
291#[repr(C)]
292pub struct ErlNifPort {
293    port_id: ERL_NIF_TERM, // internal, may change
294}
295// ref https://github.com/erlang/otp/blob/maint/erts/emulator/beam/erl_nif.h#L155
296
297/// See [ErlNifBinaryToTerm](http://erlang.org/doc/man/erl_nif.html#ErlNifBinaryToTerm) in the Erlang docs.
298pub type ErlNifBinaryToTerm = c_int;
299pub const ERL_NIF_BIN2TERM_SAFE: ErlNifBinaryToTerm = 0x2000_0000;
300
301pub const ERL_NIF_THR_UNDEFINED: c_int = 0;
302pub const ERL_NIF_THR_NORMAL_SCHEDULER: c_int = 1;
303pub const ERL_NIF_THR_DIRTY_CPU_SCHEDULER: c_int = 2;
304pub const ERL_NIF_THR_DIRTY_IO_SCHEDULER: c_int = 3;
305
306/// See [ErlNifHash](http://www.erlang.org/doc/man/erl_nif.html#ErlNifHash) in the Erlang docs.
307#[derive(Copy, Clone)]
308#[repr(C)]
309pub enum ErlNifHash {
310    // from https://github.com/erlang/otp/blob/83e20c62057ebc1d8064bf57b01be560cd244e1d/erts/emulator/beam/erl_nif.h#L242
311    ERL_NIF_INTERNAL_HASH = 1,
312    ERL_NIF_PHASH2 = 2,
313}
314
315/// See [ErlNifTermType](http://www.erlang.org/doc/man/erl_nif.html#ErlNifTermType) in the Erlang docs.
316#[cfg(feature = "nif_version_2_15")]
317#[derive(Copy, Clone)]
318#[repr(C)]
319pub enum ErlNifTermType {
320    // from https://github.com/erlang/otp/blob/6618ce7b6a621e92db72ea4f01f7d38553c8818c/erts/emulator/beam/erl_nif.h#L291
321    ERL_NIF_TERM_TYPE_ATOM = 1,
322    ERL_NIF_TERM_TYPE_BITSTRING = 2,
323    ERL_NIF_TERM_TYPE_FLOAT = 3,
324    ERL_NIF_TERM_TYPE_FUN = 4,
325    ERL_NIF_TERM_TYPE_INTEGER = 5,
326    ERL_NIF_TERM_TYPE_LIST = 6,
327    ERL_NIF_TERM_TYPE_MAP = 7,
328    ERL_NIF_TERM_TYPE_PID = 8,
329    ERL_NIF_TERM_TYPE_PORT = 9,
330    ERL_NIF_TERM_TYPE_REFERENCE = 10,
331    ERL_NIF_TERM_TYPE_TUPLE = 11,
332
333    /* This is a dummy value intended to coax the compiler into warning about
334     * unhandled values in a switch even if all the above values have been
335     * handled. We can add new entries at any time so the user must always
336     * have a default case. */
337    ERL_NIF_TERM_TYPE__MISSING_DEFAULT_CASE__READ_THE_MANUAL = -1,
338}
339
340/// See [ErlNifOption](http://www.erlang.org/doc/man/erl_nif.html#ErlNifOption) in the Erlang docs.
341#[cfg(feature = "nif_version_2_17")]
342#[derive(Copy, Clone)]
343#[repr(C)]
344pub enum ErlNifOption {
345    // from https://github.com/erlang/otp/blob/1b3c6214d4bf359f7e5c143bef5c5ad9c90c5536/erts/emulator/beam/erl_nif.h#L333
346    ERL_NIF_OPT_DELAY_HALT = 1,
347    ERL_NIF_OPT_ON_HALT = 2,
348}
349
350// Include the file generated by `build.rs`.
351include!(concat!(env!("OUT_DIR"), "/nif_api.snippet"));
352// example of included content:
353// extern "C" {
354//     pub fn enif_priv_data(arg1: *mut ErlNifEnv) -> *mut c_void;
355//     pub fn enif_alloc(size: size_t) -> *mut c_void;
356//     pub fn enif_free(ptr: *mut c_void);
357//     pub fn enif_is_atom(arg1: *mut ErlNifEnv, term: ERL_NIF_TERM) -> c_int;
358//     pub fn enif_is_binary(arg1: *mut ErlNifEnv, term: ERL_NIF_TERM) -> c_int;
359// ...