1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
//! Unified routines to print data.

use atty::{self, Stream};
use libc::{self, signal};
use std::{fmt::Display, time::SystemTime};

/// Write a solution line (`"s ..."`) to stdout.
pub fn print_solution(verdict: &str) {
    write_to_stdout!("s {}\n", verdict);
}

/// Write a key-value pair to stdout.
pub fn print_key_value(key: &str, value: impl Display) {
    requires!(key.len() < 35);
    comment!("{:<35} {:>15}", format!("{}:", key), value);
}

/// We handle SIGPIPE ourselves to avoid printing errors.
pub fn install_signal_handler() {
    // You can't disable assert! in Rust so this is fine.
    assert!(unsafe { signal(libc::SIGPIPE, libc::SIG_DFL) } != libc::SIG_ERR);
}

/// Our version of `std::unreachable()`, unsafe if invariants are disabled.
pub fn unreachable() -> ! {
    invariant!(false, "unreachable");
    unsafe { std::hint::unreachable_unchecked() }
}

/// Check whether we are writing to a terminal.
pub fn is_a_tty() -> bool {
    atty::is(Stream::Stdout)
}

/// A RAII object that prints a timing message when it is destroyed.
pub struct Timer {
    /// The name of the thing that is being timed
    name: &'static str,
    /// The start time, set at construction time
    start: SystemTime,
    /// Whether this timer should be silenced
    pub disabled: bool,
}

impl Timer {
    /// Create a timer with a given name.
    pub fn name(name: &'static str) -> Timer {
        Timer {
            name,
            start: SystemTime::now(),
            disabled: false,
        }
    }
}

impl Drop for Timer {
    /// Write the elapsed time as comment.
    fn drop(&mut self) {
        if self.disabled {
            return;
        }
        let elapsed_time = self.start.elapsed().expect("failed to get time");
        print_key_value(
            &format!("{} (s)", self.name),
            format!(
                "{}.{:03}",
                elapsed_time.as_secs(),
                elapsed_time.subsec_millis()
            ),
        );
    }
}