1use std::borrow::Cow;
5use std::mem;
6use std::sync::Arc;
7
8use dashmap::DashMap;
9use futures::future::OptionFuture;
10use futures::future::join_all;
11use futures::join;
12use move_core_types::account_address::AccountAddress;
13use sui_types::dynamic_field::DynamicFieldType;
14use sui_types::dynamic_field::visitor as DFV;
15use sui_types::dynamic_field::visitor::FieldVisitor;
16
17use crate::v2::error::FormatError;
18use crate::v2::parser as P;
19use crate::v2::value as V;
20use crate::v2::visitor::extractor::Extractor;
21
22pub struct Interpreter<S: V::Store> {
24 store: S,
25
26 cache: DashMap<AccountAddress, Option<Arc<V::OwnedSlice>>>,
29
30 root: V::OwnedSlice,
31}
32
33impl<S: V::Store> Interpreter<S> {
34 pub fn new(root: V::OwnedSlice, store: S) -> Self {
38 Self {
39 store,
40 cache: DashMap::new(),
41 root,
42 }
43 }
44
45 pub(crate) async fn eval_strands<'s>(
48 &'s self,
49 strands: &'s [P::Strand<'s>],
50 ) -> Result<Option<Vec<V::Strand<'s>>>, FormatError> {
51 join_all(strands.iter().map(|strand| async move {
52 match strand {
53 P::Strand::Text(s) => Ok(Some(V::Strand::Text(s))),
54 P::Strand::Expr(P::Expr {
55 offset,
56 alternates,
57 transform,
58 }) => {
59 let transform = transform.unwrap_or_default();
60 Ok(self
61 .eval_alts(alternates)
62 .await?
63 .map(move |value| V::Strand::Value {
64 value,
65 transform,
66 offset: *offset,
67 }))
68 }
69 }
70 }))
71 .await
72 .into_iter()
73 .collect()
74 }
75
76 async fn eval_alts<'s>(
81 &'s self,
82 alts: &'s [P::Chain<'s>],
83 ) -> Result<Option<V::Value<'s>>, FormatError> {
84 for chain in alts {
85 if let Some(v) = self.eval_chain(chain).await? {
86 return Ok(Some(v));
87 }
88 }
89
90 Ok(None)
91 }
92
93 pub(crate) async fn eval_chain<'s>(
104 &'s self,
105 chain: &'s P::Chain<'s>,
106 ) -> Result<Option<V::Value<'s>>, FormatError> {
107 use V::Accessor as A;
108 use V::Value as VV;
109
110 let root: OptionFuture<_> = chain
112 .root
113 .as_ref()
114 .map(|literal| self.eval_literal(literal))
115 .into();
116
117 let accessors = join_all(chain.accessors.iter().map(|a| self.eval_accessor(a)));
118 let (root, accessors) = join!(root, accessors,);
119
120 let mut root = match root {
121 Some(Ok(Some(root))) => root,
122 Some(Ok(None)) => return Ok(None),
123 Some(Err(e)) => return Err(e),
124
125 None => VV::Slice(self.root.as_slice()),
127 };
128
129 let Some(mut accessors) = accessors
130 .into_iter()
131 .collect::<Result<Option<Vec<_>>, _>>()?
132 else {
133 return Ok(None);
134 };
135
136 accessors.reverse();
137 while let Some(accessor) = accessors.last() {
138 match (root, accessor) {
139 (VV::Address(a), A::DFIndex(i)) => {
140 let df_id = i.derive_dynamic_field_id(a)?.into();
141 let Some(slice) = self.object(df_id).await? else {
142 return Ok(None);
143 };
144
145 let field = match FieldVisitor::deserialize(slice.bytes, slice.layout) {
146 Ok(f) => f,
147 Err(DFV::Error::Visitor(e)) => return Err(FormatError::Visitor(e)),
148 Err(_) => return Ok(None),
149 };
150
151 if field.kind != DynamicFieldType::DynamicField {
152 return Ok(None);
153 }
154
155 accessors.pop();
156 root = VV::Slice(V::Slice {
157 bytes: field.value_bytes,
158 layout: field.value_layout,
159 });
160 }
161
162 (VV::Address(a), A::DOFIndex(i)) => {
163 let df_id = i.derive_dynamic_object_field_id(a)?.into();
164 let Some(slice) = self.object(df_id).await? else {
165 return Ok(None);
166 };
167
168 let field = match FieldVisitor::deserialize(slice.bytes, slice.layout) {
169 Ok(f) => f,
170 Err(DFV::Error::Visitor(e)) => return Err(FormatError::Visitor(e)),
171 Err(_) => return Ok(None),
172 };
173
174 if field.kind != DynamicFieldType::DynamicObject {
175 return Ok(None);
176 }
177
178 let Ok(id) = AccountAddress::from_bytes(field.value_bytes) else {
179 return Ok(None);
180 };
181
182 let Some(value_slice) = self.object(id).await? else {
183 return Ok(None);
184 };
185
186 accessors.pop();
187 root = VV::Slice(value_slice);
188 }
189
190 (VV::Address(a), A::Derived(i)) => {
191 let id = i.derive_object_id(a)?.into();
192 let Some(slice) = self.object(id).await? else {
193 return Ok(None);
194 };
195
196 accessors.pop();
197 root = VV::Slice(slice);
198 }
199
200 (VV::Bytes(bs), accessor) => {
203 let Some(&b) = accessor.as_numeric_index().and_then(|i| bs.get(i as usize))
204 else {
205 return Ok(None);
206 };
207
208 accessors.pop();
209 root = VV::U8(b);
210 }
211
212 (VV::String(s), A::Field(f)) if *f == "bytes" => {
215 accessors.pop();
216 root = VV::Bytes(s)
217 }
218
219 (VV::Vector(mut xs), accessor) => {
222 let Some(i) = accessor.as_numeric_index() else {
223 return Ok(None);
224 };
225
226 accessors.pop();
227 root = if i as usize >= xs.elements.len() {
228 return Ok(None);
229 } else {
230 xs.elements.swap_remove(i as usize)
231 };
232 }
233
234 (VV::Struct(V::Struct { fields, .. }) | VV::Enum(V::Enum { fields, .. }), a) => {
236 let Some(value) = fields.get(a) else {
237 return Ok(None);
238 };
239
240 accessors.pop();
241 root = value;
242 }
243
244 (VV::Slice(slice), _) => {
248 let Some(value) = Extractor::deserialize_slice(slice, &mut accessors)? else {
249 return Ok(None);
250 };
251
252 root = value;
253 }
254
255 (
257 VV::Address(_)
258 | VV::Bool(_)
259 | VV::String(_)
260 | VV::U8(_)
261 | VV::U16(_)
262 | VV::U32(_)
263 | VV::U64(_)
264 | VV::U128(_)
265 | VV::U256(_),
266 _,
267 ) => return Ok(None),
268 }
269 }
270
271 Ok(Some(root))
272 }
273
274 async fn eval_accessor<'s>(
279 &'s self,
280 acc: &'s P::Accessor<'s>,
281 ) -> Result<Option<V::Accessor<'s>>, FormatError> {
282 use P::Accessor as PA;
283 use V::Accessor as VA;
284
285 Ok(match acc {
286 PA::Field(f) => Some(VA::Field(f.as_str())),
287 PA::Positional(i) => Some(VA::Positional(*i)),
288 PA::Index(chain) => Box::pin(self.eval_chain(chain)).await?.map(VA::Index),
289 PA::DFIndex(chain) => Box::pin(self.eval_chain(chain)).await?.map(VA::DFIndex),
290 PA::DOFIndex(chain) => Box::pin(self.eval_chain(chain)).await?.map(VA::DOFIndex),
291 PA::Derived(chain) => Box::pin(self.eval_chain(chain)).await?.map(VA::Derived),
292 })
293 }
294
295 pub(crate) async fn eval_literal<'s>(
300 &'s self,
301 lit: &'s P::Literal<'s>,
302 ) -> Result<Option<V::Value<'s>>, FormatError> {
303 use P::Literal as L;
304 use V::Value as VV;
305
306 Ok(match lit {
307 L::Self_ => Some(VV::Slice(self.root.as_slice())),
308 L::Address(a) => Some(VV::Address(*a)),
309 L::Bool(b) => Some(VV::Bool(*b)),
310 L::U8(n) => Some(VV::U8(*n)),
311 L::U16(n) => Some(VV::U16(*n)),
312 L::U32(n) => Some(VV::U32(*n)),
313 L::U64(n) => Some(VV::U64(*n)),
314 L::U128(n) => Some(VV::U128(*n)),
315 L::U256(n) => Some(VV::U256(*n)),
316 L::ByteArray(bs) => Some(VV::Bytes(bs.into())),
317
318 L::String(s) => match s.clone() {
319 Cow::Borrowed(s) => Some(VV::String(Cow::Borrowed(s.as_bytes()))),
320 Cow::Owned(s) => Some(VV::String(Cow::Owned(s.into_bytes()))),
321 },
322
323 L::Vector(v) => self.eval_chains(&v.elements).await.and_then(|elements| {
324 let Some(elements) = elements else {
325 return Ok(None);
326 };
327
328 let type_ = if let Some(explicit) = &v.type_ {
331 Cow::Borrowed(explicit)
332 } else if let Some(first) = elements.first() {
333 Cow::Owned(first.type_())
334 } else {
335 return Err(FormatError::VectorNoType);
336 };
337
338 for e in &elements {
339 let element_type = e.type_();
340 if element_type != *type_ {
341 return Err(FormatError::VectorTypeMismatch {
342 offset: v.offset,
343 this: type_.into_owned(),
344 that: element_type,
345 });
346 }
347 }
348
349 Ok(Some(VV::Vector(V::Vector { type_, elements })))
350 })?,
351
352 L::Struct(s) => self.eval_fields(&s.fields).await?.map(|fields| {
353 VV::Struct(V::Struct {
354 type_: &s.type_,
355 fields,
356 })
357 }),
358
359 L::Enum(e) => self.eval_fields(&e.fields).await?.map(|fields| {
360 VV::Enum(V::Enum {
361 type_: &e.type_,
362 variant_name: e.variant_name,
363 variant_index: e.variant_index,
364 fields,
365 })
366 }),
367 })
368 }
369
370 async fn eval_fields<'s>(
375 &'s self,
376 field: &'s P::Fields<'s>,
377 ) -> Result<Option<V::Fields<'s>>, FormatError> {
378 Ok(match field {
379 P::Fields::Positional(fs) => self.eval_chains(fs).await?.map(V::Fields::Positional),
380 P::Fields::Named(fs) => self
381 .eval_chains(fs.iter().map(|(_, f)| f))
382 .await?
383 .map(|vs| V::Fields::Named(fs.iter().map(|(n, _)| *n).zip(vs).collect())),
384 })
385 }
386
387 async fn eval_chains<'s>(
392 &'s self,
393 chains: impl IntoIterator<Item = &'s P::Chain<'s>>,
394 ) -> Result<Option<Vec<V::Value<'s>>>, FormatError> {
395 let values = chains
396 .into_iter()
397 .map(|chain| Box::pin(self.eval_chain(chain)));
398
399 join_all(values).await.into_iter().collect()
400 }
401
402 async fn object<'s>(&'s self, id: AccountAddress) -> Result<Option<V::Slice<'s>>, FormatError> {
408 let owned = if let Some(cached) = self.cache.get(&id) {
409 cached.clone()
410 } else {
411 let loaded = self
412 .store
413 .object(id)
414 .await
415 .map_err(|e| FormatError::Store(Arc::new(e)))?
416 .map(Arc::new);
417
418 self.cache.entry(id).or_insert(loaded).clone()
419 };
420
421 let Some(owned) = owned.as_ref() else {
422 return Ok(None);
423 };
424
425 let slice = owned.as_slice();
429 Ok(Some(unsafe {
430 mem::transmute::<V::Slice<'_>, V::Slice<'s>>(slice)
431 }))
432 }
433}