use super::{
header::AccountHeader,
tree::{FilterEdge, WEIGHT_IS_OUTGOING},
wasmimport::HostImport,
wasmstore::Store,
};
use solana_sdk::pubkey::Pubkey;
use std::collections::{BTreeMap, VecDeque};
pub trait GuestFilter {
fn program_id_list(&self) -> Vec<Pubkey>;
fn edge(&self, header: &AccountHeader, data: &[u8]) -> VecDeque<FilterEdge>;
}
#[repr(C, align(8))]
pub struct CatscopeFilter {
host_import: HostImport,
l_program_id: Vec<Pubkey>,
l_filter: Vec<Box<dyn GuestFilter + 'static>>,
m_filter_by_pubkey: BTreeMap<Pubkey, usize>, m_filter_by_listindex: BTreeMap<usize, usize>, }
impl CatscopeFilter {
pub fn new(
mut list: VecDeque<Box<dyn GuestFilter + 'static>>,
host_import: HostImport,
) -> Self {
let mut m_filter_by_pubkey = BTreeMap::new();
let mut l_filter = Vec::new();
let mut l_program_id = Vec::new();
let mut m_filter_by_listindex = BTreeMap::new();
let mut k = 0;
let mut j = 0;
while let Some(filter) = list.pop_front() {
let list = filter.program_id_list();
for pubkey in list.iter() {
m_filter_by_pubkey.insert(*pubkey, k);
m_filter_by_listindex.insert(j, k);
l_program_id.push(*pubkey);
j += 1;
}
l_filter.push(filter);
k += 1;
}
Self {
host_import,
l_program_id,
l_filter,
m_filter_by_listindex,
m_filter_by_pubkey,
}
}
pub fn store(&self) -> &Store {
self.host_import.store()
}
pub fn store_mut(&mut self) -> &mut Store {
self.host_import.store_mut()
}
}
impl GuestFilter for CatscopeFilter {
fn program_id_list(&self) -> Vec<Pubkey> {
self.l_program_id.clone()
}
fn edge(&self, header: &AccountHeader, data: &[u8]) -> VecDeque<FilterEdge> {
let program_id = &header.owner;
let o_k = self.m_filter_by_pubkey.get(program_id);
if o_k.is_none() {
return VecDeque::new();
}
let mut list = if let Some(filter) = self.l_filter.get(*o_k.unwrap()) {
filter.edge(header, data)
} else {
VecDeque::new()
};
list.iter_mut().for_each(|a| {
a.set_outgoing(&header.pubkey);
});
list
}
}
pub fn weight_set_outgoing(edge: &mut FilterEdge) {
edge.weight |= WEIGHT_IS_OUTGOING;
}
pub fn ptr_to_filter<'a, T>(buffer_ptr: u64) -> Option<&'a mut T> {
let cat_ptr = buffer_ptr as *mut T;
if cat_ptr.is_null() {
return None;
}
let s = unsafe { cat_ptr.as_mut().unwrap() };
Some(s)
}