summaryrefslogtreecommitdiffstats
path: root/third_party/rust/leb128/src/bin/leb128-repl.rs
blob: 4f6c43e36757eb08dd74fc884ac7a7fff7f9e5c4 (plain)
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
use leb128;

use std::io::{self, BufRead, Write};
use std::str;

fn display(bytes: &[u8]) -> String {
    let mut s = vec![];

    // Base 10.
    write!(&mut s, "{:?}\n", bytes).unwrap();

    // Hex.
    write!(&mut s, "[").unwrap();
    for (i, b) in bytes.iter().enumerate() {
        if i != 0 {
            write!(&mut s, ", ").unwrap();
        }
        write!(&mut s, "{:0x}", b).unwrap();
    }
    writeln!(&mut s, "]").unwrap();

    // Binary.
    write!(&mut s, "[").unwrap();
    for (i, b) in bytes.iter().enumerate() {
        if i != 0 {
            write!(&mut s, ", ").unwrap();
        }
        write!(&mut s, "{:08b}", b).unwrap();
    }
    writeln!(&mut s, "]").unwrap();

    String::from_utf8(s).unwrap()
}

fn main() {
    println!(
        "
LEB128 Read-Eval-Print-Loop!

Converts numbers to signed and unsigned LEB128 and displays the results in
base-10, hex, and binary.
"
    );

    let mut stdin = io::BufReader::new(io::stdin());
    let mut stdout = io::stdout();

    let mut buf = vec![];

    loop {
        stdout.write_all(b"> ").expect("failed to write to stdout");
        stdout.flush().expect("failed to flush stdout");

        buf.clear();
        let n = stdin
            .read_until(b'\n', &mut buf)
            .expect("failed to read line from stdin");
        if n == 0 {
            break;
        }

        let uleb = str::from_utf8(&buf)
            .ok()
            .and_then(|s| s.trim().parse().ok())
            .and_then(|n: u64| {
                let mut s = vec![];
                leb128::write::unsigned(&mut s, n).ok()?;
                Some(display(&s))
            })
            .unwrap_or_else(|| "error\n".into());
        stdout
            .write_all(b"# unsigned LEB128\n")
            .and_then(|_| stdout.write_all(uleb.as_bytes()))
            .and_then(|_| stdout.write_all(b"\n"))
            .expect("failed to write to stdout");

        let leb = str::from_utf8(&buf)
            .ok()
            .and_then(|s| s.trim().parse().ok())
            .and_then(|n: i64| {
                let mut s = vec![];
                leb128::write::signed(&mut s, n).ok()?;
                Some(display(&s))
            })
            .unwrap_or_else(|| "error\n".into());
        stdout
            .write_all(b"# signed LEB128\n")
            .and_then(|_| stdout.write_all(leb.as_bytes()))
            .and_then(|_| stdout.write_all(b"\n"))
            .expect("failed to write to stdout");

        stdout.flush().expect("failed to flush stdout");
    }
}