use 0x1::option;
use 0x2::dynamic_field;
use 0x2::object;
use 0x2::transfer;
use 0x2::tx_context;
Resource Config
struct Config<WriteCap> has key
Fields
Struct Setting
struct Setting<Value: copy, drop, store> has drop, store
Fields
Struct SettingData
struct SettingData<Value: copy, drop, store> has drop, store
Fields
Constants
const EBCSSerializationFailure: u64 = 2;
const EAlreadySetForEpoch: u64 = 0;
const ENotSetForEpoch: u64 = 1;
Function new
public(friend) fun new<WriteCap>(_cap: &mut WriteCap, ctx: &mut tx_context::TxContext): config::Config<WriteCap>
Implementation
public(package) fun new<WriteCap>(_cap: &mut WriteCap, ctx: &mut TxContext): Config<WriteCap> {
Config<WriteCap> { id: object::new(ctx) }
}
Function create
public(friend) fun create<WriteCap>(cap: &mut WriteCap, ctx: &mut tx_context::TxContext)
Implementation
Function add_for_current_epoch
public(friend) fun add_for_current_epoch<WriteCap, Name: copy, drop, store, Value: copy, drop, store>(config: &mut config::Config<WriteCap>, _cap: &mut WriteCap, name: Name, value: Value, ctx: &mut tx_context::TxContext): option::Option<Value>
Implementation
public(package) fun add_for_current_epoch<
WriteCap,
Name: copy + drop + store,
Value: copy + drop + store,
>(
config: &mut Config<WriteCap>,
_cap: &mut WriteCap,
name: Name,
value: Value,
ctx: &mut TxContext,
): Option<Value> {
let epoch = ctx.epoch();
if (!field::exists_(&config.id, name)) {
let sobj = Setting {
data: option::some(SettingData {
newer_value_epoch: epoch,
newer_value: option::some(value),
older_value_opt: option::none(),
}),
};
field::add(&mut config.id, name, sobj);
option::none()
} else {
let sobj: &mut Setting<Value> = field::borrow_mut(&mut config.id, name);
let SettingData {
newer_value_epoch,
newer_value,
older_value_opt,
} = sobj.data.extract();
let (older_value_opt, removed_value) =
if (epoch > newer_value_epoch) {
// if the `newer_value` is for a previous epoch, move it to `older_value_opt`
(move newer_value, move older_value_opt)
} else {
// the current epoch cannot be less than the `newer_value_epoch`
assert!(epoch == newer_value_epoch);
// if the `newer_value` is for the current epoch, then the option must be `none`
assert!(newer_value.is_none(), EAlreadySetForEpoch);
(move older_value_opt, option::none())
};
sobj.data.fill(SettingData {
newer_value_epoch: epoch,
newer_value: option::some(value),
older_value_opt,
});
removed_value
}
}
Function remove_for_current_epoch
public(friend) fun remove_for_current_epoch<WriteCap, Name: copy, drop, store, Value: copy, drop, store>(config: &mut config::Config<WriteCap>, _cap: &mut WriteCap, name: Name, ctx: &mut tx_context::TxContext): option::Option<Value>
Implementation
public(package) fun remove_for_current_epoch<
WriteCap,
Name: copy + drop + store,
Value: copy + drop + store,
>(
config: &mut Config<WriteCap>,
_cap: &mut WriteCap,
name: Name,
ctx: &mut TxContext,
): Option<Value> {
let epoch = ctx.epoch();
if (!field::exists_(&config.id, name)) return option::none();
let sobj: &mut Setting<Value> = field::borrow_mut(&mut config.id, name);
let SettingData {
newer_value_epoch,
newer_value,
older_value_opt,
} = sobj.data.extract();
let (older_value_opt, removed_value) =
if (epoch > newer_value_epoch) {
// if the `newer_value` is for a previous epoch, move it to `older_value_opt`
(move newer_value, option::none())
} else {
// the current epoch cannot be less than the `newer_value_epoch`
assert!(epoch == newer_value_epoch);
(move older_value_opt, move newer_value)
};
let older_value_opt_is_none = older_value_opt.is_none();
sobj.data.fill(SettingData {
newer_value_epoch: epoch,
newer_value: option::none(),
older_value_opt,
});
if (older_value_opt_is_none) {
field::remove<_, Setting<Value>>(&mut config.id, name);
};
removed_value
}
Function exists_with_type
public(friend) fun exists_with_type<WriteCap, Name: copy, drop, store, Value: copy, drop, store>(config: &config::Config<WriteCap>, name: Name): bool
Implementation
public(package) fun exists_with_type<
WriteCap,
Name: copy + drop + store,
Value: copy + drop + store,
>(
config: &Config<WriteCap>,
name: Name,
): bool {
field::exists_with_type<_, Setting<Value>>(&config.id, name)
}
Function exists_with_type_for_current_epoch
public(friend) fun exists_with_type_for_current_epoch<WriteCap, Name: copy, drop, store, Value: copy, drop, store>(config: &config::Config<WriteCap>, name: Name, ctx: &tx_context::TxContext): bool
Implementation
public(package) fun exists_with_type_for_current_epoch<
WriteCap,
Name: copy + drop + store,
Value: copy + drop + store,
>(
config: & Config<WriteCap>,
name: Name,
ctx: &TxContext,
): bool {
field::exists_with_type<_, Setting<Value>>(&config.id, name) && {
let epoch = ctx.epoch();
let sobj: &Setting<Value> = field::borrow(&config.id, name);
epoch == sobj.data.borrow().newer_value_epoch &&
sobj.data.borrow().newer_value.is_some()
}
}
Function borrow_for_current_epoch_mut
public(friend) fun borrow_for_current_epoch_mut<WriteCap, Name: copy, drop, store, Value: copy, drop, store>(config: &mut config::Config<WriteCap>, _cap: &mut WriteCap, name: Name, ctx: &mut tx_context::TxContext): &mut Value
Implementation
public(package) fun borrow_for_current_epoch_mut<
WriteCap,
Name: copy + drop + store,
Value: copy + drop + store,
>(
config: &mut Config<WriteCap>,
_cap: &mut WriteCap,
name: Name,
ctx: &mut TxContext,
): &mut Value {
let epoch = ctx.epoch();
let sobj: &mut Setting<Value> = field::borrow_mut(&mut config.id, name);
let data = sobj.data.borrow_mut();
assert!(data.newer_value_epoch == epoch, ENotSetForEpoch);
assert!(data.newer_value.is_some(), ENotSetForEpoch);
data.newer_value.borrow_mut()
}
Function borrow_most_recent
public(friend) fun borrow_most_recent<WriteCap, Name: copy, drop, store, Value: copy, drop, store>(config: &config::Config<WriteCap>, name: Name): &Value
Implementation
public(package) fun borrow_most_recent<
WriteCap,
Name: copy + drop + store,
Value: copy + drop + store,
>(
config: &Config<WriteCap>,
name: Name,
): &Value {
let sobj: &Setting<Value> = field::borrow(&config.id, name);
let data = sobj.data.borrow();
assert!(data.newer_value.is_some(), ENotSetForEpoch);
data.newer_value.borrow()
}
Function read_setting
public(friend) fun read_setting<Name: copy, drop, store, Value: copy, drop, store>(config: object::ID, name: Name, ctx: &tx_context::TxContext): option::Option<Value>
Implementation
public(package) fun read_setting<Name: copy + drop + store, Value: copy + drop + store>(
config: ID,
name: Name,
ctx: &TxContext,
): Option<Value> {
use sui::dynamic_field::Field;
let config_id = config.to_address();
let setting_df = field::hash_type_and_key(config_id, name);
read_setting_impl<Field<Name, Setting<Value>>, Setting<Value>, SettingData<Value>, Value>(
config_id,
setting_df,
ctx.epoch(),
)
}
Function read_setting_impl
fun read_setting_impl<FieldSettingValue: key, SettingValue: store, SettingDataValue: store, Value: copy, drop, store>(config: address, name: address, current_epoch: u64): option::Option<Value>
Implementation
native fun read_setting_impl<
FieldSettingValue: key,
SettingValue: store,
SettingDataValue: store,
Value: copy + drop + store,
>(
config: address,
name: address,
current_epoch: u64,
): Option<Value>;