#![allow(clippy::missing_panics_doc, clippy::should_implement_trait)]
use core::ffi::c_void;
use std::ptr::NonNull;
use crate::bridge_support::{bridge_ptr_result, c_string_arg, sanitized_c_string};
use crate::error::LogError;
use crate::ffi;
use crate::os_log::{Level, OSLog};
use crate::os_signpost_id::OSSignpostId;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Privacy {
Public,
Private,
}
impl Privacy {
const fn raw(self) -> i32 {
match self {
Self::Public => 0,
Self::Private => 1,
}
}
}
const fn severity_for_level(level: Level) -> i32 {
match level {
Level::Default => 0,
Level::Debug => 2,
Level::Info => 3,
Level::Error => 6,
Level::Fault => 8,
}
}
pub struct Logger {
ptr: NonNull<c_void>,
}
impl Logger {
fn bridge_default() -> Self {
Self {
ptr: NonNull::new(unsafe { ffi::apple_log_logger_default() })
.expect("Swift bridge never returns NULL for Logger.default"),
}
}
pub fn new(subsystem: &str, category: &str) -> Result<Self, LogError> {
let subsystem = c_string_arg("subsystem", subsystem)?;
let category = c_string_arg("category", category)?;
let ptr = bridge_ptr_result("Logger::new", |error_out| unsafe {
ffi::apple_log_logger_create(subsystem.as_ptr(), category.as_ptr(), error_out)
})?;
Ok(Self { ptr })
}
pub fn from_os_log(log: &OSLog) -> Result<Self, LogError> {
let ptr = bridge_ptr_result("Logger::from_os_log", |error_out| unsafe {
ffi::apple_log_logger_from_os_log(log.as_ptr(), error_out)
})?;
Ok(Self { ptr })
}
#[must_use]
pub fn default() -> Self {
Self::bridge_default()
}
#[must_use]
pub fn disabled() -> Self {
Self {
ptr: NonNull::new(unsafe { ffi::apple_log_logger_disabled() })
.expect("Swift bridge never returns NULL for Logger.disabled"),
}
}
fn write(&self, severity: i32, privacy: Privacy, message: &str) {
let message = sanitized_c_string(message);
unsafe {
ffi::apple_log_logger_log(self.ptr.as_ptr(), severity, privacy.raw(), message.as_ptr());
}
}
pub fn log(&self, level: Level, message: &str) {
self.write(severity_for_level(level), Privacy::Public, message);
}
pub fn log_with_privacy(&self, level: Level, message: &str, privacy: Privacy) {
self.write(severity_for_level(level), privacy, message);
}
pub fn trace(&self, message: &str) {
self.write(1, Privacy::Public, message);
}
pub fn debug(&self, message: &str) {
self.write(2, Privacy::Public, message);
}
pub fn info(&self, message: &str) {
self.write(3, Privacy::Public, message);
}
pub fn notice(&self, message: &str) {
self.write(4, Privacy::Public, message);
}
pub fn warning(&self, message: &str) {
self.write(5, Privacy::Public, message);
}
pub fn error(&self, message: &str) {
self.write(6, Privacy::Public, message);
}
pub fn critical(&self, message: &str) {
self.write(7, Privacy::Public, message);
}
pub fn fault(&self, message: &str) {
self.write(8, Privacy::Public, message);
}
#[must_use]
pub fn is_enabled(&self, level: Level) -> bool {
unsafe { ffi::apple_log_logger_is_enabled(self.ptr.as_ptr(), level as u8) }
}
#[must_use]
pub fn signpost_id(&self) -> OSSignpostId {
OSSignpostId::from_u64(unsafe { ffi::apple_log_logger_signpost_id(self.ptr.as_ptr()) })
}
#[must_use]
pub fn signpost_id_from_pointer<T>(&self, pointer: *const T) -> OSSignpostId {
OSSignpostId::from_u64(unsafe {
ffi::apple_log_logger_signpost_id_from_pointer(self.ptr.as_ptr(), pointer.cast())
})
}
#[must_use]
pub fn signposts_enabled(&self) -> bool {
unsafe { ffi::apple_log_logger_signposts_enabled(self.ptr.as_ptr()) }
}
pub fn signpost_event(&self, id: OSSignpostId, name: &str, message: &str) {
let name = sanitized_c_string(name);
let message = sanitized_c_string(message);
unsafe {
ffi::apple_log_logger_signpost_event(
self.ptr.as_ptr(),
id.as_u64(),
name.as_ptr(),
message.as_ptr(),
);
}
}
pub fn signpost_interval_begin(&self, id: OSSignpostId, name: &str) {
let name = sanitized_c_string(name);
unsafe {
ffi::apple_log_logger_signpost_interval_begin(
self.ptr.as_ptr(),
id.as_u64(),
name.as_ptr(),
);
}
}
pub fn signpost_animation_interval_begin(&self, id: OSSignpostId, name: &str) {
let name = sanitized_c_string(name);
unsafe {
ffi::apple_log_logger_signpost_animation_interval_begin(
self.ptr.as_ptr(),
id.as_u64(),
name.as_ptr(),
);
}
}
pub fn signpost_interval_end(&self, id: OSSignpostId, name: &str) {
let name = sanitized_c_string(name);
unsafe {
ffi::apple_log_logger_signpost_interval_end(self.ptr.as_ptr(), id.as_u64(), name.as_ptr());
}
}
pub(crate) const fn as_ptr(&self) -> *mut c_void {
self.ptr.as_ptr()
}
}
impl Default for Logger {
fn default() -> Self {
Self::bridge_default()
}
}
impl Drop for Logger {
fn drop(&mut self) {
unsafe { ffi::apple_log_logger_release(self.ptr.as_ptr()) };
}
}