1#[cfg(unix)]
4use std::os::unix::io::{AsFd, AsRawFd};
5use std::{
6 boxed::Box as Box_,
7 sync::{Arc, Mutex, OnceLock},
8};
9
10use crate::{GStr, GString, LogWriterOutput, ffi, translate::*};
11
12#[derive(Debug)]
13pub struct LogHandlerId(u32);
14
15#[doc(hidden)]
16impl FromGlib<u32> for LogHandlerId {
17 #[inline]
18 unsafe fn from_glib(value: u32) -> Self {
19 Self(value)
20 }
21}
22
23#[doc(hidden)]
24impl IntoGlib for LogHandlerId {
25 type GlibType = u32;
26
27 #[inline]
28 fn into_glib(self) -> u32 {
29 self.0
30 }
31}
32
33#[derive(Copy, Clone, Debug, PartialEq, Eq)]
34pub enum LogLevel {
35 #[doc(alias = "G_LOG_LEVEL_ERROR")]
36 Error,
37 #[doc(alias = "G_LOG_LEVEL_CRITICAL")]
38 Critical,
39 #[doc(alias = "G_LOG_LEVEL_WARNING")]
40 Warning,
41 #[doc(alias = "G_LOG_LEVEL_MESSAGE")]
42 Message,
43 #[doc(alias = "G_LOG_LEVEL_INFO")]
44 Info,
45 #[doc(alias = "G_LOG_LEVEL_DEBUG")]
46 Debug,
47}
48
49#[doc(hidden)]
50impl IntoGlib for LogLevel {
51 type GlibType = u32;
52
53 #[inline]
54 fn into_glib(self) -> u32 {
55 match self {
56 Self::Error => ffi::G_LOG_LEVEL_ERROR,
57 Self::Critical => ffi::G_LOG_LEVEL_CRITICAL,
58 Self::Warning => ffi::G_LOG_LEVEL_WARNING,
59 Self::Message => ffi::G_LOG_LEVEL_MESSAGE,
60 Self::Info => ffi::G_LOG_LEVEL_INFO,
61 Self::Debug => ffi::G_LOG_LEVEL_DEBUG,
62 }
63 }
64}
65
66#[doc(hidden)]
67impl FromGlib<u32> for LogLevel {
68 #[inline]
69 unsafe fn from_glib(value: u32) -> Self {
70 if value & ffi::G_LOG_LEVEL_ERROR != 0 {
71 Self::Error
72 } else if value & ffi::G_LOG_LEVEL_CRITICAL != 0 {
73 Self::Critical
74 } else if value & ffi::G_LOG_LEVEL_WARNING != 0 {
75 Self::Warning
76 } else if value & ffi::G_LOG_LEVEL_MESSAGE != 0 {
77 Self::Message
78 } else if value & ffi::G_LOG_LEVEL_INFO != 0 {
79 Self::Info
80 } else if value & ffi::G_LOG_LEVEL_DEBUG != 0 {
81 Self::Debug
82 } else {
83 panic!("Unknown log level: {value}")
84 }
85 }
86}
87
88impl LogLevel {
89 #[doc(hidden)]
90 pub fn priority(&self) -> &'static str {
91 match self {
92 Self::Error => "3",
93 Self::Critical => "4",
94 Self::Warning => "4",
95 Self::Message => "5",
96 Self::Info => "6",
97 Self::Debug => "7",
98 }
99 }
100}
101
102bitflags::bitflags! {
103 #[doc(alias = "GLogLevelFlags")]
104 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
105 pub struct LogLevels: u32 {
106 #[doc(alias = "G_LOG_LEVEL_ERROR")]
107 const LEVEL_ERROR = ffi::G_LOG_LEVEL_ERROR;
108 #[doc(alias = "G_LOG_LEVEL_CRITICAL")]
109 const LEVEL_CRITICAL = ffi::G_LOG_LEVEL_CRITICAL;
110 #[doc(alias = "G_LOG_LEVEL_WARNING")]
111 const LEVEL_WARNING = ffi::G_LOG_LEVEL_WARNING;
112 #[doc(alias = "G_LOG_LEVEL_MESSAGE")]
113 const LEVEL_MESSAGE = ffi::G_LOG_LEVEL_MESSAGE;
114 #[doc(alias = "G_LOG_LEVEL_INFO")]
115 const LEVEL_INFO = ffi::G_LOG_LEVEL_INFO;
116 #[doc(alias = "G_LOG_LEVEL_DEBUG")]
117 const LEVEL_DEBUG = ffi::G_LOG_LEVEL_DEBUG;
118 }
119}
120
121#[doc(hidden)]
122impl IntoGlib for LogLevels {
123 type GlibType = ffi::GLogLevelFlags;
124
125 #[inline]
126 fn into_glib(self) -> ffi::GLogLevelFlags {
127 self.bits()
128 }
129}
130
131#[doc(hidden)]
132impl FromGlib<ffi::GLogLevelFlags> for LogLevels {
133 #[inline]
134 unsafe fn from_glib(value: ffi::GLogLevelFlags) -> Self {
135 Self::from_bits_truncate(value)
136 }
137}
138
139fn to_log_flags(fatal: bool, recursion: bool) -> u32 {
140 (if fatal { ffi::G_LOG_FLAG_FATAL } else { 0 })
141 | if recursion {
142 ffi::G_LOG_FLAG_RECURSION
143 } else {
144 0
145 }
146}
147
148#[doc(alias = "g_log_set_handler_full")]
149pub fn log_set_handler<P: Fn(Option<&str>, LogLevel, &str) + Send + Sync + 'static>(
150 log_domain: Option<&str>,
151 log_levels: LogLevels,
152 fatal: bool,
153 recursion: bool,
154 log_func: P,
155) -> LogHandlerId {
156 let log_func_data: Box_<P> = Box_::new(log_func);
157 unsafe extern "C" fn log_func_func<
158 P: Fn(Option<&str>, LogLevel, &str) + Send + Sync + 'static,
159 >(
160 log_domain: *const libc::c_char,
161 log_level: ffi::GLogLevelFlags,
162 message: *const libc::c_char,
163 user_data: ffi::gpointer,
164 ) {
165 unsafe {
166 let log_domain: Borrowed<Option<GString>> = from_glib_borrow(log_domain);
167 let message: Borrowed<GString> = from_glib_borrow(message);
168 let callback: &P = &*(user_data as *mut _);
169 (*callback)(
170 (*log_domain).as_ref().map(|s| s.as_str()),
171 from_glib(log_level),
172 message.as_str(),
173 );
174 }
175 }
176 let log_func = Some(log_func_func::<P> as _);
177 unsafe extern "C" fn destroy_func<
178 P: Fn(Option<&str>, LogLevel, &str) + Send + Sync + 'static,
179 >(
180 data: ffi::gpointer,
181 ) {
182 unsafe {
183 let _callback: Box_<P> = Box_::from_raw(data as *mut _);
184 }
185 }
186 let destroy_call4 = Some(destroy_func::<P> as _);
187 let super_callback0: Box_<P> = log_func_data;
188 unsafe {
189 from_glib(ffi::g_log_set_handler_full(
190 log_domain.to_glib_none().0,
191 log_levels.into_glib() | to_log_flags(fatal, recursion),
192 log_func,
193 Box_::into_raw(super_callback0) as *mut _,
194 destroy_call4,
195 ))
196 }
197}
198
199#[doc(alias = "g_log_remove_handler")]
200pub fn log_remove_handler(log_domain: Option<&str>, handler_id: LogHandlerId) {
201 unsafe {
202 ffi::g_log_remove_handler(log_domain.to_glib_none().0, handler_id.into_glib());
203 }
204}
205
206#[doc(alias = "g_log_set_always_fatal")]
207pub fn log_set_always_fatal(fatal_levels: LogLevels) -> LogLevels {
208 unsafe { from_glib(ffi::g_log_set_always_fatal(fatal_levels.into_glib())) }
209}
210
211#[doc(alias = "g_log_set_fatal_mask")]
212pub fn log_set_fatal_mask(log_domain: Option<&str>, fatal_levels: LogLevels) -> LogLevels {
213 unsafe {
214 from_glib(ffi::g_log_set_fatal_mask(
215 log_domain.to_glib_none().0,
216 fatal_levels.into_glib(),
217 ))
218 }
219}
220
221type PrintCallback = dyn Fn(&str) + Send + Sync + 'static;
222
223fn print_handler() -> &'static Mutex<Option<Arc<PrintCallback>>> {
224 static MUTEX: OnceLock<Mutex<Option<Arc<PrintCallback>>>> = OnceLock::new();
225 MUTEX.get_or_init(|| Mutex::new(None))
226}
227
228#[doc(alias = "g_set_print_handler")]
231pub fn set_print_handler<P: Fn(&str) + Send + Sync + 'static>(func: P) {
232 unsafe extern "C" fn func_func(string: *const libc::c_char) {
233 unsafe {
234 if let Some(callback) = print_handler()
235 .lock()
236 .expect("Failed to lock PRINT_HANDLER")
237 .as_ref()
238 .map(Arc::clone)
239 {
240 let string: Borrowed<GString> = from_glib_borrow(string);
241 (*callback)(string.as_str())
242 }
243 }
244 }
245 *print_handler()
246 .lock()
247 .expect("Failed to lock PRINT_HANDLER to change callback") = Some(Arc::new(func));
248 unsafe { ffi::g_set_print_handler(Some(func_func as _)) };
249}
250
251pub fn unset_print_handler() {
254 *print_handler()
255 .lock()
256 .expect("Failed to lock PRINT_HANDLER to remove callback") = None;
257 unsafe { ffi::g_set_print_handler(None) };
258}
259
260fn printerr_handler() -> &'static Mutex<Option<Arc<PrintCallback>>> {
261 static MUTEX: OnceLock<Mutex<Option<Arc<PrintCallback>>>> = OnceLock::new();
262 MUTEX.get_or_init(|| Mutex::new(None))
263}
264
265#[doc(alias = "g_set_printerr_handler")]
268pub fn set_printerr_handler<P: Fn(&str) + Send + Sync + 'static>(func: P) {
269 unsafe extern "C" fn func_func(string: *const libc::c_char) {
270 unsafe {
271 if let Some(callback) = printerr_handler()
272 .lock()
273 .expect("Failed to lock PRINTERR_HANDLER")
274 .as_ref()
275 .map(Arc::clone)
276 {
277 let string: Borrowed<GString> = from_glib_borrow(string);
278 (*callback)(string.as_str())
279 }
280 }
281 }
282 *printerr_handler()
283 .lock()
284 .expect("Failed to lock PRINTERR_HANDLER to change callback") = Some(Arc::new(func));
285 unsafe { ffi::g_set_printerr_handler(Some(func_func as _)) };
286}
287
288pub fn unset_printerr_handler() {
291 *printerr_handler()
292 .lock()
293 .expect("Failed to lock PRINTERR_HANDLER to remove callback") = None;
294 unsafe { ffi::g_set_printerr_handler(None) };
295}
296
297type LogCallback = dyn Fn(Option<&str>, LogLevel, &str) + Send + Sync + 'static;
298
299fn default_handler() -> &'static Mutex<Option<Arc<LogCallback>>> {
300 static MUTEX: OnceLock<Mutex<Option<Arc<LogCallback>>>> = OnceLock::new();
301 MUTEX.get_or_init(|| Mutex::new(None))
302}
303
304#[doc(alias = "g_log_set_default_handler")]
307pub fn log_set_default_handler<P: Fn(Option<&str>, LogLevel, &str) + Send + Sync + 'static>(
308 log_func: P,
309) {
310 unsafe extern "C" fn func_func(
311 log_domain: *const libc::c_char,
312 log_levels: ffi::GLogLevelFlags,
313 message: *const libc::c_char,
314 _user_data: ffi::gpointer,
315 ) {
316 unsafe {
317 if let Some(callback) = default_handler()
318 .lock()
319 .expect("Failed to lock DEFAULT_HANDLER")
320 .as_ref()
321 .map(Arc::clone)
322 {
323 let log_domain: Borrowed<Option<GString>> = from_glib_borrow(log_domain);
324 let message: Borrowed<GString> = from_glib_borrow(message);
325 (*callback)(
326 (*log_domain).as_ref().map(|s| s.as_str()),
327 from_glib(log_levels),
328 message.as_str(),
329 );
330 }
331 }
332 }
333 *default_handler()
334 .lock()
335 .expect("Failed to lock DEFAULT_HANDLER to change callback") = Some(Arc::new(log_func));
336 unsafe { ffi::g_log_set_default_handler(Some(func_func as _), std::ptr::null_mut()) };
337}
338
339#[doc(alias = "g_log_set_default_handler")]
342pub fn log_unset_default_handler() {
343 *default_handler()
344 .lock()
345 .expect("Failed to lock DEFAULT_HANDLER to remove callback") = None;
346 unsafe {
347 ffi::g_log_set_default_handler(Some(ffi::g_log_default_handler), std::ptr::null_mut())
348 };
349}
350
351#[doc(alias = "g_log_default_handler")]
352pub fn log_default_handler(log_domain: Option<&str>, log_level: LogLevel, message: Option<&str>) {
353 unsafe {
354 ffi::g_log_default_handler(
355 log_domain.to_glib_none().0,
356 log_level.into_glib(),
357 message.to_glib_none().0,
358 std::ptr::null_mut(),
359 )
360 }
361}
362
363#[repr(transparent)]
371#[derive(Debug)]
372#[doc(alias = "GLogField")]
373pub struct LogField<'a>(ffi::GLogField, std::marker::PhantomData<&'a GStr>);
374
375impl<'a> LogField<'a> {
376 pub fn new(key: &'a GStr, value: &[u8]) -> Self {
379 let (value, length) = if value.is_empty() {
380 (&[0u8] as &[u8], -1isize)
383 } else {
384 (value, value.len().try_into().unwrap())
385 };
386 Self(
387 ffi::GLogField {
388 key: key.as_ptr(),
389 value: value.as_ptr() as *const _,
390 length,
391 },
392 Default::default(),
393 )
394 }
395 pub fn new_user_data(key: &'a GStr, data: usize) -> Self {
405 Self(
406 ffi::GLogField {
407 key: key.as_ptr(),
408 value: data as *const _,
409 length: 0,
410 },
411 Default::default(),
412 )
413 }
414 pub fn key(&self) -> &str {
417 unsafe { std::ffi::CStr::from_ptr(self.0.key as *const _) }
418 .to_str()
419 .unwrap()
420 }
421 pub fn value_bytes(&self) -> Option<&[u8]> {
425 match self.0.length {
426 0 => None,
427 n if n < 0 => {
428 Some(unsafe { std::ffi::CStr::from_ptr(self.0.value as *const _) }.to_bytes())
429 }
430 _ => Some(unsafe {
431 std::slice::from_raw_parts(self.0.value as *const u8, self.0.length as usize)
432 }),
433 }
434 }
435 pub fn value_str(&self) -> Option<&str> {
439 std::str::from_utf8(self.value_bytes()?).ok()
440 }
441 pub fn user_data(&self) -> Option<usize> {
445 (self.0.length == 0).then_some(self.0.value as usize)
446 }
447}
448
449type WriterCallback = dyn Fn(LogLevel, &[LogField<'_>]) -> LogWriterOutput + Send + Sync + 'static;
450
451static WRITER_FUNC: OnceLock<Box<WriterCallback>> = OnceLock::new();
452
453#[doc(alias = "g_log_set_writer_func")]
454pub fn log_set_writer_func<
455 P: Fn(LogLevel, &[LogField<'_>]) -> LogWriterOutput + Send + Sync + 'static,
456>(
457 writer_func: P,
458) {
459 if WRITER_FUNC.set(Box::new(writer_func)).is_err() {
460 panic!("Writer func can only be set once");
461 }
462 unsafe extern "C" fn writer_trampoline(
463 log_level: ffi::GLogLevelFlags,
464 fields: *const ffi::GLogField,
465 n_fields: libc::size_t,
466 _user_data: ffi::gpointer,
467 ) -> ffi::GLogWriterOutput {
468 unsafe {
469 let writer_func = WRITER_FUNC.get().unwrap();
470 let fields = std::slice::from_raw_parts(fields as *const LogField<'_>, n_fields);
471 writer_func(from_glib(log_level), fields).into_glib()
472 }
473 }
474 unsafe {
475 ffi::g_log_set_writer_func(Some(writer_trampoline), std::ptr::null_mut(), None);
476 }
477}
478
479#[macro_export]
480#[doc(hidden)]
481macro_rules! g_log_inner {
482 ($log_domain:expr, $log_level:expr, $format:literal $(,$arg:expr)* $(,)?) => {{
483 let mut w = $crate::GStringBuilder::default();
484
485 if !std::fmt::Write::write_fmt(&mut w, std::format_args!($format, $($arg),*)).is_err() {
487 unsafe {
488 $crate::ffi::g_log(
489 $crate::translate::ToGlibPtr::to_glib_none(&$log_domain).0,
490 <$crate::LogLevel as $crate::translate::IntoGlib>::into_glib(
491 $log_level
492 ),
493 b"%s\0".as_ptr() as *const _,
494 $crate::translate::ToGlibPtr::<*const std::os::raw::c_char>::to_glib_none(
495 &w.into_string()
496 ).0,
497 );
498 }
499 }
500 }};
501}
502
503#[macro_export]
544macro_rules! g_log {
545 ($log_level:expr, $format:literal $(,$arg:expr)* $(,)?) => {{
546 $crate::g_log_inner!(None::<&str>, $log_level, $format, $($arg),*);
547 }};
548 ($log_domain:expr, $log_level:expr, $format:literal $(,$arg:expr)* $(,)?) => {{
549 let log_domain = <Option<&str> as std::convert::From<_>>::from($log_domain);
550 $crate::g_log_inner!(log_domain, $log_level, $format, $($arg),*);
551 }};
552}
553
554#[macro_export]
582macro_rules! g_error {
583 ($log_domain:expr, $format:literal, $($arg:expr),* $(,)?) => {{
584 $crate::g_log!($log_domain, $crate::LogLevel::Error, $format, $($arg),*);
585 }};
586 ($log_domain:expr, $format:literal $(,)?) => {{
587 $crate::g_log!($log_domain, $crate::LogLevel::Error, $format);
588 }};
589}
590
591#[macro_export]
619macro_rules! g_critical {
620 ($log_domain:expr, $format:literal, $($arg:expr),* $(,)?) => {{
621 $crate::g_log!($log_domain, $crate::LogLevel::Critical, $format, $($arg),*);
622 }};
623 ($log_domain:expr, $format:literal $(,)?) => {{
624 $crate::g_log!($log_domain, $crate::LogLevel::Critical, $format);
625 }};
626}
627
628#[macro_export]
656macro_rules! g_warning {
657 ($log_domain:expr, $format:literal, $($arg:expr),* $(,)?) => {{
658 $crate::g_log!($log_domain, $crate::LogLevel::Warning, $format, $($arg),*);
659 }};
660 ($log_domain:expr, $format:literal $(,)?) => {{
661 $crate::g_log!($log_domain, $crate::LogLevel::Warning, $format);
662 }};
663}
664
665#[macro_export]
693macro_rules! g_message {
694 ($log_domain:expr, $format:literal, $($arg:expr),* $(,)?) => {{
695 $crate::g_log!($log_domain, $crate::LogLevel::Message, $format, $($arg),*);
696 }};
697 ($log_domain:expr, $format:literal $(,)?) => {{
698 $crate::g_log!($log_domain, $crate::LogLevel::Message, $format);
699 }};
700}
701
702#[macro_export]
730macro_rules! g_info {
731 ($log_domain:expr, $format:literal, $($arg:expr),* $(,)?) => {{
732 $crate::g_log!($log_domain, $crate::LogLevel::Info, $format, $($arg),*);
733 }};
734 ($log_domain:expr, $format:literal $(,)?) => {{
735 $crate::g_log!($log_domain, $crate::LogLevel::Info, $format);
736 }};
737}
738
739#[macro_export]
767macro_rules! g_debug {
768 ($log_domain:expr, $format:literal, $($arg:expr),* $(,)?) => {{
769 $crate::g_log!($log_domain, $crate::LogLevel::Debug, $format, $($arg),*);
770 }};
771 ($log_domain:expr, $format:literal $(,)?) => {{
772 $crate::g_log!($log_domain, $crate::LogLevel::Debug, $format);
773 }};
774}
775
776#[doc(hidden)]
777#[macro_export]
778macro_rules! g_print_inner {
779 ($func:ident, $format:expr $(, $arg:expr)* $(,)?) => {{
780 let mut w = $crate::GStringBuilder::default();
781
782 if !std::fmt::Write::write_fmt(&mut w, std::format_args!($format, $($arg),*)).is_err() {
784 unsafe {
785 $crate::ffi::$func(
786 b"%s\0".as_ptr() as *const _,
787 $crate::translate::ToGlibPtr::<*const std::os::raw::c_char>::to_glib_none(
788 &w.into_string()
789 ).0,
790 );
791 }
792 }
793 }};
794}
795
796#[macro_export]
817macro_rules! g_print {
818 ($format:expr $(,$arg:expr)* $(,)?) => {{
819 $crate::g_print_inner!(g_print, $format, $($arg),*);
820 }};
821}
822
823#[macro_export]
844macro_rules! g_printerr {
845 ($format:expr $(, $arg:expr)* $(,)?) => {{
846 $crate::g_print_inner!(g_printerr, $format, $($arg),*);
847 }};
848}
849
850#[macro_export]
887macro_rules! log_structured {
888 ($log_domain:expr, $log_level:expr, {$($key:expr => $format:expr $(,$arg:expr)* $(,)?);+ $(;)?} $(,)?) => {{
889 let log_domain = <Option<&str> as std::convert::From<_>>::from($log_domain);
890 let log_domain_str = log_domain.unwrap_or_default();
891 let level: $crate::LogLevel = $log_level;
892 let field_count =
893 <[()]>::len(&[$($crate::log_structured_inner!(@clear $key)),+])
894 + log_domain.map(|_| 2usize).unwrap_or(1usize)
895 + 3;
896
897 let mut line = [0u8; 32]; let line = {
899 use std::io::Write;
900
901 let mut cursor = std::io::Cursor::new(&mut line[..]);
902 std::write!(&mut cursor, "{}", line!()).unwrap();
903 let pos = cursor.position() as usize;
904 &line[..pos]
905 };
906
907 $crate::log_structured_array(
908 level,
909 &[
910 $crate::LogField::new(
911 $crate::gstr!("PRIORITY"),
912 level.priority().as_bytes(),
913 ),
914 $crate::LogField::new(
915 $crate::gstr!("CODE_FILE"),
916 file!().as_bytes(),
917 ),
918 $crate::LogField::new(
919 $crate::gstr!("CODE_LINE"),
920 line,
921 ),
922 $crate::LogField::new(
923 $crate::gstr!("CODE_FUNC"),
924 $crate::function_name!().as_bytes(),
925 ),
926 $(
927 $crate::LogField::new(
928 $crate::log_structured_inner!(@key $key),
929 $crate::log_structured_inner!(@value $format $(,$arg)*),
930 ),
931 )+
932 $crate::LogField::new(
933 $crate::gstr!("GLIB_DOMAIN"),
934 log_domain_str.as_bytes(),
935 ),
936 ][0..field_count],
937 )
938 }};
939}
940
941#[doc(hidden)]
942#[macro_export]
943macro_rules! log_structured_inner {
944 (@clear $($_:tt)*) => { () };
945 (@key $key:literal) => { $crate::gstr!($key) };
946 (@key $key:expr) => { std::convert::AsRef::<$crate::GStr>::as_ref(&$key) };
947 (@value $value:expr) => { std::convert::AsRef::<[u8]>::as_ref(&$value) };
948 (@value $format:expr $(,$arg:expr)+) => {
949 {
950 let mut builder = $crate::GStringBuilder::default();
951 if std::fmt::Write::write_fmt(&mut builder, format_args!($format, $($arg),+)).is_err() {
952 return;
953 }
954 builder.into_string()
955 }.as_str().as_bytes()
956 };
957}
958
959#[doc(alias = "g_log_structured_array")]
960#[inline]
961pub fn log_structured_array(log_level: LogLevel, fields: &[LogField<'_>]) {
962 unsafe {
963 ffi::g_log_structured_array(
964 log_level.into_glib(),
965 fields.as_ptr() as *const ffi::GLogField,
966 fields.len(),
967 )
968 }
969}
970
971#[doc(alias = "g_log_variant")]
972#[inline]
973pub fn log_variant(log_domain: Option<&str>, log_level: LogLevel, fields: &crate::Variant) {
974 unsafe {
975 ffi::g_log_variant(
976 log_domain.to_glib_none().0,
977 log_level.into_glib(),
978 fields.to_glib_none().0,
979 );
980 }
981}
982
983#[cfg(unix)]
984#[cfg_attr(docsrs, doc(cfg(unix)))]
985#[doc(alias = "g_log_writer_supports_color")]
986#[inline]
987pub fn log_writer_supports_color(output_fd: impl AsFd) -> bool {
988 unsafe {
989 from_glib(ffi::g_log_writer_supports_color(
990 output_fd.as_fd().as_raw_fd(),
991 ))
992 }
993}
994
995#[cfg(unix)]
996#[cfg_attr(docsrs, doc(cfg(unix)))]
997#[doc(alias = "g_log_writer_is_journald")]
998#[inline]
999pub fn log_writer_is_journald(output_fd: impl AsFd) -> bool {
1000 unsafe { from_glib(ffi::g_log_writer_is_journald(output_fd.as_fd().as_raw_fd())) }
1001}
1002
1003#[doc(alias = "g_log_writer_format_fields")]
1004#[inline]
1005pub fn log_writer_format_fields(
1006 log_level: LogLevel,
1007 fields: &[LogField<'_>],
1008 use_color: bool,
1009) -> GString {
1010 unsafe {
1011 from_glib_full(ffi::g_log_writer_format_fields(
1012 log_level.into_glib(),
1013 fields.as_ptr() as *const ffi::GLogField,
1014 fields.len(),
1015 use_color.into_glib(),
1016 ))
1017 }
1018}
1019
1020#[doc(alias = "g_log_writer_journald")]
1021#[inline]
1022pub fn log_writer_journald(log_level: LogLevel, fields: &[LogField<'_>]) -> LogWriterOutput {
1023 unsafe {
1024 from_glib(ffi::g_log_writer_journald(
1025 log_level.into_glib(),
1026 fields.as_ptr() as *const ffi::GLogField,
1027 fields.len(),
1028 std::ptr::null_mut(),
1029 ))
1030 }
1031}
1032
1033#[doc(alias = "g_log_writer_standard_streams")]
1034#[inline]
1035pub fn log_writer_standard_streams(
1036 log_level: LogLevel,
1037 fields: &[LogField<'_>],
1038) -> LogWriterOutput {
1039 unsafe {
1040 from_glib(ffi::g_log_writer_standard_streams(
1041 log_level.into_glib(),
1042 fields.as_ptr() as *const ffi::GLogField,
1043 fields.len(),
1044 std::ptr::null_mut(),
1045 ))
1046 }
1047}
1048
1049#[doc(alias = "g_log_writer_default")]
1050#[inline]
1051pub fn log_writer_default(log_level: LogLevel, fields: &[LogField<'_>]) -> LogWriterOutput {
1052 unsafe {
1053 from_glib(ffi::g_log_writer_default(
1054 log_level.into_glib(),
1055 fields.as_ptr() as *const ffi::GLogField,
1056 fields.len(),
1057 std::ptr::null_mut(),
1058 ))
1059 }
1060}
1061
1062#[cfg(feature = "v2_68")]
1073#[cfg_attr(docsrs, doc(cfg(feature = "v2_68")))]
1074#[doc(alias = "g_log_writer_default_set_use_stderr")]
1075#[inline]
1076pub unsafe fn log_writer_default_set_use_stderr(use_stderr: bool) {
1077 unsafe {
1078 ffi::g_log_writer_default_set_use_stderr(use_stderr.into_glib());
1079 }
1080}
1081
1082#[cfg(feature = "v2_68")]
1083#[cfg_attr(docsrs, doc(cfg(feature = "v2_68")))]
1084#[doc(alias = "g_log_writer_default_would_drop")]
1085#[inline]
1086pub fn log_writer_default_would_drop(log_level: LogLevel, log_domain: Option<&str>) -> bool {
1087 unsafe {
1088 from_glib(ffi::g_log_writer_default_would_drop(
1089 log_level.into_glib(),
1090 log_domain.to_glib_none().0,
1091 ))
1092 }
1093}