Skip to main content

malachite_base/unsigned_vector/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::num::basic::unsigneds::PrimitiveUnsigned;
10use crate::unsigned_vector::UnsignedVector;
11use alloc::vec::Vec;
12use core::str::FromStr;
13
14impl<T: PrimitiveUnsigned> FromStr for UnsignedVector<T> {
15    type Err = ();
16
17    /// Converts a string to an [`UnsignedVector`].
18    ///
19    /// This reads back what [`Display`](core::fmt::Display) writes: the elements in order,
20    /// separated by `", "` and enclosed in parentheses, with `()` for the 0-dimensional vector.
21    /// Each element is read the way `T`'s [`FromStr`] reads one, so it may have leading zeros or a
22    /// single leading `'+'`. Any other spacing, such as `(1,2)` or `( 1, 2 )`, is rejected, as is
23    /// an empty element or one that is out of `T`'s range.
24    ///
25    /// If the string does not represent an [`UnsignedVector`], an `Err` is returned.
26    ///
27    /// # Worst-case complexity
28    /// $T(n) = O(n)$
29    ///
30    /// $M(n) = O(n)$
31    ///
32    /// where $T$ is time, $M$ is additional memory, and $n$ is `s.len()`.
33    ///
34    /// # Examples
35    /// ```
36    /// use core::str::FromStr;
37    /// use malachite_base::unsigned_vector::UnsignedVector;
38    /// use malachite_base::vector::Vector;
39    ///
40    /// assert_eq!(
41    ///     UnsignedVector::<u32>::from_str("(1, 2, 3)")
42    ///         .unwrap()
43    ///         .to_string(),
44    ///     "(1, 2, 3)"
45    /// );
46    /// assert_eq!(
47    ///     UnsignedVector::<u32>::from_str("(5)").unwrap().to_string(),
48    ///     "(5)"
49    /// );
50    /// assert_eq!(
51    ///     UnsignedVector::<u32>::from_str("()").unwrap().dimension(),
52    ///     0
53    /// );
54    ///
55    /// // An element may be written as `u32::from_str` accepts it.
56    /// assert_eq!(
57    ///     UnsignedVector::<u32>::from_str("(007, +8)")
58    ///         .unwrap()
59    ///         .to_string(),
60    ///     "(7, 8)"
61    /// );
62    ///
63    /// assert!(UnsignedVector::<u32>::from_str("").is_err());
64    /// assert!(UnsignedVector::<u32>::from_str("1, 2").is_err());
65    /// assert!(UnsignedVector::<u32>::from_str("(1,2)").is_err());
66    /// assert!(UnsignedVector::<u32>::from_str("( 1, 2 )").is_err());
67    /// assert!(UnsignedVector::<u32>::from_str("(1, )").is_err());
68    /// assert!(UnsignedVector::<u32>::from_str("(-1)").is_err());
69    /// assert!(UnsignedVector::<u8>::from_str("(256)").is_err());
70    /// ```
71    fn from_str(s: &str) -> Result<Self, ()> {
72        let inner = s
73            .strip_prefix('(')
74            .and_then(|s| s.strip_suffix(')'))
75            .ok_or(())?;
76        if inner.is_empty() {
77            return Ok(Self {
78                elements: Vec::new(),
79            });
80        }
81        Ok(Self {
82            elements: inner
83                .split(", ")
84                .map(|x| T::from_str(x).map_err(|_| ()))
85                .collect::<Result<_, _>>()?,
86        })
87    }
88}