fuels_types/
enum_variants.rs1use 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 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 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}