Skip to main content

revive_common/
object.rs

1//! The revive binary object helper module.
2
3use std::str::FromStr;
4
5use serde::{Deserialize, Serialize};
6
7/// The binary object format.
8///
9/// Unlinked contracts are stored in a different object format
10/// than final (linked) contract blobs.
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
12pub enum ObjectFormat {
13    /// The unlinked ELF object format.
14    ELF,
15    /// The fully linked PVM format.
16    PVM,
17}
18
19impl ObjectFormat {
20    pub const PVM_MAGIC: [u8; 4] = *b"PVM\0";
21    pub const ELF_MAGIC: [u8; 4] = [0x7f, b'E', b'L', b'F'];
22}
23
24impl FromStr for ObjectFormat {
25    type Err = anyhow::Error;
26
27    fn from_str(value: &str) -> Result<Self, Self::Err> {
28        match value {
29            "ELF" => Ok(Self::ELF),
30            "PVM" => Ok(Self::PVM),
31            _ => anyhow::bail!(
32                "Unknown object format: {value}. Supported formats: {}, {}",
33                Self::ELF,
34                Self::PVM,
35            ),
36        }
37    }
38}
39
40impl TryFrom<&[u8]> for ObjectFormat {
41    type Error = &'static str;
42
43    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
44        if value.starts_with(&Self::PVM_MAGIC) {
45            return Ok(Self::PVM);
46        }
47        if value.starts_with(&Self::ELF_MAGIC) {
48            return Ok(Self::ELF);
49        }
50        Err("expected a contract object")
51    }
52}
53
54impl std::fmt::Display for ObjectFormat {
55    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56        match self {
57            Self::ELF => write!(f, "ELF"),
58            Self::PVM => write!(f, "PVM"),
59        }
60    }
61}