Skip to content

Commit d41b205

Browse files
1313Copilot
andcommitted
Merge ffi/wrappers: sc_retained! macro + null-checked constructors
Consolidates ~21 hand-written retain/release impls into the audited sc_retained! macro and folds 10 raw-pointer call sites onto from_retained_ptr (None-on-null). SCStream and SCRecordingOutput keep their hand-written Drop/Clone (teardown ordering / delegate refcount). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2 parents 62629dd + 91fcea3 commit d41b205

11 files changed

Lines changed: 212 additions & 245 deletions

File tree

src/content_sharing_picker.rs

Lines changed: 14 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -285,25 +285,12 @@ impl Default for SCContentSharingPickerConfiguration {
285285
}
286286
}
287287

288-
impl Clone for SCContentSharingPickerConfiguration {
289-
fn clone(&self) -> Self {
290-
unsafe {
291-
Self {
292-
ptr: crate::ffi::sc_content_sharing_picker_configuration_retain(self.ptr),
293-
}
294-
}
295-
}
296-
}
297-
298-
impl Drop for SCContentSharingPickerConfiguration {
299-
fn drop(&mut self) {
300-
if !self.ptr.is_null() {
301-
unsafe {
302-
crate::ffi::sc_content_sharing_picker_configuration_release(self.ptr);
303-
}
304-
}
305-
}
306-
}
288+
crate::utils::retained::sc_retained!(
289+
SCContentSharingPickerConfiguration,
290+
field = ptr,
291+
retain = crate::ffi::sc_content_sharing_picker_configuration_retain,
292+
release = crate::ffi::sc_content_sharing_picker_configuration_release,
293+
);
307294

308295
impl std::fmt::Debug for SCContentSharingPickerConfiguration {
309296
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@@ -441,11 +428,7 @@ impl SCPickerResult {
441428
(0..count)
442429
.filter_map(|i| {
443430
let ptr = unsafe { crate::ffi::sc_picker_result_get_window_at(self.ptr, i) };
444-
if ptr.is_null() {
445-
None
446-
} else {
447-
Some(crate::shareable_content::SCWindow::from_ffi_owned(ptr))
448-
}
431+
unsafe { crate::shareable_content::SCWindow::from_retained_ptr(ptr) }
449432
})
450433
.collect()
451434
}
@@ -479,11 +462,7 @@ impl SCPickerResult {
479462
(0..count)
480463
.filter_map(|i| {
481464
let ptr = unsafe { crate::ffi::sc_picker_result_get_display_at(self.ptr, i) };
482-
if ptr.is_null() {
483-
None
484-
} else {
485-
Some(crate::shareable_content::SCDisplay::from_ffi_owned(ptr))
486-
}
465+
unsafe { crate::shareable_content::SCDisplay::from_retained_ptr(ptr) }
487466
})
488467
.collect()
489468
}
@@ -497,11 +476,7 @@ impl SCPickerResult {
497476
(0..count)
498477
.filter_map(|i| {
499478
let ptr = unsafe { crate::ffi::sc_picker_result_get_application_at(self.ptr, i) };
500-
if ptr.is_null() {
501-
None
502-
} else {
503-
Some(crate::shareable_content::SCRunningApplication::from_ffi_owned(ptr))
504-
}
479+
unsafe { crate::shareable_content::SCRunningApplication::from_retained_ptr(ptr) }
505480
})
506481
.collect()
507482
}
@@ -543,15 +518,11 @@ impl SCPickerResult {
543518
}
544519
}
545520

546-
impl Drop for SCPickerResult {
547-
fn drop(&mut self) {
548-
if !self.ptr.is_null() {
549-
unsafe {
550-
crate::ffi::sc_picker_result_release(self.ptr);
551-
}
552-
}
553-
}
554-
}
521+
crate::utils::retained::sc_retained!(
522+
SCPickerResult,
523+
field = ptr,
524+
release = crate::ffi::sc_picker_result_release,
525+
);
555526

556527
impl std::fmt::Debug for SCPickerResult {
557528
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {

src/recording_output.rs

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -259,25 +259,12 @@ impl Default for SCRecordingOutputConfiguration {
259259
}
260260
}
261261

262-
impl Clone for SCRecordingOutputConfiguration {
263-
fn clone(&self) -> Self {
264-
unsafe {
265-
Self {
266-
ptr: crate::ffi::sc_recording_output_configuration_retain(self.ptr),
267-
}
268-
}
269-
}
270-
}
271-
272-
impl Drop for SCRecordingOutputConfiguration {
273-
fn drop(&mut self) {
274-
if !self.ptr.is_null() {
275-
unsafe {
276-
crate::ffi::sc_recording_output_configuration_release(self.ptr);
277-
}
278-
}
279-
}
280-
}
262+
crate::utils::retained::sc_retained!(
263+
SCRecordingOutputConfiguration,
264+
field = ptr,
265+
retain = crate::ffi::sc_recording_output_configuration_retain,
266+
release = crate::ffi::sc_recording_output_configuration_release,
267+
);
281268

282269
impl std::fmt::Debug for SCRecordingOutputConfiguration {
283270
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {

src/screenshot_manager.rs

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,15 +1031,11 @@ impl Default for SCScreenshotConfiguration {
10311031
}
10321032

10331033
#[cfg(feature = "macos_26_0")]
1034-
impl Drop for SCScreenshotConfiguration {
1035-
fn drop(&mut self) {
1036-
if !self.ptr.is_null() {
1037-
unsafe {
1038-
crate::ffi::sc_screenshot_configuration_release(self.ptr);
1039-
}
1040-
}
1041-
}
1042-
}
1034+
crate::utils::retained::sc_retained!(
1035+
SCScreenshotConfiguration,
1036+
field = ptr,
1037+
release = crate::ffi::sc_screenshot_configuration_release,
1038+
);
10431039

10441040
#[cfg(feature = "macos_26_0")]
10451041
unsafe impl Send for SCScreenshotConfiguration {}
@@ -1116,15 +1112,11 @@ impl std::fmt::Debug for SCScreenshotOutput {
11161112
}
11171113

11181114
#[cfg(feature = "macos_26_0")]
1119-
impl Drop for SCScreenshotOutput {
1120-
fn drop(&mut self) {
1121-
if !self.ptr.is_null() {
1122-
unsafe {
1123-
crate::ffi::sc_screenshot_output_release(self.ptr);
1124-
}
1125-
}
1126-
}
1127-
}
1115+
crate::utils::retained::sc_retained!(
1116+
SCScreenshotOutput,
1117+
field = ptr,
1118+
release = crate::ffi::sc_screenshot_output_release,
1119+
);
11281120

11291121
#[cfg(feature = "macos_26_0")]
11301122
unsafe impl Send for SCScreenshotOutput {}

src/shareable_content/display.rs

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,17 @@ impl SCDisplay {
4646
Self(ptr)
4747
}
4848

49-
/// Create from FFI-owned pointer (caller transfers ownership)
50-
#[allow(dead_code)]
51-
pub(crate) fn from_ffi_owned(ptr: *const c_void) -> Self {
52-
Self(ptr)
49+
/// Create from an FFI-owned (retained) pointer, returning `None` if null.
50+
///
51+
/// # Safety
52+
/// `ptr` must be null or a valid retained `SCDisplay` pointer transferred
53+
/// from the Swift FFI bridge (ownership moves into the returned wrapper).
54+
pub(crate) unsafe fn from_retained_ptr(ptr: *const c_void) -> Option<Self> {
55+
if ptr.is_null() {
56+
None
57+
} else {
58+
Some(unsafe { Self::from_ptr(ptr) })
59+
}
5360
}
5461

5562
/// Get the raw pointer (used internally)
@@ -125,21 +132,11 @@ impl SCDisplay {
125132
}
126133
}
127134

128-
impl Drop for SCDisplay {
129-
fn drop(&mut self) {
130-
if !self.0.is_null() {
131-
unsafe {
132-
crate::ffi::sc_display_release(self.0);
133-
}
134-
}
135-
}
136-
}
137-
138-
impl Clone for SCDisplay {
139-
fn clone(&self) -> Self {
140-
unsafe { Self(crate::ffi::sc_display_retain(self.0)) }
141-
}
142-
}
135+
crate::utils::retained::sc_retained!(
136+
SCDisplay,
137+
retain = crate::ffi::sc_display_retain,
138+
release = crate::ffi::sc_display_release,
139+
);
143140

144141
unsafe impl Send for SCDisplay {}
145142
unsafe impl Sync for SCDisplay {}

src/shareable_content/mod.rs

Lines changed: 13 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -130,12 +130,6 @@ impl std::hash::Hash for SCShareableContent {
130130
}
131131
}
132132

133-
impl Clone for SCShareableContent {
134-
fn clone(&self) -> Self {
135-
unsafe { Self(crate::ffi::sc_shareable_content_retain(self.0)) }
136-
}
137-
}
138-
139133
impl SCShareableContent {
140134
/// Create from raw pointer (used internally)
141135
///
@@ -212,9 +206,7 @@ impl SCShareableContent {
212206

213207
for i in 0..count {
214208
let display_ptr = crate::ffi::sc_shareable_content_get_display_at(self.0, i);
215-
if !display_ptr.is_null() {
216-
displays.push(SCDisplay::from_ptr(display_ptr));
217-
}
209+
displays.extend(SCDisplay::from_retained_ptr(display_ptr));
218210
}
219211

220212
displays
@@ -247,9 +239,7 @@ impl SCShareableContent {
247239

248240
for i in 0..count {
249241
let window_ptr = crate::ffi::sc_shareable_content_get_window_at(self.0, i);
250-
if !window_ptr.is_null() {
251-
windows.push(SCWindow::from_ptr(window_ptr));
252-
}
242+
windows.extend(SCWindow::from_retained_ptr(window_ptr));
253243
}
254244

255245
windows
@@ -280,9 +270,7 @@ impl SCShareableContent {
280270

281271
for i in 0..count {
282272
let app_ptr = crate::ffi::sc_shareable_content_get_application_at(self.0, i);
283-
if !app_ptr.is_null() {
284-
apps.push(SCRunningApplication::from_ptr(app_ptr));
285-
}
273+
apps.extend(SCRunningApplication::from_retained_ptr(app_ptr));
286274
}
287275

288276
apps
@@ -321,15 +309,11 @@ impl SCShareableContent {
321309
}
322310
}
323311

324-
impl Drop for SCShareableContent {
325-
fn drop(&mut self) {
326-
if !self.0.is_null() {
327-
unsafe {
328-
crate::ffi::sc_shareable_content_release(self.0);
329-
}
330-
}
331-
}
332-
}
312+
crate::utils::retained::sc_retained!(
313+
SCShareableContent,
314+
retain = crate::ffi::sc_shareable_content_retain,
315+
release = crate::ffi::sc_shareable_content_release,
316+
);
333317

334318
impl fmt::Debug for SCShareableContent {
335319
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -586,22 +570,11 @@ impl SCShareableContentInfo {
586570
}
587571

588572
#[cfg(feature = "macos_14_0")]
589-
impl Drop for SCShareableContentInfo {
590-
fn drop(&mut self) {
591-
if !self.0.is_null() {
592-
unsafe {
593-
crate::ffi::sc_shareable_content_info_release(self.0);
594-
}
595-
}
596-
}
597-
}
598-
599-
#[cfg(feature = "macos_14_0")]
600-
impl Clone for SCShareableContentInfo {
601-
fn clone(&self) -> Self {
602-
unsafe { Self(crate::ffi::sc_shareable_content_info_retain(self.0)) }
603-
}
604-
}
573+
crate::utils::retained::sc_retained!(
574+
SCShareableContentInfo,
575+
retain = crate::ffi::sc_shareable_content_info_retain,
576+
release = crate::ffi::sc_shareable_content_info_release,
577+
);
605578

606579
#[cfg(feature = "macos_14_0")]
607580
impl fmt::Debug for SCShareableContentInfo {

src/shareable_content/running_application.rs

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,17 @@ impl SCRunningApplication {
4646
Self(ptr)
4747
}
4848

49-
/// Create from FFI-owned pointer (caller transfers ownership)
50-
#[allow(dead_code)]
51-
pub(crate) fn from_ffi_owned(ptr: *const c_void) -> Self {
52-
Self(ptr)
49+
/// Create from an FFI-owned (retained) pointer, returning `None` if null.
50+
///
51+
/// # Safety
52+
/// `ptr` must be null or a valid retained `SCRunningApplication` pointer
53+
/// transferred from the Swift FFI bridge (ownership moves into the wrapper).
54+
pub(crate) unsafe fn from_retained_ptr(ptr: *const c_void) -> Option<Self> {
55+
if ptr.is_null() {
56+
None
57+
} else {
58+
Some(unsafe { Self::from_ptr(ptr) })
59+
}
5360
}
5461

5562
/// Get the raw pointer (used internally)
@@ -81,21 +88,11 @@ impl SCRunningApplication {
8188
}
8289
}
8390

84-
impl Drop for SCRunningApplication {
85-
fn drop(&mut self) {
86-
if !self.0.is_null() {
87-
unsafe {
88-
crate::ffi::sc_running_application_release(self.0);
89-
}
90-
}
91-
}
92-
}
93-
94-
impl Clone for SCRunningApplication {
95-
fn clone(&self) -> Self {
96-
unsafe { Self(crate::ffi::sc_running_application_retain(self.0)) }
97-
}
98-
}
91+
crate::utils::retained::sc_retained!(
92+
SCRunningApplication,
93+
retain = crate::ffi::sc_running_application_retain,
94+
release = crate::ffi::sc_running_application_release,
95+
);
9996

10097
impl fmt::Debug for SCRunningApplication {
10198
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

0 commit comments

Comments
 (0)