Skip to main content

vihaco_runtime/
stack_batch.rs

1// SPDX-FileCopyrightText: 2026 The vihaco Authors
2// SPDX-License-Identifier: MIT
3
4use std::ops::Deref;
5
6use smallvec::SmallVec;
7
8/// Owned operands in their original stack order.
9///
10/// Up to eight values stay inline. Larger batches use heap storage. The backing
11/// collection and capacity are implementation details; receiving a batch never
12/// borrows program storage. Components can retain it after execution.
13#[derive(Debug, Clone, PartialEq, Eq)]
14pub struct StackBatch<T> {
15    pub(crate) values: SmallVec<[T; 8]>,
16}
17
18impl<T> StackBatch<T> {
19    pub fn as_slice(&self) -> &[T] {
20        self.values.as_slice()
21    }
22
23    pub fn len(&self) -> usize {
24        self.values.len()
25    }
26
27    pub fn is_empty(&self) -> bool {
28        self.values.is_empty()
29    }
30}
31
32impl<T> AsRef<[T]> for StackBatch<T> {
33    fn as_ref(&self) -> &[T] {
34        self.as_slice()
35    }
36}
37
38impl<T> Deref for StackBatch<T> {
39    type Target = [T];
40    fn deref(&self) -> &Self::Target {
41        self.as_slice()
42    }
43}
44
45/// Consuming iterator over a [`StackBatch`], without materializing another buffer.
46pub struct StackBatchIntoIter<T>(smallvec::IntoIter<[T; 8]>);
47
48impl<T> Iterator for StackBatchIntoIter<T> {
49    type Item = T;
50    fn next(&mut self) -> Option<T> {
51        self.0.next()
52    }
53    fn size_hint(&self) -> (usize, Option<usize>) {
54        self.0.size_hint()
55    }
56}
57
58impl<T> DoubleEndedIterator for StackBatchIntoIter<T> {
59    fn next_back(&mut self) -> Option<T> {
60        self.0.next_back()
61    }
62}
63
64impl<T> ExactSizeIterator for StackBatchIntoIter<T> {}
65
66impl<T> std::iter::FusedIterator for StackBatchIntoIter<T> {}
67
68impl<T> IntoIterator for StackBatch<T> {
69    type Item = T;
70    type IntoIter = StackBatchIntoIter<T>;
71    fn into_iter(self) -> Self::IntoIter {
72        StackBatchIntoIter(self.values.into_iter())
73    }
74}
75
76impl<'a, T> IntoIterator for &'a StackBatch<T> {
77    type Item = &'a T;
78    type IntoIter = std::slice::Iter<'a, T>;
79    fn into_iter(self) -> Self::IntoIter {
80        self.as_slice().iter()
81    }
82}