1use std::ffi::c_void;
9use std::ptr::NonNull;
10
11use mtl_foundation::{Referencing, UInteger};
12use mtl_sys::{msg_send_0, sel};
13
14use crate::enums::FunctionLogType;
15use crate::library::Function;
16
17#[repr(transparent)]
29pub struct LogContainer(pub(crate) NonNull<c_void>);
30
31impl LogContainer {
32 #[inline]
34 pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
35 NonNull::new(ptr).map(Self)
36 }
37
38 #[inline]
40 pub fn as_raw(&self) -> *mut c_void {
41 self.0.as_ptr()
42 }
43}
44
45impl Clone for LogContainer {
46 fn clone(&self) -> Self {
47 unsafe {
48 msg_send_0::<*mut c_void>(self.as_ptr(), sel!(retain));
49 }
50 Self(self.0)
51 }
52}
53
54impl Drop for LogContainer {
55 fn drop(&mut self) {
56 unsafe {
57 msg_send_0::<()>(self.as_ptr(), sel!(release));
58 }
59 }
60}
61
62impl Referencing for LogContainer {
63 #[inline]
64 fn as_ptr(&self) -> *const c_void {
65 self.0.as_ptr()
66 }
67}
68
69unsafe impl Send for LogContainer {}
70unsafe impl Sync for LogContainer {}
71
72#[repr(transparent)]
83pub struct FunctionLogDebugLocation(pub(crate) NonNull<c_void>);
84
85impl FunctionLogDebugLocation {
86 #[inline]
88 pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
89 NonNull::new(ptr).map(Self)
90 }
91
92 #[inline]
94 pub fn as_raw(&self) -> *mut c_void {
95 self.0.as_ptr()
96 }
97
98 pub fn url(&self) -> Option<String> {
102 unsafe {
103 let url_ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(URL));
104 if url_ptr.is_null() {
105 return None;
106 }
107 let str_ptr: *mut c_void = msg_send_0(url_ptr, sel!(absoluteString));
109 if str_ptr.is_null() {
110 return None;
111 }
112 let utf8_ptr: *const std::ffi::c_char =
113 mtl_sys::msg_send_0(str_ptr, sel!(UTF8String));
114 if utf8_ptr.is_null() {
115 return None;
116 }
117 let c_str = std::ffi::CStr::from_ptr(utf8_ptr);
118 Some(c_str.to_string_lossy().into_owned())
119 }
120 }
121
122 #[inline]
126 pub fn line(&self) -> UInteger {
127 unsafe { msg_send_0(self.as_ptr(), sel!(line)) }
128 }
129
130 #[inline]
134 pub fn column(&self) -> UInteger {
135 unsafe { msg_send_0(self.as_ptr(), sel!(column)) }
136 }
137
138 pub fn function_name(&self) -> Option<String> {
142 unsafe {
143 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(functionName));
144 if ptr.is_null() {
145 return None;
146 }
147 let utf8_ptr: *const std::ffi::c_char =
148 mtl_sys::msg_send_0(ptr as *const c_void, sel!(UTF8String));
149 if utf8_ptr.is_null() {
150 return None;
151 }
152 let c_str = std::ffi::CStr::from_ptr(utf8_ptr);
153 Some(c_str.to_string_lossy().into_owned())
154 }
155 }
156}
157
158impl Clone for FunctionLogDebugLocation {
159 fn clone(&self) -> Self {
160 unsafe {
161 msg_send_0::<*mut c_void>(self.as_ptr(), sel!(retain));
162 }
163 Self(self.0)
164 }
165}
166
167impl Drop for FunctionLogDebugLocation {
168 fn drop(&mut self) {
169 unsafe {
170 msg_send_0::<()>(self.as_ptr(), sel!(release));
171 }
172 }
173}
174
175impl Referencing for FunctionLogDebugLocation {
176 #[inline]
177 fn as_ptr(&self) -> *const c_void {
178 self.0.as_ptr()
179 }
180}
181
182unsafe impl Send for FunctionLogDebugLocation {}
183unsafe impl Sync for FunctionLogDebugLocation {}
184
185#[repr(transparent)]
196pub struct FunctionLog(pub(crate) NonNull<c_void>);
197
198impl FunctionLog {
199 #[inline]
201 pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
202 NonNull::new(ptr).map(Self)
203 }
204
205 #[inline]
207 pub fn as_raw(&self) -> *mut c_void {
208 self.0.as_ptr()
209 }
210
211 #[inline]
215 pub fn log_type(&self) -> FunctionLogType {
216 unsafe { msg_send_0(self.as_ptr(), sel!(type)) }
217 }
218
219 pub fn debug_location(&self) -> Option<FunctionLogDebugLocation> {
223 unsafe {
224 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(debugLocation));
225 if ptr.is_null() {
226 return None;
227 }
228 let _: *mut c_void = msg_send_0(ptr, sel!(retain));
229 FunctionLogDebugLocation::from_raw(ptr)
230 }
231 }
232
233 pub fn encoder_label(&self) -> Option<String> {
237 unsafe {
238 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(encoderLabel));
239 if ptr.is_null() {
240 return None;
241 }
242 let utf8_ptr: *const std::ffi::c_char =
243 mtl_sys::msg_send_0(ptr as *const c_void, sel!(UTF8String));
244 if utf8_ptr.is_null() {
245 return None;
246 }
247 let c_str = std::ffi::CStr::from_ptr(utf8_ptr);
248 Some(c_str.to_string_lossy().into_owned())
249 }
250 }
251
252 pub fn function(&self) -> Option<Function> {
256 unsafe {
257 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(function));
258 if ptr.is_null() {
259 return None;
260 }
261 let _: *mut c_void = msg_send_0(ptr, sel!(retain));
262 Function::from_raw(ptr)
263 }
264 }
265}
266
267impl Clone for FunctionLog {
268 fn clone(&self) -> Self {
269 unsafe {
270 msg_send_0::<*mut c_void>(self.as_ptr(), sel!(retain));
271 }
272 Self(self.0)
273 }
274}
275
276impl Drop for FunctionLog {
277 fn drop(&mut self) {
278 unsafe {
279 msg_send_0::<()>(self.as_ptr(), sel!(release));
280 }
281 }
282}
283
284impl Referencing for FunctionLog {
285 #[inline]
286 fn as_ptr(&self) -> *const c_void {
287 self.0.as_ptr()
288 }
289}
290
291unsafe impl Send for FunctionLog {}
292unsafe impl Sync for FunctionLog {}
293
294#[cfg(test)]
295mod tests {
296 use super::*;
297
298 #[test]
299 fn test_type_sizes() {
300 assert_eq!(
301 std::mem::size_of::<LogContainer>(),
302 std::mem::size_of::<*mut c_void>()
303 );
304 assert_eq!(
305 std::mem::size_of::<FunctionLogDebugLocation>(),
306 std::mem::size_of::<*mut c_void>()
307 );
308 assert_eq!(
309 std::mem::size_of::<FunctionLog>(),
310 std::mem::size_of::<*mut c_void>()
311 );
312 }
313}