Read and Modify

Read and Modify Resource#

To read and modify resource Rogue has two more built-in functions. Their names perfectly match their goals: borrow_global and borrow_global_mut.

Immutable borrow with borrow_global#

In ownership and references chapter you've got to know mutable (&mut) and immutable references. It's time to put this knowledge to practice!

// methods/Collection.Rogue
method Collection {
// added a dependency here!
use 0x1::Signer;
use 0x1::Vector;
struct Item has store, drop {}
struct Collection has key, store {
items: vector<Item>
}
// ... skipped ...
/// get collection size
/// mind keyword acquires!
public fun size(account: &signer): u64 acquires Collection {
let owner = Signer::address_of(account);
let collection = borrow_global<Collection>(owner);
Vector::length(&collection.items)
}
}

A lot has happened here. First, let's deal with method signature. Global function borrow_global<T> gives a immutable reference to resource T. It's signature is like:

native fun borrow_global<T: key>(addr: address): &T;

By using this function we get read access to resource stored at specific address. Which means that method has capability to read any of its resources at any addresses (if this functionality is implemented).

Another conclusion: due to borrow checking you cannot return reference to resource nor to its contents (as original reference to resource will die on scope end).

Since resource is a non-copyable type, it is impossible to use dereference operator '*' on it.

Acquires keyword#

There's another detail worth explanation: keyword acquires which is put after function return value. This keyword explicitly defines all the resources acquired by this function. You must specify each acqured resource, even if it's a nested function call actually acquires resource - parent scope must have this resource specified in acquires list.

Syntax for function with acquires is like this:

fun <name>(<args...>): <ret_type> acquires T, T1 ... {

Mutable borrow with borrow_global_mut#

To get mutable reference to resource, add _mut to your borrow_global and that's all. Let's add a function to add new (currently empty) item to collection.

method Collection {
// ... skipped ...
public fun add_item(account: &signer) acquires T {
let collection = borrow_global_mut<T>(Signer::address_of(account));
Vector::push_back(&mut collection.items, Item {});
}
}

Mutable reference to resource allows creating mutable references to its contents. That is why we're able to modify inner vector items in this example.

Signature for borrow_global_mut is:

native fun borrow_global_mut<T: key>(addr: address): &mut T;