1use std::borrow::Cow;
2use std::fmt;
3
4use fake::{Dummy, Fake, Faker};
5use pathfinder_crypto::Felt;
6use rand::Rng;
7use serde::{Deserialize, Serialize};
8use serde_json::value::RawValue;
9use serde_with::serde_as;
10
11use crate::{ByteCodeOffset, EntryPoint};
12
13pub const CLASS_DEFINITION_MAX_ALLOWED_SIZE: u64 = 4 * 1024 * 1024;
14
15#[derive(Debug, Deserialize, Dummy)]
16pub enum ClassDefinition<'a> {
17 Sierra(Sierra<'a>),
18 Cairo(Cairo<'a>),
19}
20
21#[derive(Debug, Deserialize, Serialize)]
22#[serde(deny_unknown_fields)]
23pub struct Sierra<'a> {
24 pub abi: Cow<'a, str>,
26
27 pub sierra_program: Vec<Felt>,
29
30 pub contract_class_version: Cow<'a, str>,
32
33 pub entry_points_by_type: SierraEntryPoints,
35}
36
37impl<T> Dummy<T> for Sierra<'_> {
38 fn dummy_with_rng<R: Rng + ?Sized>(_: &T, rng: &mut R) -> Self {
39 Self {
40 abi: "[]".into(),
41 sierra_program: Faker.fake_with_rng(rng),
42 contract_class_version: "0.1.0".into(),
43 entry_points_by_type: Faker.fake_with_rng(rng),
44 }
45 }
46}
47
48#[derive(Debug, Deserialize, Serialize)]
49#[serde(deny_unknown_fields)]
50pub struct Cairo<'a> {
51 pub abi: Cow<'a, RawValue>,
53
54 pub program: Cow<'a, RawValue>,
56
57 pub entry_points_by_type: CairoEntryPoints,
59}
60
61impl<T> Dummy<T> for Cairo<'_> {
62 fn dummy_with_rng<R: Rng + ?Sized>(_: &T, rng: &mut R) -> Self {
63 Self {
64 abi: Cow::Owned(
65 RawValue::from_string("[]".into()).unwrap(),
66 ),
67 program: Cow::Owned(
68 RawValue::from_string(
69 r#"
70 {
71 "attributes": [],
72 "builtins": [],
73 "data": [],
74 "debug_info": null,
75 "hints": {},
76 "identifiers": {},
77 "main_scope": "__main__",
78 "prime": "0x800000000000011000000000000000000000000000000000000000000000001",
79 "reference_manager": {}
80 }
81 "#.into()
82 )
83 .unwrap(),
84 ),
85 entry_points_by_type: Faker.fake_with_rng(rng),
86 }
87 }
88}
89
90#[derive(Debug, Clone, Deserialize, Serialize, Dummy)]
91#[serde(deny_unknown_fields)]
92pub struct SierraEntryPoints {
93 #[serde(rename = "EXTERNAL")]
94 pub external: Vec<SelectorAndFunctionIndex>,
95 #[serde(rename = "L1_HANDLER")]
96 pub l1_handler: Vec<SelectorAndFunctionIndex>,
97 #[serde(rename = "CONSTRUCTOR")]
98 pub constructor: Vec<SelectorAndFunctionIndex>,
99}
100
101#[derive(Debug, Deserialize, Serialize, Dummy)]
102#[serde(deny_unknown_fields)]
103pub struct CairoEntryPoints {
104 #[serde(rename = "EXTERNAL")]
105 pub external: Vec<SelectorAndOffset>,
106 #[serde(rename = "L1_HANDLER")]
107 pub l1_handler: Vec<SelectorAndOffset>,
108 #[serde(rename = "CONSTRUCTOR")]
109 pub constructor: Vec<SelectorAndOffset>,
110}
111
112#[derive(Copy, Clone, Debug, serde::Deserialize, serde::Serialize, PartialEq, Hash, Eq)]
113#[serde(deny_unknown_fields)]
114pub enum EntryPointType {
115 #[serde(rename = "EXTERNAL")]
116 External,
117 #[serde(rename = "L1_HANDLER")]
118 L1Handler,
119 #[serde(rename = "CONSTRUCTOR")]
120 Constructor,
121}
122
123impl fmt::Display for EntryPointType {
124 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125 use EntryPointType::*;
126 f.pad(match self {
127 External => "EXTERNAL",
128 L1Handler => "L1_HANDLER",
129 Constructor => "CONSTRUCTOR",
130 })
131 }
132}
133
134#[serde_as]
135#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, PartialEq)]
136#[serde(deny_unknown_fields)]
137pub struct SelectorAndOffset {
138 pub selector: EntryPoint,
139 #[serde_as(as = "OffsetSerde")]
140 pub offset: ByteCodeOffset,
141}
142
143#[derive(serde::Deserialize, serde::Serialize)]
144#[serde(untagged)]
145pub enum OffsetSerde {
146 HexStr(Felt),
147 Decimal(u64),
148}
149
150impl serde_with::SerializeAs<ByteCodeOffset> for OffsetSerde {
151 fn serialize_as<S>(source: &ByteCodeOffset, serializer: S) -> Result<S::Ok, S::Error>
152 where
153 S: serde::Serializer,
154 {
155 use serde::Serialize;
156
157 Felt::serialize(&source.0, serializer)
158 }
159}
160
161impl<'de> serde_with::DeserializeAs<'de, ByteCodeOffset> for OffsetSerde {
162 fn deserialize_as<D>(deserializer: D) -> Result<ByteCodeOffset, D::Error>
163 where
164 D: serde::Deserializer<'de>,
165 {
166 use serde::Deserialize;
167
168 let offset = OffsetSerde::deserialize(deserializer)?;
169 let offset = match offset {
170 OffsetSerde::HexStr(felt) => felt,
171 OffsetSerde::Decimal(decimal) => Felt::from_u64(decimal),
172 };
173 Ok(ByteCodeOffset(offset))
174 }
175}
176
177impl<T> Dummy<T> for SelectorAndOffset {
178 fn dummy_with_rng<R: rand::prelude::Rng + ?Sized>(_: &T, rng: &mut R) -> Self {
179 Self {
180 selector: Faker.fake_with_rng(rng),
181 offset: ByteCodeOffset(Felt::from_u64(rng.gen())),
182 }
183 }
184}
185
186#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, Dummy)]
188#[serde(deny_unknown_fields)]
189pub struct SelectorAndFunctionIndex {
190 pub selector: EntryPoint,
191 pub function_idx: u64,
192}