Make Script::fmt_asm a static method and add Script::str_asm

This makes it convenient to print/construct the script assembly on
byte slices withoout having to clone them to copy them to create a
Script struct.
This commit is contained in:
Steven Roose 2021-02-10 14:23:38 +01:00
parent 96fa4b7d9b
commit 851a3a15c0
No known key found for this signature in database
GPG Key ID: 2F2A88D7F8D68E87
1 changed files with 25 additions and 15 deletions

View File

@ -458,11 +458,11 @@ impl Script {
Ok(bitcoinconsensus::verify (&self.0[..], amount, spending, index)?) Ok(bitcoinconsensus::verify (&self.0[..], amount, spending, index)?)
} }
/// Write the assembly decoding of the script to the formatter. /// Write the assembly decoding of the script bytes to the formatter.
pub fn fmt_asm(&self, f: &mut dyn fmt::Write) -> fmt::Result { pub fn bytes_to_asm_fmt(script: &[u8], f: &mut dyn fmt::Write) -> fmt::Result {
let mut index = 0; let mut index = 0;
while index < self.0.len() { while index < script.len() {
let opcode = opcodes::All::from(self.0[index]); let opcode = opcodes::All::from(script[index]);
index += 1; index += 1;
let data_len = if let opcodes::Class::PushBytes(n) = opcode.classify() { let data_len = if let opcodes::Class::PushBytes(n) = opcode.classify() {
@ -470,31 +470,31 @@ impl Script {
} else { } else {
match opcode { match opcode {
opcodes::all::OP_PUSHDATA1 => { opcodes::all::OP_PUSHDATA1 => {
if self.0.len() < index + 1 { if script.len() < index + 1 {
f.write_str("<unexpected end>")?; f.write_str("<unexpected end>")?;
break; break;
} }
match read_uint(&self.0[index..], 1) { match read_uint(&script[index..], 1) {
Ok(n) => { index += 1; n as usize } Ok(n) => { index += 1; n as usize }
Err(_) => { f.write_str("<bad length>")?; break; } Err(_) => { f.write_str("<bad length>")?; break; }
} }
} }
opcodes::all::OP_PUSHDATA2 => { opcodes::all::OP_PUSHDATA2 => {
if self.0.len() < index + 2 { if script.len() < index + 2 {
f.write_str("<unexpected end>")?; f.write_str("<unexpected end>")?;
break; break;
} }
match read_uint(&self.0[index..], 2) { match read_uint(&script[index..], 2) {
Ok(n) => { index += 2; n as usize } Ok(n) => { index += 2; n as usize }
Err(_) => { f.write_str("<bad length>")?; break; } Err(_) => { f.write_str("<bad length>")?; break; }
} }
} }
opcodes::all::OP_PUSHDATA4 => { opcodes::all::OP_PUSHDATA4 => {
if self.0.len() < index + 4 { if script.len() < index + 4 {
f.write_str("<unexpected end>")?; f.write_str("<unexpected end>")?;
break; break;
} }
match read_uint(&self.0[index..], 4) { match read_uint(&script[index..], 4) {
Ok(n) => { index += 4; n as usize } Ok(n) => { index += 4; n as usize }
Err(_) => { f.write_str("<bad length>")?; break; } Err(_) => { f.write_str("<bad length>")?; break; }
} }
@ -513,8 +513,8 @@ impl Script {
// Write any pushdata // Write any pushdata
if data_len > 0 { if data_len > 0 {
f.write_str(" ")?; f.write_str(" ")?;
if index + data_len <= self.0.len() { if index + data_len <= script.len() {
for ch in &self.0[index..index + data_len] { for ch in &script[index..index + data_len] {
write!(f, "{:02x}", ch)?; write!(f, "{:02x}", ch)?;
} }
index += data_len; index += data_len;
@ -527,11 +527,21 @@ impl Script {
Ok(()) Ok(())
} }
/// Write the assembly decoding of the script to the formatter.
pub fn fmt_asm(&self, f: &mut dyn fmt::Write) -> fmt::Result {
Script::bytes_to_asm_fmt(self.as_ref(), f)
}
/// Create an assembly decoding of the script in the given byte slice.
pub fn bytes_to_asm(script: &[u8]) -> String {
let mut buf = String::new();
Script::bytes_to_asm_fmt(script, &mut buf).unwrap();
buf
}
/// Get the assembly decoding of the script. /// Get the assembly decoding of the script.
pub fn asm(&self) -> String { pub fn asm(&self) -> String {
let mut buf = String::new(); Script::bytes_to_asm(self.as_ref())
self.fmt_asm(&mut buf).unwrap();
buf
} }
} }