1#[cfg(unix)]
4use std::os::unix::io::AsRawFd;
5use std::{
6 boxed::Box as Box_,
7 sync::{Arc, Mutex, OnceLock},
8};
9
10use crate::{ffi, translate::*, GStr, GString, LogWriterOutput};
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 let log_domain: Borrowed<Option<GString>> = from_glib_borrow(log_domain);
166 let message: Borrowed<GString> = from_glib_borrow(message);
167 let callback: &P = &*(user_data as *mut _);
168 (*callback)(
169 (*log_domain).as_ref().map(|s| s.as_str()),
170 from_glib(log_level),
171 message.as_str(),
172 );
173 }
174 let log_func = Some(log_func_func::<P> as _);
175 unsafe extern "C" fn destroy_func<
176 P: Fn(Option<&str>, LogLevel, &str) + Send + Sync + 'static,
177 >(
178 data: ffi::gpointer,
179 ) {
180 let _callback: Box_<P> = Box_::from_raw(data as *mut _);
181 }
182 let destroy_call4 = Some(destroy_func::<P> as _);
183 let super_callback0: Box_<P> = log_func_data;
184 unsafe {
185 from_glib(ffi::g_log_set_handler_full(
186 log_domain.to_glib_none().0,
187 log_levels.into_glib() | to_log_flags(fatal, recursion),
188 log_func,
189 Box_::into_raw(super_callback0) as *mut _,
190 destroy_call4,
191 ))
192 }
193}
194
195#[doc(alias = "g_log_remove_handler")]
196pub fn log_remove_handler(log_domain: Option<&str>, handler_id: LogHandlerId) {
197 unsafe {
198 ffi::g_log_remove_handler(log_domain.to_glib_none().0, handler_id.into_glib());
199 }
200}
201
202#[doc(alias = "g_log_set_always_fatal")]
203pub fn log_set_always_fatal(fatal_levels: LogLevels) -> LogLevels {
204 unsafe { from_glib(ffi::g_log_set_always_fatal(fatal_levels.into_glib())) }
205}
206
207#[doc(alias = "g_log_set_fatal_mask")]
208pub fn log_set_fatal_mask(log_domain: Option<&str>, fatal_levels: LogLevels) -> LogLevels {
209 unsafe {
210 from_glib(ffi::g_log_set_fatal_mask(
211 log_domain.to_glib_none().0,
212 fatal_levels.into_glib(),
213 ))
214 }
215}
216
217type PrintCallback = dyn Fn(&str) + Send + Sync + 'static;
218
219fn print_handler() -> &'static Mutex<Option<Arc<PrintCallback>>> {
220 static MUTEX: OnceLock<Mutex<Option<Arc<PrintCallback>>>> = OnceLock::new();
221 MUTEX.get_or_init(|| Mutex::new(None))
222}
223
224#[doc(alias = "g_set_print_handler")]
227pub fn set_print_handler<P: Fn(&str) + Send + Sync + 'static>(func: P) {
228 unsafe extern "C" fn func_func(string: *const libc::c_char) {
229 if let Some(callback) = print_handler()
230 .lock()
231 .expect("Failed to lock PRINT_HANDLER")
232 .as_ref()
233 .map(Arc::clone)
234 {
235 let string: Borrowed<GString> = from_glib_borrow(string);
236 (*callback)(string.as_str())
237 }
238 }
239 *print_handler()
240 .lock()
241 .expect("Failed to lock PRINT_HANDLER to change callback") = Some(Arc::new(func));
242 unsafe { ffi::g_set_print_handler(Some(func_func as _)) };
243}
244
245pub fn unset_print_handler() {
248 *print_handler()
249 .lock()
250 .expect("Failed to lock PRINT_HANDLER to remove callback") = None;
251 unsafe { ffi::g_set_print_handler(None) };
252}
253
254fn printerr_handler() -> &'static Mutex<Option<Arc<PrintCallback>>> {
255 static MUTEX: OnceLock<Mutex<Option<Arc<PrintCallback>>>> = OnceLock::new();
256 MUTEX.get_or_init(|| Mutex::new(None))
257}
258
259#[doc(alias = "g_set_printerr_handler")]
262pub fn set_printerr_handler<P: Fn(&str) + Send + Sync + 'static>(func: P) {
263 unsafe extern "C" fn func_func(string: *const libc::c_char) {
264 if let Some(callback) = printerr_handler()
265 .lock()
266 .expect("Failed to lock PRINTERR_HANDLER")
267 .as_ref()
268 .map(Arc::clone)
269 {
270 let string: Borrowed<GString> = from_glib_borrow(string);
271 (*callback)(string.as_str())
272 }
273 }
274 *printerr_handler()
275 .lock()
276 .expect("Failed to lock PRINTERR_HANDLER to change callback") = Some(Arc::new(func));
277 unsafe { ffi::g_set_printerr_handler(Some(func_func as _)) };
278}
279
280pub fn unset_printerr_handler() {
283 *printerr_handler()
284 .lock()
285 .expect("Failed to lock PRINTERR_HANDLER to remove callback") = None;
286 unsafe { ffi::g_set_printerr_handler(None) };
287}
288
289type LogCallback = dyn Fn(Option<&str>, LogLevel, &str) + Send + Sync + 'static;
290
291fn default_handler() -> &'static Mutex<Option<Arc<LogCallback>>> {
292 static MUTEX: OnceLock<Mutex<Option<Arc<LogCallback>>>> = OnceLock::new();
293 MUTEX.get_or_init(|| Mutex::new(None))
294}
295
296#[doc(alias = "g_log_set_default_handler")]
299pub fn log_set_default_handler<P: Fn(Option<&str>, LogLevel, &str) + Send + Sync + 'static>(
300 log_func: P,
301) {
302 unsafe extern "C" fn func_func(
303 log_domain: *const libc::c_char,
304 log_levels: ffi::GLogLevelFlags,
305 message: *const libc::c_char,
306 _user_data: ffi::gpointer,
307 ) {
308 if let Some(callback) = default_handler()
309 .lock()
310 .expect("Failed to lock DEFAULT_HANDLER")
311 .as_ref()
312 .map(Arc::clone)
313 {
314 let log_domain: Borrowed<Option<GString>> = from_glib_borrow(log_domain);
315 let message: Borrowed<GString> = from_glib_borrow(message);
316 (*callback)(
317 (*log_domain).as_ref().map(|s| s.as_str()),
318 from_glib(log_levels),
319 message.as_str(),
320 );
321 }
322 }
323 *default_handler()
324 .lock()
325 .expect("Failed to lock DEFAULT_HANDLER to change callback") = Some(Arc::new(log_func));
326 unsafe { ffi::g_log_set_default_handler(Some(func_func as _), std::ptr::null_mut()) };
327}
328
329#[doc(alias = "g_log_set_default_handler")]
332pub fn log_unset_default_handler() {
333 *default_handler()
334 .lock()
335 .expect("Failed to lock DEFAULT_HANDLER to remove callback") = None;
336 unsafe {
337 ffi::g_log_set_default_handler(Some(ffi::g_log_default_handler), std::ptr::null_mut())
338 };
339}
340
341#[doc(alias = "g_log_default_handler")]
342pub fn log_default_handler(log_domain: Option<&str>, log_level: LogLevel, message: Option<&str>) {
343 unsafe {
344 ffi::g_log_default_handler(
345 log_domain.to_glib_none().0,
346 log_level.into_glib(),
347 message.to_glib_none().0,
348 std::ptr::null_mut(),
349 )
350 }
351}
352
353#[repr(transparent)]
361#[derive(Debug)]
362#[doc(alias = "GLogField")]
363pub struct LogField<'a>(ffi::GLogField, std::marker::PhantomData<&'a GStr>);
364
365impl<'a> LogField<'a> {
366 pub fn new(key: &'a GStr, value: &[u8]) -> Self {
369 let (value, length) = if value.is_empty() {
370 (&[0u8] as &[u8], -1isize)
373 } else {
374 (value, value.len().try_into().unwrap())
375 };
376 Self(
377 ffi::GLogField {
378 key: key.as_ptr(),
379 value: value.as_ptr() as *const _,
380 length,
381 },
382 Default::default(),
383 )
384 }
385 pub fn new_user_data(key: &'a GStr, data: usize) -> Self {
395 Self(
396 ffi::GLogField {
397 key: key.as_ptr(),
398 value: data as *const _,
399 length: 0,
400 },
401 Default::default(),
402 )
403 }
404 pub fn key(&self) -> &str {
407 unsafe { std::ffi::CStr::from_ptr(self.0.key as *const _) }
408 .to_str()
409 .unwrap()
410 }
411 pub fn value_bytes(&self) -> Option<&[u8]> {
415 match self.0.length {
416 0 => None,
417 n if n < 0 => {
418 Some(unsafe { std::ffi::CStr::from_ptr(self.0.value as *const _) }.to_bytes())
419 }
420 _ => Some(unsafe {
421 std::slice::from_raw_parts(self.0.value as *const u8, self.0.length as usize)
422 }),
423 }
424 }
425 pub fn value_str(&self) -> Option<&str> {
429 std::str::from_utf8(self.value_bytes()?).ok()
430 }
431 pub fn user_data(&self) -> Option<usize> {
435 (self.0.length == 0).then_some(self.0.value as usize)
436 }
437}
438
439type WriterCallback = dyn Fn(LogLevel, &[LogField<'_>]) -> LogWriterOutput + Send + Sync + 'static;
440
441static WRITER_FUNC: OnceLock<Box<WriterCallback>> = OnceLock::new();
442
443#[doc(alias = "g_log_set_writer_func")]
444pub fn log_set_writer_func<
445 P: Fn(LogLevel, &[LogField<'_>]) -> LogWriterOutput + Send + Sync + 'static,
446>(
447 writer_func: P,
448) {
449 if WRITER_FUNC.set(Box::new(writer_func)).is_err() {
450 panic!("Writer func can only be set once");
451 }
452 unsafe extern "C" fn writer_trampoline(
453 log_level: ffi::GLogLevelFlags,
454 fields: *const ffi::GLogField,
455 n_fields: libc::size_t,
456 _user_data: ffi::gpointer,
457 ) -> ffi::GLogWriterOutput {
458 let writer_func = WRITER_FUNC.get().unwrap();
459 let fields = std::slice::from_raw_parts(fields as *const LogField<'_>, n_fields);
460 writer_func(from_glib(log_level), fields).into_glib()
461 }
462 unsafe {
463 ffi::g_log_set_writer_func(Some(writer_trampoline), std::ptr::null_mut(), None);
464 }
465}
466
467#[macro_export]
468#[doc(hidden)]
469macro_rules! g_log_inner {
470 ($log_domain:expr, $log_level:expr, $format:literal $(,$arg:expr)* $(,)?) => {{
471 let mut w = $crate::GStringBuilder::default();
472
473 if !std::fmt::Write::write_fmt(&mut w, std::format_args!($format, $($arg),*)).is_err() {
475 unsafe {
476 $crate::ffi::g_log(
477 $crate::translate::ToGlibPtr::to_glib_none(&$log_domain).0,
478 <$crate::LogLevel as $crate::translate::IntoGlib>::into_glib(
479 $log_level
480 ),
481 b"%s\0".as_ptr() as *const _,
482 $crate::translate::ToGlibPtr::<*const std::os::raw::c_char>::to_glib_none(
483 &w.into_string()
484 ).0,
485 );
486 }
487 }
488 }};
489}
490
491#[macro_export]
532macro_rules! g_log {
533 ($log_level:expr, $format:literal $(,$arg:expr)* $(,)?) => {{
534 $crate::g_log_inner!(None::<&str>, $log_level, $format, $($arg),*);
535 }};
536 ($log_domain:expr, $log_level:expr, $format:literal $(,$arg:expr)* $(,)?) => {{
537 let log_domain = <Option<&str> as std::convert::From<_>>::from($log_domain);
538 $crate::g_log_inner!(log_domain, $log_level, $format, $($arg),*);
539 }};
540}
541
542#[macro_export]
570macro_rules! g_error {
571 ($log_domain:expr, $format:literal, $($arg:expr),* $(,)?) => {{
572 $crate::g_log!($log_domain, $crate::LogLevel::Error, $format, $($arg),*);
573 }};
574 ($log_domain:expr, $format:literal $(,)?) => {{
575 $crate::g_log!($log_domain, $crate::LogLevel::Error, $format);
576 }};
577}
578
579#[macro_export]
607macro_rules! g_critical {
608 ($log_domain:expr, $format:literal, $($arg:expr),* $(,)?) => {{
609 $crate::g_log!($log_domain, $crate::LogLevel::Critical, $format, $($arg),*);
610 }};
611 ($log_domain:expr, $format:literal $(,)?) => {{
612 $crate::g_log!($log_domain, $crate::LogLevel::Critical, $format);
613 }};
614}
615
616#[macro_export]
644macro_rules! g_warning {
645 ($log_domain:expr, $format:literal, $($arg:expr),* $(,)?) => {{
646 $crate::g_log!($log_domain, $crate::LogLevel::Warning, $format, $($arg),*);
647 }};
648 ($log_domain:expr, $format:literal $(,)?) => {{
649 $crate::g_log!($log_domain, $crate::LogLevel::Warning, $format);
650 }};
651}
652
653#[macro_export]
681macro_rules! g_message {
682 ($log_domain:expr, $format:literal, $($arg:expr),* $(,)?) => {{
683 $crate::g_log!($log_domain, $crate::LogLevel::Message, $format, $($arg),*);
684 }};
685 ($log_domain:expr, $format:literal $(,)?) => {{
686 $crate::g_log!($log_domain, $crate::LogLevel::Message, $format);
687 }};
688}
689
690#[macro_export]
718macro_rules! g_info {
719 ($log_domain:expr, $format:literal, $($arg:expr),* $(,)?) => {{
720 $crate::g_log!($log_domain, $crate::LogLevel::Info, $format, $($arg),*);
721 }};
722 ($log_domain:expr, $format:literal $(,)?) => {{
723 $crate::g_log!($log_domain, $crate::LogLevel::Info, $format);
724 }};
725}
726
727#[macro_export]
755macro_rules! g_debug {
756 ($log_domain:expr, $format:literal, $($arg:expr),* $(,)?) => {{
757 $crate::g_log!($log_domain, $crate::LogLevel::Debug, $format, $($arg),*);
758 }};
759 ($log_domain:expr, $format:literal $(,)?) => {{
760 $crate::g_log!($log_domain, $crate::LogLevel::Debug, $format);
761 }};
762}
763
764#[doc(hidden)]
765#[macro_export]
766macro_rules! g_print_inner {
767 ($func:ident, $format:expr $(, $arg:expr)* $(,)?) => {{
768 let mut w = $crate::GStringBuilder::default();
769
770 if !std::fmt::Write::write_fmt(&mut w, std::format_args!($format, $($arg),*)).is_err() {
772 unsafe {
773 $crate::ffi::$func(
774 b"%s\0".as_ptr() as *const _,
775 $crate::translate::ToGlibPtr::<*const std::os::raw::c_char>::to_glib_none(
776 &w.into_string()
777 ).0,
778 );
779 }
780 }
781 }};
782}
783
784#[macro_export]
805macro_rules! g_print {
806 ($format:expr $(,$arg:expr)* $(,)?) => {{
807 $crate::g_print_inner!(g_print, $format, $($arg),*);
808 }};
809}
810
811#[macro_export]
832macro_rules! g_printerr {
833 ($format:expr $(, $arg:expr)* $(,)?) => {{
834 $crate::g_print_inner!(g_printerr, $format, $($arg),*);
835 }};
836}
837
838#[macro_export]
875macro_rules! log_structured {
876 ($log_domain:expr, $log_level:expr, {$($key:expr => $format:expr $(,$arg:expr)* $(,)?);+ $(;)?} $(,)?) => {{
877 let log_domain = <Option<&str> as std::convert::From<_>>::from($log_domain);
878 let log_domain_str = log_domain.unwrap_or_default();
879 let level: $crate::LogLevel = $log_level;
880 let field_count =
881 <[()]>::len(&[$($crate::log_structured_inner!(@clear $key)),+])
882 + log_domain.map(|_| 2usize).unwrap_or(1usize)
883 + 3;
884
885 let mut line = [0u8; 32]; let line = {
887 use std::io::Write;
888
889 let mut cursor = std::io::Cursor::new(&mut line[..]);
890 std::write!(&mut cursor, "{}", line!()).unwrap();
891 let pos = cursor.position() as usize;
892 &line[..pos]
893 };
894
895 $crate::log_structured_array(
896 level,
897 &[
898 $crate::LogField::new(
899 $crate::gstr!("PRIORITY"),
900 level.priority().as_bytes(),
901 ),
902 $crate::LogField::new(
903 $crate::gstr!("CODE_FILE"),
904 file!().as_bytes(),
905 ),
906 $crate::LogField::new(
907 $crate::gstr!("CODE_LINE"),
908 line,
909 ),
910 $crate::LogField::new(
911 $crate::gstr!("CODE_FUNC"),
912 $crate::function_name!().as_bytes(),
913 ),
914 $(
915 $crate::LogField::new(
916 $crate::log_structured_inner!(@key $key),
917 $crate::log_structured_inner!(@value $format $(,$arg)*),
918 ),
919 )+
920 $crate::LogField::new(
921 $crate::gstr!("GLIB_DOMAIN"),
922 log_domain_str.as_bytes(),
923 ),
924 ][0..field_count],
925 )
926 }};
927}
928
929#[doc(hidden)]
930#[macro_export]
931macro_rules! log_structured_inner {
932 (@clear $($_:tt)*) => { () };
933 (@key $key:literal) => { $crate::gstr!($key) };
934 (@key $key:expr) => { std::convert::AsRef::<$crate::GStr>::as_ref(&$key) };
935 (@value $value:expr) => { std::convert::AsRef::<[u8]>::as_ref(&$value) };
936 (@value $format:expr $(,$arg:expr)+) => {
937 {
938 let mut builder = $crate::GStringBuilder::default();
939 if std::fmt::Write::write_fmt(&mut builder, format_args!($format, $($arg),+)).is_err() {
940 return;
941 }
942 builder.into_string()
943 }.as_str().as_bytes()
944 };
945}
946
947#[doc(alias = "g_log_structured_array")]
948#[inline]
949pub fn log_structured_array(log_level: LogLevel, fields: &[LogField<'_>]) {
950 unsafe {
951 ffi::g_log_structured_array(
952 log_level.into_glib(),
953 fields.as_ptr() as *const ffi::GLogField,
954 fields.len(),
955 )
956 }
957}
958
959#[doc(alias = "g_log_variant")]
960#[inline]
961pub fn log_variant(log_domain: Option<&str>, log_level: LogLevel, fields: &crate::Variant) {
962 unsafe {
963 ffi::g_log_variant(
964 log_domain.to_glib_none().0,
965 log_level.into_glib(),
966 fields.to_glib_none().0,
967 );
968 }
969}
970
971#[cfg(unix)]
972#[cfg_attr(docsrs, doc(cfg(unix)))]
973#[doc(alias = "g_log_writer_supports_color")]
974#[inline]
975pub fn log_writer_supports_color<T: AsRawFd>(output_fd: T) -> bool {
976 unsafe { from_glib(ffi::g_log_writer_supports_color(output_fd.as_raw_fd())) }
977}
978
979#[cfg(unix)]
980#[cfg_attr(docsrs, doc(cfg(unix)))]
981#[doc(alias = "g_log_writer_is_journald")]
982#[inline]
983pub fn log_writer_is_journald<T: AsRawFd>(output_fd: T) -> bool {
984 unsafe { from_glib(ffi::g_log_writer_is_journald(output_fd.as_raw_fd())) }
985}
986
987#[doc(alias = "g_log_writer_format_fields")]
988#[inline]
989pub fn log_writer_format_fields(
990 log_level: LogLevel,
991 fields: &[LogField<'_>],
992 use_color: bool,
993) -> GString {
994 unsafe {
995 from_glib_full(ffi::g_log_writer_format_fields(
996 log_level.into_glib(),
997 fields.as_ptr() as *const ffi::GLogField,
998 fields.len(),
999 use_color.into_glib(),
1000 ))
1001 }
1002}
1003
1004#[doc(alias = "g_log_writer_journald")]
1005#[inline]
1006pub fn log_writer_journald(log_level: LogLevel, fields: &[LogField<'_>]) -> LogWriterOutput {
1007 unsafe {
1008 from_glib(ffi::g_log_writer_journald(
1009 log_level.into_glib(),
1010 fields.as_ptr() as *const ffi::GLogField,
1011 fields.len(),
1012 std::ptr::null_mut(),
1013 ))
1014 }
1015}
1016
1017#[doc(alias = "g_log_writer_standard_streams")]
1018#[inline]
1019pub fn log_writer_standard_streams(
1020 log_level: LogLevel,
1021 fields: &[LogField<'_>],
1022) -> LogWriterOutput {
1023 unsafe {
1024 from_glib(ffi::g_log_writer_standard_streams(
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_default")]
1034#[inline]
1035pub fn log_writer_default(log_level: LogLevel, fields: &[LogField<'_>]) -> LogWriterOutput {
1036 unsafe {
1037 from_glib(ffi::g_log_writer_default(
1038 log_level.into_glib(),
1039 fields.as_ptr() as *const ffi::GLogField,
1040 fields.len(),
1041 std::ptr::null_mut(),
1042 ))
1043 }
1044}
1045
1046#[cfg(feature = "v2_68")]
1057#[cfg_attr(docsrs, doc(cfg(feature = "v2_68")))]
1058#[doc(alias = "g_log_writer_default_set_use_stderr")]
1059#[inline]
1060pub unsafe fn log_writer_default_set_use_stderr(use_stderr: bool) {
1061 ffi::g_log_writer_default_set_use_stderr(use_stderr.into_glib());
1062}
1063
1064#[cfg(feature = "v2_68")]
1065#[cfg_attr(docsrs, doc(cfg(feature = "v2_68")))]
1066#[doc(alias = "g_log_writer_default_would_drop")]
1067#[inline]
1068pub fn log_writer_default_would_drop(log_level: LogLevel, log_domain: Option<&str>) -> bool {
1069 unsafe {
1070 from_glib(ffi::g_log_writer_default_would_drop(
1071 log_level.into_glib(),
1072 log_domain.to_glib_none().0,
1073 ))
1074 }
1075}