]>
Commit | Line | Data |
---|---|---|
923072b8 FG |
1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | ||
487cf647 | 3 | use core_foundation_sys::base::CFRelease; |
923072b8 | 4 | use libc::c_char; |
487cf647 FG |
5 | use std::ptr::NonNull; |
6 | ||
7 | // A helper using to auto release the resource got from CoreFoundation. | |
8 | // More information about the ownership policy for CoreFoundation pelease refer the link below: | |
9 | // https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFMemoryMgmt/Concepts/Ownership.html#//apple_ref/doc/uid/20001148-CJBEJBHH | |
10 | #[repr(transparent)] | |
11 | pub(crate) struct CFReleaser<T>(NonNull<T>); | |
12 | ||
13 | impl<T> CFReleaser<T> { | |
14 | pub(crate) fn new(ptr: *const T) -> Option<Self> { | |
15 | // This cast is OK because `NonNull` is a transparent wrapper | |
16 | // over a `*const T`. Additionally, mutability doesn't matter with | |
17 | // pointers here. | |
18 | NonNull::new(ptr as *mut T).map(Self) | |
19 | } | |
20 | ||
21 | pub(crate) fn inner(&self) -> *const T { | |
22 | self.0.as_ptr().cast() | |
23 | } | |
24 | } | |
25 | ||
26 | impl<T> Drop for CFReleaser<T> { | |
27 | fn drop(&mut self) { | |
28 | unsafe { CFRelease(self.0.as_ptr().cast()) } | |
29 | } | |
30 | } | |
31 | ||
32 | // Safety: These are safe to implement because we only wrap non-mutable | |
33 | // CoreFoundation types, which are generally threadsafe unless noted | |
34 | // otherwise. | |
35 | unsafe impl<T> Send for CFReleaser<T> {} | |
36 | unsafe impl<T> Sync for CFReleaser<T> {} | |
923072b8 FG |
37 | |
38 | pub(crate) fn cstr_to_rust(c: *const c_char) -> Option<String> { | |
39 | cstr_to_rust_with_size(c, None) | |
40 | } | |
41 | ||
42 | pub(crate) fn cstr_to_rust_with_size(c: *const c_char, size: Option<usize>) -> Option<String> { | |
43 | if c.is_null() { | |
44 | return None; | |
45 | } | |
46 | let mut s = match size { | |
47 | Some(len) => Vec::with_capacity(len), | |
48 | None => Vec::new(), | |
49 | }; | |
50 | let mut i = 0; | |
51 | unsafe { | |
52 | loop { | |
53 | let value = *c.offset(i) as u8; | |
54 | if value == 0 { | |
55 | break; | |
56 | } | |
57 | s.push(value); | |
58 | i += 1; | |
59 | } | |
60 | String::from_utf8(s).ok() | |
61 | } | |
62 | } | |
63 | ||
923072b8 FG |
64 | pub(crate) fn vec_to_rust(buf: Vec<i8>) -> Option<String> { |
65 | String::from_utf8( | |
66 | buf.into_iter() | |
67 | .flat_map(|b| if b > 0 { Some(b as u8) } else { None }) | |
68 | .collect(), | |
69 | ) | |
70 | .ok() | |
71 | } |