fuels_types/
enum_variants.rs

1use crate::{
2    constants::{ENUM_DISCRIMINANT_WORD_WIDTH, WORD_SIZE},
3    errors::{error, Error, Result},
4    param_types::ParamType,
5};
6
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct EnumVariants {
9    param_types: Vec<ParamType>,
10}
11
12impl EnumVariants {
13    pub fn new(param_types: Vec<ParamType>) -> Result<EnumVariants> {
14        if !param_types.is_empty() {
15            Ok(EnumVariants { param_types })
16        } else {
17            Err(error!(InvalidData, "Enum variants can not be empty!"))
18        }
19    }
20
21    pub fn param_types(&self) -> &[ParamType] {
22        &self.param_types
23    }
24
25    pub fn param_type_of_variant(&self, discriminant: u8) -> Result<&ParamType> {
26        self.param_types.get(discriminant as usize).ok_or_else(|| {
27            error!(
28                InvalidData,
29                "Discriminant '{discriminant}' doesn't point to any variant: {:?}",
30                self.param_types()
31            )
32        })
33    }
34
35    pub fn only_units_inside(&self) -> bool {
36        self.param_types
37            .iter()
38            .all(|param_type| *param_type == ParamType::Unit)
39    }
40
41    /// Calculates how many WORDs are needed to encode an enum.
42    pub fn compute_encoding_width_of_enum(&self) -> usize {
43        if self.only_units_inside() {
44            return ENUM_DISCRIMINANT_WORD_WIDTH;
45        }
46        self.param_types()
47            .iter()
48            .map(|p| p.compute_encoding_width())
49            .max()
50            .map(|width| width + ENUM_DISCRIMINANT_WORD_WIDTH)
51            .expect(
52                "Will never panic because EnumVariants must have at least one variant inside it!",
53            )
54    }
55
56    /// Determines the padding needed for the provided enum variant (based on the width of the
57    /// biggest variant) and returns it.
58    pub fn compute_padding_amount(&self, variant_param_type: &ParamType) -> usize {
59        let biggest_variant_width =
60            self.compute_encoding_width_of_enum() - ENUM_DISCRIMINANT_WORD_WIDTH;
61        let variant_width = variant_param_type.compute_encoding_width();
62        (biggest_variant_width - variant_width) * WORD_SIZE
63    }
64}