use std::collections::HashMap;
use cairo_vm::types::relocatable::{MaybeRelocatable, Relocatable};
use cairo_vm::vm::vm_core::VirtualMachine;
use starknet_types_core::felt::Felt as Felt252;
pub struct DictTrackerExecScope {
data: HashMap<Felt252, MaybeRelocatable>,
idx: usize,
}
#[derive(Default)]
pub struct DictManagerExecScope {
trackers: HashMap<isize, DictTrackerExecScope>,
}
impl DictTrackerExecScope {
pub fn new(idx: usize) -> Self {
Self { data: HashMap::default(), idx }
}
}
impl DictManagerExecScope {
pub const DICT_DEFAULT_VALUE: usize = 0;
pub fn new_default_dict(
&mut self,
vm: &mut VirtualMachine,
no_temporary_segments: bool,
) -> Relocatable {
let dict_segment = if self.trackers.is_empty() || no_temporary_segments {
vm.add_memory_segment()
} else {
vm.add_temporary_segment()
};
assert!(
self.trackers
.insert(dict_segment.segment_index, DictTrackerExecScope::new(self.trackers.len()))
.is_none(),
"Segment index already in use."
);
dict_segment
}
fn get_dict_tracker(&self, dict_end: Relocatable) -> &DictTrackerExecScope {
self.trackers
.get(&dict_end.segment_index)
.expect("The given value does not point to a known dictionary.")
}
fn get_dict_tracker_mut(&mut self, dict_end: Relocatable) -> &mut DictTrackerExecScope {
self.trackers
.get_mut(&dict_end.segment_index)
.expect("The given value does not point to a known dictionary.")
}
pub fn get_dict_infos_index(&self, dict_end: Relocatable) -> usize {
self.get_dict_tracker(dict_end).idx
}
pub fn insert_to_tracker(
&mut self,
dict_end: Relocatable,
key: Felt252,
value: MaybeRelocatable,
) {
self.get_dict_tracker_mut(dict_end).data.insert(key, value);
}
pub fn get_from_tracker(
&self,
dict_end: Relocatable,
key: &Felt252,
) -> Option<MaybeRelocatable> {
self.get_dict_tracker(dict_end).data.get(key).cloned()
}
}
#[derive(Default, Debug)]
pub struct DictSquashExecScope {
pub access_indices: HashMap<Felt252, Vec<Felt252>>,
pub keys: Vec<Felt252>,
}
impl DictSquashExecScope {
pub fn current_key(&self) -> Option<Felt252> {
self.keys.last().cloned()
}
pub fn pop_current_key(&mut self) -> Option<Felt252> {
let key_accesses = self.access_indices.remove(&self.current_key().unwrap());
assert!(
key_accesses.unwrap().len() == 1,
"Key popped but not all accesses were processed."
);
self.keys.pop()
}
pub fn current_access_indices(&mut self) -> Option<&mut Vec<Felt252>> {
let current_key = self.current_key()?;
self.access_indices.get_mut(¤t_key)
}
pub fn current_access_index(&mut self) -> Option<&Felt252> {
self.current_access_indices()?.last()
}
pub fn pop_current_access_index(&mut self) -> Option<Felt252> {
self.current_access_indices()?.pop()
}
}