1use alloc::{sync::Arc, vec::Vec};
2
3use vm_core::mast::{ExternalNode, MastForest, MastNodeId};
4pub use vm_core::utils::*;
7
8use super::Felt;
9use crate::{ErrorContext, ExecutionError, Host};
10
11pub(crate) fn get_trace_len(trace: &[Vec<Felt>]) -> usize {
17 trace[0].len()
18}
19
20#[inline(always)]
22pub(crate) fn split_element(value: Felt) -> (Felt, Felt) {
23 let value = value.as_int();
24 let lo = (value as u32) as u64;
25 let hi = value >> 32;
26 (Felt::new(hi), Felt::new(lo))
27}
28
29pub(crate) fn split_element_u32_into_u16(value: Felt) -> (Felt, Felt) {
32 let (hi, lo) = split_u32_into_u16(value.as_int());
33 (Felt::new(hi as u64), Felt::new(lo as u64))
34}
35
36pub(crate) fn split_u32_into_u16(value: u64) -> (u16, u16) {
41 const U32MAX: u64 = u32::MAX as u64;
42 debug_assert!(value <= U32MAX, "not a 32-bit value");
43
44 let lo = value as u16;
45 let hi = (value >> 16) as u16;
46
47 (hi, lo)
48}
49
50pub(crate) fn resolve_external_node(
56 external_node: &ExternalNode,
57 host: &mut impl Host,
58) -> Result<(MastNodeId, Arc<MastForest>), ExecutionError> {
59 let node_digest = external_node.digest();
60 let mast_forest =
61 host.get_mast_forest(&node_digest)
62 .ok_or(ExecutionError::no_mast_forest_with_procedure(
63 node_digest,
64 &ErrorContext::default(),
65 ))?;
66
67 let root_id = mast_forest.find_procedure_root(node_digest).ok_or(
70 ExecutionError::malfored_mast_forest_in_host(node_digest, &ErrorContext::default()),
71 )?;
72
73 if mast_forest[root_id].is_external() {
76 return Err(ExecutionError::CircularExternalNode(node_digest));
77 }
78
79 Ok((root_id, mast_forest))
80}