use crate::internal_prelude::*;
use radix_rust::rust::{iter::*, mem};
use radix_substate_store_interface::interface::*;
#[derive(Clone, Debug)]
pub struct RuntimeSubstate {
pub value: IndexedScryptoValue,
}
impl RuntimeSubstate {
pub fn new(value: IndexedScryptoValue) -> Self {
Self { value }
}
}
#[derive(Clone, Debug)]
pub enum ReadOnly {
NonExistent,
Existent(RuntimeSubstate),
}
#[derive(Clone, Debug)]
pub enum Write {
Update(RuntimeSubstate),
Delete,
}
impl Write {
pub fn into_value(self) -> Option<IndexedScryptoValue> {
match self {
Write::Update(substate) => Some(substate.value),
Write::Delete => None,
}
}
}
#[derive(Clone, Debug)]
pub struct TrackedSubstate {
pub substate_key: SubstateKey,
pub substate_value: TrackedSubstateValue,
}
#[derive(Clone, Debug)]
pub enum TrackedSubstateValue {
New(RuntimeSubstate),
ReadOnly(ReadOnly),
ReadExistAndWrite(IndexedScryptoValue, Write),
ReadNonExistAndWrite(RuntimeSubstate),
WriteOnly(Write),
Garbage,
}
impl TrackedSubstate {
pub fn size(&self) -> usize {
self.substate_value.size()
}
}
impl TrackedSubstateValue {
pub fn size(&self) -> usize {
match self {
TrackedSubstateValue::New(x) => x.value.len(),
TrackedSubstateValue::ReadOnly(r) => match r {
ReadOnly::NonExistent => 0,
ReadOnly::Existent(x) => x.value.len(),
},
TrackedSubstateValue::ReadExistAndWrite(e, w) => {
e.len()
+ match w {
Write::Update(x) => x.value.len(),
Write::Delete => 0,
}
}
TrackedSubstateValue::ReadNonExistAndWrite(x) => x.value.len(),
TrackedSubstateValue::WriteOnly(w) => match w {
Write::Update(x) => x.value.len(),
Write::Delete => 0,
},
TrackedSubstateValue::Garbage => 0,
}
}
pub fn get_runtime_substate_mut(&mut self) -> Option<&mut RuntimeSubstate> {
match self {
TrackedSubstateValue::New(substate)
| TrackedSubstateValue::WriteOnly(Write::Update(substate))
| TrackedSubstateValue::ReadOnly(ReadOnly::Existent(substate))
| TrackedSubstateValue::ReadExistAndWrite(_, Write::Update(substate))
| TrackedSubstateValue::ReadNonExistAndWrite(substate) => Some(substate),
TrackedSubstateValue::WriteOnly(Write::Delete)
| TrackedSubstateValue::ReadExistAndWrite(_, Write::Delete)
| TrackedSubstateValue::ReadOnly(ReadOnly::NonExistent)
| TrackedSubstateValue::Garbage => None,
}
}
pub fn get(&self) -> Option<&IndexedScryptoValue> {
match self {
TrackedSubstateValue::New(substate)
| TrackedSubstateValue::WriteOnly(Write::Update(substate))
| TrackedSubstateValue::ReadOnly(ReadOnly::Existent(substate))
| TrackedSubstateValue::ReadExistAndWrite(_, Write::Update(substate))
| TrackedSubstateValue::ReadNonExistAndWrite(substate) => Some(&substate.value),
TrackedSubstateValue::WriteOnly(Write::Delete)
| TrackedSubstateValue::ReadExistAndWrite(_, Write::Delete)
| TrackedSubstateValue::ReadOnly(ReadOnly::NonExistent)
| TrackedSubstateValue::Garbage => None,
}
}
pub fn set(&mut self, value: IndexedScryptoValue) {
match self {
TrackedSubstateValue::Garbage => {
*self = TrackedSubstateValue::WriteOnly(Write::Update(RuntimeSubstate::new(value)));
}
TrackedSubstateValue::New(substate)
| TrackedSubstateValue::WriteOnly(Write::Update(substate))
| TrackedSubstateValue::ReadExistAndWrite(_, Write::Update(substate))
| TrackedSubstateValue::ReadNonExistAndWrite(substate) => {
substate.value = value;
}
TrackedSubstateValue::ReadOnly(ReadOnly::NonExistent) => {
let new_tracked =
TrackedSubstateValue::ReadNonExistAndWrite(RuntimeSubstate::new(value));
*self = new_tracked;
}
TrackedSubstateValue::ReadOnly(ReadOnly::Existent(old)) => {
let new_tracked = TrackedSubstateValue::ReadExistAndWrite(
old.value.clone(),
Write::Update(RuntimeSubstate::new(value)),
);
*self = new_tracked;
}
TrackedSubstateValue::ReadExistAndWrite(_, write @ Write::Delete)
| TrackedSubstateValue::WriteOnly(write @ Write::Delete) => {
*write = Write::Update(RuntimeSubstate::new(value));
}
};
}
pub fn take(&mut self) -> Option<IndexedScryptoValue> {
match self {
TrackedSubstateValue::Garbage => None,
TrackedSubstateValue::New(..) => {
let old = mem::replace(self, TrackedSubstateValue::Garbage);
old.into_value()
}
TrackedSubstateValue::WriteOnly(_) => {
let old = mem::replace(self, TrackedSubstateValue::WriteOnly(Write::Delete));
old.into_value()
}
TrackedSubstateValue::ReadExistAndWrite(_, write) => {
let write = mem::replace(write, Write::Delete);
write.into_value()
}
TrackedSubstateValue::ReadNonExistAndWrite(..) => {
let old = mem::replace(self, TrackedSubstateValue::ReadOnly(ReadOnly::NonExistent));
old.into_value()
}
TrackedSubstateValue::ReadOnly(ReadOnly::Existent(v)) => {
let new_tracked =
TrackedSubstateValue::ReadExistAndWrite(v.value.clone(), Write::Delete);
let old = mem::replace(self, new_tracked);
old.into_value()
}
TrackedSubstateValue::ReadOnly(ReadOnly::NonExistent) => None,
}
}
fn revert_writes(&mut self) {
match self {
TrackedSubstateValue::ReadOnly(..) | TrackedSubstateValue::Garbage => {}
TrackedSubstateValue::New(..) | TrackedSubstateValue::WriteOnly(_) => {
*self = TrackedSubstateValue::Garbage;
}
TrackedSubstateValue::ReadExistAndWrite(read, _) => {
*self = TrackedSubstateValue::ReadOnly(ReadOnly::Existent(RuntimeSubstate::new(
read.clone(),
)));
}
TrackedSubstateValue::ReadNonExistAndWrite(..) => {
*self = TrackedSubstateValue::ReadOnly(ReadOnly::NonExistent);
}
}
}
pub fn into_value(self) -> Option<IndexedScryptoValue> {
match self {
TrackedSubstateValue::New(substate)
| TrackedSubstateValue::WriteOnly(Write::Update(substate))
| TrackedSubstateValue::ReadOnly(ReadOnly::Existent(substate))
| TrackedSubstateValue::ReadNonExistAndWrite(substate)
| TrackedSubstateValue::ReadExistAndWrite(_, Write::Update(substate)) => {
Some(substate.value)
}
TrackedSubstateValue::WriteOnly(Write::Delete)
| TrackedSubstateValue::ReadExistAndWrite(_, Write::Delete)
| TrackedSubstateValue::ReadOnly(ReadOnly::NonExistent)
| TrackedSubstateValue::Garbage => None,
}
}
}
#[derive(Debug)]
pub struct TrackedPartition {
pub substates: BTreeMap<DbSortKey, TrackedSubstate>,
pub range_read: u32,
}
impl TrackedPartition {
pub fn new() -> Self {
Self {
substates: BTreeMap::new(),
range_read: 0,
}
}
pub fn new_with_substates(substates: BTreeMap<DbSortKey, TrackedSubstate>) -> Self {
Self {
substates,
range_read: 0,
}
}
pub fn revert_writes(&mut self) {
for substate in &mut self.substates.values_mut() {
substate.substate_value.revert_writes();
}
}
}
impl Default for TrackedPartition {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug)]
pub struct TrackedNode {
pub tracked_partitions: IndexMap<PartitionNumber, TrackedPartition>,
pub is_new: bool,
}
impl TrackedNode {
pub fn new(is_new: bool) -> Self {
Self {
tracked_partitions: index_map_new(),
is_new,
}
}
pub fn revert_writes(&mut self) {
for (_, tracked_partition) in &mut self.tracked_partitions {
tracked_partition.revert_writes();
}
}
}
#[allow(clippy::type_complexity)]
pub struct IterationCountedIter<'a, E> {
pub iter:
Box<dyn Iterator<Item = Result<(DbSortKey, (SubstateKey, IndexedScryptoValue)), E>> + 'a>,
pub num_iterations: u32,
}
impl<'a, E> IterationCountedIter<'a, E> {
#[allow(clippy::type_complexity)]
pub fn new(
iter: Box<
dyn Iterator<Item = Result<(DbSortKey, (SubstateKey, IndexedScryptoValue)), E>> + 'a,
>,
) -> Self {
Self {
iter,
num_iterations: 0u32,
}
}
}
impl<'a, E> Iterator for IterationCountedIter<'a, E> {
type Item = Result<(DbSortKey, (SubstateKey, IndexedScryptoValue)), E>;
fn next(&mut self) -> Option<Self::Item> {
self.num_iterations += 1;
self.iter.next()
}
}