nwnrs_nwscript/
int_literal.rs1#[derive(#[automatically_derived]
impl ::core::fmt::Debug for IntegerLiteralError {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "IntegerLiteralError")
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for IntegerLiteralError {
#[inline]
fn clone(&self) -> IntegerLiteralError { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for IntegerLiteralError { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for IntegerLiteralError {
#[inline]
fn eq(&self, other: &IntegerLiteralError) -> bool { true }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for IntegerLiteralError {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}Eq)]
8pub(crate) struct IntegerLiteralError;
9
10pub(crate) fn parse_wrapping_decimal_i32(input: &str) -> Result<i32, IntegerLiteralError> {
11 let mut chars = input.chars();
12 let mut sign = 1i32;
13 let mut value = 0i32;
14
15 if #[allow(non_exhaustive_omitted_patterns)] match chars.clone().next() {
Some('-') => true,
_ => false,
}matches!(chars.clone().next(), Some('-')) {
16 sign = -1;
17 chars.next();
18 }
19
20 let mut saw_digit = false;
21 for ch in chars {
22 let Some(digit) = ch.to_digit(10) else {
23 return Err(IntegerLiteralError);
24 };
25 saw_digit = true;
26 value = value.wrapping_mul(10).wrapping_add(digit.cast_signed());
27 }
28
29 if !saw_digit {
30 return Err(IntegerLiteralError);
31 }
32
33 if sign == -1 {
34 value = value.wrapping_neg();
35 }
36
37 Ok(value)
38}
39
40pub(crate) fn parse_wrapping_prefixed_i32(
41 input: &str,
42 radix: u32,
43) -> Result<i32, IntegerLiteralError> {
44 let digits = input.get(2..).ok_or(IntegerLiteralError)?;
45 if digits.is_empty() {
46 return Err(IntegerLiteralError);
47 }
48
49 let mut value = 0i32;
50 for ch in digits.chars() {
51 let Some(digit) = ch.to_digit(radix) else {
52 return Err(IntegerLiteralError);
53 };
54 value = value
55 .wrapping_mul(radix.cast_signed())
56 .wrapping_add(digit.cast_signed());
57 }
58
59 Ok(value)
60}
61
62#[cfg(test)]
63mod tests {
64 use super::{parse_wrapping_decimal_i32, parse_wrapping_prefixed_i32};
65
66 #[test]
67 fn wraps_decimal_literals_like_upstream() {
68 assert_eq!(parse_wrapping_decimal_i32("2147483647"), Ok(i32::MAX));
69 assert_eq!(parse_wrapping_decimal_i32("2147483648"), Ok(i32::MIN));
70 assert_eq!(parse_wrapping_decimal_i32("-2147483648"), Ok(i32::MIN));
71 }
72
73 #[test]
74 fn wraps_prefixed_literals_like_upstream() {
75 assert_eq!(parse_wrapping_prefixed_i32("0xffffffff", 16), Ok(-1));
76 assert_eq!(parse_wrapping_prefixed_i32("0x80000000", 16), Ok(i32::MIN));
77 assert_eq!(
78 parse_wrapping_prefixed_i32("0b11111111111111111111111111111111", 2),
79 Ok(-1)
80 );
81 assert_eq!(
82 parse_wrapping_prefixed_i32("0o20000000000", 8),
83 Ok(i32::MIN)
84 );
85 }
86}