1#![no_std]
6
7extern crate alloc;
8
9#[doc = include_str!("../README.md")]
10use alloc::{collections::BTreeMap, vec, vec::Vec};
11use core::{fmt::Debug, marker::PhantomData, mem::size_of, ops};
12
13#[doc(hidden)]
14pub use miden_serde_utils;
15#[cfg(feature = "arbitrary")]
16use proptest::prelude::*;
17use thiserror::Error;
18
19#[derive(Debug, Clone, PartialEq, Eq, Error)]
21pub enum IndexedVecError {
22 #[error("IndexedVec contains maximum number of items")]
24 TooManyItems,
25}
26
27#[cfg(feature = "arbitrary")]
28impl Arbitrary for IndexedVecError {
29 type Parameters = ();
30 type Strategy = BoxedStrategy<Self>;
31
32 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
33 Just(Self::TooManyItems).boxed()
34 }
35}
36
37pub trait Idx: Copy + Eq + Ord + Debug + From<u32> + Into<u32> {
39 #[inline]
41 fn to_usize(self) -> usize {
42 self.into() as usize
43 }
44}
45
46#[macro_export]
48macro_rules! newtype_id {
49 (
50 $(#[$a:meta])*
51 $vis:vis struct $name:ident;
52 ) => {
53 $(#[$a])*
54 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
55 #[repr(transparent)]
56 $vis struct $name(u32);
57
58 impl core::fmt::Debug for $name {
59 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
60 write!(f, "{}({})", stringify!($name), self.0)
61 }
62 }
63 impl core::fmt::Display for $name {
64 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
65 core::fmt::Display::fmt(&self.0, f)
66 }
67 }
68 impl From<u32> for $name {
69 fn from(v: u32) -> Self {
70 Self(v)
71 }
72 }
73 impl From<$name> for u32 {
74 fn from(v: $name) -> Self {
75 v.0
76 }
77 }
78 impl $crate::Idx for $name {}
79
80 impl $crate::miden_serde_utils::Serializable for $name {
81 fn write_into<W: $crate::miden_serde_utils::ByteWriter>(&self, target: &mut W) {
82 target.write_u32(self.0);
83 }
84 }
85
86 impl $crate::miden_serde_utils::Deserializable for $name {
87 fn read_from<R: $crate::miden_serde_utils::ByteReader>(source: &mut R) -> Result<Self, $crate::miden_serde_utils::DeserializationError> {
88 Ok(Self(source.read_u32()?))
89 }
90
91 fn min_serialized_size() -> usize {
92 4
93 }
94 }
95 };
96
97 ($name:ident) => {
98 $crate::newtype_id!(pub struct $name;);
99 };
100}
101
102#[cfg(test)]
103#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
104#[repr(transparent)]
105pub struct SerdeTestId(u32);
106
107#[cfg(test)]
108impl From<u32> for SerdeTestId {
109 fn from(v: u32) -> Self {
110 Self(v)
111 }
112}
113
114#[cfg(test)]
115impl From<SerdeTestId> for u32 {
116 fn from(v: SerdeTestId) -> Self {
117 v.0
118 }
119}
120
121#[cfg(test)]
122impl Idx for SerdeTestId {}
123
124#[derive(Clone, Debug, PartialEq, Eq)]
128#[cfg_attr(
129 all(feature = "arbitrary", test),
130 miden_test_serialization_macros::serialization_test(types(SerdeTestId, u32))
131)]
132pub struct IndexVec<I: Idx, T> {
133 raw: Vec<T>,
134 _m: PhantomData<I>,
135}
136
137#[cfg(feature = "arbitrary")]
138impl<I, T> Arbitrary for IndexVec<I, T>
139where
140 I: Idx + 'static,
141 T: Arbitrary + 'static,
142 T::Strategy: 'static,
143{
144 type Parameters = T::Parameters;
145 type Strategy = BoxedStrategy<Self>;
146
147 fn arbitrary_with(args: Self::Parameters) -> Self::Strategy {
148 proptest::collection::vec(any_with::<T>(args), 0..32)
149 .prop_map(|raw| Self::try_from(raw).expect("generated vector length fits in u32"))
150 .boxed()
151 }
152}
153
154impl<I: Idx, T> Default for IndexVec<I, T> {
155 fn default() -> Self {
156 Self { raw: Vec::new(), _m: PhantomData }
157 }
158}
159
160impl<I: Idx, T> IndexVec<I, T> {
161 #[inline]
163 pub fn new() -> Self {
164 Self { raw: Vec::new(), _m: PhantomData }
165 }
166
167 #[inline]
169 pub fn with_capacity(n: usize) -> Self {
170 Self {
171 raw: Vec::with_capacity(n),
172 _m: PhantomData,
173 }
174 }
175
176 #[inline]
178 pub fn len(&self) -> usize {
179 self.raw.len()
180 }
181
182 #[inline]
184 pub fn is_empty(&self) -> bool {
185 self.raw.is_empty()
186 }
187
188 #[inline]
192 pub fn push(&mut self, v: T) -> Result<I, IndexedVecError> {
193 if self.raw.len() >= u32::MAX as usize {
194 return Err(IndexedVecError::TooManyItems);
195 }
196 let id = I::from(self.raw.len() as u32);
197 self.raw.push(v);
198 Ok(id)
199 }
200
201 #[inline]
209 pub(crate) fn insert_at(&mut self, idx: I, v: T) {
210 self.raw[idx.to_usize()] = v;
211 }
212
213 #[inline]
215 pub fn get(&self, idx: I) -> Option<&T> {
216 self.raw.get(idx.to_usize())
217 }
218
219 #[inline]
221 pub fn as_slice(&self) -> &[T] {
222 &self.raw
223 }
224
225 #[inline]
227 pub fn into_inner(self) -> Vec<T> {
228 self.raw
229 }
230
231 pub fn swap_remove(&mut self, index: usize) -> T {
233 self.raw.swap_remove(index)
234 }
235
236 pub fn truncate(&mut self, new_len: usize) {
238 self.raw.truncate(new_len);
239 }
240
241 pub fn contains(&self, item: &T) -> bool
243 where
244 T: PartialEq,
245 {
246 self.raw.contains(item)
247 }
248
249 pub fn iter(&self) -> core::slice::Iter<'_, T> {
251 self.raw.iter()
252 }
253
254 pub fn iter_mut(&mut self) -> core::slice::IterMut<'_, T> {
256 self.raw.iter_mut()
257 }
258}
259
260impl<I: Idx, T> ops::Index<I> for IndexVec<I, T> {
261 type Output = T;
262 #[inline]
263 fn index(&self, index: I) -> &Self::Output {
264 &self.raw[index.to_usize()]
265 }
266}
267
268impl<I: Idx, T> ops::IndexMut<I> for IndexVec<I, T> {
269 #[inline]
270 fn index_mut(&mut self, index: I) -> &mut Self::Output {
271 &mut self.raw[index.to_usize()]
272 }
273}
274
275#[derive(Clone)]
280pub struct DenseIdMap<From: Idx, To: Idx> {
281 inner: IndexVec<From, Option<To>>,
282}
283
284impl<From: Idx, To: Idx> DenseIdMap<From, To> {
285 #[inline]
287 pub fn with_len(length: usize) -> Self {
288 Self {
289 inner: IndexVec { raw: vec![None; length], _m: PhantomData },
290 }
291 }
292
293 #[inline]
301 pub fn insert(&mut self, k: From, v: To) {
302 let idx = k.to_usize();
303 let len = self.len();
304
305 assert!(idx < len, "source ID {idx} exceeds DenseIdMap length {len}");
306 self.inner.insert_at(k, Some(v));
307 }
308
309 #[inline]
311 pub fn get(&self, k: From) -> Option<To> {
312 *self.inner.get(k)?
313 }
314
315 #[inline]
317 pub fn len(&self) -> usize {
318 self.inner.len()
319 }
320
321 #[inline]
323 pub fn is_empty(&self) -> bool {
324 self.inner.is_empty()
325 }
326}
327
328pub trait LookupByIdx<ID, V>
330where
331 ID: Idx,
332{
333 fn get(&self, id: ID) -> Option<&V>;
335}
336
337pub trait LookupByKey<K, V> {
339 fn get(&self, key: &K) -> Option<&V>;
341}
342
343impl<I, T> LookupByIdx<I, T> for IndexVec<I, T>
344where
345 I: Idx,
346{
347 fn get(&self, id: I) -> Option<&T> {
348 IndexVec::get(self, id)
349 }
350}
351
352impl<K, V> LookupByKey<K, V> for BTreeMap<K, V>
353where
354 K: Ord,
355{
356 fn get(&self, key: &K) -> Option<&V> {
357 BTreeMap::get(self, key)
358 }
359}
360
361impl<K, V> LookupByIdx<K, V> for BTreeMap<K, V>
362where
363 K: Idx,
364{
365 fn get(&self, id: K) -> Option<&V> {
366 BTreeMap::get(self, &id)
367 }
368}
369
370impl<I, T> LookupByIdx<I, T> for DenseIdMap<I, T>
371where
372 I: Idx,
373 T: Idx,
374{
375 fn get(&self, id: I) -> Option<&T> {
376 IndexVec::get(&self.inner, id).and_then(Option::as_ref)
377 }
378}
379
380impl<I: Idx, T> IntoIterator for IndexVec<I, T> {
381 type Item = T;
382 type IntoIter = vec::IntoIter<T>;
383
384 fn into_iter(self) -> Self::IntoIter {
385 self.raw.into_iter()
386 }
387}
388
389impl<'a, I: Idx, T> IntoIterator for &'a IndexVec<I, T> {
390 type Item = &'a T;
391 type IntoIter = core::slice::Iter<'a, T>;
392
393 fn into_iter(self) -> Self::IntoIter {
394 self.iter()
395 }
396}
397
398impl<I: Idx, T> TryFrom<Vec<T>> for IndexVec<I, T> {
399 type Error = IndexedVecError;
400
401 fn try_from(raw: Vec<T>) -> Result<Self, Self::Error> {
405 if raw.len() > u32::MAX as usize {
406 return Err(IndexedVecError::TooManyItems);
407 }
408 Ok(Self { raw, _m: PhantomData })
409 }
410}
411
412use miden_serde_utils::{
416 ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable, read_bounded_len,
417};
418
419impl<I, T> Serializable for IndexVec<I, T>
420where
421 I: Idx,
422 T: Serializable,
423{
424 fn write_into<W: ByteWriter>(&self, target: &mut W) {
425 self.as_slice().write_into(target);
426 }
427}
428
429impl<I, T> Deserializable for IndexVec<I, T>
430where
431 I: Idx,
432 T: Deserializable,
433{
434 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
435 let vec: Vec<T> = Deserializable::read_from(source)?;
436 IndexVec::try_from(vec).map_err(|_| {
437 DeserializationError::InvalidValue("IndexVec length exceeds u32::MAX".into())
438 })
439 }
440}
441
442impl<I, T> IndexVec<I, T>
443where
444 I: Idx,
445 T: Deserializable,
446{
447 pub fn read_from_bounded<R: ByteReader>(
449 source: &mut R,
450 label: &str,
451 ) -> Result<Self, DeserializationError> {
452 let len = read_bounded_len(source, label, <T as Deserializable>::min_serialized_size())?;
453 if len > u32::MAX as usize {
454 return Err(DeserializationError::InvalidValue(
455 "IndexVec length exceeds u32::MAX".into(),
456 ));
457 }
458
459 let mut vec = Vec::<T>::with_capacity(bounded_initial_capacity::<T, _>(source, len));
460 for element in source.read_many_iter(len)? {
461 vec.push(element?);
462 }
463
464 Ok(Self { raw: vec, _m: PhantomData })
465 }
466}
467
468impl<I, T> IndexVec<I, T>
469where
470 I: Idx,
471{
472 pub fn read_from_bounded_with<R: ByteReader>(
475 source: &mut R,
476 label: &str,
477 min_element_size: usize,
478 deserializer: impl Fn(&mut R) -> Result<T, DeserializationError>,
479 ) -> Result<Self, DeserializationError> {
480 let len = read_bounded_len(source, label, min_element_size)?;
481 if len > u32::MAX as usize {
482 return Err(DeserializationError::InvalidValue(
483 "IndexVec length exceeds u32::MAX".into(),
484 ));
485 }
486
487 let mut vec = Vec::<T>::with_capacity(bounded_initial_capacity::<T, _>(source, len));
488 for _ in 0..len {
489 vec.push(deserializer(source)?);
490 }
491
492 Ok(Self { raw: vec, _m: PhantomData })
493 }
494}
495
496fn bounded_initial_capacity<T, R: ByteReader>(source: &R, len: usize) -> usize {
504 let element_size = size_of::<T>();
505 if element_size == 0 {
506 len
507 } else {
508 len.min(source.max_alloc(element_size))
509 }
510}
511
512#[cfg(test)]
513mod tests {
514 use alloc::string::{String, ToString};
515
516 use miden_serde_utils::{BudgetedReader, SliceReader};
517
518 use super::*;
519
520 newtype_id!(TestId);
522 newtype_id!(TestId2);
523
524 #[test]
525 fn bounded_initial_capacity_uses_in_memory_element_size() {
526 let reader = BudgetedReader::new(SliceReader::new(&[]), 256);
527
528 assert_eq!(bounded_initial_capacity::<[u8; 64], _>(&reader, 100), 4);
529 assert_eq!(bounded_initial_capacity::<[u8; 64], _>(&reader, 2), 2);
530 assert_eq!(bounded_initial_capacity::<(), _>(&reader, 100), 100);
531 }
532
533 #[test]
534 fn test_indexvec_basic() {
535 let mut vec = IndexVec::<TestId, String>::new();
536 let id1 = vec.push("hello".to_string()).unwrap();
537 let id2 = vec.push("world".to_string()).unwrap();
538
539 assert_eq!(vec.len(), 2);
540 assert_eq!(&vec[id1], "hello");
541 assert_eq!(&vec[id2], "world");
542 assert_eq!(vec.get(TestId::from(0)), Some(&"hello".to_string()));
543 assert_eq!(vec.get(TestId::from(2)), None);
544 }
545
546 #[test]
547 fn test_dense_id_map() {
548 let mut map = DenseIdMap::<TestId, TestId2>::with_len(2);
549 map.insert(TestId::from(0), TestId2::from(10));
550 map.insert(TestId::from(1), TestId2::from(11));
551
552 assert_eq!(map.len(), 2);
553 assert_eq!(map.get(TestId::from(0)), Some(TestId2::from(10)));
554 assert_eq!(map.get(TestId::from(1)), Some(TestId2::from(11)));
555 assert_eq!(map.get(TestId::from(2)), None);
556 }
557}