apple_log/
os_signposter.rs1#![allow(clippy::missing_panics_doc, clippy::should_implement_trait)]
2
3use core::ffi::c_void;
4use std::ptr::NonNull;
5
6use crate::bridge_support::{bridge_ptr_result, c_string_arg, sanitized_c_string};
7use crate::error::LogError;
8use crate::ffi;
9use crate::logger::Logger;
10use crate::os_log::OSLog;
11use crate::os_signpost_id::OSSignpostId;
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
15pub struct OSSignpostInterval {
16 id: OSSignpostId,
17 animation: bool,
18}
19
20impl OSSignpostInterval {
21 #[must_use]
22 pub const fn id(self) -> OSSignpostId {
23 self.id
24 }
25
26 #[must_use]
27 pub const fn is_animation(self) -> bool {
28 self.animation
29 }
30}
31
32pub struct OSSignposter {
34 ptr: NonNull<c_void>,
35}
36
37impl OSSignposter {
38 fn bridge_default() -> Self {
39 Self {
40 ptr: NonNull::new(unsafe { ffi::apple_log_os_signposter_default() })
41 .expect("Swift bridge never returns NULL for OSSignposter.default"),
42 }
43 }
44
45 pub fn new(subsystem: &str, category: &str) -> Result<Self, LogError> {
51 let subsystem = c_string_arg("subsystem", subsystem)?;
52 let category = c_string_arg("category", category)?;
53 let ptr = bridge_ptr_result("OSSignposter::new", |error_out| unsafe {
54 ffi::apple_log_os_signposter_create(subsystem.as_ptr(), category.as_ptr(), error_out)
55 })?;
56 Ok(Self { ptr })
57 }
58
59 pub fn from_os_log(log: &OSLog) -> Result<Self, LogError> {
65 let ptr = bridge_ptr_result("OSSignposter::from_os_log", |error_out| unsafe {
66 ffi::apple_log_os_signposter_from_os_log(log.as_ptr(), error_out)
67 })?;
68 Ok(Self { ptr })
69 }
70
71 pub fn from_logger(logger: &Logger) -> Result<Self, LogError> {
77 let ptr = bridge_ptr_result("OSSignposter::from_logger", |error_out| unsafe {
78 ffi::apple_log_os_signposter_from_logger(logger.as_ptr(), error_out)
79 })?;
80 Ok(Self { ptr })
81 }
82
83 #[must_use]
84 pub fn default() -> Self {
85 Self::bridge_default()
86 }
87
88 #[must_use]
89 pub fn disabled() -> Self {
90 Self {
91 ptr: NonNull::new(unsafe { ffi::apple_log_os_signposter_disabled() })
92 .expect("Swift bridge never returns NULL for OSSignposter.disabled"),
93 }
94 }
95
96 #[must_use]
97 pub fn is_enabled(&self) -> bool {
98 unsafe { ffi::apple_log_os_signposter_is_enabled(self.ptr.as_ptr()) }
99 }
100
101 #[must_use]
102 pub fn make_signpost_id(&self) -> OSSignpostId {
103 OSSignpostId::from_u64(unsafe {
104 ffi::apple_log_os_signposter_make_signpost_id(self.ptr.as_ptr())
105 })
106 }
107
108 #[must_use]
109 pub fn make_signpost_id_from_pointer<T>(&self, pointer: *const T) -> OSSignpostId {
110 OSSignpostId::from_u64(unsafe {
111 ffi::apple_log_os_signposter_make_signpost_id_from_pointer(
112 self.ptr.as_ptr(),
113 pointer.cast(),
114 )
115 })
116 }
117
118 pub fn emit_event(&self, name: &str, id: OSSignpostId, message: &str) {
119 let name = sanitized_c_string(name);
120 let message = sanitized_c_string(message);
121 unsafe {
122 ffi::apple_log_os_signposter_emit_event(
123 self.ptr.as_ptr(),
124 id.as_u64(),
125 name.as_ptr(),
126 message.as_ptr(),
127 );
128 }
129 }
130
131 #[must_use]
132 pub fn begin_interval(
133 &self,
134 name: &str,
135 id: OSSignpostId,
136 message: &str,
137 ) -> OSSignpostInterval {
138 let name = sanitized_c_string(name);
139 let message = sanitized_c_string(message);
140 unsafe {
141 ffi::apple_log_os_signposter_begin_interval(
142 self.ptr.as_ptr(),
143 id.as_u64(),
144 name.as_ptr(),
145 message.as_ptr(),
146 );
147 }
148 OSSignpostInterval {
149 id,
150 animation: false,
151 }
152 }
153
154 #[must_use]
155 pub fn begin_animation_interval(
156 &self,
157 name: &str,
158 id: OSSignpostId,
159 message: &str,
160 ) -> OSSignpostInterval {
161 let name = sanitized_c_string(name);
162 let message = sanitized_c_string(message);
163 unsafe {
164 ffi::apple_log_os_signposter_begin_animation_interval(
165 self.ptr.as_ptr(),
166 id.as_u64(),
167 name.as_ptr(),
168 message.as_ptr(),
169 );
170 }
171 OSSignpostInterval {
172 id,
173 animation: true,
174 }
175 }
176
177 pub fn end_interval(&self, name: &str, interval: OSSignpostInterval, message: &str) {
178 let name = sanitized_c_string(name);
179 let message = sanitized_c_string(message);
180 unsafe {
181 ffi::apple_log_os_signposter_end_interval(
182 self.ptr.as_ptr(),
183 interval.id.as_u64(),
184 name.as_ptr(),
185 message.as_ptr(),
186 );
187 }
188 }
189
190 pub fn with_interval_signpost<T>(
191 &self,
192 name: &str,
193 id: OSSignpostId,
194 message: &str,
195 around: impl FnOnce() -> T,
196 ) -> T {
197 let interval = self.begin_interval(name, id, message);
198 let result = around();
199 self.end_interval(name, interval, message);
200 result
201 }
202}
203
204impl Default for OSSignposter {
205 fn default() -> Self {
206 Self::bridge_default()
207 }
208}
209
210impl Drop for OSSignposter {
211 fn drop(&mut self) {
212 unsafe { ffi::apple_log_os_signposter_release(self.ptr.as_ptr()) };
213 }
214}