1use alloc::vec::Vec;
2use core::ops::{Bound, Range};
3
4#[cfg(feature = "std")]
7pub use miden_crypto::utils::ReadAdapter;
8pub use miden_crypto::{
9 stark::matrix::{Matrix, RowMajorMatrix},
10 utils::{
11 assume_init_vec, flatten_slice_elements, flatten_vector_elements, group_slice_elements,
12 uninit_vector,
13 },
14};
15pub use miden_formatting::hex::{DisplayHex, ToHex, to_hex};
16pub use miden_utils_indexing::{
17 DenseIdMap, Idx, IndexVec, IndexedVecError, LookupByIdx, newtype_id,
18};
19
20use crate::{Felt, Word, crypto::hash::Blake3_256, field::PrimeCharacteristicRing};
21
22pub trait ToElements {
26 fn to_elements(&self) -> Vec<Felt>;
27}
28
29impl<const N: usize> ToElements for [u64; N] {
30 fn to_elements(&self) -> Vec<Felt> {
31 self.iter().map(|&v| Felt::from_u64(v)).collect()
32 }
33}
34
35impl ToElements for Vec<u64> {
36 fn to_elements(&self) -> Vec<Felt> {
37 self.iter().map(|&v| Felt::from_u64(v)).collect()
38 }
39}
40
41pub fn hash_string_to_word<'a>(value: impl Into<&'a str>) -> Word {
47 let digest_bytes: [u8; 32] = Blake3_256::hash(value.into().as_bytes()).into();
48 [
49 Felt::new_unchecked(u64::from_le_bytes(digest_bytes[0..8].try_into().unwrap())),
50 Felt::new_unchecked(u64::from_le_bytes(digest_bytes[8..16].try_into().unwrap())),
51 Felt::new_unchecked(u64::from_le_bytes(digest_bytes[16..24].try_into().unwrap())),
52 Felt::new_unchecked(u64::from_le_bytes(digest_bytes[24..32].try_into().unwrap())),
53 ]
54 .into()
55}
56
57pub trait IntoBytes<const N: usize> {
61 fn into_bytes(self) -> [u8; N];
62}
63
64impl IntoBytes<32> for [Felt; 4] {
65 fn into_bytes(self) -> [u8; 32] {
66 let mut result = [0; 32];
67
68 result[..8].copy_from_slice(&self[0].as_canonical_u64().to_le_bytes());
69 result[8..16].copy_from_slice(&self[1].as_canonical_u64().to_le_bytes());
70 result[16..24].copy_from_slice(&self[2].as_canonical_u64().to_le_bytes());
71 result[24..].copy_from_slice(&self[3].as_canonical_u64().to_le_bytes());
72
73 result
74 }
75}
76
77pub const fn range(start: usize, len: usize) -> Range<usize> {
82 Range { start, end: start + len }
83}
84
85pub fn bound_into_included_u64<I>(bound: Bound<&I>, is_start: bool) -> Option<u64>
90where
91 I: Clone + Into<u64>,
92{
93 match bound {
94 Bound::Excluded(i) => {
95 let val = i.clone().into();
96 if is_start {
97 val.checked_add(1)
98 } else {
99 val.checked_sub(1)
100 }
101 },
102 Bound::Included(i) => Some(i.clone().into()),
103 Bound::Unbounded => {
104 if is_start {
105 Some(0)
106 } else {
107 Some(u64::MAX)
108 }
109 },
110 }
111}
112
113const BYTES_PER_U32: usize = size_of::<u32>();
120
121pub fn bytes_to_packed_u32_elements(bytes: &[u8]) -> Vec<Felt> {
143 bytes
144 .chunks(BYTES_PER_U32)
145 .map(|chunk| {
146 let mut packed = [0u8; BYTES_PER_U32];
148 packed[..chunk.len()].copy_from_slice(chunk);
149 Felt::from_u32(u32::from_le_bytes(packed))
150 })
151 .collect()
152}
153
154pub fn packed_u32_elements_to_bytes(elements: &[Felt]) -> Vec<u8> {
174 elements
175 .iter()
176 .flat_map(|felt| {
177 let value = felt.as_canonical_u64() as u32;
178 value.to_le_bytes()
179 })
180 .collect()
181}
182
183#[cfg(test)]
187mod tests {
188 use alloc::vec::Vec;
189
190 use proptest::prelude::*;
191
192 use super::*;
193
194 proptest! {
195 #[test]
196 fn proptest_packed_u32_elements_roundtrip(values in prop::collection::vec(any::<u32>(), 0..100)) {
197 let felts: Vec<Felt> = values.iter().map(|&v| Felt::from_u32(v)).collect();
199
200 let bytes = packed_u32_elements_to_bytes(&felts);
202 let roundtrip_felts = bytes_to_packed_u32_elements(&bytes);
203
204 prop_assert_eq!(felts, roundtrip_felts);
206 }
207 }
208
209 #[test]
210 fn test_bound_into_included_u64() {
211 let val = 10u64;
212 assert_eq!(bound_into_included_u64(Bound::Included(&val), true), Some(10));
213 assert_eq!(bound_into_included_u64(Bound::Included(&val), false), Some(10));
214 assert_eq!(bound_into_included_u64(Bound::Excluded(&val), true), Some(11));
215 assert_eq!(bound_into_included_u64(Bound::Excluded(&val), false), Some(9));
216 assert_eq!(bound_into_included_u64(Bound::<&u64>::Unbounded, true), Some(0));
217 assert_eq!(bound_into_included_u64(Bound::<&u64>::Unbounded, false), Some(u64::MAX));
218
219 let max_val = u64::MAX;
221 assert_eq!(bound_into_included_u64(Bound::Excluded(&max_val), true), None);
222 assert_eq!(bound_into_included_u64(Bound::Excluded(&max_val), false), Some(u64::MAX - 1));
223
224 let zero_val = 0u64;
225 assert_eq!(bound_into_included_u64(Bound::Excluded(&zero_val), true), Some(1));
226 assert_eq!(bound_into_included_u64(Bound::Excluded(&zero_val), false), None);
227 }
228
229 #[test]
230 #[should_panic]
231 fn debug_assert_is_checked() {
232 debug_assert!(false);
240 }
241}