aboutsummaryrefslogtreecommitdiffstats
path: root/examples/fuzz.rs
blob: f02536824b94a2be4eb5f4fdb91092d6eb79c5d6 (plain) (blame)
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use std::io::Read as _;

#[path = "../tests/helpers/mod.rs"]
mod helpers;

fn check_full(vt_base: &vt100::Screen, idx: usize) {
    let mut input = vec![];
    input.extend(vt_base.state_formatted());
    let mut vt_full = vt100::Parser::default();
    vt_full.process(&input);
    assert!(
        helpers::compare_screens(vt_full.screen(), vt_base),
        "{}: full:\n{}",
        idx,
        helpers::format_bytes(&input),
    );
}

fn check_diff_empty(
    vt_base: &vt100::Screen,
    empty: &vt100::Screen,
    idx: usize,
) {
    let mut input = vec![];
    input.extend(vt_base.state_diff(empty));
    let mut vt_diff_empty = vt100::Parser::default();
    vt_diff_empty.process(&input);
    assert!(
        helpers::compare_screens(vt_diff_empty.screen(), vt_base),
        "{}: diff-empty:\n{}",
        idx,
        helpers::format_bytes(&input),
    );
}

fn check_diff(
    vt_base: &vt100::Screen,
    vt_diff: &mut vt100::Parser,
    prev: &vt100::Screen,
    idx: usize,
) {
    let mut input = vec![];
    input.extend(vt_base.state_diff(prev));
    vt_diff.process(&input);
    assert!(
        helpers::compare_screens(vt_diff.screen(), vt_base),
        "{}: diff:\n{}",
        idx,
        helpers::format_bytes(&input),
    );
}

fn check_rows(vt_base: &vt100::Screen, idx: usize) {
    let mut input = vec![];
    let mut wrapped = false;
    for (idx, row) in vt_base.rows_formatted(0, 80).enumerate() {
        input.extend(b"\x1b[m");
        if !wrapped {
            input.extend(format!("\x1b[{}H", idx + 1).as_bytes());
        }
        input.extend(&row);
        wrapped = vt_base.row_wrapped(idx.try_into().unwrap());
    }
    input.extend(b"\x1b[m");
    input.extend(&vt_base.cursor_state_formatted());
    input.extend(&vt_base.attributes_formatted());
    input.extend(&vt_base.input_mode_formatted());
    input.extend(&vt_base.title_formatted());
    let mut vt_rows = vt100::Parser::default();
    vt_rows.process(&input);
    assert!(
        helpers::compare_screens(vt_rows.screen(), vt_base),
        "{}: rows:\n{}",
        idx,
        helpers::format_bytes(&input),
    );
}

fn read_byte() -> Option<u8> {
    let mut byte = [0];
    match std::io::stdin().read(&mut byte) {
        Ok(bytes) => {
            if bytes != 1 {
                return None;
            }
        }
        Err(e) => {
            eprintln!("{e}");
            return None;
        }
    }
    Some(byte[0])
}

fn main() {
    let mut vt_base = vt100::Parser::default();
    let mut vt_diff = vt100::Parser::default();
    let mut prev_screen = vt_base.screen().clone();
    let empty_screen = vt100::Parser::default().screen().clone();
    let mut idx = 0;
    while let Some(byte) = read_byte() {
        vt_base.process(&[byte]);

        check_full(vt_base.screen(), idx);
        check_diff_empty(vt_base.screen(), &empty_screen, idx);
        check_diff(vt_base.screen(), &mut vt_diff, &prev_screen, idx);
        check_rows(vt_base.screen(), idx);

        prev_screen = vt_base.screen().clone();
        idx += 1;
    }
}