pub mod eof;
pub mod legacy;
pub use eof::Eof;
pub use legacy::{JumpTable, LegacyAnalyzedBytecode};
use crate::{keccak256, Bytes, B256, KECCAK_EMPTY};
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Bytecode {
LegacyRaw(Bytes),
LegacyAnalyzed(LegacyAnalyzedBytecode),
Eof(Eof),
}
impl Default for Bytecode {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl Bytecode {
#[inline]
pub fn new() -> Self {
Self::LegacyAnalyzed(LegacyAnalyzedBytecode::default())
}
#[inline]
pub fn legacy_jump_table(&self) -> Option<&JumpTable> {
match &self {
Self::LegacyAnalyzed(analyzed) => Some(analyzed.jump_table()),
_ => None,
}
}
pub fn hash_slow(&self) -> B256 {
if self.is_empty() {
KECCAK_EMPTY
} else {
keccak256(self.original_byte_slice())
}
}
#[inline]
pub const fn eof(&self) -> Option<&Eof> {
match self {
Self::Eof(eof) => Some(eof),
_ => None,
}
}
#[inline]
pub const fn is_eof(&self) -> bool {
matches!(self, Self::Eof(_))
}
#[inline]
pub fn new_raw(bytecode: Bytes) -> Self {
Self::LegacyRaw(bytecode)
}
pub unsafe fn new_analyzed(
bytecode: Bytes,
original_len: usize,
jump_table: JumpTable,
) -> Self {
Self::LegacyAnalyzed(LegacyAnalyzedBytecode::new(
bytecode,
original_len,
jump_table,
))
}
#[inline]
pub fn bytecode(&self) -> &Bytes {
match self {
Self::LegacyRaw(bytes) => bytes,
Self::LegacyAnalyzed(analyzed) => analyzed.bytecode(),
Self::Eof(eof) => eof
.body
.code(0)
.expect("Valid EOF has at least one code section"),
}
}
pub fn is_execution_ready(&self) -> bool {
!matches!(self, Self::LegacyRaw(_))
}
#[inline]
pub fn bytes(&self) -> Bytes {
match self {
Self::LegacyRaw(bytes) => bytes.clone(),
Self::LegacyAnalyzed(analyzed) => analyzed.bytecode().clone(),
Self::Eof(eof) => eof.raw().clone(),
}
}
#[inline]
pub fn bytes_slice(&self) -> &[u8] {
match self {
Self::LegacyRaw(bytes) => bytes,
Self::LegacyAnalyzed(analyzed) => analyzed.bytecode(),
Self::Eof(eof) => eof.raw(),
}
}
#[inline]
pub fn original_bytes(&self) -> Bytes {
match self {
Self::LegacyRaw(bytes) => bytes.clone(),
Self::LegacyAnalyzed(analyzed) => analyzed.original_bytes(),
Self::Eof(eof) => eof.raw().clone(),
}
}
#[inline]
pub fn original_byte_slice(&self) -> &[u8] {
match self {
Self::LegacyRaw(bytes) => bytes,
Self::LegacyAnalyzed(analyzed) => analyzed.original_byte_slice(),
Self::Eof(eof) => eof.raw(),
}
}
#[inline]
pub fn len(&self) -> usize {
match self {
Self::LegacyRaw(bytes) => bytes.len(),
Self::LegacyAnalyzed(analyzed) => analyzed.original_len(),
Self::Eof(eof) => eof.size(),
}
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}