1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
//! C FFI (CFFI) layer for `dtact-util`'s six native primitives.
//!
//! Covers `io`, `fs`, `process`, `signal`, `stream`, and `timer`, exposed as
//! a **blocking, synchronous** `extern "C"` surface for callers in C, C++,
//! or any language with a C FFI.
//!
//! Enabled by the `ffi` Cargo feature (off by default; implies `native`).
//! Header files (`dtact_util.h` / `dtact_util.hpp`) are generated by
//! `build.rs` via cbindgen when the crate is built with `DEV=1` set.
//!
//! # Design
//!
//! Every handle this layer hands back to C is a **raw owning pointer**
//! produced by [`Box::into_raw`] and reclaimed by [`Box::from_raw`] (rather
//! than an opaque integer index into a handle table). A non-null pointer
//! returned by a `*_create` / `*_open` / `*_spawn` / `*_connect` / `*_bind`
//! function is owned by the caller and MUST eventually be handed back to
//! the matching `*_close` / `*_free` / `*_wait` function exactly once — that
//! call takes ownership and drops the underlying Rust object. Using a handle
//! after it has been freed, or freeing it twice, is undefined behavior.
//!
//! Blocking is genuine: each call drives the underlying async operation to
//! completion on the calling thread via a small internal [`block_on`] spin
//! executor before returning. A few operations also offer a non-blocking
//! flavor where blocking-only would be a real usability regression.
//!
//! # Error reporting
//!
//! One convention is used across all six modules: a **thread-local
//! last-error string**. When a fallible function fails it returns a
//! sentinel (a null pointer, or a negative length / `-1` byte count, or a
//! nonzero `int`) and stores a human-readable message retrievable via
//! [`dtact_util_last_error_message`]. The returned pointer is valid until
//! the next `dtact-util` FFI call *on the same thread*; copy it out if you
//! need to keep it. A successful call clears the thread-local error.
//!
//! # Safety
//!
//! This contract applies to **every** `unsafe extern "C"` function in this
//! module and its submodules; it is stated here once and referenced from
//! each function's own `# Safety` section:
//!
//! - Every non-null handle pointer passed in must have been returned by the
//! corresponding `dtact-util` FFI constructor, must not have been freed,
//! and must not be used concurrently from another thread unless that
//! function is explicitly documented as thread-safe. Passing a null,
//! dangling, or foreign pointer is undefined behavior (null is checked
//! and reported as an error where a handle is required, but a non-null
//! invalid pointer cannot be detected).
//! - Every `*const c_char` string pointer must be non-null and point to a
//! valid NUL-terminated C string.
//! - Every `(buf, len)` pair must describe a single allocation of at least
//! `len` bytes that stays valid for the duration of the call; read
//! functions write up to `len` bytes into it, write functions read `len`
//! bytes from it.
//! - Out-pointer parameters (`*mut *mut T`) must be non-null and point to
//! writable storage for one pointer.
use RefCell;
use ;
use Future;
thread_local!
/// Store `msg` as this thread's last-error string.
pub
/// Clear this thread's last-error string (called at the start of a
/// successful operation).
pub
/// Convenience: record an `std::io::Error` (or any `Display`) as the last
/// error.
pub
/// Return the current thread's last-error message as a NUL-terminated C
/// string, or null if no error has been recorded since the last successful
/// call.
///
/// The returned pointer is owned by the library and remains valid only
/// until the next `dtact-util` FFI call on this thread. Do not free it.
///
/// # Safety
///
/// See the [`crate::ffi`] module-level Safety contract. This function reads
/// only thread-local state and takes no pointer arguments.
pub unsafe extern "C"
/// Minimal single-threaded blocking executor: polls `fut` to completion on
/// the calling thread with a no-op waker, yielding between polls. Every
/// blocking FFI entry point drives its async work through this.
///
/// This is sound for this crate's futures because their completions are
/// driven by dedicated backend worker threads (`IOCP`/`io_uring` workers, the
/// timer wheel thread, the process/blocking pools, or the peer endpoint for
/// in-process streams), not by the waker — the waker is purely an
/// optimization we can safely elide by re-polling.
pub
/// Borrow a `*const c_char` as `&str`, recording an error and returning
/// `None` on null or invalid UTF-8.
///
/// # Safety
///
/// `ptr`, if non-null, must be a valid NUL-terminated C string.
pub unsafe