tidecoin_primitives/script/
builder.rs1use core::fmt;
4
5use super::{Error, Script, ScriptBuf};
6use crate::opcodes::all::{
7 OP_CHECKMULTISIG, OP_CHECKMULTISIGVERIFY, OP_CHECKSIG, OP_CHECKSIGVERIFY, OP_EQUAL,
8 OP_EQUALVERIFY, OP_NUMEQUAL, OP_NUMEQUALVERIFY, OP_VERIFY,
9};
10use crate::opcodes::Opcode;
11use crate::prelude::Vec;
12
13#[derive(PartialEq, Eq, Clone)]
15pub struct Builder<T>(ScriptBuf<T>, Option<Opcode>);
16
17impl<T> Builder<T> {
18 pub const fn new() -> Self {
20 Self(ScriptBuf::new(), None)
21 }
22
23 pub fn with_capacity(capacity: usize) -> Self {
25 Self(ScriptBuf::with_capacity(capacity), None)
26 }
27
28 pub fn len(&self) -> usize {
30 self.0.len()
31 }
32
33 pub fn is_empty(&self) -> bool {
35 self.0.is_empty()
36 }
37
38 pub fn push_int(mut self, n: i32) -> Result<Self, Error> {
44 self.0.push_int(n)?;
45 self.1 = None;
46 Ok(self)
47 }
48
49 #[must_use]
51 pub fn push_int_unchecked(mut self, n: i64) -> Self {
52 self.0.push_int_unchecked(n);
53 self.1 = None;
54 self
55 }
56
57 #[must_use]
59 pub fn push_int_non_minimal(mut self, data: i64) -> Self {
60 self.0.push_int_non_minimal(data);
61 self.1 = None;
62 self
63 }
64
65 #[must_use]
67 pub fn push_slice<D: AsRef<[u8]>>(mut self, data: D) -> Self {
68 self.0.push_slice(data);
69 self.1 = None;
70 self
71 }
72
73 #[must_use]
75 pub fn push_slice_non_minimal<D: AsRef<[u8]>>(mut self, data: D) -> Self {
76 self.0.push_slice_non_minimal(data);
77 self.1 = None;
78 self
79 }
80
81 #[must_use]
83 pub fn push_opcode(mut self, opcode: Opcode) -> Self {
84 self.0.push_opcode(opcode);
85 self.1 = Some(opcode);
86 self
87 }
88
89 #[must_use]
91 pub fn push_verify(mut self) -> Self {
92 match opcode_to_verify(self.1) {
93 Some(opcode) => {
94 self.0.as_byte_vec().pop();
95 self.push_opcode(opcode)
96 }
97 None => self.push_opcode(OP_VERIFY),
98 }
99 }
100
101 pub fn into_script(self) -> ScriptBuf<T> {
103 self.0
104 }
105
106 pub fn into_bytes(self) -> Vec<u8> {
108 self.0.into_bytes()
109 }
110
111 pub fn as_script(&self) -> &Script<T> {
113 self.0.as_script()
114 }
115
116 pub fn as_bytes(&self) -> &[u8] {
118 self.0.as_bytes()
119 }
120}
121
122impl<T> Default for Builder<T> {
123 fn default() -> Self {
124 Self::new()
125 }
126}
127
128impl<T> From<Vec<u8>> for Builder<T> {
129 fn from(v: Vec<u8>) -> Self {
130 let script = ScriptBuf::from_bytes(v);
131 let last_op = script.last_opcode();
132 Self(script, last_op)
133 }
134}
135
136impl<T> fmt::Display for Builder<T> {
137 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
138 fmt::Display::fmt(&self.0, f)
139 }
140}
141
142impl<T> fmt::Debug for Builder<T> {
143 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
144 fmt::Display::fmt(self, f)
145 }
146}
147
148fn opcode_to_verify(opcode: Option<Opcode>) -> Option<Opcode> {
149 opcode.and_then(|opcode| match opcode {
150 OP_EQUAL => Some(OP_EQUALVERIFY),
151 OP_NUMEQUAL => Some(OP_NUMEQUALVERIFY),
152 OP_CHECKSIG => Some(OP_CHECKSIGVERIFY),
153 OP_CHECKMULTISIG => Some(OP_CHECKMULTISIGVERIFY),
154 _ => None,
155 })
156}