1#![no_std]
6
7extern crate alloc;
8
9mod csr;
10#[doc = include_str!("../README.md")]
11use alloc::{collections::BTreeMap, vec, vec::Vec};
12use core::{fmt::Debug, marker::PhantomData, ops};
13
14pub use csr::{CsrMatrix, CsrValidationError};
15#[cfg(feature = "arbitrary")]
16use proptest::prelude::*;
17#[cfg(feature = "serde")]
18use serde::{Deserialize, Serialize};
19use thiserror::Error;
20
21#[derive(Debug, Clone, PartialEq, Eq, Error)]
23pub enum IndexedVecError {
24 #[error("IndexedVec contains maximum number of items")]
26 TooManyItems,
27}
28
29#[cfg(feature = "arbitrary")]
30impl Arbitrary for IndexedVecError {
31 type Parameters = ();
32 type Strategy = BoxedStrategy<Self>;
33
34 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
35 Just(Self::TooManyItems).boxed()
36 }
37}
38
39pub trait Idx: Copy + Eq + Ord + Debug + From<u32> + Into<u32> {
41 #[inline]
43 fn to_usize(self) -> usize {
44 self.into() as usize
45 }
46}
47
48#[macro_export]
50macro_rules! newtype_id {
51 ($name:ident) => {
52 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
53 #[repr(transparent)]
54 pub struct $name(u32);
55
56 impl core::fmt::Debug for $name {
57 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
58 write!(f, "{}({})", stringify!($name), self.0)
59 }
60 }
61 impl From<u32> for $name {
62 fn from(v: u32) -> Self {
63 Self(v)
64 }
65 }
66 impl From<$name> for u32 {
67 fn from(v: $name) -> Self {
68 v.0
69 }
70 }
71 impl $crate::Idx for $name {}
72 };
73}
74
75#[cfg(test)]
76#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
77#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
78#[repr(transparent)]
79pub struct SerdeTestId(u32);
80
81#[cfg(test)]
82impl From<u32> for SerdeTestId {
83 fn from(v: u32) -> Self {
84 Self(v)
85 }
86}
87
88#[cfg(test)]
89impl From<SerdeTestId> for u32 {
90 fn from(v: SerdeTestId) -> Self {
91 v.0
92 }
93}
94
95#[cfg(test)]
96impl Idx for SerdeTestId {}
97
98#[derive(Clone, Debug, PartialEq, Eq)]
102#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
103#[cfg_attr(
104 all(feature = "arbitrary", test),
105 miden_test_serde_macros::serde_test(binary_serde(true), types(SerdeTestId, u32))
106)]
107pub struct IndexVec<I: Idx, T> {
108 raw: Vec<T>,
109 _m: PhantomData<I>,
110}
111
112#[cfg(feature = "arbitrary")]
113impl<I, T> Arbitrary for IndexVec<I, T>
114where
115 I: Idx + 'static,
116 T: Arbitrary + 'static,
117 T::Strategy: 'static,
118{
119 type Parameters = T::Parameters;
120 type Strategy = BoxedStrategy<Self>;
121
122 fn arbitrary_with(args: Self::Parameters) -> Self::Strategy {
123 proptest::collection::vec(any_with::<T>(args), 0..32)
124 .prop_map(|raw| Self::try_from(raw).expect("generated vector length fits in u32"))
125 .boxed()
126 }
127}
128
129impl<I: Idx, T> Default for IndexVec<I, T> {
130 fn default() -> Self {
131 Self { raw: Vec::new(), _m: PhantomData }
132 }
133}
134
135impl<I: Idx, T> IndexVec<I, T> {
136 #[inline]
138 pub fn new() -> Self {
139 Self { raw: Vec::new(), _m: PhantomData }
140 }
141
142 #[inline]
144 pub fn with_capacity(n: usize) -> Self {
145 Self {
146 raw: Vec::with_capacity(n),
147 _m: PhantomData,
148 }
149 }
150
151 #[inline]
153 pub fn len(&self) -> usize {
154 self.raw.len()
155 }
156
157 #[inline]
159 pub fn is_empty(&self) -> bool {
160 self.raw.is_empty()
161 }
162
163 #[inline]
167 pub fn push(&mut self, v: T) -> Result<I, IndexedVecError> {
168 if self.raw.len() >= u32::MAX as usize {
169 return Err(IndexedVecError::TooManyItems);
170 }
171 let id = I::from(self.raw.len() as u32);
172 self.raw.push(v);
173 Ok(id)
174 }
175
176 #[inline]
184 pub(crate) fn insert_at(&mut self, idx: I, v: T) {
185 self.raw[idx.to_usize()] = v;
186 }
187
188 #[inline]
190 pub fn get(&self, idx: I) -> Option<&T> {
191 self.raw.get(idx.to_usize())
192 }
193
194 #[inline]
196 pub fn as_slice(&self) -> &[T] {
197 &self.raw
198 }
199
200 #[inline]
202 pub fn into_inner(self) -> Vec<T> {
203 self.raw
204 }
205
206 pub fn swap_remove(&mut self, index: usize) -> T {
208 self.raw.swap_remove(index)
209 }
210
211 pub fn contains(&self, item: &T) -> bool
213 where
214 T: PartialEq,
215 {
216 self.raw.contains(item)
217 }
218
219 pub fn iter(&self) -> core::slice::Iter<'_, T> {
221 self.raw.iter()
222 }
223
224 pub fn iter_mut(&mut self) -> core::slice::IterMut<'_, T> {
226 self.raw.iter_mut()
227 }
228}
229
230impl<I: Idx, T> ops::Index<I> for IndexVec<I, T> {
231 type Output = T;
232 #[inline]
233 fn index(&self, index: I) -> &Self::Output {
234 &self.raw[index.to_usize()]
235 }
236}
237
238impl<I: Idx, T> ops::IndexMut<I> for IndexVec<I, T> {
239 #[inline]
240 fn index_mut(&mut self, index: I) -> &mut Self::Output {
241 &mut self.raw[index.to_usize()]
242 }
243}
244
245#[derive(Clone)]
250pub struct DenseIdMap<From: Idx, To: Idx> {
251 inner: IndexVec<From, Option<To>>,
252}
253
254impl<From: Idx, To: Idx> DenseIdMap<From, To> {
255 #[inline]
257 pub fn with_len(length: usize) -> Self {
258 Self {
259 inner: IndexVec { raw: vec![None; length], _m: PhantomData },
260 }
261 }
262
263 #[inline]
271 pub fn insert(&mut self, k: From, v: To) {
272 let idx = k.to_usize();
273 let len = self.len();
274
275 assert!(idx < len, "source ID {idx} exceeds DenseIdMap length {len}");
276 self.inner.insert_at(k, Some(v));
277 }
278
279 #[inline]
281 pub fn get(&self, k: From) -> Option<To> {
282 *self.inner.get(k)?
283 }
284
285 #[inline]
287 pub fn len(&self) -> usize {
288 self.inner.len()
289 }
290
291 #[inline]
293 pub fn is_empty(&self) -> bool {
294 self.inner.is_empty()
295 }
296}
297
298pub trait LookupByIdx<ID, V>
300where
301 ID: Idx,
302{
303 fn get(&self, id: ID) -> Option<&V>;
305}
306
307pub trait LookupByKey<K, V> {
309 fn get(&self, key: &K) -> Option<&V>;
311}
312
313impl<I, T> LookupByIdx<I, T> for IndexVec<I, T>
314where
315 I: Idx,
316{
317 fn get(&self, id: I) -> Option<&T> {
318 IndexVec::get(self, id)
319 }
320}
321
322impl<K, V> LookupByKey<K, V> for BTreeMap<K, V>
323where
324 K: Ord,
325{
326 fn get(&self, key: &K) -> Option<&V> {
327 BTreeMap::get(self, key)
328 }
329}
330
331impl<K, V> LookupByIdx<K, V> for BTreeMap<K, V>
332where
333 K: Idx,
334{
335 fn get(&self, id: K) -> Option<&V> {
336 BTreeMap::get(self, &id)
337 }
338}
339
340impl<I, T> LookupByIdx<I, T> for DenseIdMap<I, T>
341where
342 I: Idx,
343 T: Idx,
344{
345 fn get(&self, id: I) -> Option<&T> {
346 IndexVec::get(&self.inner, id).and_then(Option::as_ref)
347 }
348}
349
350impl<I: Idx, T> IntoIterator for IndexVec<I, T> {
351 type Item = T;
352 type IntoIter = vec::IntoIter<T>;
353
354 fn into_iter(self) -> Self::IntoIter {
355 self.raw.into_iter()
356 }
357}
358
359impl<'a, I: Idx, T> IntoIterator for &'a IndexVec<I, T> {
360 type Item = &'a T;
361 type IntoIter = core::slice::Iter<'a, T>;
362
363 fn into_iter(self) -> Self::IntoIter {
364 self.iter()
365 }
366}
367
368impl<I: Idx, T> TryFrom<Vec<T>> for IndexVec<I, T> {
369 type Error = IndexedVecError;
370
371 fn try_from(raw: Vec<T>) -> Result<Self, Self::Error> {
375 if raw.len() > u32::MAX as usize {
376 return Err(IndexedVecError::TooManyItems);
377 }
378 Ok(Self { raw, _m: PhantomData })
379 }
380}
381
382use miden_crypto::utils::{
386 ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable,
387};
388
389impl<I, T> Serializable for IndexVec<I, T>
390where
391 I: Idx,
392 T: Serializable,
393{
394 fn write_into<W: ByteWriter>(&self, target: &mut W) {
395 self.as_slice().write_into(target);
396 }
397}
398
399impl<I, T> Deserializable for IndexVec<I, T>
400where
401 I: Idx,
402 T: Deserializable,
403{
404 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
405 let vec: Vec<T> = Deserializable::read_from(source)?;
406 IndexVec::try_from(vec).map_err(|_| {
407 DeserializationError::InvalidValue("IndexVec length exceeds u32::MAX".into())
408 })
409 }
410}
411
412#[cfg(test)]
413mod tests {
414 use alloc::string::{String, ToString};
415
416 use super::*;
417
418 newtype_id!(TestId);
420 newtype_id!(TestId2);
421
422 #[test]
423 fn test_indexvec_basic() {
424 let mut vec = IndexVec::<TestId, String>::new();
425 let id1 = vec.push("hello".to_string()).unwrap();
426 let id2 = vec.push("world".to_string()).unwrap();
427
428 assert_eq!(vec.len(), 2);
429 assert_eq!(&vec[id1], "hello");
430 assert_eq!(&vec[id2], "world");
431 assert_eq!(vec.get(TestId::from(0)), Some(&"hello".to_string()));
432 assert_eq!(vec.get(TestId::from(2)), None);
433 }
434
435 #[test]
436 fn test_dense_id_map() {
437 let mut map = DenseIdMap::<TestId, TestId2>::with_len(2);
438 map.insert(TestId::from(0), TestId2::from(10));
439 map.insert(TestId::from(1), TestId2::from(11));
440
441 assert_eq!(map.len(), 2);
442 assert_eq!(map.get(TestId::from(0)), Some(TestId2::from(10)));
443 assert_eq!(map.get(TestId::from(1)), Some(TestId2::from(11)));
444 assert_eq!(map.get(TestId::from(2)), None);
445 }
446}