use alloc::{collections::VecDeque, vec::Vec};
use crate::{Felt, Word, field::QuotientMap, program::InputError};
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct AdviceStack {
stack: VecDeque<Felt>,
}
impl AdviceStack {
pub fn new() -> Self {
Self::default()
}
pub fn try_from_values<I>(values: I) -> Result<Self, InputError>
where
I: IntoIterator<Item = u64>,
{
values
.into_iter()
.map(|value| {
Felt::from_canonical_checked(value).ok_or(InputError::InvalidStackElement(value))
})
.collect()
}
pub fn len(&self) -> usize {
self.stack.len()
}
pub fn is_empty(&self) -> bool {
self.stack.is_empty()
}
pub fn iter(&self) -> impl Iterator<Item = &Felt> {
self.stack.iter()
}
pub fn append_element(&mut self, value: Felt) -> &mut Self {
self.stack.push_back(value);
self
}
pub fn append_elements<I>(&mut self, values: I) -> &mut Self
where
I: IntoIterator<Item = Felt>,
{
self.stack.extend(values);
self
}
pub fn prepend_elements<I>(&mut self, values: I) -> &mut Self
where
I: IntoIterator<Item = Felt>,
{
let values: Vec<Felt> = values.into_iter().collect();
for value in values.into_iter().rev() {
self.stack.push_front(value);
}
self
}
pub fn push_element(&mut self, value: Felt) -> &mut Self {
self.stack.push_front(value);
self
}
pub fn prepend_word(&mut self, word: Word) -> &mut Self {
self.prepend_elements(word.iter().copied())
}
pub fn prepend_stack(&mut self, stack: AdviceStack) -> &mut Self {
self.prepend_elements(stack.into_elements())
}
pub fn append_for_adv_push(&mut self, slice: &[Felt]) -> &mut Self {
for elem in slice.iter().rev() {
self.stack.push_back(*elem);
}
self
}
pub fn append_word(&mut self, word: Word) -> &mut Self {
self.stack.extend(word.iter().copied());
self
}
pub fn append_dword(&mut self, words: [Word; 2]) -> &mut Self {
for word in words {
self.append_word(word);
}
self
}
pub fn append_for_adv_pipe(&mut self, slice: &[Felt]) -> &mut Self {
assert!(
slice.len().is_multiple_of(8),
"append_for_adv_pipe requires slice length to be a multiple of 8, got {}",
slice.len()
);
self.stack.extend(slice.iter().copied());
self
}
pub fn consume_element(&mut self) -> Option<Felt> {
self.stack.pop_front()
}
pub fn consume_word(&mut self) -> Option<Word> {
if self.stack.len() < 4 {
return None;
}
Some(Word::new([
self.consume_element().expect("checked len"),
self.consume_element().expect("checked len"),
self.consume_element().expect("checked len"),
self.consume_element().expect("checked len"),
]))
}
pub fn consume_dword(&mut self) -> Option<[Word; 2]> {
if self.stack.len() < 8 {
return None;
}
Some([self.consume_word()?, self.consume_word()?])
}
pub fn into_elements(self) -> Vec<Felt> {
self.stack.into_iter().collect()
}
}
impl From<Vec<Felt>> for AdviceStack {
fn from(stack: Vec<Felt>) -> Self {
Self { stack: stack.into() }
}
}
impl From<VecDeque<Felt>> for AdviceStack {
fn from(stack: VecDeque<Felt>) -> Self {
Self { stack }
}
}
impl From<AdviceStack> for Vec<Felt> {
fn from(stack: AdviceStack) -> Self {
stack.into_elements()
}
}
impl FromIterator<Felt> for AdviceStack {
fn from_iter<T: IntoIterator<Item = Felt>>(iter: T) -> Self {
Self { stack: iter.into_iter().collect() }
}
}