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
//! FFI string utilities
//!
//! Helper functions for retrieving strings from C/Objective-C APIs
//! that use buffer-based string retrieval patterns.
use CStr;
/// Default buffer size for FFI string retrieval
pub const DEFAULT_BUFFER_SIZE: usize = 1024;
/// Smaller buffer size for short strings (e.g., device IDs, stream names)
pub const SMALL_BUFFER_SIZE: usize = 256;
/// Retrieves a string from an FFI function that writes to a buffer.
///
/// This is a common pattern in Objective-C FFI where a function:
/// 1. Takes a buffer pointer and length
/// 2. Writes a null-terminated string to the buffer
/// 3. Returns a boolean indicating success
///
/// # Arguments
/// * `buffer_size` - Size of the buffer to allocate
/// * `ffi_call` - A closure that takes (`buffer_ptr`, `buffer_len`) and returns success bool
///
/// # Returns
/// * `Some(String)` if the FFI call succeeded and the string was valid UTF-8
/// * `None` if the FFI call failed or returned an empty string
///
/// # Safety
/// The caller must ensure the `ffi_call` closure does not write beyond the
/// provided `buffer_len`. This function defends against the closure writing
/// a non-NUL-terminated string by scanning the buffer up to its declared
/// length and treating the absence of a terminator as failure (returns
/// `None`) rather than reading past the buffer with `CStr::from_ptr`.
///
/// # Example
/// ```
/// use screencapturekit::utils::ffi_string::ffi_string_from_buffer;
///
/// let result = unsafe {
/// ffi_string_from_buffer(64, |buf, len| {
/// // Simulate FFI call that writes "hello" to buffer
/// let src = b"hello\0";
/// if len >= src.len() as isize {
/// std::ptr::copy_nonoverlapping(src.as_ptr(), buf as *mut u8, src.len());
/// true
/// } else {
/// false
/// }
/// })
/// };
/// assert_eq!(result, Some("hello".to_string()));
/// ```
pub unsafe
/// Same as [`ffi_string_from_buffer`] but returns an empty string on failure
/// instead of `None`.
///
/// Useful when the API should always return a string, even if empty.
///
/// # Safety
/// The caller must ensure that the FFI call writes valid UTF-8 data to the buffer.
pub unsafe
/// Retrieves a string from an FFI function that returns an owned C string pointer.
///
/// This is more efficient than buffer-based retrieval as it avoids pre-allocation.
/// The FFI function allocates the string (via `strdup`) and this function takes
/// ownership and frees it.
///
/// # Arguments
/// * `ffi_call` - A closure that returns an owned C string pointer (or null)
///
/// # Returns
/// * `Some(String)` if the pointer was non-null and valid UTF-8
/// * `None` if the pointer was null
///
/// # Safety
/// The caller must ensure the returned pointer was allocated by Swift's `strdup`
/// or equivalent, and that `sc_free_string` properly frees it. The pointer is
/// freed via an RAII guard, so a panic in `to_string_lossy` (extremely rare —
/// only OOM) does not leak the Swift-allocated buffer.
pub unsafe
/// Same as [`ffi_string_owned`] but returns an empty string on failure.
///
/// # Safety
/// Same requirements as [`ffi_string_owned`].
pub unsafe