1use std::collections::HashMap;
2
3use triton_vm::prelude::*;
4
5use crate::prelude::*;
6use crate::traits::basic_snippet::Reviewer;
7use crate::traits::basic_snippet::SignOffFingerprint;
8
9#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash)]
28pub struct Length;
29
30impl BasicSnippet for Length {
31 fn parameters(&self) -> Vec<(DataType, String)> {
32 vec![(DataType::VoidPointer, "*list".to_string())]
33 }
34
35 fn return_values(&self) -> Vec<(DataType, String)> {
36 vec![(DataType::Bfe, "list_length".to_string())]
37 }
38
39 fn entrypoint(&self) -> String {
40 "tasmlib_list_length".to_string()
41 }
42
43 fn code(&self, _: &mut Library) -> Vec<LabelledInstruction> {
44 triton_asm! {
45 {self.entrypoint()}:
48 read_mem 1
49 pop 1
50 return
51 }
52 }
53
54 fn sign_offs(&self) -> HashMap<Reviewer, SignOffFingerprint> {
55 let mut sign_offs = HashMap::new();
56 sign_offs.insert(Reviewer("ferdinand"), 0x5d27afc762ace284.into());
57 sign_offs
58 }
59}
60
61#[cfg(test)]
62mod tests {
63 use rand::prelude::*;
64
65 use super::*;
66 use crate::rust_shadowing_helper_functions::list::insert_random_list;
67 use crate::test_prelude::*;
68
69 impl Accessor for Length {
70 fn rust_shadow(
71 &self,
72 stack: &mut Vec<BFieldElement>,
73 memory: &HashMap<BFieldElement, BFieldElement>,
74 ) -> Result<(), RustShadowError> {
75 let list_ptr = stack.pop().ok_or(RustShadowError::StackUnderflow)?;
76 let list_length = *memory.get(&list_ptr).ok_or(RustShadowError::Other)?;
77 stack.push(list_length);
78
79 Ok(())
80 }
81
82 fn pseudorandom_initial_state(
83 &self,
84 seed: [u8; 32],
85 _: Option<BenchmarkCase>,
86 ) -> AccessorInitialState {
87 let mut rng = StdRng::from_seed(seed);
88 let list_ptr = rng.random();
89 let list_len = rng.random_range(0..=1 << 10);
90
91 let mut memory = HashMap::default();
92 insert_random_list(&DataType::Digest, list_ptr, list_len, &mut memory);
93 let stack = [self.init_stack_for_isolated_run(), vec![list_ptr]].concat();
94
95 AccessorInitialState { stack, memory }
96 }
97 }
98
99 #[macro_rules_attr::apply(test)]
100 fn rust_shadow() {
101 ShadowedAccessor::new(Length).test();
102 }
103}
104
105#[cfg(test)]
106mod benches {
107 use super::*;
108 use crate::test_prelude::*;
109
110 #[macro_rules_attr::apply(test)]
111 fn length_long_benchmark() {
112 ShadowedAccessor::new(Length).bench();
113 }
114}