sui move table 和 bag

引言

本文通过阅读分析table、bag的源码实现,深入理解此类型的使用方法和实现原理。

table

上一篇文章我们阅读了dynamic_field源码,知道了动态字段的实现原理,那么在看table就会很简单了。table.move定义了一个Table结构体

    struct Table<phantom K: copy + drop + store, phantom V: store> has key, store {
        /// the ID of this table
        id: UID,
        /// the number of key-value pairs in the table
        size: u64,
    }

其实这个Table obj就是dynamic_field中为其增添子对象的object,这里来回忆一下

    public fun add<Name: copy + drop + store, Value: store>(
        // we use &mut UID in several spots for access control
        object: &mut UID,
        name: Name,
        value: Value,
    ) {
        let object_addr = object::uid_to_address(object);
        let hash = hash_type_and_key(object_addr, name);
        assert!(!has_child_object(object_addr, hash), EFieldAlreadyExists);
        let field = Field {
            id: object::new_uid_from_hash(hash),
            name,
            value,
        };
        add_child_object(object_addr, field)
    }

Table就是拥有filed的父对象,其中的size代表了拥有filed动态字段的数量,初始为0.
需要注意的是,Table结构体在创建时就指定好它能储存哪种类型的键值对struct Table<phantom K: copy + drop + store, phantom V: store> has key, store,不能储存不同类型的键值对。

创建

    public fun new<K: copy + drop + store, V: store>(ctx: &mut TxContext): Table<K, V> {
        Table {
            id: object::new(ctx),
            size: 0,
        }
    }

调用new创建返回一个Table obj,需要指定固定类型的key和value

增加/删除

    public fun add<K: copy + drop + store, V: store>(table: &mut Table<K, V>, k: K, v: V) {
        field::add(&mut table.id, k, v);
        table.size = table.size + 1;
    }

    public fun remove<K: copy + drop + store, V: store>(table: &mut Table<K, V>, k: K): V {
        let v = field::remove(&mut table.id, k);
        table.size = table.size - 1;
        v
    }

要注意的是,添加的key和value必须与table的两个phantom一致
实现很简单,调用dynamic_field的add remove方法,然后变更长度信息

获取

    public fun borrow<K: copy + drop + store, V: store>(table: &Table<K, V>, k: K): &V {
        field::borrow(&table.id, k)
    }

    /// Mutably borrows the value associated with the key in the table `table: &mut Table<K, V>`.
    /// Aborts with `sui::dynamic_field::EFieldDoesNotExist` if the table does not have an entry with
    /// that key `k: K`.
    public fun borrow_mut<K: copy + drop + store, V: store>(table: &mut Table<K, V>, k: K): &mut V {
        field::borrow_mut(&mut table.id, k)
    }

同样是简单调用dynamic_field中的函数取得value的可变和不可变借用

其他函数

    public fun contains<K: copy + drop + store, V: store>(table: &Table<K, V>, k: K): bool {
        field::exists_with_type<K, V>(&table.id, k)
    }

    /// Returns the size of the table, the number of key-value pairs
    public fun length<K: copy + drop + store, V: store>(table: &Table<K, V>): u64 {
        table.size
    }

    /// Returns true iff the table is empty (if `length` returns `0`)
    public fun is_empty<K: copy + drop + store, V: store>(table: &Table<K, V>): bool {
        table.size == 0
    }

    /// Destroys an empty table
    /// Aborts with `ETableNotEmpty` if the table still contains values
    public fun destroy_empty<K: copy + drop + store, V: store>(table: Table<K, V>) {
        let Table { id, size } = table;
        assert!(size == 0, ETableNotEmpty);
        object::delete(id)
    }

    /// Drop a possibly non-empty table.
    /// Usable only if the value type `V` has the `drop` ability
    public fun drop<K: copy + drop + store, V: drop + store>(table: Table<K, V>) {
        let Table { id, size: _ } = table;
        object::delete(id)
    }

contains判断table相应键是否存在
length返回table动态字段的数目
is_empty判断table是否为空
destroy_empty可以解构一个空的table
drop可以用来解构非空的table

bag

bag与table的差别在于 它可以储存不同类型的键值对 在bag的结构体定义时,bag没有规定键值的类型

    struct Bag has key, store {
        /// the ID of this bag
        id: UID,
        /// the number of key-value pairs in the bag
        size: u64,
    }

其他部分和table的实现一致

总结

table、bag是对dynamic_field的简单封装。其中,table限定了键值对的类型,在创建时需要指定类型,并且只能存储相同类型的键值对;而bag则是一种更灵活的数据结构,可以存储不同类型的键值对。通过本文的阐述,应该可以更深入地理解这两种数据结构的使用方法和实现原理,从而更好地应用于实际的开发中。

Move语言学习交流QQ群: 79489587
Sui官方中文开发者电报群: https://t.me/sui_dev_cn

  • 12
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值