sui_graphql_rpc/types/
move_enum.rs

1// Copyright (c) Mysten Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use async_graphql::*;
5use sui_package_resolver::{DataDef, MoveData, VariantDef};
6
7use crate::error::Error;
8
9use super::{
10    move_module::MoveModule,
11    move_struct::{MoveField, MoveStructTypeParameter},
12    open_move_type::{abilities, MoveAbility},
13    sui_address::SuiAddress,
14};
15
16pub(crate) struct MoveEnum {
17    defining_id: SuiAddress,
18    module: String,
19    name: String,
20    abilities: Vec<MoveAbility>,
21    type_parameters: Vec<MoveStructTypeParameter>,
22    variants: Vec<MoveEnumVariant>,
23    checkpoint_viewed_at: u64,
24}
25
26/// Information for a particular Move variant
27pub(crate) struct MoveEnumVariant {
28    name: String,
29    fields: Vec<MoveField>,
30}
31
32/// Description of an enum type, defined in a Move module.
33#[Object]
34impl MoveEnum {
35    /// The module this enum was originally defined in.
36    pub(crate) async fn module(&self, ctx: &Context<'_>) -> Result<MoveModule> {
37        let Some(module) = MoveModule::query(
38            ctx,
39            self.defining_id,
40            &self.module,
41            self.checkpoint_viewed_at,
42        )
43        .await
44        .extend()?
45        else {
46            return Err(Error::Internal(format!(
47                "Failed to load module for enum: {}::{}::{}",
48                self.defining_id, self.module, self.name,
49            )))
50            .extend();
51        };
52
53        Ok(module)
54    }
55
56    /// The enum's (unqualified) type name.
57    pub(crate) async fn name(&self) -> &str {
58        &self.name
59    }
60
61    /// The enum's abilities.
62    pub(crate) async fn abilities(&self) -> Option<&Vec<MoveAbility>> {
63        Some(&self.abilities)
64    }
65
66    /// Constraints on the enum's formal type parameters.  Move bytecode does not name type
67    /// parameters, so when they are referenced (e.g. in field types) they are identified by their
68    /// index in this list.
69    pub(crate) async fn type_parameters(&self) -> Option<&Vec<MoveStructTypeParameter>> {
70        Some(&self.type_parameters)
71    }
72
73    /// The names and types of the enum's fields.  Field types reference type parameters, by their
74    /// index in the defining enum's `typeParameters` list.
75    pub(crate) async fn variants(&self) -> Option<&Vec<MoveEnumVariant>> {
76        Some(&self.variants)
77    }
78}
79
80#[Object]
81impl MoveEnumVariant {
82    /// The name of the variant
83    pub(crate) async fn name(&self) -> &str {
84        &self.name
85    }
86
87    /// The names and types of the variant's fields.  Field types reference type parameters, by their
88    /// index in the defining enum's `typeParameters` list.
89    pub(crate) async fn fields(&self) -> Option<&Vec<MoveField>> {
90        Some(&self.fields)
91    }
92}
93
94impl MoveEnum {
95    pub(crate) fn new(
96        module: String,
97        name: String,
98        def: DataDef,
99        checkpoint_viewed_at: u64,
100    ) -> Result<Self, Error> {
101        let type_parameters = def
102            .type_params
103            .into_iter()
104            .map(|param| MoveStructTypeParameter {
105                constraints: abilities(param.constraints),
106                is_phantom: param.is_phantom,
107            })
108            .collect();
109
110        let MoveData::Enum(variants) = def.data else {
111            // This should never happen, as the data should always be an enum if we're calling
112            // this function. So signal an internal error if it does.
113            return Err(Error::Internal(format!(
114                "Expected enum data, but got: {:?}",
115                def.data
116            )));
117        };
118        let variants = variants
119            .into_iter()
120            .map(|VariantDef { name, signatures }| MoveEnumVariant {
121                name,
122                fields: signatures
123                    .into_iter()
124                    .map(|(name, signature)| MoveField {
125                        name,
126                        type_: signature.into(),
127                    })
128                    .collect(),
129            })
130            .collect();
131
132        Ok(MoveEnum {
133            defining_id: SuiAddress::from(def.defining_id),
134            module,
135            name,
136            abilities: abilities(def.abilities),
137            type_parameters,
138            variants,
139            checkpoint_viewed_at,
140        })
141    }
142}