wayland_backend/
debug.rs

1//! Debugging helpers to handle `WAYLAND_DEBUG` env variable.
2
3use std::{
4    fmt::Display,
5    os::unix::io::AsRawFd,
6    time::{SystemTime, UNIX_EPOCH},
7};
8
9use crate::protocol::Argument;
10
11/// The `WAYLAND_DEBUG` env variable is set to debug client.
12pub fn has_debug_client_env() -> bool {
13    matches!(std::env::var_os("WAYLAND_DEBUG"), Some(str) if str == "1" || str == "client")
14}
15
16/// Print the dispatched message to stderr in a following format:
17///
18/// `[timestamp] <- interface@id.msg_name(args)`
19#[cfg_attr(coverage, coverage(off))]
20pub fn print_dispatched_message<Id: Display, Fd: AsRawFd>(
21    interface: &str,
22    id: u32,
23    msg_name: &str,
24    args: &[Argument<Id, Fd>],
25) {
26    // Add timestamp to output.
27    print_timestamp();
28
29    eprint!(" <- {}@{}.{}, ({})", interface, id, msg_name, DisplaySlice(args));
30
31    // Add a new line.
32    eprintln!();
33}
34
35/// Print the send message to stderr in a following format:
36///
37/// `[timestamp] -> interface@id.msg_name(args)`
38#[cfg_attr(coverage, coverage(off))]
39pub fn print_send_message<Id: Display, Fd: AsRawFd>(
40    interface: &str,
41    id: u32,
42    msg_name: &str,
43    args: &[Argument<Id, Fd>],
44    discarded: bool,
45) {
46    // Add timestamp to output.
47    print_timestamp();
48
49    if discarded {
50        eprint!("[discarded]");
51    }
52
53    eprint!(" -> {}@{}.{}({})", interface, id, msg_name, DisplaySlice(args));
54
55    // Add a new line.
56    eprintln!();
57}
58
59pub(crate) struct DisplaySlice<'a, D>(pub &'a [D]);
60
61impl<D: Display> Display for DisplaySlice<'_, D> {
62    #[cfg_attr(coverage, coverage(off))]
63    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64        let mut it = self.0.iter();
65        if let Some(val) = it.next() {
66            write!(f, "{}", val)?;
67        }
68        for val in it {
69            write!(f, ", {}", val)?;
70        }
71        Ok(())
72    }
73}
74
75/// Print timestamp in seconds.microseconds format.
76#[cfg_attr(coverage, coverage(off))]
77fn print_timestamp() {
78    if let Ok(timestamp) = SystemTime::now().duration_since(UNIX_EPOCH) {
79        // NOTE this is all to make timestamps the same with libwayland, so the log doesn't look
80        // out of place when sys tries to log on their own.
81        let time = (timestamp.as_secs() * 1000000 + timestamp.subsec_nanos() as u64 / 1000) as u32;
82        // NOTE annotate timestamp so we know which library emmited the log entry.
83        eprint!("[{:7}.{:03}][rs]", time / 1000, time % 1000);
84    }
85}