1use std::borrow::Cow;
5use std::mem;
6use std::sync::Arc;
7
8use mysten_common::ZipDebugEqIteratorExt;
9
10use dashmap::DashMap;
11use futures::future::OptionFuture;
12use futures::future::join_all;
13use futures::join;
14use move_core_types::account_address::AccountAddress;
15use sui_types::dynamic_field::DynamicFieldType;
16use sui_types::dynamic_field::visitor as DFV;
17use sui_types::dynamic_field::visitor::FieldVisitor;
18
19use crate::v2::error::FormatError;
20use crate::v2::parser as P;
21use crate::v2::value as V;
22use crate::v2::visitor::extractor::Extractor;
23
24pub struct Interpreter<S: V::Store> {
26 store: S,
27
28 cache: DashMap<(AccountAddress, bool), Option<Arc<V::OwnedSlice>>>,
34
35 root: V::OwnedSlice,
36}
37
38impl<S: V::Store> Interpreter<S> {
39 pub fn new(root: V::OwnedSlice, store: S) -> Self {
43 Self {
44 store,
45 cache: DashMap::new(),
46 root,
47 }
48 }
49
50 pub(crate) async fn eval_strands<'s>(
53 &'s self,
54 strands: &'s [P::Strand<'s>],
55 ) -> Result<Option<Vec<V::Strand<'s>>>, FormatError> {
56 join_all(strands.iter().map(|strand| async move {
57 match strand {
58 P::Strand::Text(s) => Ok(Some(V::Strand::Text(s))),
59 P::Strand::Expr(P::Expr {
60 offset,
61 alternates,
62 transform,
63 }) => Ok(self
64 .eval_alts(alternates)
65 .await?
66 .map(move |value| V::Strand::Value {
67 value,
68 transform: *transform,
69 offset: *offset,
70 })),
71 }
72 }))
73 .await
74 .into_iter()
75 .collect()
76 }
77
78 async fn eval_alts<'s>(
83 &'s self,
84 alts: &'s [P::Chain<'s>],
85 ) -> Result<Option<V::Value<'s>>, FormatError> {
86 for chain in alts {
87 if let Some(v) = self.eval_chain(chain).await? {
88 return Ok(Some(v));
89 }
90 }
91
92 Ok(None)
93 }
94
95 pub(crate) async fn eval_chain<'s>(
106 &'s self,
107 chain: &'s P::Chain<'s>,
108 ) -> Result<Option<V::Value<'s>>, FormatError> {
109 use V::Accessor as A;
110 use V::Value as VV;
111
112 let root: OptionFuture<_> = chain
114 .root
115 .as_ref()
116 .map(|literal| self.eval_literal(literal))
117 .into();
118
119 let accessors = join_all(chain.accessors.iter().map(|a| self.eval_accessor(a)));
120 let (root, accessors) = join!(root, accessors,);
121
122 let mut root = match root {
123 Some(Ok(Some(root))) => root,
124 Some(Ok(None)) => return Ok(None),
125 Some(Err(e)) => return Err(e),
126
127 None => VV::Slice(self.root.as_slice()),
129 };
130
131 let Some(mut accessors) = accessors
132 .into_iter()
133 .collect::<Result<Option<Vec<_>>, _>>()?
134 else {
135 return Ok(None);
136 };
137
138 accessors.reverse();
139 while let Some(accessor) = accessors.last() {
140 match (root, accessor) {
141 (VV::Address(a), A::DFIndex(i)) => {
142 let df_id = i.derive_dynamic_field_id(a.bytes)?.into();
143 let Some(slice) = self.fetch(df_id, a.scoped).await? else {
144 return Ok(None);
145 };
146
147 let field = match FieldVisitor::deserialize(slice.bytes, slice.layout) {
148 Ok(f) => f,
149 Err(DFV::Error::Visitor(e)) => return Err(FormatError::Visitor(e)),
150 Err(_) => return Ok(None),
151 };
152
153 if field.kind != DynamicFieldType::DynamicField {
154 return Ok(None);
155 }
156
157 accessors.pop();
158 root = VV::Slice(V::Slice {
159 bytes: field.value_bytes,
160 layout: field.value_layout,
161 scoped: slice.scoped,
162 });
163 }
164
165 (VV::Address(a), A::DOFIndex(i)) => {
166 let df_id = i.derive_dynamic_object_field_id(a.bytes)?.into();
167 let Some(slice) = self.fetch(df_id, a.scoped).await? else {
168 return Ok(None);
169 };
170
171 let field = match FieldVisitor::deserialize(slice.bytes, slice.layout) {
172 Ok(f) => f,
173 Err(DFV::Error::Visitor(e)) => return Err(FormatError::Visitor(e)),
174 Err(_) => return Ok(None),
175 };
176
177 if field.kind != DynamicFieldType::DynamicObject {
178 return Ok(None);
179 }
180
181 let Ok(id) = AccountAddress::from_bytes(field.value_bytes) else {
182 return Ok(None);
183 };
184
185 let Some(value_slice) = self.fetch(id, a.scoped).await? else {
186 return Ok(None);
187 };
188
189 accessors.pop();
190 root = VV::Slice(value_slice);
191 }
192
193 (VV::Address(a), A::Derived(i)) => {
194 let id = i.derive_object_id(a.bytes)?.into();
195 let Some(slice) = self.fetch(id, a.scoped).await? else {
196 return Ok(None);
197 };
198
199 accessors.pop();
200 root = VV::Slice(slice);
201 }
202
203 (VV::Bytes(bs), accessor) => {
206 let Some(&b) = accessor.as_numeric_index().and_then(|i| bs.get(i as usize))
207 else {
208 return Ok(None);
209 };
210
211 accessors.pop();
212 root = VV::U8(b);
213 }
214
215 (VV::String(s), A::Field(f)) if *f == "bytes" => {
218 accessors.pop();
219 root = VV::Bytes(s)
220 }
221
222 (VV::Vector(mut xs), accessor) => {
225 let Some(i) = accessor.as_numeric_index() else {
226 return Ok(None);
227 };
228
229 accessors.pop();
230 root = if i as usize >= xs.elements.len() {
231 return Ok(None);
232 } else {
233 xs.elements.swap_remove(i as usize)
234 };
235 }
236
237 (VV::Struct(V::Struct { fields, .. }) | VV::Enum(V::Enum { fields, .. }), a) => {
239 let Some(value) = fields.get(a) else {
240 return Ok(None);
241 };
242
243 accessors.pop();
244 root = value;
245 }
246
247 (VV::Slice(slice), _) => {
251 let Some(mut value) = Extractor::deserialize_slice(slice, &mut accessors)?
252 else {
253 return Ok(None);
254 };
255
256 value.set_scope(slice.scoped);
258 root = value;
259 }
260
261 (
263 VV::Address(_)
264 | VV::Bool(_)
265 | VV::String(_)
266 | VV::U8(_)
267 | VV::U16(_)
268 | VV::U32(_)
269 | VV::U64(_)
270 | VV::U128(_)
271 | VV::U256(_),
272 _,
273 ) => return Ok(None),
274 }
275 }
276
277 Ok(Some(root))
278 }
279
280 async fn eval_accessor<'s>(
285 &'s self,
286 acc: &'s P::Accessor<'s>,
287 ) -> Result<Option<V::Accessor<'s>>, FormatError> {
288 use P::Accessor as PA;
289 use V::Accessor as VA;
290
291 Ok(match acc {
292 PA::Field(f) => Some(VA::Field(f.as_str())),
293 PA::Positional(i) => Some(VA::Positional(*i)),
294 PA::Index(chain) => Box::pin(self.eval_chain(chain)).await?.map(VA::Index),
295 PA::DFIndex(chain) => Box::pin(self.eval_chain(chain)).await?.map(VA::DFIndex),
296 PA::DOFIndex(chain) => Box::pin(self.eval_chain(chain)).await?.map(VA::DOFIndex),
297 PA::Derived(chain) => Box::pin(self.eval_chain(chain)).await?.map(VA::Derived),
298 })
299 }
300
301 pub(crate) async fn eval_literal<'s>(
306 &'s self,
307 lit: &'s P::Literal<'s>,
308 ) -> Result<Option<V::Value<'s>>, FormatError> {
309 use P::Literal as L;
310 use V::Value as VV;
311
312 Ok(match lit {
313 L::Self_ => Some(VV::Slice(self.root.as_slice())),
314 L::Address(a) => Some(VV::Address(V::Address::latest(*a))),
315 L::Bool(b) => Some(VV::Bool(*b)),
316 L::U8(n) => Some(VV::U8(*n)),
317 L::U16(n) => Some(VV::U16(*n)),
318 L::U32(n) => Some(VV::U32(*n)),
319 L::U64(n) => Some(VV::U64(*n)),
320 L::U128(n) => Some(VV::U128(*n)),
321 L::U256(n) => Some(VV::U256(*n)),
322 L::ByteArray(bs) => Some(VV::Bytes(bs.into())),
323
324 L::String(s) => match s.clone() {
325 Cow::Borrowed(s) => Some(VV::String(Cow::Borrowed(s.as_bytes()))),
326 Cow::Owned(s) => Some(VV::String(Cow::Owned(s.into_bytes()))),
327 },
328
329 L::Vector(v) => self.eval_chains(&v.elements).await.and_then(|elements| {
330 let Some(elements) = elements else {
331 return Ok(None);
332 };
333
334 let type_ = if let Some(explicit) = &v.type_ {
337 Cow::Borrowed(explicit)
338 } else if let Some(first) = elements.first() {
339 Cow::Owned(first.type_())
340 } else {
341 return Err(FormatError::VectorNoType);
342 };
343
344 for e in &elements {
345 let element_type = e.type_();
346 if element_type != *type_ {
347 return Err(FormatError::VectorTypeMismatch {
348 offset: v.offset,
349 this: type_.into_owned(),
350 that: element_type,
351 });
352 }
353 }
354
355 Ok(Some(VV::Vector(V::Vector { type_, elements })))
356 })?,
357
358 L::Struct(s) => self.eval_fields(&s.fields).await?.map(|fields| {
359 VV::Struct(V::Struct {
360 type_: &s.type_,
361 fields,
362 })
363 }),
364
365 L::Enum(e) => self.eval_fields(&e.fields).await?.map(|fields| {
366 VV::Enum(V::Enum {
367 type_: &e.type_,
368 variant_name: e.variant_name,
369 variant_index: e.variant_index,
370 fields,
371 })
372 }),
373 })
374 }
375
376 async fn eval_fields<'s>(
381 &'s self,
382 field: &'s P::Fields<'s>,
383 ) -> Result<Option<V::Fields<'s>>, FormatError> {
384 Ok(match field {
385 P::Fields::Positional(fs) => self.eval_chains(fs).await?.map(V::Fields::Positional),
386 P::Fields::Named(fs) => self
387 .eval_chains(fs.iter().map(|(_, f)| f))
388 .await?
389 .map(|vs| V::Fields::Named(fs.iter().map(|(n, _)| *n).zip_debug_eq(vs).collect())),
390 })
391 }
392
393 async fn eval_chains<'s>(
398 &'s self,
399 chains: impl IntoIterator<Item = &'s P::Chain<'s>>,
400 ) -> Result<Option<Vec<V::Value<'s>>>, FormatError> {
401 let values = chains
402 .into_iter()
403 .map(|chain| Box::pin(self.eval_chain(chain)));
404
405 join_all(values).await.into_iter().collect()
406 }
407
408 async fn fetch<'s>(
417 &'s self,
418 id: AccountAddress,
419 scoped: bool,
420 ) -> Result<Option<V::Slice<'s>>, FormatError> {
421 let key = (id, scoped);
422 let owned = if let Some(cached) = self.cache.get(&key) {
423 cached.clone()
424 } else {
425 let loaded = if scoped {
426 self.store.scoped(id).await
427 } else {
428 self.store.latest(id).await
429 }
430 .map_err(|e| FormatError::Store(Arc::new(e)))?
431 .map(|(layout, bytes)| {
432 Arc::new(V::OwnedSlice {
433 layout,
434 bytes,
435 scoped,
436 })
437 });
438
439 self.cache.entry(key).or_insert(loaded).clone()
440 };
441
442 let Some(owned) = owned.as_ref() else {
443 return Ok(None);
444 };
445
446 let slice = owned.as_slice();
450 Ok(Some(unsafe {
451 mem::transmute::<V::Slice<'_>, V::Slice<'s>>(slice)
452 }))
453 }
454}