miden_core/program/stack/
outputs.rs1use alloc::vec::Vec;
2use core::ops::Deref;
3
4use super::{MIN_STACK_DEPTH, get_num_stack_values};
5use crate::{
6 Felt, WORD_SIZE, Word, ZERO,
7 serde::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable},
8};
9
10#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
17pub struct StackOutputs {
18 elements: [Felt; MIN_STACK_DEPTH],
19}
20
21impl StackOutputs {
22 pub fn new(values: &[Felt]) -> Result<Self, OutputError> {
30 if values.len() > MIN_STACK_DEPTH {
31 return Err(OutputError::OutputStackTooBig(MIN_STACK_DEPTH, values.len()));
32 }
33
34 let mut elements = [ZERO; MIN_STACK_DEPTH];
35 elements[..values.len()].copy_from_slice(values);
36
37 Ok(Self { elements })
38 }
39
40 pub fn get_element(&self, idx: usize) -> Option<Felt> {
46 self.elements.get(idx).cloned()
47 }
48
49 pub fn get_word(&self, idx: usize) -> Option<Word> {
58 if idx > MIN_STACK_DEPTH - WORD_SIZE {
59 return None;
60 }
61
62 Some(Word::from([
63 self.elements[idx],
64 self.elements[idx + 1],
65 self.elements[idx + 2],
66 self.elements[idx + 3],
67 ]))
68 }
69
70 pub fn get_num_elements(&self, num_outputs: usize) -> &[Felt] {
72 let len = self.elements.len().min(num_outputs);
73 &self.elements[..len]
74 }
75
76 #[cfg(any(test, feature = "testing"))]
86 pub fn try_from_ints<I>(iter: I) -> Result<Self, OutputError>
87 where
88 I: IntoIterator<Item = u64>,
89 {
90 use miden_crypto::field::QuotientMap;
91
92 let values = iter
94 .into_iter()
95 .map(|v| Felt::from_canonical_checked(v).ok_or(OutputError::InvalidStackElement(v)))
96 .collect::<Result<Vec<Felt>, _>>()?;
97
98 Self::new(&values)
99 }
100
101 #[cfg(any(test, feature = "testing"))]
103 pub fn as_int_vec(&self) -> Vec<u64> {
104 use miden_crypto::field::PrimeField64;
105
106 self.elements.iter().map(|e| (*e).as_canonical_u64()).collect()
107 }
108}
109
110impl Deref for StackOutputs {
111 type Target = [Felt; MIN_STACK_DEPTH];
112
113 fn deref(&self) -> &Self::Target {
114 &self.elements
115 }
116}
117
118impl From<[Felt; MIN_STACK_DEPTH]> for StackOutputs {
119 fn from(value: [Felt; MIN_STACK_DEPTH]) -> Self {
120 Self { elements: value }
121 }
122}
123
124#[cfg(any(test, feature = "testing"))]
125impl AsMut<[Felt]> for StackOutputs {
126 fn as_mut(&mut self) -> &mut [Felt] {
128 &mut self.elements
129 }
130}
131
132impl Serializable for StackOutputs {
136 fn write_into<W: ByteWriter>(&self, target: &mut W) {
137 let num_stack_values = get_num_stack_values(self);
138 target.write_u8(num_stack_values);
139 target.write_many(&self.elements[..num_stack_values as usize]);
140 }
141}
142
143impl Deserializable for StackOutputs {
144 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
145 let num_elements = source.read_u8()?;
146
147 let elements: Vec<Felt> =
148 source.read_many_iter::<Felt>(num_elements.into())?.collect::<Result<_, _>>()?;
149
150 StackOutputs::new(&elements).map_err(|err| {
151 DeserializationError::InvalidValue(format!("failed to create stack outputs: {err}",))
152 })
153 }
154}
155
156#[derive(Clone, Debug, thiserror::Error)]
160pub enum OutputError {
161 #[error("value {0} exceeds field modulus")]
162 InvalidStackElement(u64),
163 #[error("number of output values on the stack cannot exceed {0}, but was {1}")]
164 OutputStackTooBig(usize, usize),
165}