tasm_lib/
io.rs

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
use std::fmt::Display;

use triton_vm::prelude::*;

pub mod read_input;
pub mod write_to_stdout;

#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub enum InputSource {
    StdIn,
    SecretIn,
}

impl Display for InputSource {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let str = match self {
            InputSource::StdIn => "stdin",
            InputSource::SecretIn => "secin",
        };

        write!(f, "{}", str)
    }
}

/// Return the code to write `n` words to output
/// ```text
/// BEFORE: _ [words; n]
/// AFTER:  _
/// ```
pub fn write_words(n: usize) -> Vec<LabelledInstruction> {
    let num_full_chunk_writes = n / 5;
    let num_remaining_words = n % 5;
    let mut instructions = vec![triton_instr!(write_io 5); num_full_chunk_writes];
    if num_remaining_words > 0 {
        instructions.extend(triton_asm!(write_io {
            num_remaining_words
        }));
    }

    instructions
}

impl InputSource {
    /// The name of the instruction that reads from this input source
    pub const fn instruction_name(&self) -> &str {
        match self {
            InputSource::StdIn => "read_io",
            InputSource::SecretIn => "divine",
        }
    }

    /// Return a string identifiying the input source and usable as assembly label
    pub fn label_friendly_name(&self) -> &str {
        match self {
            InputSource::StdIn => "stdin",
            InputSource::SecretIn => "secin",
        }
    }

    /// Return the code used to read `n` words from the input source.
    /// ```text
    /// BEFORE: _
    /// AFTER:  _ [read_words; n]
    /// ```
    pub fn read_words(&self, n: usize) -> Vec<LabelledInstruction> {
        let input_instruction = self.instruction_name();

        let num_full_chunk_reads = n / 5;
        let num_remaining_words = n % 5;
        let mut instructions =
            vec![triton_asm!({input_instruction} 5); num_full_chunk_reads].concat();
        if num_remaining_words > 0 {
            instructions.extend(triton_asm!({input_instruction} {num_remaining_words}));
        }

        instructions
    }
}