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