evmole 0.8.4

Extracts function selectors and arguments from EVM bytecode
Documentation
use super::{U256, element::Element};
use std::fmt;

#[derive(Clone)]
pub struct Stack<T> {
    pub data: Vec<Element<T>>,
}

impl<T: fmt::Debug> fmt::Debug for Stack<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{} elems:", self.data.len())?;
        for el in &self.data {
            write!(
                f,
                "\n  - {} | {:?}",
                el.data
                    .iter()
                    .map(|v| format!("{v:02x}"))
                    .collect::<Vec<_>>()
                    .join(""),
                el.label
            )?;
        }
        Ok(())
    }
}

#[derive(Debug)]
pub struct IndexError;

impl std::fmt::Display for IndexError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "IndexError")
    }
}

impl std::error::Error for IndexError {}

type Result<T> = std::result::Result<T, IndexError>;

impl<T: Clone> Stack<T> {
    pub fn new() -> Self {
        Self { data: Vec::new() }
    }

    pub fn push(&mut self, val: Element<T>) {
        self.data.push(val)
    }

    pub fn pop(&mut self) -> Result<Element<T>> {
        self.data.pop().ok_or(IndexError)
    }

    pub fn peek(&self) -> Result<&Element<T>> {
        self.data.last().ok_or(IndexError)
    }

    pub fn peek_mut(&mut self) -> Result<&mut Element<T>> {
        self.data.last_mut().ok_or(IndexError)
    }

    pub fn dup(&mut self, n: u8) -> Result<()> {
        let idx = n as usize;
        if self.data.len() < idx {
            Err(IndexError)
        } else {
            self.data.push(self.data[self.data.len() - idx].clone());
            Ok(())
        }
    }

    pub fn swap(&mut self, n: u8) -> Result<()> {
        let dlen = self.data.len();
        let idx = n as usize;
        if dlen <= idx {
            Err(IndexError)
        } else {
            self.data.swap(dlen - 1, dlen - 1 - idx);
            Ok(())
        }
    }

    pub fn push_data(&mut self, data: [u8; 32]) {
        self.data.push(Element { data, label: None });
    }

    pub fn push_uint(&mut self, val: U256) {
        self.push_data(val.to_be_bytes());
    }

    pub fn pop_uint(&mut self) -> Result<U256> {
        match self.data.pop() {
            Some(v) => Ok(v.into()),
            None => Err(IndexError),
        }
    }
}