Skip to main content

miden_core/program/stack/
inputs.rs

1use alloc::vec::Vec;
2use core::{ops::Deref, slice};
3
4use super::{MIN_STACK_DEPTH, get_num_stack_values};
5use crate::{
6    Felt, ZERO,
7    serde::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable},
8};
9
10// STACK INPUTS
11// ================================================================================================
12
13/// Defines the initial state of the VM's operand stack.
14///
15/// The first element is at position 0 (top of stack).
16#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
17#[cfg_attr(
18    all(feature = "arbitrary", test),
19    miden_test_serialization_macros::serialization_test
20)]
21pub struct StackInputs {
22    elements: [Felt; MIN_STACK_DEPTH],
23}
24
25impl StackInputs {
26    // CONSTRUCTORS
27    // --------------------------------------------------------------------------------------------
28
29    /// Returns [StackInputs] from a list of values.
30    ///
31    /// The first element will be at position 0 (top of stack).
32    ///
33    /// # Errors
34    /// Returns an error if the number of input values exceeds the allowed maximum.
35    pub fn new(values: &[Felt]) -> Result<Self, InputError> {
36        if values.len() > MIN_STACK_DEPTH {
37            return Err(InputError::InputStackTooBig(MIN_STACK_DEPTH, values.len()));
38        }
39
40        let mut elements = [ZERO; MIN_STACK_DEPTH];
41        elements[..values.len()].copy_from_slice(values);
42
43        Ok(Self { elements })
44    }
45
46    // TESTING
47    // --------------------------------------------------------------------------------------------
48
49    /// Attempts to create stack inputs from an iterator of integers.
50    ///
51    /// # Errors
52    /// Returns an error if:
53    /// - The values do not represent a valid field element.
54    /// - Number of values in the iterator exceeds the allowed maximum number of input values.
55    #[cfg(any(test, feature = "testing"))]
56    pub fn try_from_ints<I>(iter: I) -> Result<Self, InputError>
57    where
58        I: IntoIterator<Item = u64>,
59    {
60        use crate::field::QuotientMap;
61
62        let values = iter
63            .into_iter()
64            .map(|v| Felt::from_canonical_checked(v).ok_or(InputError::InvalidStackElement(v)))
65            .collect::<Result<Vec<_>, _>>()?;
66
67        Self::new(&values)
68    }
69}
70
71impl Deref for StackInputs {
72    type Target = [Felt; MIN_STACK_DEPTH];
73
74    fn deref(&self) -> &Self::Target {
75        &self.elements
76    }
77}
78
79impl From<[Felt; MIN_STACK_DEPTH]> for StackInputs {
80    fn from(value: [Felt; MIN_STACK_DEPTH]) -> Self {
81        Self { elements: value }
82    }
83}
84
85impl<'a> IntoIterator for &'a StackInputs {
86    type Item = &'a Felt;
87    type IntoIter = slice::Iter<'a, Felt>;
88
89    fn into_iter(self) -> Self::IntoIter {
90        self.elements.iter()
91    }
92}
93
94impl IntoIterator for StackInputs {
95    type Item = Felt;
96    type IntoIter = core::array::IntoIter<Felt, 16>;
97
98    fn into_iter(self) -> Self::IntoIter {
99        self.elements.into_iter()
100    }
101}
102
103// SERIALIZATION
104// ================================================================================================
105
106impl Serializable for StackInputs {
107    fn write_into<W: ByteWriter>(&self, target: &mut W) {
108        let num_stack_values = get_num_stack_values(self);
109        target.write_u8(num_stack_values);
110        target.write_many(&self.elements[..num_stack_values as usize]);
111    }
112}
113
114impl Deserializable for StackInputs {
115    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
116        let num_elements = source.read_u8()?;
117        let elements: Vec<Felt> =
118            source.read_many_iter::<Felt>(num_elements.into())?.collect::<Result<_, _>>()?;
119
120        StackInputs::new(&elements).map_err(|err| {
121            DeserializationError::InvalidValue(format!("failed to create stack inputs: {err}",))
122        })
123    }
124}
125
126// INPUT ERROR
127// ================================================================================================
128
129#[derive(Clone, Debug, thiserror::Error)]
130pub enum InputError {
131    #[error("value {0} exceeds field modulus")]
132    InvalidStackElement(u64),
133    #[error("number of input values on the stack cannot exceed {0}, but was {1}")]
134    InputStackTooBig(usize, usize),
135}
136
137// ARBITRARY (proptest)
138// ================================================================================================
139
140#[cfg(any(test, feature = "arbitrary"))]
141mod arbitrary {
142    use proptest::prelude::*;
143
144    use super::{MIN_STACK_DEPTH, StackInputs};
145    use crate::Felt;
146
147    impl Arbitrary for StackInputs {
148        type Parameters = ();
149        type Strategy = BoxedStrategy<Self>;
150
151        fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
152            // Any field elements are valid stack inputs. Serialization trims trailing zeros and
153            // deserialization re-pads with `ZERO`, and `Felt` equality ignores representation,
154            // so exact round-trip equality holds.
155            any::<[Felt; MIN_STACK_DEPTH]>().prop_map(StackInputs::from).boxed()
156        }
157    }
158}