Skip to main content

malachite_nz/integer/conversion/string/
from_string.rs

1// Copyright © 2026 Mikhail Hogrefe
2//
3// This file is part of Malachite.
4//
5// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
6// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
8
9use crate::integer::Integer;
10use crate::natural::Natural;
11use core::ops::Neg;
12use core::str::FromStr;
13use malachite_base::num::conversion::traits::FromStringBase;
14
15impl FromStr for Integer {
16    type Err = ();
17
18    /// Converts an string to an [`Integer`].
19    ///
20    /// If the string does not represent a valid [`Integer`], an `Err` is returned. To be valid, the
21    /// string must be nonempty and only contain the [`char`]s `'0'` through `'9'`, with an optional
22    /// single leading `'-'` or `'+'`. Leading zeros are allowed, as are the strings `"-0"` and
23    /// `"+0"`. The strings `"-"` and `"+"` are not.
24    ///
25    /// # Worst-case complexity
26    /// $T(n) = O(n (\log n)^2 \log\log n)$
27    ///
28    /// $M(n) = O(n \log n)$
29    ///
30    /// where $T$ is time, $M$ is additional memory, and $n$ is `s.len()`.
31    ///
32    /// # Examples
33    /// ```
34    /// use core::str::FromStr;
35    /// use malachite_nz::integer::Integer;
36    ///
37    /// assert_eq!(Integer::from_str("123456").unwrap(), 123456);
38    /// assert_eq!(Integer::from_str("00123456").unwrap(), 123456);
39    /// assert_eq!(Integer::from_str("0").unwrap(), 0);
40    /// assert_eq!(Integer::from_str("-123456").unwrap(), -123456);
41    /// assert_eq!(Integer::from_str("-00123456").unwrap(), -123456);
42    /// assert_eq!(Integer::from_str("-0").unwrap(), 0);
43    /// assert_eq!(Integer::from_str("+123456").unwrap(), 123456);
44    /// assert_eq!(Integer::from_str("+0").unwrap(), 0);
45    ///
46    /// assert!(Integer::from_str("").is_err());
47    /// assert!(Integer::from_str("a").is_err());
48    /// assert!(Integer::from_str("+").is_err());
49    /// assert!(Integer::from_str("+-5").is_err());
50    /// ```
51    #[inline]
52    fn from_str(s: &str) -> Result<Self, ()> {
53        Self::from_string_base(10, s).ok_or(())
54    }
55}
56
57impl FromStringBase for Integer {
58    /// Converts an string, in a specified base, to an [`Integer`].
59    ///
60    /// If the string does not represent a valid [`Integer`], an `Err` is returned. To be valid, the
61    /// string must be nonempty and only contain the [`char`]s `'0'` through `'9'`, `'a'` through
62    /// `'z'`, and `'A'` through `'Z'`, with an optional single leading `'-'` or `'+'`; and only
63    /// characters that represent digits smaller than the base are allowed. Leading zeros are
64    /// allowed, as is the string `"-0"`. The string `"-"` is not.
65    ///
66    /// # Worst-case complexity
67    /// $T(n) = O(n (\log n)^2 \log\log n)$
68    ///
69    /// $M(n) = O(n \log n)$
70    ///
71    /// where $T$ is time, $M$ is additional memory, and $n$ is `s.len()`.
72    ///
73    /// # Panics
74    /// Panics if `base` is less than 2 or greater than 62.
75    ///
76    /// # Examples
77    /// ```
78    /// use malachite_base::num::conversion::traits::FromStringBase;
79    /// use malachite_nz::integer::Integer;
80    ///
81    /// assert_eq!(Integer::from_string_base(10, "123456").unwrap(), 123456);
82    /// assert_eq!(Integer::from_string_base(10, "00123456").unwrap(), 123456);
83    /// assert_eq!(Integer::from_string_base(16, "0").unwrap(), 0);
84    /// assert_eq!(
85    ///     Integer::from_string_base(16, "deadbeef").unwrap(),
86    ///     3735928559i64
87    /// );
88    /// assert_eq!(
89    ///     Integer::from_string_base(16, "deAdBeEf").unwrap(),
90    ///     3735928559i64
91    /// );
92    /// assert_eq!(Integer::from_string_base(10, "-123456").unwrap(), -123456);
93    /// assert_eq!(Integer::from_string_base(10, "-00123456").unwrap(), -123456);
94    ///
95    /// // above base 36, the uppercase and lowercase letters are distinct digits
96    /// assert_eq!(Integer::from_string_base(62, "-G8").unwrap(), -1000);
97    /// assert_eq!(Integer::from_string_base(62, "-g8").unwrap(), -2612);
98    /// assert_eq!(Integer::from_string_base(16, "-0").unwrap(), 0);
99    /// assert_eq!(
100    ///     Integer::from_string_base(16, "-deadbeef").unwrap(),
101    ///     -3735928559i64
102    /// );
103    /// assert_eq!(
104    ///     Integer::from_string_base(16, "-deAdBeEf").unwrap(),
105    ///     -3735928559i64
106    /// );
107    ///
108    /// assert!(Integer::from_string_base(10, "").is_none());
109    /// assert!(Integer::from_string_base(10, "a").is_none());
110    /// assert!(Integer::from_string_base(2, "2").is_none());
111    /// assert!(Integer::from_string_base(2, "-2").is_none());
112    /// ```
113    #[inline]
114    fn from_string_base(base: u8, s: &str) -> Option<Self> {
115        if let Some(abs_string) = s.strip_prefix('-') {
116            if abs_string.starts_with('+') {
117                None
118            } else {
119                Natural::from_string_base(base, abs_string).map(Neg::neg)
120            }
121        } else {
122            Natural::from_string_base(base, s).map(Self::from)
123        }
124    }
125}