miden_core/utils/
mod.rs

1use alloc::vec::Vec;
2use core::{
3    fmt::Debug,
4    ops::{Bound, Range},
5};
6
7// RE-EXPORTS
8// ================================================================================================
9pub use miden_crypto::{
10    hash::blake::{Blake3_256, Blake3Digest},
11    utils::{
12        ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable, SliceReader,
13        uninit_vector,
14    },
15};
16#[cfg(feature = "std")]
17pub use winter_utils::ReadAdapter;
18pub use winter_utils::group_slice_elements;
19
20use crate::{Felt, Word};
21
22pub mod math {
23    pub use winter_math::batch_inversion;
24}
25
26// TO ELEMENTS
27// ================================================================================================
28
29pub trait ToElements {
30    fn to_elements(&self) -> Vec<Felt>;
31}
32
33impl<const N: usize> ToElements for [u64; N] {
34    fn to_elements(&self) -> Vec<Felt> {
35        self.iter().map(|&v| Felt::new(v)).collect()
36    }
37}
38
39impl ToElements for Vec<u64> {
40    fn to_elements(&self) -> Vec<Felt> {
41        self.iter().map(|&v| Felt::new(v)).collect()
42    }
43}
44
45// TO WORD
46// ================================================================================================
47
48/// Hashes the provided string using the BLAKE3 hash function and converts the resulting digest into
49/// a [`Word`].
50pub fn hash_string_to_word<'a>(value: impl Into<&'a str>) -> Word {
51    let digest_bytes: [u8; 32] = Blake3_256::hash(value.into().as_bytes()).into();
52    [
53        Felt::new(u64::from_le_bytes(digest_bytes[0..8].try_into().unwrap())),
54        Felt::new(u64::from_le_bytes(digest_bytes[8..16].try_into().unwrap())),
55        Felt::new(u64::from_le_bytes(digest_bytes[16..24].try_into().unwrap())),
56        Felt::new(u64::from_le_bytes(digest_bytes[24..32].try_into().unwrap())),
57    ]
58    .into()
59}
60
61// INTO BYTES
62// ================================================================================================
63
64pub trait IntoBytes<const N: usize> {
65    fn into_bytes(self) -> [u8; N];
66}
67
68impl IntoBytes<32> for [Felt; 4] {
69    fn into_bytes(self) -> [u8; 32] {
70        let mut result = [0; 32];
71
72        result[..8].copy_from_slice(&self[0].as_int().to_le_bytes());
73        result[8..16].copy_from_slice(&self[1].as_int().to_le_bytes());
74        result[16..24].copy_from_slice(&self[2].as_int().to_le_bytes());
75        result[24..].copy_from_slice(&self[3].as_int().to_le_bytes());
76
77        result
78    }
79}
80
81// PUSH MANY
82// ================================================================================================
83
84pub trait PushMany<T> {
85    fn push_many(&mut self, value: T, n: usize);
86}
87
88impl<T: Copy> PushMany<T> for Vec<T> {
89    fn push_many(&mut self, value: T, n: usize) {
90        let new_len = self.len() + n;
91        self.resize(new_len, value);
92    }
93}
94
95// RANGE
96// ================================================================================================
97
98/// Returns a [Range] initialized with the specified `start` and with `end` set to `start` + `len`.
99pub const fn range(start: usize, len: usize) -> Range<usize> {
100    Range { start, end: start + len }
101}
102
103/// Converts and parses a [Bound] into an included u64 value.
104pub fn bound_into_included_u64<I>(bound: Bound<&I>, is_start: bool) -> u64
105where
106    I: Clone + Into<u64>,
107{
108    match bound {
109        Bound::Excluded(i) => i.clone().into().saturating_sub(1),
110        Bound::Included(i) => i.clone().into(),
111        Bound::Unbounded => {
112            if is_start {
113                0
114            } else {
115                u64::MAX
116            }
117        },
118    }
119}
120
121// ARRAY CONSTRUCTORS
122// ================================================================================================
123
124/// Returns an array of N vectors initialized with the specified capacity.
125pub fn new_array_vec<T: Debug, const N: usize>(capacity: usize) -> [Vec<T>; N] {
126    (0..N)
127        .map(|_| Vec::with_capacity(capacity))
128        .collect::<Vec<_>>()
129        .try_into()
130        .expect("failed to convert vector to array")
131}
132
133#[test]
134#[should_panic]
135fn debug_assert_is_checked() {
136    // enforce the release checks to always have `RUSTFLAGS="-C debug-assertions".
137    //
138    // some upstream tests are performed with `debug_assert`, and we want to assert its correctness
139    // downstream.
140    //
141    // for reference, check
142    // https://github.com/0xMiden/miden-vm/issues/433
143    debug_assert!(false);
144}
145
146// FORMATTING
147// ================================================================================================
148
149pub use miden_formatting::hex::{DisplayHex, ToHex, to_hex};