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 inputs(&self) -> Vec<(DataType, String)> {
32 vec![(DataType::VoidPointer, "*list".to_string())]
33 }
34
35 fn outputs(&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"), 0xe8173cec5dd4649.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 ) {
75 let list_ptr = stack.pop().unwrap();
76 let list_length = memory[&list_ptr];
77 stack.push(list_length);
78 }
79
80 fn pseudorandom_initial_state(
81 &self,
82 seed: [u8; 32],
83 _: Option<BenchmarkCase>,
84 ) -> AccessorInitialState {
85 let mut rng = StdRng::from_seed(seed);
86 let list_ptr = rng.random();
87 let list_len = rng.random_range(0..=1 << 10);
88
89 let mut memory = HashMap::default();
90 insert_random_list(&DataType::Digest, list_ptr, list_len, &mut memory);
91 let stack = [self.init_stack_for_isolated_run(), vec![list_ptr]].concat();
92
93 AccessorInitialState { stack, memory }
94 }
95 }
96
97 #[test]
98 fn rust_shadow() {
99 ShadowedAccessor::new(Length).test();
100 }
101}
102
103#[cfg(test)]
104mod benches {
105 use super::*;
106 use crate::test_prelude::*;
107
108 #[test]
109 fn length_long_benchmark() {
110 ShadowedAccessor::new(Length).bench();
111 }
112}