1use crate::int::I256;
4
5impl_from_str! {
6 impl FromStr for I256;
7}
8
9pub const fn const_from_str_prefixed(src: &str) -> I256 {
10 assert!(!src.is_empty(), "empty string");
11
12 let bytes = src.as_bytes();
13 let (negate, start) = match bytes[0] {
14 b'+' => (false, 1),
15 b'-' => (true, 1),
16 _ => (false, 0),
17 };
18 let uint = crate::parse::const_from_str_prefixed(bytes, start as _);
19
20 let int = {
21 let (hi, lo) = if negate {
22 let (hi, lo) = uint.into_words();
23 let (lo, carry) = (!lo).overflowing_add(1);
24 let hi = (!hi).wrapping_add(carry as _);
25 (hi, lo)
26 } else {
27 uint.into_words()
28 };
29 I256::from_words(hi as _, lo as _)
30 };
31
32 if matches!((negate, int.signum128()), (false, -1) | (true, 1)) {
33 panic!("overflows integer type");
34 }
35
36 int
37}
38
39#[cfg(test)]
40mod tests {
41 use super::*;
42 use crate::parse::from_str_radix;
43 use core::num::IntErrorKind;
44
45 #[test]
46 fn from_str() {
47 assert_eq!("42".parse::<I256>().unwrap(), 42);
48 }
49
50 #[test]
51 fn from_str_prefixed() {
52 assert_eq!(from_str_radix::<I256>("0b101", 2, Some("0b")).unwrap(), 5);
53 assert_eq!(from_str_radix::<I256>("-0xf", 16, Some("0x")).unwrap(), -15);
54 }
55
56 #[test]
57 fn from_str_errors() {
58 assert_eq!(
59 from_str_radix::<I256>("", 2, None).unwrap_err().kind(),
60 &IntErrorKind::Empty,
61 );
62 assert_eq!(
63 from_str_radix::<I256>("?", 2, None).unwrap_err().kind(),
64 &IntErrorKind::InvalidDigit,
65 );
66 assert_eq!(
67 from_str_radix::<I256>("1", 16, Some("0x"))
68 .unwrap_err()
69 .kind(),
70 &IntErrorKind::InvalidDigit,
71 );
72 assert_eq!(
73 from_str_radix::<I256>(
74 "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz",
75 36,
76 None
77 )
78 .unwrap_err()
79 .kind(),
80 &IntErrorKind::PosOverflow,
81 );
82 assert_eq!(
83 from_str_radix::<I256>(
84 "-zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz",
85 36,
86 None
87 )
88 .unwrap_err()
89 .kind(),
90 &IntErrorKind::NegOverflow,
91 );
92 }
93
94 #[test]
95 fn const_parse() {
96 assert_eq!(const_from_str_prefixed("-0b1101"), -0b1101);
97 assert_eq!(const_from_str_prefixed("0o777"), 0o777);
98 assert_eq!(const_from_str_prefixed("-0x1f"), -0x1f);
99 assert_eq!(const_from_str_prefixed("+42"), 42);
100
101 assert_eq!(
102 const_from_str_prefixed(
103 "0x7fff_ffff_ffff_ffff_ffff_ffff_ffff_fffe\
104 baae_dce6_af48_a03b_bfd2_5e8c_d036_4141"
105 ),
106 I256::from_words(
107 0x7fff_ffff_ffff_ffff_ffff_ffff_ffff_fffe,
108 0xbaae_dce6_af48_a03b_bfd2_5e8c_d036_4141_u128 as _,
109 ),
110 );
111
112 assert_eq!(
113 const_from_str_prefixed(
114 "-0x8000_0000_0000_0000_0000_0000_0000_0000\
115 0000_0000_0000_0000_0000_0000_0000_0000"
116 ),
117 I256::MIN,
118 );
119 assert_eq!(
120 const_from_str_prefixed(
121 "+0x7fff_ffff_ffff_ffff_ffff_ffff_ffff_ffff\
122 ffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff"
123 ),
124 I256::MAX,
125 );
126 }
127
128 #[test]
129 #[should_panic]
130 fn const_parse_overflow() {
131 const_from_str_prefixed(
132 "0x8000_0000_0000_0000_0000_0000_0000_0000\
133 0000_0000_0000_0000_0000_0000_0000_0000",
134 );
135 }
136
137 #[test]
138 #[should_panic]
139 fn const_parse_negative_overflow() {
140 const_from_str_prefixed(
141 "-0x8000_0000_0000_0000_0000_0000_0000_0000\
142 0000_0000_0000_0000_0000_0000_0000_0001",
143 );
144 }
145
146 #[test]
147 #[should_panic]
148 fn const_parse_invalid() {
149 const_from_str_prefixed("invalid");
150 }
151}