1use crate::U256;
9use core::fmt;
10
11pub(crate) const HEX_DIGITS: usize = 64;
13
14#[cfg(feature = "fmt")]
17pub(crate) const DEC_DIGITS: usize = 78;
18
19pub(crate) const LOWER: [u8; 16] = *b"0123456789abcdef";
20
21#[cfg(feature = "fmt")]
24pub(crate) const UPPER: [u8; 16] = *b"0123456789ABCDEF";
25
26pub(crate) fn hex_digits<'a>(
29 n: &U256,
30 buf: &'a mut [u8; HEX_DIGITS],
31 table: &[u8; 16],
32) -> &'a str {
33 let mut pos = buf.len();
34 let mut v = *n;
35
36 if v.is_zero() {
37 pos -= 1;
38 buf[pos] = b'0';
39 } else {
40 while !v.is_zero() {
41 pos -= 1;
42 buf[pos] = table[(v.to_limbs()[0] & 0xf) as usize];
43 v = v.wrapping_shr(4);
44 }
45 }
46
47 core::str::from_utf8(&buf[pos..]).expect("hex digits are ASCII")
48}
49
50impl fmt::Debug for U256 {
51 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58 let mut buf = [0u8; HEX_DIGITS];
59 f.write_str("0x")?;
60 f.write_str(hex_digits(self, &mut buf, &LOWER))
61 }
62}
63
64#[cfg(feature = "fmt")]
65impl fmt::LowerHex for U256 {
66 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67 let mut buf = [0u8; HEX_DIGITS];
68 let digits = hex_digits(self, &mut buf, &LOWER);
69 f.pad_integral(true, "0x", digits)
74 }
75}
76
77#[cfg(feature = "fmt")]
78impl fmt::UpperHex for U256 {
79 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
80 let mut buf = [0u8; HEX_DIGITS];
81 let digits = hex_digits(self, &mut buf, &UPPER);
82 f.pad_integral(true, "0x", digits)
84 }
85}
86
87#[cfg(feature = "fmt")]
89pub(crate) fn dec_digits<'a>(
90 n: &U256,
91 buf: &'a mut [u8; DEC_DIGITS],
92) -> &'a str {
93 let mut pos = buf.len();
94 let mut v = *n;
95
96 if v.is_zero() {
97 pos -= 1;
98 buf[pos] = b'0';
99 }
100
101 while !v.is_zero() {
104 let (q, r) = v.div_rem_small(1_000_000_000);
105 v = q;
106 let mut r = r;
107 let count = if v.is_zero() {
110 let mut d = 0;
111 let mut t = r;
112 while t != 0 {
113 d += 1;
114 t /= 10;
115 }
116 d
117 } else {
118 9
119 };
120 let mut i = 0;
121 while i < count {
122 pos -= 1;
123 buf[pos] = b'0' + (r % 10) as u8;
124 r /= 10;
125 i += 1;
126 }
127 }
128
129 core::str::from_utf8(&buf[pos..]).expect("decimal digits are ASCII")
130}
131
132#[cfg(feature = "fmt")]
133impl fmt::Display for U256 {
134 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135 let mut buf = [0u8; DEC_DIGITS];
136 let digits = dec_digits(self, &mut buf);
137 f.pad_integral(true, "", digits)
138 }
139}
140
141#[cfg(feature = "fmt")]
143#[derive(Debug, Clone, Copy, PartialEq, Eq)]
144pub enum ParseU256Error {
145 Empty,
147 InvalidDigit,
149 Overflow,
151}
152
153#[cfg(feature = "fmt")]
154impl fmt::Display for ParseU256Error {
155 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
156 f.write_str(match self {
157 Self::Empty => "cannot parse an empty string as U256",
158 Self::InvalidDigit => "invalid decimal digit",
159 Self::Overflow => "value does not fit in 256 bits",
160 })
161 }
162}
163
164#[cfg(all(feature = "fmt", feature = "std"))]
165impl std::error::Error for ParseU256Error {}
166
167#[cfg(feature = "fmt")]
168impl core::str::FromStr for U256 {
169 type Err = ParseU256Error;
170
171 fn from_str(s: &str) -> Result<Self, Self::Err> {
172 if s.is_empty() {
173 return Err(ParseU256Error::Empty);
174 }
175
176 let mut acc = U256::ZERO;
177 for byte in s.bytes() {
178 if !byte.is_ascii_digit() {
179 return Err(ParseU256Error::InvalidDigit);
180 }
181 let (scaled, overflow) = acc.overflowing_mul_u32(10);
182 if overflow {
183 return Err(ParseU256Error::Overflow);
184 }
185 let (next, overflow) =
186 scaled.overflowing_add(U256::from_u32((byte - b'0') as u32));
187 if overflow {
188 return Err(ParseU256Error::Overflow);
189 }
190 acc = next;
191 }
192
193 Ok(acc)
194 }
195}