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

Code before:
    U32(u32),
    U256(int256::U256),
    // NOTE: Added in v8
    Closure(AnnotatedMoveClosure),
    RawStruct(RawMoveStruct),
    // NOTE: Added in bytecode version v9, do not reorder!
    I8(i8),
    I16(i16),
    I32(i32),
    I64(i64),
    I128(i128),
    I256(int256::I256),
}

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),

Review comment (performance):
These keys seem pretty expensive, in theory we need only a type tag for resource or module id + index? a general question: why we need fats type in the first place? TypeTag has all the info (apart from abilities and enums), but we can keep some extra context on a side? I wonder if we can just switch to tag-based views and travers tag tree to save on any fat type computation

Code after:
    U32(u32),
    U256(int256::U256),
    // NOTE: Added in v8
    Closure(AnnotatedMoveClosure),
    RawStruct(RawMoveStruct),
    // NOTE: Added in bytecode version v9, do not reorder!
    I8(i8),
    I16(i16),
    I32(i32),
    I64(i64),
    I128(i128),
    I256(int256::I256),
}

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)
    }