1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
use crate::types::errors::{error, Result};

pub type NamedParamType = (String, ParamType);

#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum ParamType {
    Unit,
    Bool,
    U8,
    U16,
    U32,
    U64,
    U128,
    U256,
    B256,
    Bytes,
    String,
    RawSlice,
    StringArray(usize),
    StringSlice,
    Tuple(Vec<ParamType>),
    Array(Box<ParamType>, usize),
    Vector(Box<ParamType>),
    Struct {
        name: String,
        fields: Vec<NamedParamType>,
        generics: Vec<ParamType>,
    },
    Enum {
        name: String,
        enum_variants: EnumVariants,
        generics: Vec<ParamType>,
    },
}

pub enum ReturnLocation {
    Return,
    ReturnData,
}

#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct EnumVariants {
    variants: Vec<NamedParamType>,
}

impl EnumVariants {
    pub fn new(variants: Vec<NamedParamType>) -> Result<EnumVariants> {
        if variants.is_empty() {
            return Err(error!(Other, "enum variants cannot be empty!"));
        }

        Ok(EnumVariants { variants })
    }

    pub fn variants(&self) -> &Vec<NamedParamType> {
        &self.variants
    }

    pub fn param_types(&self) -> impl Iterator<Item = &ParamType> {
        self.variants.iter().map(|(_, param_type)| param_type)
    }

    pub fn select_variant(&self, discriminant: u64) -> Result<&NamedParamType> {
        self.variants.get(discriminant as usize).ok_or_else(|| {
            error!(
                Other,
                "discriminant `{discriminant}` doesn't point to any variant: {:?}",
                self.variants()
            )
        })
    }
}