hdp_primitives/processed_types/
uint256.rs1use alloy::primitives::{hex::FromHex, B256};
5use anyhow::Result;
6use serde::{Deserialize, Serialize};
7use serde_with::serde_as;
8use starknet::core::serde::unsigned_field_element::UfeHex;
9use starknet_crypto::FieldElement;
10use std::str::FromStr;
11
12use crate::utils::bytes_to_hex_string;
13
14#[serde_as]
15#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Eq, Hash)]
16pub struct Uint256 {
17 #[serde_as(as = "UfeHex")]
18 pub low: FieldElement,
19 #[serde_as(as = "UfeHex")]
20 pub high: FieldElement,
21}
22
23impl Uint256 {
24 pub fn from_strs(high: &str, low: &str) -> Result<Self> {
25 Ok(Self {
26 high: FieldElement::from_hex_be(high)?,
27 low: FieldElement::from_hex_be(low)?,
28 })
29 }
30
31 pub fn from_felts(high: FieldElement, low: FieldElement) -> Self {
32 Self { high, low }
33 }
34
35 pub fn from_le_hex_str(hex_str: &str) -> Result<Self> {
36 let clean_hex = hex_str.trim_start_matches("0x");
37 let mut fix_hex: B256 = B256::from_hex(clean_hex)?;
38 fix_hex.reverse();
39
40 let high_part = fix_hex[..16].to_vec();
41 let low_part = fix_hex[16..].to_vec();
42
43 Ok(Self {
44 high: FieldElement::from_hex_be(&bytes_to_hex_string(&high_part))?,
45 low: FieldElement::from_hex_be(&bytes_to_hex_string(&low_part))?,
46 })
47 }
48
49 pub fn from_be_hex_str(hex_str: &str) -> Result<Self> {
50 let clean_hex = hex_str.trim_start_matches("0x");
51 let padded_hex = format!("{:0>64}", clean_hex);
52 let (high_part, low_part) = padded_hex.split_at(32);
53 Ok(Self {
54 high: FieldElement::from_hex_be(&format!("0x{}", high_part))?,
55 low: FieldElement::from_hex_be(&format!("0x{}", low_part))?,
56 })
57 }
58
59 pub fn to_combined_string(&self) -> B256 {
61 let high_padded = format!(
63 "{:0>32}",
64 bytes_to_hex_string(&self.high.to_bytes_be()[16..])
65 )
66 .trim_start_matches("0x")
67 .to_string();
68 let low_padded = format!(
69 "{:0>32}",
70 bytes_to_hex_string(&self.low.to_bytes_be()[16..])
71 )
72 .trim_start_matches("0x")
73 .to_string();
74
75 B256::from_str(&format!("0x{}{}", high_padded, low_padded)).unwrap()
76 }
77}
78
79#[cfg(test)]
80mod tests {
81
82 use starknet::macros::felt;
83
84 use super::*;
85
86 #[test]
87 fn test_combine_parts_into_big_endian_hex() {
88 let uint256 = Uint256::from_felts(
89 FieldElement::from_hex_be("0x988c19313bcbfb19fcc4da12e3adb46c").unwrap(),
90 FieldElement::from_hex_be("0xf6fbdd08af91b1d8df80c6e755159f1").unwrap(),
91 );
92 assert_eq!(
93 uint256.to_combined_string(),
94 B256::from_str("0x988c19313bcbfb19fcc4da12e3adb46c0f6fbdd08af91b1d8df80c6e755159f1")
95 .unwrap()
96 );
97
98 let uint256 = Uint256::from_felts(
99 felt!("0x988c19313bcbfb19fcc4da12e3adb46"),
100 felt!("0xf6fbdd08af91b1d8df80c6e755159f1"),
101 );
102 assert_eq!(
103 uint256.to_combined_string(),
104 B256::from_str("0x0988c19313bcbfb19fcc4da12e3adb460f6fbdd08af91b1d8df80c6e755159f1")
105 .unwrap()
106 );
107
108 let uint256 = Uint256::from_felts(
109 felt!("0x988c19313bcbfb19fcc4da12e3adb4"),
110 felt!("0xf6fbdd08af91b1d8df80c6e755159f1"),
111 );
112 assert_eq!(
113 uint256.to_combined_string(),
114 B256::from_str("0x00988c19313bcbfb19fcc4da12e3adb40f6fbdd08af91b1d8df80c6e755159f1")
115 .unwrap()
116 );
117 }
118
119 #[test]
120 fn test_split_big_endian_hex_into_parts() {
121 let hex_str = "0x60870c80ce4e1d0c35e34f08b1648e8a4fdc7818eea7caedbd316c63a3863562";
122 let result = Uint256::from_be_hex_str(hex_str).unwrap();
123 assert_eq!(
124 result,
125 Uint256::from_felts(
126 felt!("0x60870c80ce4e1d0c35e34f08b1648e8a"),
127 felt!("0x4fdc7818eea7caedbd316c63a3863562"),
128 )
129 );
130 assert_eq!(result.to_combined_string().to_string(), hex_str);
131 }
132
133 #[test]
134 fn test_split_little_endian_hex_into_parts() {
135 let hex_str = "0x8ddadb3a246d9988d78871b11dca322a2df53381bfacb9edc42cedfd263b691d";
136 let result = Uint256::from_le_hex_str(hex_str).unwrap();
137 assert_eq!(
138 result,
139 Uint256::from_felts(
140 felt!("0x1d693b26fded2cc4edb9acbf8133f52d"),
141 felt!("0x2a32ca1db17188d788996d243adbda8d"),
142 )
143 );
144 }
145
146 #[test]
147 fn test_uint256_serde() {
148 let target = Uint256::from_felts(
149 felt!("0x1d693b26fded2cc4edb9acbf8133f52d"),
150 felt!("0x2a32ca1db17188d788996d243adbda8d"),
151 );
152 let string = serde_json::to_string_pretty(&target).unwrap();
153 let json_file = std::fs::read_to_string("./fixtures/uint256.json").unwrap();
154 let expected = json_file.trim();
155 assert_eq!(string, expected);
156 }
157}