hdp_primitives/
utils.rs

1use alloy::primitives::hex::{self};
2use alloy::primitives::{FixedBytes, B256, U256};
3use anyhow::Result;
4use starknet_crypto::FieldElement;
5
6/// Convert a `FixedBytes<32>` which originally encoded from utf8 string into original utf8 string value
7pub fn fixed_bytes_str_to_utf8_str(input_bytes: FixedBytes<32>) -> Result<String> {
8    // Find the position of the first zero byte, if any, to trim the padding.
9    let trim_position = input_bytes
10        .iter()
11        .position(|&x| x == 0)
12        .unwrap_or(input_bytes.len());
13    Ok(String::from_utf8(input_bytes[..trim_position].to_vec())?)
14}
15
16/// Convert a utf8 string into `FixedBytes<32>` by padding zero bytes to the end
17pub fn utf8_str_to_fixed_bytes32(s: &str) -> FixedBytes<32> {
18    let mut fixed_bytes = [0u8; 32];
19    let bytes = s.as_bytes();
20    for (i, &byte) in bytes.iter().enumerate().take(32) {
21        fixed_bytes[i] = byte;
22    }
23
24    FixedBytes::from(fixed_bytes)
25}
26
27/// Convert a byte array into a hex string
28pub fn bytes_to_hex_string(bytes: &[u8]) -> String {
29    format!("0x{}", hex::encode(bytes))
30}
31
32/// Convert a hex string into a byte array
33pub fn hex_string_to_bytes(hex_string: &str) -> Result<Vec<u8>> {
34    let hex_string = hex_string.trim_start_matches("0x");
35    Ok(hex::decode(hex_string)?)
36}
37
38/// Get the last byte of a byte array as a u8
39pub fn last_byte_to_u8(bytes: &[u8]) -> u8 {
40    *bytes.last().unwrap_or(&0)
41}
42
43/// Convert a transaction index to a transaction key
44pub fn tx_index_to_tx_key(tx_index: u64) -> String {
45    let binding = alloy_rlp::encode(U256::from(tx_index));
46    format!("0x{}", hex::encode(binding))
47}
48
49/// Convert a `FieldElement` into a `FixedBytes<32>`
50pub fn felt_to_bytes32(felt: FieldElement) -> FixedBytes<32> {
51    let felt_bytes = felt.to_bytes_be();
52    B256::from(felt_bytes)
53}
54
55/// Convert a hex string into integer
56pub fn hex_string_to_uint(hex_string: &str) -> u64 {
57    let hex_string = hex_string.trim_start_matches("0x");
58    u64::from_str_radix(hex_string, 16).expect("Cannot convert hex string to uint")
59}
60
61#[cfg(test)]
62mod tests {
63    use std::str::FromStr;
64
65    use super::*;
66    use alloy::primitives::{hex::FromHex, FixedBytes};
67
68    #[test]
69    fn test_bytes32_to_str() {
70        let value = "0x6d61780000000000000000000000000000000000000000000000000000000000";
71        let input = FixedBytes::from_hex(value).unwrap();
72        let result = fixed_bytes_str_to_utf8_str(input).unwrap();
73        assert_eq!(result, "max".to_string());
74
75        let value = "0x6d696e0000000000000000000000000000000000000000000000000000000000";
76        let input = FixedBytes::from_hex(value).unwrap();
77        let result = fixed_bytes_str_to_utf8_str(input).unwrap();
78        assert_eq!(result, "min".to_string());
79
80        let value = "0x73756d0000000000000000000000000000000000000000000000000000000000";
81        let input = FixedBytes::from_hex(value).unwrap();
82        let result = fixed_bytes_str_to_utf8_str(input).unwrap();
83        assert_eq!(result, "sum".to_string());
84
85        let value = "0x6176670000000000000000000000000000000000000000000000000000000000";
86        let input = FixedBytes::from_hex(value).unwrap();
87        let result = fixed_bytes_str_to_utf8_str(input).unwrap();
88        assert_eq!(result, "avg".to_string());
89    }
90
91    #[test]
92    fn test_bytes_to_hex_string() {
93        let input = [0, 0, 0, 0, 0];
94        let result = bytes_to_hex_string(&input);
95        assert_eq!(result, "0x0000000000");
96        assert_eq!(hex_string_to_bytes(&result).unwrap(), input);
97
98        let input = [0, 0, 0, 9, 2];
99        let result = bytes_to_hex_string(&input);
100        assert_eq!(result, "0x0000000902");
101
102        let hex = "030fff";
103        let input = hex_string_to_bytes(hex).unwrap();
104        assert_eq!(input, [3, 15, 255]);
105        let result = bytes_to_hex_string(&input);
106        assert_eq!(result, "0x030fff");
107        assert_eq!(hex_string_to_bytes(&result).unwrap(), input);
108    }
109
110    #[test]
111    fn test_last_byte_to_u8() {
112        let input = [0, 0, 0, 0, 0];
113        let result = last_byte_to_u8(&input);
114        assert_eq!(result, 0);
115
116        let input = [0, 0, 0, 9, 2];
117        let result = last_byte_to_u8(&input);
118        assert_eq!(result, 2);
119
120        let input = [0, 0, 0, 9, 255];
121        let result = last_byte_to_u8(&input);
122        assert_eq!(result, 255);
123    }
124
125    #[test]
126    fn test_tx_index_to_tx_key() {
127        // no rlp prefix
128        let tx_index = 127u64;
129        let tx_key = tx_index_to_tx_key(tx_index);
130        let expected_tx_key = "0x7f".to_string();
131
132        assert_eq!(tx_key, expected_tx_key);
133
134        // rlpx prefix
135        let tx_index = 303u64;
136        let tx_key = tx_index_to_tx_key(tx_index);
137        let expected_tx_key = "0x82012f".to_string();
138
139        assert_eq!(tx_key, expected_tx_key);
140    }
141
142    #[test]
143    fn test_felt_to_bytes32() {
144        let felt = FieldElement::from_str(
145            "0x034d4ff54bc5c6cfee6719bfaa94ffa374071e8d656b74823681a955e9033dd9",
146        )
147        .unwrap();
148        let bytes32 = felt_to_bytes32(felt);
149        assert_eq!(bytes32, felt.to_bytes_be());
150    }
151
152    #[test]
153    fn test_hex_string_to_uint() {
154        let hex_string = "0x1b";
155        let result = hex_string_to_uint(hex_string);
156        assert_eq!(result, 27);
157    }
158}