Repository: aptos-labs/aptos-core
File: third_party/move/tools/move-resource-viewer/src/lib.rs (Rust)

Code before:
pub struct MoveValueAnnotator<V> {
    module_viewer: V,
    /// A cache for fat type info for structs. For a generic struct, the uninstantiated
    /// FatStructType of the base definition will be stored here as well.
    fat_struct_def_cache: RefCell<BTreeMap<StructName, FatStructRef>>,
    /// A cache for fat type info for struct instantiations. This cache is build from
    /// substituting parameters for the uninstantiated types in `fat_struct_def_cache`.
    fat_struct_inst_cache: RefCell<BTreeMap<(StructName, Vec<FatType>), FatStructRef>>,
}

#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
struct StructName {
    address: AccountAddress,
    module: Identifier,
    name: Identifier,
}

impl<V: CompiledModuleView> MoveValueAnnotator<V> {
    pub fn new(module_viewer: V) -> Self {
        Self {
            module_viewer,
            fat_struct_def_cache: RefCell::default(),
            fat_struct_inst_cache: RefCell::default(),
        }
    }

    pub fn get_type_layout_with_types(&self, type_tag: &TypeTag) -> anyhow::Result<MoveTypeLayout> {
        TypeLayoutBuilder::build_with_types(type_tag, &self.module_viewer)
    }

    pub fn view_module(&self, id: &ModuleId) -> anyhow::Result<Option<V::Item>> {
        self.module_viewer.view_compiled_module(id)
    }

    pub fn view_existing_module(&self, id: &ModuleId) -> anyhow::Result<V::Item> {
        match self.view_module(id)? {
            Some(module) => Ok(module),
            None => bail!("Module {:?} can't be found", id),
        }
    }

    pub fn view_script_arguments(
        &self,
        script_bytes: &[u8],
        args: &[TransactionArgument],
        ty_args: &[TypeTag],
    ) -> anyhow::Result<Vec<AnnotatedMoveValue>> {
        let mut limit = Limiter::default();
        let compiled_script = CompiledScript::deserialize(script_bytes)
            .map_err(|err| anyhow!("Failed to deserialzie script: {:?}", err))?;
        let param_tys = compiled_script

Review comment (bug):
Once thing that becomes wrong now with caches are limits, `Limiter` may not error when it could have before: this is probably fine as this is not gas and just to bound execution to some fixed number of steps, probably is worth mentioning somewhere?

Code after:
pub struct MoveValueAnnotator<V> {
    module_viewer: V,
    /// A cache for fat type info for structs. For a generic struct, the uninstantiated
    /// FatStructType of the base definition will be stored here as well.
    ///
    /// Notice that this cache (and the next one) effect the computation `Limit`: no-cached
    /// annotation may hit limits which cached ones don't. Since limits aren't precise metering,
    /// this effect is expected and OK.
    fat_struct_def_cache: RefCell<BTreeMap<StructName, FatStructRef>>,
    /// A cache for fat type info for struct instantiations. This cache is build from
    /// substituting parameters for the uninstantiated types in `fat_struct_def_cache`.
    fat_struct_inst_cache: RefCell<BTreeMap<(StructName, Vec<FatType>), FatStructRef>>,
}

#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
struct StructName {
    address: AccountAddress,
    module: Identifier,
    name: Identifier,
}

impl<V: CompiledModuleView> MoveValueAnnotator<V> {
    pub fn new(module_viewer: V) -> Self {
        Self {
            module_viewer,
            fat_struct_def_cache: RefCell::default(),
            fat_struct_inst_cache: RefCell::default(),
        }
    }

    pub fn get_type_layout_with_types(&self, type_tag: &TypeTag) -> anyhow::Result<MoveTypeLayout> {
        TypeLayoutBuilder::build_with_types(type_tag, &self.module_viewer)
    }

    pub fn view_module(&self, id: &ModuleId) -> anyhow::Result<Option<V::Item>> {
        self.module_viewer.view_compiled_module(id)
    }

    pub fn view_existing_module(&self, id: &ModuleId) -> anyhow::Result<V::Item> {
        match self.view_module(id)? {
            Some(module) => Ok(module),
            None => bail!("Module {:?} can't be found", id),
        }
    }

    pub fn view_script_arguments(
        &self,
        script_bytes: &[u8],
        args: &[TransactionArgument],
        ty_args: &[TypeTag],
    ) -> anyhow::Result<Vec<AnnotatedMoveValue>> {