cairo_vm/types/
builtin_name.rs

1use serde::{Deserialize, Serialize};
2
3#[cfg(feature = "test_utils")]
4use arbitrary::{self, Arbitrary};
5
6// Internal constants
7const OUTPUT_BUILTIN_NAME: &str = "output";
8const HASH_BUILTIN_NAME: &str = "pedersen";
9const RANGE_CHECK_BUILTIN_NAME: &str = "range_check";
10const RANGE_CHECK_96_BUILTIN_NAME: &str = "range_check96";
11const SIGNATURE_BUILTIN_NAME: &str = "ecdsa";
12const BITWISE_BUILTIN_NAME: &str = "bitwise";
13const EC_OP_BUILTIN_NAME: &str = "ec_op";
14const KECCAK_BUILTIN_NAME: &str = "keccak";
15const POSEIDON_BUILTIN_NAME: &str = "poseidon";
16const SEGMENT_ARENA_BUILTIN_NAME: &str = "segment_arena";
17const ADD_MOD_BUILTIN_NAME: &str = "add_mod";
18const MUL_MOD_BUILTIN_NAME: &str = "mul_mod";
19
20const OUTPUT_BUILTIN_NAME_WITH_SUFFIX: &str = "output_builtin";
21const HASH_BUILTIN_NAME_WITH_SUFFIX: &str = "pedersen_builtin";
22const RANGE_CHECK_BUILTIN_NAME_WITH_SUFFIX: &str = "range_check_builtin";
23const RANGE_CHECK_96_BUILTIN_NAME_WITH_SUFFIX: &str = "range_check96_builtin";
24const SIGNATURE_BUILTIN_NAME_WITH_SUFFIX: &str = "ecdsa_builtin";
25const BITWISE_BUILTIN_NAME_WITH_SUFFIX: &str = "bitwise_builtin";
26const EC_OP_BUILTIN_NAME_WITH_SUFFIX: &str = "ec_op_builtin";
27const KECCAK_BUILTIN_NAME_WITH_SUFFIX: &str = "keccak_builtin";
28const POSEIDON_BUILTIN_NAME_WITH_SUFFIX: &str = "poseidon_builtin";
29const SEGMENT_ARENA_BUILTIN_NAME_WITH_SUFFIX: &str = "segment_arena_builtin";
30const ADD_MOD_BUILTIN_NAME_WITH_SUFFIX: &str = "add_mod_builtin";
31const MUL_MOD_BUILTIN_NAME_WITH_SUFFIX: &str = "mul_mod_builtin";
32
33/// Enum representing the name of a cairo builtin
34#[cfg_attr(feature = "test_utils", derive(Arbitrary))]
35#[derive(Serialize, Deserialize, Debug, PartialEq, Copy, Clone, Eq, Hash)]
36#[allow(non_camel_case_types)]
37pub enum BuiltinName {
38    output,
39    range_check,
40    pedersen,
41    ecdsa,
42    keccak,
43    bitwise,
44    ec_op,
45    poseidon,
46    segment_arena,
47    range_check96,
48    add_mod,
49    mul_mod,
50}
51
52impl BuiltinName {
53    /// Converts a [`BuiltinName`] to its string representation adding the "_builtin" suffix
54    ///
55    /// ## Example
56    ///
57    /// ```
58    /// # use cairo_vm::types::builtin_name::BuiltinName;
59    ///
60    /// let builtin_name = BuiltinName::poseidon;
61    /// assert_eq!(builtin_name.to_str_with_suffix(), "poseidon_builtin");
62    ///
63    /// ```
64    pub fn to_str_with_suffix(self) -> &'static str {
65        match self {
66            BuiltinName::output => OUTPUT_BUILTIN_NAME_WITH_SUFFIX,
67            BuiltinName::range_check => RANGE_CHECK_BUILTIN_NAME_WITH_SUFFIX,
68            BuiltinName::pedersen => HASH_BUILTIN_NAME_WITH_SUFFIX,
69            BuiltinName::ecdsa => SIGNATURE_BUILTIN_NAME_WITH_SUFFIX,
70            BuiltinName::keccak => KECCAK_BUILTIN_NAME_WITH_SUFFIX,
71            BuiltinName::bitwise => BITWISE_BUILTIN_NAME_WITH_SUFFIX,
72            BuiltinName::ec_op => EC_OP_BUILTIN_NAME_WITH_SUFFIX,
73            BuiltinName::poseidon => POSEIDON_BUILTIN_NAME_WITH_SUFFIX,
74            BuiltinName::segment_arena => SEGMENT_ARENA_BUILTIN_NAME_WITH_SUFFIX,
75            BuiltinName::range_check96 => RANGE_CHECK_96_BUILTIN_NAME_WITH_SUFFIX,
76            BuiltinName::add_mod => ADD_MOD_BUILTIN_NAME_WITH_SUFFIX,
77            BuiltinName::mul_mod => MUL_MOD_BUILTIN_NAME_WITH_SUFFIX,
78        }
79    }
80
81    /// Converts a [`BuiltinName`] to its string representation
82    ///
83    /// ## Example
84    ///
85    /// ```
86    /// # use cairo_vm::types::builtin_name::BuiltinName;
87    ///
88    /// let builtin_name = BuiltinName::poseidon;
89    /// assert_eq!(builtin_name.to_str(), "poseidon");
90    ///
91    /// ```
92    pub fn to_str(self) -> &'static str {
93        match self {
94            BuiltinName::output => OUTPUT_BUILTIN_NAME,
95            BuiltinName::range_check => RANGE_CHECK_BUILTIN_NAME,
96            BuiltinName::pedersen => HASH_BUILTIN_NAME,
97            BuiltinName::ecdsa => SIGNATURE_BUILTIN_NAME,
98            BuiltinName::keccak => KECCAK_BUILTIN_NAME,
99            BuiltinName::bitwise => BITWISE_BUILTIN_NAME,
100            BuiltinName::ec_op => EC_OP_BUILTIN_NAME,
101            BuiltinName::poseidon => POSEIDON_BUILTIN_NAME,
102            BuiltinName::segment_arena => SEGMENT_ARENA_BUILTIN_NAME,
103            BuiltinName::range_check96 => RANGE_CHECK_96_BUILTIN_NAME,
104            BuiltinName::add_mod => ADD_MOD_BUILTIN_NAME,
105            BuiltinName::mul_mod => MUL_MOD_BUILTIN_NAME,
106        }
107    }
108
109    /// Converts a [`BuiltinName`] from its string representation removing the "_builtin" suffix
110    ///
111    /// ## Example
112    ///
113    /// ```
114    /// # use cairo_vm::types::builtin_name::BuiltinName;
115    ///
116    /// assert_eq!(BuiltinName::from_str_with_suffix("poseidon_builtin"), Some(BuiltinName::poseidon));
117    ///
118    /// assert_eq!(BuiltinName::from_str_with_suffix("unknown"), None);
119    ///
120    /// ```
121    pub fn from_str_with_suffix(suffixed_str: &str) -> Option<Self> {
122        match suffixed_str {
123            OUTPUT_BUILTIN_NAME_WITH_SUFFIX => Some(BuiltinName::output),
124            RANGE_CHECK_BUILTIN_NAME_WITH_SUFFIX => Some(BuiltinName::range_check),
125            HASH_BUILTIN_NAME_WITH_SUFFIX => Some(BuiltinName::pedersen),
126            SIGNATURE_BUILTIN_NAME_WITH_SUFFIX => Some(BuiltinName::ecdsa),
127            KECCAK_BUILTIN_NAME_WITH_SUFFIX => Some(BuiltinName::keccak),
128            BITWISE_BUILTIN_NAME_WITH_SUFFIX => Some(BuiltinName::bitwise),
129            EC_OP_BUILTIN_NAME_WITH_SUFFIX => Some(BuiltinName::ec_op),
130            POSEIDON_BUILTIN_NAME_WITH_SUFFIX => Some(BuiltinName::poseidon),
131            SEGMENT_ARENA_BUILTIN_NAME_WITH_SUFFIX => Some(BuiltinName::segment_arena),
132            RANGE_CHECK_96_BUILTIN_NAME_WITH_SUFFIX => Some(BuiltinName::range_check96),
133            ADD_MOD_BUILTIN_NAME_WITH_SUFFIX => Some(BuiltinName::add_mod),
134            MUL_MOD_BUILTIN_NAME_WITH_SUFFIX => Some(BuiltinName::mul_mod),
135            _ => None,
136        }
137    }
138
139    // Implementing this as a trait would generate confusion as `Display` impl uses suffixed version
140    #[allow(clippy::should_implement_trait)]
141    /// Converts a [`BuiltinName`] from its string representation
142    ///
143    /// ## Example
144    ///
145    /// ```
146    /// # use cairo_vm::types::builtin_name::BuiltinName;
147    ///
148    /// assert_eq!(BuiltinName::from_str("poseidon"), Some(BuiltinName::poseidon));
149    ///
150    /// assert_eq!(BuiltinName::from_str("unknown"), None);
151    ///
152    /// ```
153    pub fn from_str(str: &str) -> Option<Self> {
154        match str {
155            OUTPUT_BUILTIN_NAME => Some(BuiltinName::output),
156            RANGE_CHECK_BUILTIN_NAME => Some(BuiltinName::range_check),
157            HASH_BUILTIN_NAME => Some(BuiltinName::pedersen),
158            SIGNATURE_BUILTIN_NAME => Some(BuiltinName::ecdsa),
159            KECCAK_BUILTIN_NAME => Some(BuiltinName::keccak),
160            BITWISE_BUILTIN_NAME => Some(BuiltinName::bitwise),
161            EC_OP_BUILTIN_NAME => Some(BuiltinName::ec_op),
162            POSEIDON_BUILTIN_NAME => Some(BuiltinName::poseidon),
163            SEGMENT_ARENA_BUILTIN_NAME => Some(BuiltinName::segment_arena),
164            RANGE_CHECK_96_BUILTIN_NAME => Some(BuiltinName::range_check96),
165            ADD_MOD_BUILTIN_NAME => Some(BuiltinName::add_mod),
166            MUL_MOD_BUILTIN_NAME => Some(BuiltinName::mul_mod),
167            _ => None,
168        }
169    }
170}
171
172/// NOTE: Adds "_builtin" suffix
173impl core::fmt::Display for BuiltinName {
174    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
175        self.to_str_with_suffix().fmt(f)
176    }
177}
178
179// Implementation of custom serialization & deserialization for maps using builtin names with suffixes as keys
180pub(crate) mod serde_generic_map_impl {
181    use super::BuiltinName;
182    use crate::stdlib::{collections::HashMap, string::String};
183    use serde::{de::Error, ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer};
184
185    pub fn serialize<S, V>(
186        values: &HashMap<BuiltinName, V>,
187        serializer: S,
188    ) -> Result<S::Ok, S::Error>
189    where
190        S: Serializer,
191        V: Serialize,
192    {
193        let mut map_serializer = serializer.serialize_map(Some(values.len()))?;
194        for (key, val) in values {
195            map_serializer.serialize_entry(key.to_str_with_suffix(), val)?
196        }
197        map_serializer.end()
198    }
199
200    pub fn deserialize<'de, D: Deserializer<'de>, V: Deserialize<'de>>(
201        d: D,
202    ) -> Result<HashMap<BuiltinName, V>, D::Error> {
203        // First deserialize keys into String
204        let map = HashMap::<String, V>::deserialize(d)?;
205        // Then match keys to BuiltinName and handle invalid names
206        map.into_iter()
207            .map(|(k, v)| BuiltinName::from_str_with_suffix(&k).map(|k| (k, v)))
208            .collect::<Option<HashMap<_, _>>>()
209            .ok_or(D::Error::custom("Invalid builtin name"))
210    }
211}