use super::{
chiplets::hasher::{self, Digest},
utils::{
collections::{BTreeMap, Vec},
Box,
},
Felt, FieldElement, Operation,
};
use core::fmt;
pub mod blocks;
use blocks::CodeBlock;
#[derive(Clone, Debug)]
pub struct Program {
root: CodeBlock,
kernel: Kernel,
cb_table: CodeBlockTable,
}
impl Program {
pub fn new(root: CodeBlock) -> Self {
Self::with_kernel(root, Kernel::default(), CodeBlockTable::default())
}
pub fn with_kernel(root: CodeBlock, kernel: Kernel, cb_table: CodeBlockTable) -> Self {
Self {
root,
kernel,
cb_table,
}
}
pub fn root(&self) -> &CodeBlock {
&self.root
}
pub fn hash(&self) -> Digest {
self.root.hash()
}
pub fn kernel(&self) -> &Kernel {
&self.kernel
}
pub fn cb_table(&self) -> &CodeBlockTable {
&self.cb_table
}
}
impl fmt::Display for Program {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "begin {} end", self.root)
}
}
#[derive(Clone, Debug, Default)]
pub struct CodeBlockTable(BTreeMap<[u8; 32], CodeBlock>);
impl CodeBlockTable {
pub fn get(&self, hash: Digest) -> Option<&CodeBlock> {
let key: [u8; 32] = hash.into();
self.0.get(&key)
}
pub fn has(&self, hash: Digest) -> bool {
let key: [u8; 32] = hash.into();
self.0.contains_key(&key)
}
pub fn insert(&mut self, block: CodeBlock) {
let key: [u8; 32] = block.hash().into();
self.0.insert(key, block);
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct Kernel(Vec<Digest>);
impl Kernel {
pub fn new(proc_hashes: &[Digest]) -> Self {
let mut hash_map: BTreeMap<[u8; 32], Digest> = BTreeMap::new();
proc_hashes.iter().cloned().for_each(|r| {
hash_map.insert(r.into(), r);
});
Self(hash_map.values().copied().collect())
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn contains_proc(&self, proc_hash: Digest) -> bool {
self.0.iter().any(|&h| h == proc_hash)
}
pub fn proc_hashes(&self) -> &[Digest] {
&self.0
}
}