1 | //! Debugging helpers to handle `WAYLAND_DEBUG` env variable. |
2 | |
3 | use std::{ |
4 | fmt::Display, |
5 | os::unix::prelude::AsRawFd, |
6 | time::{SystemTime, UNIX_EPOCH}, |
7 | }; |
8 | |
9 | use crate::protocol::Argument; |
10 | |
11 | /// The `WAYLAND_DEBUG` env variable is set to debug client. |
12 | pub 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))] |
20 | pub 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))] |
39 | pub 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 | |
59 | pub(crate) struct DisplaySlice<'a, D>(pub &'a [D]); |
60 | |
61 | impl<'a, D: Display> Display for DisplaySlice<'a, D> { |
62 | #[cfg_attr (coverage, coverage(off))] |
63 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
64 | let mut it: Iter<'_, D> = self.0.iter(); |
65 | if let Some(val: &D) = it.next() { |
66 | write!(f, " {}" , val)?; |
67 | } |
68 | for val: &D 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))] |
77 | fn print_timestamp() { |
78 | if let Ok(timestamp: Duration) = 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: u32 = (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 | } |
86 | |