Module 0x2::versioned
- Resource
Versioned
- Struct
VersionChangeCap
- Constants
- Function
create
- Function
version
- Function
load_value
- Function
load_value_mut
- Function
remove_value_for_upgrade
- Function
upgrade
- Function
destroy
use 0x2::dynamic_field;
use 0x2::object;
use 0x2::tx_context;
Resource Versioned
A wrapper type that supports versioning of the inner type. The inner type is a dynamic field of the Versioned object, and is keyed using version. User of this type could load the inner object using corresponding type based on the version. You can also upgrade the inner object to a new type version. If you want to support lazy upgrade of the inner type, one caveat is that all APIs would have to use mutable reference even if it's a read-only API.
struct Versioned has store, key
Fields
id: object::UID
version: u64
Struct VersionChangeCap
Represents a hot potato object generated when we take out the dynamic field. This is to make sure that we always put a new value back.
structVersionChangeCap
Fields
versioned_id: object::ID
old_version: u64
Constants
Failed to upgrade the inner object due to invalid capability or new version.
const EInvalidUpgrade: u64 = 0;
Function create
Create a new Versioned object that contains a initial value of type T
with an initial version.
public fun create<T: store>(init_version: u64, init_value: T, ctx: &mut tx_context::TxContext): versioned::Versioned
Implementation
public fun create<T: store>(init_version: u64, init_value: T, ctx: &mut TxContext): Versioned {
let mut self = Versioned {
id: object::new(ctx),
version: init_version,
};
dynamic_field::add(&mut self.id, init_version, init_value);
self
}
Function version
Get the current version of the inner type.
public fun version(self: &versioned::Versioned): u64
Function load_value
Load the inner value based on the current version. Caller specifies an expected type T. If the type mismatch, the load will fail.
public fun load_value<T: store>(self: &versioned::Versioned): &T
Implementation
public fun load_value<T: store>(self: &Versioned): &T {
dynamic_field::borrow(&self.id, self.version)
}
Function load_value_mut
Similar to load_value, but return a mutable reference.
public fun load_value_mut<T: store>(self: &mut versioned::Versioned): &mut T
Implementation
public fun load_value_mut<T: store>(self: &mut Versioned): &mut T {
dynamic_field::borrow_mut(&mut self.id, self.version)
}
Function remove_value_for_upgrade
Take the inner object out for upgrade. To ensure we always upgrade properly, a capability object is returned and must be used when we upgrade.
public fun remove_value_for_upgrade<T: store>(self: &mut versioned::Versioned): (T, versioned::VersionChangeCap)
Implementation
public fun remove_value_for_upgrade<T: store>(self: &mut Versioned): (T, VersionChangeCap) {
(
dynamic_field::remove(&mut self.id, self.version),
VersionChangeCap {
versioned_id: object::id(self),
old_version: self.version,
}
)
}
Function upgrade
Upgrade the inner object with a new version and new value. Must use the capability returned by calling remove_value_for_upgrade.
public fun upgrade<T: store>(self: &mut versioned::Versioned, new_version: u64, new_value: T, cap: versioned::VersionChangeCap)
Implementation
public fun upgrade<T: store>(self: &mut Versioned, new_version: u64, new_value: T, cap: VersionChangeCap) {
let VersionChangeCap { versioned_id, old_version } = cap;
assert!(versioned_id == object::id(self), EInvalidUpgrade);
assert!(old_version < new_version, EInvalidUpgrade);
dynamic_field::add(&mut self.id, new_version, new_value);
self.version = new_version;
}
Function destroy
Destroy this Versioned container, and return the inner object.
public fun destroy<T: store>(self: versioned::Versioned): T
Implementation
public fun destroy<T: store>(self: Versioned): T {
let Versioned { mut id, version } = self;
let ret = dynamic_field::remove(&mut id, version);
id.delete();
ret
}