https://github.com/python/cpython/blob/4e665351082c50018fb31d80db25b4693057393e/Objects/longobject.c#L2977 https://github.com/python/cpython/blob/4e665351082c50018fb31d80db25b4693057393e/Objects/longobject.c#L2884
(
buf: &[u8],
mut base: u32,
digit_limit: usize,
)
| 39 | // https://github.com/python/cpython/blob/4e665351082c50018fb31d80db25b4693057393e/Objects/longobject.c#L2977 |
| 40 | // https://github.com/python/cpython/blob/4e665351082c50018fb31d80db25b4693057393e/Objects/longobject.c#L2884 |
| 41 | pub fn bytes_to_int( |
| 42 | buf: &[u8], |
| 43 | mut base: u32, |
| 44 | digit_limit: usize, |
| 45 | ) -> Result<BigInt, BytesToIntError> { |
| 46 | if base != 0 && !(2..=36).contains(&base) { |
| 47 | return Err(BytesToIntError::InvalidBase); |
| 48 | } |
| 49 | |
| 50 | let mut buf = buf.trim_ascii(); |
| 51 | |
| 52 | // split sign |
| 53 | let sign = match buf.first() { |
| 54 | Some(b'+') => Some(Sign::Plus), |
| 55 | Some(b'-') => Some(Sign::Minus), |
| 56 | None => return Err(BytesToIntError::InvalidLiteral { base }), |
| 57 | _ => None, |
| 58 | }; |
| 59 | |
| 60 | if sign.is_some() { |
| 61 | buf = &buf[1..]; |
| 62 | } |
| 63 | |
| 64 | let mut error_if_nonzero = false; |
| 65 | if base == 0 { |
| 66 | match (buf.first(), buf.get(1)) { |
| 67 | (Some(v), _) if *v != b'0' => base = 10, |
| 68 | (_, Some(b'x' | b'X')) => base = 16, |
| 69 | (_, Some(b'o' | b'O')) => base = 8, |
| 70 | (_, Some(b'b' | b'B')) => base = 2, |
| 71 | (_, _) => { |
| 72 | // "old" (C-style) octal literal, now invalid. it might still be zero though |
| 73 | base = 10; |
| 74 | error_if_nonzero = true; |
| 75 | } |
| 76 | } |
| 77 | } |
| 78 | |
| 79 | if error_if_nonzero { |
| 80 | if let [_first, others @ .., last] = buf { |
| 81 | let is_zero = *last == b'0' && others.iter().all(|&c| c == b'0' || c == b'_'); |
| 82 | if !is_zero { |
| 83 | return Err(BytesToIntError::InvalidLiteral { base }); |
| 84 | } |
| 85 | } |
| 86 | return Ok(BigInt::zero()); |
| 87 | } |
| 88 | |
| 89 | if buf.first().is_some_and(|&v| v == b'0') |
| 90 | && buf.get(1).is_some_and(|&v| { |
| 91 | (base == 16 && (v == b'x' || v == b'X')) |
| 92 | || (base == 8 && (v == b'o' || v == b'O')) |
| 93 | || (base == 2 && (v == b'b' || v == b'B')) |
| 94 | }) |
| 95 | { |
| 96 | buf = &buf[2..]; |
| 97 | |
| 98 | // One underscore allowed here |