use num_bigint::BigUint;
use num_traits::Num;
use pathfinder_crypto::Felt;
use serde::{Deserialize, Serialize};
use crate::EntryPoint;
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
pub struct CasmContractClass {
pub bytecode: Vec<Felt>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub bytecode_segment_lengths: Option<NestedIntList>,
pub compiler_version: String,
pub hints: serde_json::Value,
pub entry_points_by_type: CasmContractEntryPoints,
pub prime: BigUintAsHex,
}
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
pub struct CasmContractEntryPoints {
#[serde(rename = "EXTERNAL")]
pub external: Vec<CasmContractEntryPoint>,
#[serde(rename = "L1_HANDLER")]
pub l1_handler: Vec<CasmContractEntryPoint>,
#[serde(rename = "CONSTRUCTOR")]
pub constructor: Vec<CasmContractEntryPoint>,
}
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
pub struct CasmContractEntryPoint {
pub selector: EntryPoint,
pub offset: usize,
pub builtins: Vec<String>,
}
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
#[serde(transparent)]
pub struct BigUintAsHex {
#[serde(
serialize_with = "serialize_big_uint",
deserialize_with = "deserialize_big_uint"
)]
pub value: BigUint,
}
pub fn serialize_big_uint<S>(num: &BigUint, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&format!("{num:#x}"))
}
pub fn deserialize_big_uint<'a, D>(deserializer: D) -> Result<BigUint, D::Error>
where
D: serde::Deserializer<'a>,
{
let s = &<String as serde::Deserialize>::deserialize(deserializer)?;
match s.strip_prefix("0x") {
Some(num_no_prefix) => BigUint::from_str_radix(num_no_prefix, 16)
.map_err(|error| serde::de::Error::custom(format!("{error}"))),
None => Err(serde::de::Error::custom(format!(
"{s} does not start with `0x` is missing."
))),
}
}
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
#[serde(untagged)]
pub enum NestedIntList {
Leaf(usize),
Node(Vec<NestedIntList>),
}
impl TryFrom<&str> for CasmContractClass {
type Error = serde_json::Error;
fn try_from(value: &str) -> Result<Self, Self::Error> {
serde_json::from_str(value)
}
}