cairo-lang-sierra 2.19.2

Sierra representation.
Documentation
use bimap::BiMap;
use itertools::chain;
use num_bigint::BigInt;
use starknet_types_core::felt::Felt as Felt252;

use crate::ids::ConcreteTypeId;
use crate::program::{ConcreteTypeLongId, GenericArg};

pub fn build_bijective_mapping() -> BiMap<ConcreteTypeId, ConcreteTypeLongId> {
    let mut elements = BiMap::new();
    elements.insert("T".into(), as_type_long_id("T", &[]));
    elements.insert("u32".into(), as_type_long_id("u32", &[]));
    elements.insert("u64".into(), as_type_long_id("u64", &[]));
    elements.insert("u128".into(), as_type_long_id("u128", &[]));
    elements.insert("bytes31".into(), as_type_long_id("bytes31", &[]));
    elements.insert("felt252".into(), as_type_long_id("felt252", &[]));
    elements.insert("Tuple<>".into(), as_named_type_long_id("Struct", "Tuple", &[]));
    elements.insert(
        "U128AndFelt252".into(),
        as_named_type_long_id("Struct", "U128AndFelt252", &["u128", "felt252"]),
    );
    elements
        .insert("Option".into(), as_named_type_long_id("Enum", "Option", &["felt252", "Tuple<>"]));
    elements.insert("NonZeroFelt252".into(), as_type_long_id("NonZero", &["felt252"]));
    elements.insert("NonZeroU128".into(), as_type_long_id("NonZero", &["u128"]));
    elements.insert("ArrayFelt252".into(), as_type_long_id("Array", &["felt252"]));
    elements.insert("ArrayFelt252".into(), as_type_long_id("Array", &["felt252"]));
    elements.insert(
        "BoundedInt0_3".into(),
        as_type_long_id_value_args("BoundedInt", &[BigInt::from(0), BigInt::from(3)]),
    );
    elements.insert(
        "BoundedInt0_-1".into(),
        as_type_long_id_value_args("BoundedInt", &[BigInt::from(0), Felt252::from(-1).to_bigint()]),
    );
    elements.insert(
        "BoundedInt0_10".into(),
        as_type_long_id_value_args("BoundedInt", &[BigInt::from(0), BigInt::from(10)]),
    );
    elements.insert(
        "BoundedInt0_0".into(),
        as_type_long_id_value_args("BoundedInt", &[BigInt::from(0), BigInt::from(0)]),
    );
    elements.insert(
        "BoundedInt2_3".into(),
        as_type_long_id_value_args("BoundedInt", &[BigInt::from(2), BigInt::from(3)]),
    );
    elements.insert("ArrayU128".into(), as_type_long_id("Array", &["u128"]));
    elements.insert("BoxU128".into(), as_type_long_id("Box", &["u128"]));
    elements.insert("UninitializedFelt252".into(), as_type_long_id("Uninitialized", &["felt252"]));
    elements.insert("Uninitializedu128".into(), as_type_long_id("Uninitialized", &["u128"]));
    elements.insert("GasBuiltin".into(), as_type_long_id("GasBuiltin", &[]));
    elements.insert("RangeCheck".into(), as_type_long_id("RangeCheck", &[]));
    elements.insert("U128MulGuarantee".into(), as_type_long_id("U128MulGuarantee", &[]));
    elements.insert("System".into(), as_type_long_id("System", &[]));
    elements.insert("StorageBaseAddress".into(), as_type_long_id("StorageBaseAddress", &[]));
    elements.insert("StorageAddress".into(), as_type_long_id("StorageAddress", &[]));
    elements.insert("ContractAddress".into(), as_type_long_id("ContractAddress", &[]));
    elements.insert("SnapshotRangeCheck".into(), as_type_long_id("Snapshot", &["RangeCheck"]));
    elements.insert("SnapshotArrayU128".into(), as_type_long_id("Snapshot", &["ArrayU128"]));
    elements.insert("SnapshotU128".into(), as_type_long_id("Snapshot", &["u128"]));
    elements.insert(
        "NonDupStruct".into(),
        as_named_type_long_id("Struct", "NonDupStruct", &["felt252", "RangeCheck"]),
    );
    elements.insert("SnapshotNonDupStruct".into(), as_type_long_id("Snapshot", &["NonDupStruct"]));
    elements.insert(
        "NonDupEnum".into(),
        as_named_type_long_id("Enum", "NonDupEnum", &["felt252", "RangeCheck"]),
    );
    elements.insert("SnapshotNonDupEnum".into(), as_type_long_id("Snapshot", &["NonDupEnum"]));
    elements
}

fn as_type_long_id(name: &str, args: &[&str]) -> ConcreteTypeLongId {
    ConcreteTypeLongId {
        generic_id: name.into(),
        generic_args: args.iter().map(|s| GenericArg::Type(ConcreteTypeId::from(*s))).collect(),
    }
}

fn as_type_long_id_value_args(name: &str, args: &[BigInt]) -> ConcreteTypeLongId {
    ConcreteTypeLongId {
        generic_id: name.into(),
        generic_args: args.iter().map(|b| GenericArg::Value(b.clone())).collect(),
    }
}

fn as_named_type_long_id(generic_name: &str, user_name: &str, args: &[&str]) -> ConcreteTypeLongId {
    ConcreteTypeLongId {
        generic_id: generic_name.into(),
        generic_args: chain!(
            [GenericArg::UserType(user_name.into())],
            args.iter().map(|s| GenericArg::Type(ConcreteTypeId::from(*s)))
        )
        .collect(),
    }
}