<commit_before>use godcoin::{prelude::*, script::*};
use std::{error::Error, num::ParseIntError};

#[derive(Clone, Debug)]
pub enum BuildError {
    EmptyScript,
    ScriptSizeOverflow,
    UnknownOp(String),
    MissingArgForOp(String),
    WifError(WifError),
    Other(String),
}

pub fn build(ops: &[String]) -> Result<Script, BuildError> {
    let mut builder = Builder::new();

    let mut iter = ops.iter();
    while let Some(op) = iter.next() {
        builder = match op.as_ref() {
            // Push value
            "OP_FALSE" => builder.try_push(OpFrame::False),
            "OP_TRUE" => builder.try_push(OpFrame::True),
            "OP_PUBKEY" => {
                let key = iter.next();
                if let Some(key) = key {
                    let key = PublicKey::from_wif(key).map_err(BuildError::WifError)?;
                    builder.try_push(OpFrame::PubKey(key))
                } else {
                    return Err(BuildError::MissingArgForOp(op.to_owned()));
                }
            }
            // Logic
            "OP_NOT" => builder.try_push(OpFrame::OpNot),
            "OP_IF" => builder.try_push(OpFrame::OpIf),
            "OP_ELSE" => builder.try_push(OpFrame::OpElse),
            "OP_ENDIF" => builder.try_push(OpFrame::OpEndIf),
            "OP_RETURN" => builder.try_push(OpFrame::OpReturn),
            // Crypto
            "OP_CHECKSIG" => builder.try_push(OpFrame::OpCheckSig),
            "OP_CHECKSIGFASTFAIL" => builder.try_push(OpFrame::OpCheckSigFastFail),
            "OP_CHECKMULTISIG" => {
                let threshold = iter
                    .next()
                    .ok_or_else(|| BuildError::MissingArgForOp(op.to_owned()))?
                    .parse()
                    .map_err(|e: ParseIntError| BuildError::Other(e.description().to_owned()))?;
                let key_count = iter
                    .next()
                    .ok_or_else(|| BuildError::MissingArgForOp(op.to_owned()))?
                    .parse()
                    .map_err(|e: ParseIntError| BuildError::Other(e.description().to_owned()))?;<commit_msg>CLI script builder supports pushing assets<commit_after>use godcoin::{prelude::*, script::*};
use std::{error::Error, num::ParseIntError};

#[derive(Clone, Debug)]
pub enum BuildError {
    EmptyScript,
    ScriptSizeOverflow,
    UnknownOp(String),
    MissingArgForOp(String),
    WifError(WifError),
    AssetParseError(AssetError),
    Other(String),
}

pub fn build(ops: &[String]) -> Result<Script, BuildError> {
    let mut builder = Builder::new();

    let mut iter = ops.iter();
    while let Some(op) = iter.next() {
        builder = match op.as_ref() {
            // Push value
            "OP_FALSE" => builder.try_push(OpFrame::False),
            "OP_TRUE" => builder.try_push(OpFrame::True),
            "OP_PUBKEY" => {
                let key = iter.next();
                if let Some(key) = key {
                    let key = PublicKey::from_wif(key).map_err(BuildError::WifError)?;
                    builder.try_push(OpFrame::PubKey(key))
                } else {
                    return Err(BuildError::MissingArgForOp(op.to_owned()));
                }
            }
            "OP_ASSET" => {
                let asset = iter.next();
                if let Some(asset) = asset {
                    let asset = asset.parse().map_err(BuildError::AssetParseError)?;
                    builder.try_push(OpFrame::Asset(asset))
                } else {
                    return Err(BuildError::MissingArgForOp(op.to_owned()));
                }
            }
            // Logic
            "OP_NOT" => builder.try_push(OpFrame::OpNot),
            "OP_IF" => builder.try_push(OpFrame::OpIf),
            "OP_ELSE" => builder.try_push(OpFrame::OpElse),
            "OP_ENDIF" => builder.try_push(OpFrame::OpEndIf),
            "OP_RETURN" => builder.try_push(OpFrame::OpReturn),
            // Crypto
            "OP_CHECKSIG" => builder.try_push(OpFrame::OpCheckSig),
            "OP_CHECKSIGFASTFAIL" => builder.try_push(OpFrame::OpCheckSigFastFail),
            "OP_CHECKMULTISIG" => {
                let threshold = iter
                    .next()
                    .ok_or_else(|| BuildError::MissingArgForOp(op.to_owned()))?
                    .parse()
                    .map_err(|e: ParseIntError| BuildError::Other(e.description().to_owned()))?;
                let key_count = iter
                    .next()
                    .ok_or_else(|| BuildError::MissingArgForOp(op.to_owned()))?
                    .parse()
                    .map_err(|e: ParseIntError| BuildError::Other(e.description().to_owned()))?;
{'fraction_non_alphanumeric': 0.14154175588865098, 'fraction_numerical': 0.0, 'mean_word_length': 1.899441340782123, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 30, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3418596', 'n_tokens_mistral': 1409, 'n_tokens_neox': 1364, 'n_words': 212}