1use move_core_types::{
7 account_address::AccountAddress, annotated_value::MoveTypeLayout, annotated_visitor as AV,
8 u256::U256,
9};
10
11use crate::base_types::RESOLVED_STD_OPTION;
12
13#[derive(thiserror::Error, Debug)]
15#[error("Unexpected type")]
16pub struct Error;
17
18pub struct OptionVisitor<'a, T>(pub &'a mut T);
21
22impl<'b, 'l, T, E> AV::Visitor<'b, 'l> for OptionVisitor<'_, T>
23where
24 T: AV::Visitor<'b, 'l, Error = E>,
25 E: From<Error> + From<AV::Error>,
26{
27 type Value = Option<T::Value>;
28 type Error = E;
29
30 fn visit_vector(
31 &mut self,
32 driver: &mut AV::VecDriver<'_, 'b, 'l>,
33 ) -> Result<Self::Value, Self::Error> {
34 match driver.len() {
35 0 => Ok(None),
36 1 => driver.next_element(self.0),
37 _ => Err(Error.into()),
38 }
39 }
40
41 fn visit_struct(
42 &mut self,
43 driver: &mut AV::StructDriver<'_, 'b, 'l>,
44 ) -> Result<Self::Value, Self::Error> {
45 if is_option(driver.struct_layout()) {
46 driver
47 .next_field(self)?
48 .ok_or_else(|| Error.into())
49 .map(|(_, option)| option)
50 } else {
51 Err(Error.into())
52 }
53 }
54
55 fn visit_u8(
58 &mut self,
59 _: &AV::ValueDriver<'_, 'b, 'l>,
60 _: u8,
61 ) -> Result<Self::Value, Self::Error> {
62 Err(Error.into())
63 }
64
65 fn visit_u16(
66 &mut self,
67 _: &AV::ValueDriver<'_, 'b, 'l>,
68 _: u16,
69 ) -> Result<Self::Value, Self::Error> {
70 Err(Error.into())
71 }
72
73 fn visit_u32(
74 &mut self,
75 _: &AV::ValueDriver<'_, 'b, 'l>,
76 _: u32,
77 ) -> Result<Self::Value, Self::Error> {
78 Err(Error.into())
79 }
80
81 fn visit_u64(
82 &mut self,
83 _: &AV::ValueDriver<'_, 'b, 'l>,
84 _: u64,
85 ) -> Result<Self::Value, Self::Error> {
86 Err(Error.into())
87 }
88
89 fn visit_u128(
90 &mut self,
91 _: &AV::ValueDriver<'_, 'b, 'l>,
92 _: u128,
93 ) -> Result<Self::Value, Self::Error> {
94 Err(Error.into())
95 }
96
97 fn visit_u256(
98 &mut self,
99 _: &AV::ValueDriver<'_, 'b, 'l>,
100 _: U256,
101 ) -> Result<Self::Value, Self::Error> {
102 Err(Error.into())
103 }
104
105 fn visit_bool(
106 &mut self,
107 _: &AV::ValueDriver<'_, 'b, 'l>,
108 _: bool,
109 ) -> Result<Self::Value, Self::Error> {
110 Err(Error.into())
111 }
112
113 fn visit_address(
114 &mut self,
115 _: &AV::ValueDriver<'_, 'b, 'l>,
116 _: AccountAddress,
117 ) -> Result<Self::Value, Self::Error> {
118 Err(Error.into())
119 }
120
121 fn visit_signer(
122 &mut self,
123 _: &AV::ValueDriver<'_, 'b, 'l>,
124 _: AccountAddress,
125 ) -> Result<Self::Value, Self::Error> {
126 Err(Error.into())
127 }
128
129 fn visit_variant(
130 &mut self,
131 _: &mut AV::VariantDriver<'_, 'b, 'l>,
132 ) -> Result<Self::Value, Self::Error> {
133 Err(Error.into())
134 }
135}
136
137fn is_option(struct_layout: &move_core_types::annotated_value::MoveStructLayout) -> bool {
139 let ty = &struct_layout.type_;
140
141 if (&ty.address, ty.module.as_ref(), ty.name.as_ref()) != RESOLVED_STD_OPTION {
142 return false;
143 }
144
145 if ty.type_params.len() != 1 {
146 return false;
147 }
148
149 let Some(type_param) = ty.type_params.first() else {
150 return false;
151 };
152
153 if struct_layout.fields.len() != 1 {
154 return false;
155 }
156
157 let Some(field) = struct_layout.fields.first() else {
158 return false;
159 };
160
161 if field.name.as_str() != "vec" {
162 return false;
163 }
164
165 match &field.layout {
166 MoveTypeLayout::Vector(elem) => {
167 if !elem.is_type(type_param) {
168 return false;
169 }
170 }
171 _ => return false,
172 }
173
174 true
175}