[go: up one dir, main page]

sdl2/
log.rs

1use crate::sys;
2use std::convert::TryInto;
3use std::ffi::{CStr, CString};
4use std::ptr::null_mut;
5
6#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
7pub enum Category {
8    Application,
9    Error,
10    Assert,
11    System,
12    Audio,
13    Video,
14    Render,
15    Input,
16    Test,
17    Custom,
18    Unknown,
19}
20
21impl Category {
22    #[allow(dead_code)]
23    fn from_ll(value: u32) -> Category {
24        if value == sys::SDL_LogCategory::SDL_LOG_CATEGORY_APPLICATION as u32 {
25            Category::Application
26        } else if value == sys::SDL_LogCategory::SDL_LOG_CATEGORY_ERROR as u32 {
27            Category::Error
28        } else if value == sys::SDL_LogCategory::SDL_LOG_CATEGORY_ASSERT as u32 {
29            Category::Assert
30        } else if value == sys::SDL_LogCategory::SDL_LOG_CATEGORY_SYSTEM as u32 {
31            Category::System
32        } else if value == sys::SDL_LogCategory::SDL_LOG_CATEGORY_AUDIO as u32 {
33            Category::Audio
34        } else if value == sys::SDL_LogCategory::SDL_LOG_CATEGORY_VIDEO as u32 {
35            Category::Video
36        } else if value == sys::SDL_LogCategory::SDL_LOG_CATEGORY_RENDER as u32 {
37            Category::Render
38        } else if value == sys::SDL_LogCategory::SDL_LOG_CATEGORY_INPUT as u32 {
39            Category::Input
40        } else if value == sys::SDL_LogCategory::SDL_LOG_CATEGORY_TEST as u32 {
41            Category::Test
42        } else {
43            Category::Custom
44        }
45    }
46
47    fn into_ll(value: Category) -> u32 {
48        return match value {
49            Category::Application => sys::SDL_LogCategory::SDL_LOG_CATEGORY_APPLICATION as u32,
50            Category::Error => sys::SDL_LogCategory::SDL_LOG_CATEGORY_ERROR as u32,
51            Category::Assert => sys::SDL_LogCategory::SDL_LOG_CATEGORY_ASSERT as u32,
52            Category::System => sys::SDL_LogCategory::SDL_LOG_CATEGORY_SYSTEM as u32,
53            Category::Audio => sys::SDL_LogCategory::SDL_LOG_CATEGORY_AUDIO as u32,
54            Category::Video => sys::SDL_LogCategory::SDL_LOG_CATEGORY_VIDEO as u32,
55            Category::Render => sys::SDL_LogCategory::SDL_LOG_CATEGORY_RENDER as u32,
56            Category::Input => sys::SDL_LogCategory::SDL_LOG_CATEGORY_INPUT as u32,
57            Category::Test => sys::SDL_LogCategory::SDL_LOG_CATEGORY_TEST as u32,
58            Category::Custom => sys::SDL_LogCategory::SDL_LOG_CATEGORY_CUSTOM as u32,
59            Category::Unknown => sys::SDL_LogCategory::SDL_LOG_CATEGORY_APPLICATION as u32,
60        };
61    }
62}
63
64#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
65pub enum Priority {
66    Verbose,
67    Debug,
68    Info,
69    Warn,
70    Error,
71    Critical,
72}
73
74impl Priority {
75    fn from_ll(value: sys::SDL_LogPriority) -> Priority {
76        use crate::sys::SDL_LogPriority::*;
77        match value {
78            SDL_LOG_PRIORITY_VERBOSE => Priority::Verbose,
79            SDL_LOG_PRIORITY_DEBUG => Priority::Debug,
80            SDL_LOG_PRIORITY_INFO => Priority::Info,
81            SDL_LOG_PRIORITY_WARN => Priority::Warn,
82            SDL_LOG_PRIORITY_ERROR => Priority::Error,
83            SDL_LOG_PRIORITY_CRITICAL | _ => Priority::Critical,
84        }
85    }
86}
87
88fn dummy(_priority: Priority, _category: Category, _message: &str) {}
89
90#[allow(non_upper_case_globals)]
91// NEVER make this public
92static mut custom_log_fn: fn(Priority, Category, &str) = dummy;
93
94unsafe extern "C" fn rust_sdl2_log_fn(
95    _userdata: *mut libc::c_void,
96    category: libc::c_int,
97    priority: sys::SDL_LogPriority,
98    message: *const libc::c_char,
99) {
100    let category = Category::from_ll(category as u32);
101    let priority = Priority::from_ll(priority);
102    let message = CStr::from_ptr(message).to_string_lossy();
103    custom_log_fn(priority, category, &message);
104}
105
106#[doc(alias = "SDL_LogSetOutputFunction")]
107pub fn set_output_function(callback: fn(Priority, Category, &str)) {
108    unsafe {
109        custom_log_fn = callback;
110        sys::SDL_LogSetOutputFunction(Some(rust_sdl2_log_fn), null_mut());
111    };
112}
113
114/// Standard log function which takes as priority INFO and
115/// as category APPLICATION
116#[doc(alias = "SDL_Log")]
117pub fn log(message: &str) {
118    let message = message.replace('%', "%%");
119    let message = CString::new(message).unwrap();
120    unsafe {
121        crate::sys::SDL_Log(message.as_ptr());
122    }
123}
124
125/// Log function which takes as priority CRITICAL and category APPLICATION
126#[doc(alias = "SDL_LogCritial")]
127pub fn log_critical(message: &str) {
128    log_with_category(message, Category::Application, Priority::Critical);
129}
130
131/// Log function which takes as priority DEBUG and category APPLICATION
132#[doc(alias = "SDL_LogDebug")]
133pub fn log_debug(message: &str) {
134    log_with_category(message, Category::Application, Priority::Debug);
135}
136
137/// Log function which takes as priority ERROR and category APPLICATION
138#[doc(alias = "SDL_LogError")]
139pub fn log_error(message: &str) {
140    log_with_category(message, Category::Application, Priority::Error);
141}
142
143/// Log function which takes as priority INFO and category APPLICATION
144#[doc(alias = "SDL_LogInfo")]
145pub fn log_info(message: &str) {
146    log_with_category(message, Category::Application, Priority::Info);
147}
148
149/// Log function which takes as priority VERBOSE and category APPLICATION
150#[doc(alias = "SDL_LogVerbose")]
151pub fn log_verbose(message: &str) {
152    log_with_category(message, Category::Application, Priority::Verbose);
153}
154
155/// Log function which takes as priority WARN and category APPLICATION
156#[doc(alias = "SDL_LogWarn")]
157pub fn log_warn(message: &str) {
158    log_with_category(message, Category::Application, Priority::Warn);
159}
160
161/// Log function where Category and Priority can be specified
162pub fn log_with_category(message: &str, category: Category, priority: Priority) {
163    let message = message.replace('%', "%%");
164    let message = CString::new(message).unwrap();
165    let uccategory = Category::into_ll(category).try_into();
166    let ccategory = match uccategory {
167        Err(_) => Category::into_ll(Category::Application).try_into().unwrap(),
168        Ok(success) => success,
169    };
170
171    unsafe {
172        match priority {
173            Priority::Critical => crate::sys::SDL_LogCritical(ccategory, message.as_ptr()),
174            Priority::Debug => crate::sys::SDL_LogDebug(ccategory, message.as_ptr()),
175            Priority::Error => crate::sys::SDL_LogError(ccategory, message.as_ptr()),
176            Priority::Info => crate::sys::SDL_LogInfo(ccategory, message.as_ptr()),
177            Priority::Verbose => crate::sys::SDL_LogVerbose(ccategory, message.as_ptr()),
178            Priority::Warn => crate::sys::SDL_LogWarn(ccategory, message.as_ptr()),
179        }
180    }
181}