0x1::Collection2Provide a account based vector for save resource item. The resource in CollectionStore can borrowed by anyone, anyone can get immutable ref of item. and the owner of Collection can allow others to add item to Collection or get mut ref from Collection.git
CollectionCollectionStorelengthborrowpush_backborrow_mutpop_backremoveappendappend_allexists_atis_acceptacceptputput_alltakecreate_collectionlength_ofborrow_collectionreturn_collectiondestroy_collectiondestroy_emptyuse 0x1::Errors;
use 0x1::Option;
use 0x1::Signer;
use 0x1::Vector;
CollectionCollection in memory, can not drop & store.
struct Collection<T>
items: vector<T>
owner: address
can_put: bool
can_mut: bool
can_take: bool
CollectionStoreCollection in global store.
struct CollectionStore<T: store> has key
items: Option::Option<vector<T>>
anyone_can_put: bool
anyone_can_mut: bool
The operator require the collection owner or collection set anyone_can_put to true.
const ERR_COLLECTION_CAN_NOT_ADD: u64 = 102;
The operator require the collection owner or collection set anyone_can_mut to true.
const ERR_COLLECTION_CAN_NOT_MUT: u64 = 103;
The operator require the collection owner
const ERR_COLLECTION_CAN_NOT_TAKE: u64 = 104;
const ERR_COLLECTION_INVALID_BORROW_STATE: u64 = 105;
const ERR_COLLECTION_IS_NOT_EMPTY: u64 = 106;
const ERR_COLLECTION_NOT_EXIST: u64 = 101;
lengthReturn the length of the collection.
public fun length<T>(c: &Collection2::Collection<T>): u64
public fun length<T>(c: &Collection<T>): u64{
Vector::length(&c.items)
}
aborts_if false;
borrowAcquire an immutable reference to the ith element of the collection c.
Aborts if i is out of bounds.
public fun borrow<T>(c: &Collection2::Collection<T>, i: u64): &T
public fun borrow<T>(c: &Collection<T>, i: u64): &T{
Vector::borrow(&c.items, i)
}
push_backAdd item v to the end of the collection c.
require owner of Collection.
public fun push_back<T>(c: &mut Collection2::Collection<T>, t: T)
public fun push_back<T>(c: &mut Collection<T>, t: T){
assert!(c.can_put, Errors::requires_address(ERR_COLLECTION_CAN_NOT_ADD));
Vector::push_back<T>(&mut c.items, t);
}
borrow_mutReturn a mutable reference to the ith item in the Collection c.
Aborts if i is out of bounds.
public fun borrow_mut<T>(c: &mut Collection2::Collection<T>, i: u64): &mut T
public fun borrow_mut<T>(c: &mut Collection<T>, i: u64): &mut T{
assert!(c.can_mut, Errors::requires_address(ERR_COLLECTION_CAN_NOT_MUT));
Vector::borrow_mut<T>(&mut c.items, i)
}
pop_backPop an element from the end of vector v.
Aborts if v is empty.
public fun pop_back<T>(c: &mut Collection2::Collection<T>): T
public fun pop_back<T>(c: &mut Collection<T>): T {
assert!(c.can_take, Errors::requires_address(ERR_COLLECTION_CAN_NOT_TAKE));
Vector::pop_back<T>(&mut c.items)
}
removepublic fun remove<T>(c: &mut Collection2::Collection<T>, i: u64): T
public fun remove<T>(c: &mut Collection<T>, i: u64): T{
assert!(c.can_take, Errors::requires_address(ERR_COLLECTION_CAN_NOT_TAKE));
Vector::remove<T>(&mut c.items, i)
}
appendpublic fun append<T>(c: &mut Collection2::Collection<T>, other: T)
public fun append<T>(c: &mut Collection<T>, other: T) {
assert!(c.can_put, Errors::requires_address(ERR_COLLECTION_CAN_NOT_ADD));
Vector::append<T>(&mut c.items, Vector::singleton(other))
}
append_allpublic fun append_all<T>(c: &mut Collection2::Collection<T>, other: vector<T>)
public fun append_all<T>(c: &mut Collection<T>, other: vector<T>) {
assert!(c.can_put, Errors::requires_address(ERR_COLLECTION_CAN_NOT_ADD));
Vector::append<T>(&mut c.items, other)
}
exists_atcheck the Collection exists in addr
public fun exists_at<T: store>(addr: address): bool
public fun exists_at<T: store>(addr: address): bool{
exists<CollectionStore<T>>(addr)
}
aborts_if false;
is_acceptcheck addr is accept T and other can send T to addr,
it means exists a Collection of T at addr and anyone_can_put of the Collection is true
public fun is_accept<T: store>(addr: address): bool
public fun is_accept<T: store>(addr: address): bool acquires CollectionStore {
if (!exists<CollectionStore<T>>(addr)){
return false
};
let cs = borrow_global<CollectionStore<T>>(addr);
cs.anyone_can_put
}
acceptsigner allow other send T to self create a Collection of T and set anyone_can_put to true if the Collection exists, just update anyone_can_put to true
public fun accept<T: store>(signer: &signer)
public fun accept<T: store>(signer: &signer) acquires CollectionStore {
let addr = Signer::address_of(signer);
if (!exists<CollectionStore<T>>(addr)){
Self::create_collection<T>(signer, true, false);
};
let cs = borrow_global_mut<CollectionStore<T>>(addr);
if (!cs.anyone_can_put) {
cs.anyone_can_put = true;
}
}
putPut items to to_addr’s Collection of T
put = borrow_collection
public fun put<T: store>(signer: &signer, owner: address, item: T)
public fun put<T: store>(signer: &signer, owner: address, item: T) acquires CollectionStore{
let c = Self::borrow_collection(signer, owner);
Self::append(&mut c, item);
Self::return_collection(c);
}
aborts_if false;
put_allPut all items to owner’s collection of T.
public fun put_all<T: store>(signer: &signer, owner: address, items: vector<T>)
public fun put_all<T: store>(signer: &signer, owner: address, items: vector<T>) acquires CollectionStore{
let c = Self::borrow_collection(signer, owner);
Self::append_all(&mut c, items);
Self::return_collection(c);
}
aborts_if false;
takeTake last item from signer’s Collection of T.
public fun take<T: store>(signer: &signer): T
public fun take<T: store>(signer: &signer): T acquires CollectionStore{
let addr = Signer::address_of(signer);
let c = borrow_collection<T>(signer, addr);
let item = pop_back(&mut c);
return_collection(c);
item
}
aborts_if false;
create_collectionpublic fun create_collection<T: store>(signer: &signer, anyone_can_put: bool, anyone_can_mut: bool)
public fun create_collection<T:store>(signer: &signer, anyone_can_put: bool, anyone_can_mut: bool) {
move_to(signer, CollectionStore<T>{items: Option::some(Vector::empty<T>()), anyone_can_put, anyone_can_mut})
}
length_ofReturn the length of Collectionowner, if collection do not exist, return 0.
public fun length_of<T: store>(owner: address): u64
public fun length_of<T: store>(owner: address) : u64 acquires CollectionStore{
if (exists_at<T>(owner)){
let cs = borrow_global_mut<CollectionStore<T>>(owner);
//if items is None, indicate it is borrowed
assert!(!Option::is_none(&cs.items), Errors::invalid_state(ERR_COLLECTION_INVALID_BORROW_STATE));
let items = Option::borrow(&cs.items);
Vector::length(items)
}else{
0
}
}
borrow_collectionBorrow collection of T from owner, auto detected the collection’s can_put |
can_mut | can_take by the sender and Collection config. |
public fun borrow_collection<T: store>(sender: &signer, owner: address): Collection2::Collection<T>
public fun borrow_collection<T: store>(sender: &signer, owner: address): Collection<T> acquires CollectionStore{
assert!(exists_at<T>(owner), Errors::invalid_state(ERR_COLLECTION_NOT_EXIST));
let cs = borrow_global_mut<CollectionStore<T>>(owner);
//if items is None, indicate it is borrowed
assert!(!Option::is_none(&cs.items), Errors::invalid_state(ERR_COLLECTION_INVALID_BORROW_STATE));
let items = Option::extract(&mut cs.items);
let is_owner = owner == Signer::address_of(sender);
let can_put = cs.anyone_can_put || is_owner;
let can_mut = cs.anyone_can_mut || is_owner;
let can_take = is_owner;
Collection{
items,
owner,
can_put,
can_mut,
can_take,
}
}
aborts_if false;
return_collectionReturn the Collection of T
public fun return_collection<T: store>(c: Collection2::Collection<T>)
public fun return_collection<T: store>(c: Collection<T>) acquires CollectionStore{
let Collection{ items, owner, can_put:_, can_mut:_, can_take:_ } = c;
let cs = borrow_global_mut<CollectionStore<T>>(owner);
assert!(Option::is_none(&cs.items), Errors::invalid_state(ERR_COLLECTION_INVALID_BORROW_STATE));
Option::fill(&mut cs.items, items);
}
aborts_if false;
destroy_collectionpublic fun destroy_collection<T: store>(signer: &signer)
public fun destroy_collection<T: store>(signer: &signer) acquires CollectionStore{
let c = move_from<CollectionStore<T>>(Signer::address_of(signer));
destroy_empty(c);
}
aborts_if false;
destroy_emptyfun destroy_empty<T: store>(c: Collection2::CollectionStore<T>)
fun destroy_empty<T: store>(c: CollectionStore<T>){
let CollectionStore{ items, anyone_can_put:_, anyone_can_mut:_,} = c;
if (Option::is_some(&items)) {
let item_vec = Option::extract(&mut items);
assert!(Vector::is_empty(&item_vec), Errors::invalid_state(ERR_COLLECTION_IS_NOT_EMPTY));
Vector::destroy_empty(item_vec);
Option::destroy_none(items);
}else{
Option::destroy_none(items);
}
}
aborts_if false;
pragma verify = false;
pragma aborts_if_is_strict = false;