Skip to main content

mini_bitcoin_script/
token.rs

1use crate::opcode::Opcode;
2
3/// A parsed script element — either an opcode instruction or pushed data.
4///
5/// This is the output of the tokenizer and the input to the execution engine.
6/// `PushData` carries the raw bytes from any of the four push-data encodings.
7/// `Op` wraps a fieldless [`Opcode`] variant.
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub enum Token {
10    /// Data pushed onto the stack by a push-data instruction.
11    /// Covers: direct push (0x01-0x4b), OP_PUSHDATA1, OP_PUSHDATA2, OP_PUSHDATA4.
12    PushData(Vec<u8>),
13
14    /// An opcode instruction (any non-push operation).
15    Op(Opcode),
16}
17
18impl std::fmt::Display for Token {
19    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20        match self {
21            Token::PushData(data) => {
22                write!(f, "<")?;
23                for byte in data {
24                    write!(f, "{byte:02x}")?;
25                }
26                write!(f, ">")
27            }
28            Token::Op(opcode) => write!(f, "{opcode}"),
29        }
30    }
31}
32
33#[cfg(test)]
34mod tests {
35    use super::*;
36
37    #[test]
38    fn display_push_data() {
39        let token = Token::PushData(vec![0x89, 0xab, 0xcd, 0xef]);
40        assert_eq!(format!("{token}"), "<89abcdef>");
41    }
42
43    #[test]
44    fn display_empty_push_data() {
45        let token = Token::PushData(vec![]);
46        assert_eq!(format!("{token}"), "<>");
47    }
48
49    #[test]
50    fn display_opcode() {
51        let token = Token::Op(Opcode::OpDup);
52        assert_eq!(format!("{token}"), "OP_DUP");
53    }
54}