Skip to main content

malachite_base/strings/
mod.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::named::Named;
10use alloc::string::String;
11use alloc::vec::Vec;
12use core::fmt::{Binary, Debug, LowerHex, Octal, UpperHex};
13use hashbrown::HashSet;
14use itertools::Itertools;
15
16/// Sorts the characters of a string slice and returns them in a new [`String`].
17///
18/// # Worst-case complexity
19/// $T(n) = O(n \log n)$
20///
21/// $M(n) = O(n)$
22///
23/// where $T$ is time, $M$ is additional memory, and $n$ is `s.len()`.
24///
25/// # Examples
26/// ```
27/// use malachite_base::strings::string_sort;
28///
29/// assert_eq!(string_sort("Hello, world!"), " !,Hdellloorw");
30/// assert_eq!(string_sort("Mississippi"), "Miiiippssss");
31/// ```
32pub fn string_sort(s: &str) -> String {
33    let mut chars = s.chars().collect_vec();
34    chars.sort_unstable();
35    chars.iter().collect()
36}
37
38/// Takes a string slice's unique characters and returns them in a new [`String`].
39///
40/// The unique characters are output in order of appearance.
41///
42/// # Worst-case complexity
43/// $T(n) = O(n)$
44///
45/// $M(n) = O(n)$
46///
47/// where $T$ is time, $M$ is additional memory, and $n$ is `s.len()`.
48///
49/// # Examples
50/// ```
51/// use malachite_base::strings::string_unique;
52///
53/// assert_eq!(string_unique("Hello, world!"), "Helo, wrd!");
54/// assert_eq!(string_unique("Mississippi"), "Misp");
55/// ```
56pub fn string_unique(s: &str) -> String {
57    let mut chars = HashSet::new();
58    let mut nub = String::new();
59    for c in s.chars() {
60        if chars.insert(c) {
61            nub.push(c);
62        }
63    }
64    nub
65}
66
67/// Returns whether all of the first string slice's characters are present in the second string
68/// slice.
69///
70/// Does not take multiplicities into account.
71///
72/// # Worst-case complexity
73/// $T(n, m) = O(n + m)$
74///
75/// $M(n, m) = O(m)$
76///
77/// where $T$ is time, $M$ is additional memory, $n$ is `s.len()`, and $m$ is `t.len()`: the second
78/// string's characters are collected into a hash set, and the first string's characters are checked
79/// against it.
80///
81/// # Examples
82/// ```
83/// use malachite_base::strings::string_is_subset;
84///
85/// assert_eq!(string_is_subset("oH, well", "Hello, world!"), true);
86/// assert_eq!(string_is_subset("MMM", "Mississippi"), true);
87/// assert_eq!(string_is_subset("Hello, World!", "Hello, world!"), false);
88/// assert_eq!(string_is_subset("j", "Mississippi"), false);
89/// ```
90pub fn string_is_subset(s: &str, t: &str) -> bool {
91    let t_chars: HashSet<char> = t.chars().collect();
92    s.chars().all(|c| t_chars.contains(&c))
93}
94
95impl_named!(String);
96
97/// A trait that provides an ergonomic way to create the string specified by a [`Debug`]
98/// implementation.
99pub trait ToDebugString: Debug {
100    fn to_debug_string(&self) -> String;
101}
102
103impl<T: Debug> ToDebugString for T {
104    /// Returns the [`String`] produced by `T`s [`Debug`] implementation.
105    ///
106    /// # Examples
107    /// ```
108    /// use malachite_base::strings::ToDebugString;
109    ///
110    /// assert_eq!([1, 2, 3].to_debug_string(), "[1, 2, 3]");
111    /// assert_eq!(
112    ///     [vec![2, 3], vec![], vec![4]].to_debug_string(),
113    ///     "[[2, 3], [], [4]]"
114    /// );
115    /// assert_eq!(Some(5).to_debug_string(), "Some(5)");
116    /// ```
117    #[inline]
118    fn to_debug_string(&self) -> String {
119        ::alloc::format!("{self:?}")
120    }
121}
122
123/// A trait that provides an ergonomic way to create the string specified by a [`Binary`]
124/// implementation.
125pub trait ToBinaryString: Binary {
126    fn to_binary_string(&self) -> String;
127}
128
129impl<T: Binary> ToBinaryString for T {
130    /// Returns the [`String`] produced by `T`s [`Binary`] implementation.
131    ///
132    /// # Examples
133    /// ```
134    /// use malachite_base::strings::ToBinaryString;
135    ///
136    /// assert_eq!(5u64.to_binary_string(), "101");
137    /// assert_eq!((-100i16).to_binary_string(), "1111111110011100");
138    /// ```
139    #[inline]
140    fn to_binary_string(&self) -> String {
141        ::alloc::format!("{self:b}")
142    }
143}
144
145/// A trait that provides an ergonomic way to create the string specified by an [`Octal`]
146/// implementation.
147pub trait ToOctalString: Octal {
148    fn to_octal_string(&self) -> String;
149}
150
151impl<T: Octal> ToOctalString for T {
152    /// Returns the [`String`] produced by `T`s [`Octal`] implementation.
153    ///
154    /// # Examples
155    /// ```
156    /// use malachite_base::strings::ToOctalString;
157    ///
158    /// assert_eq!(50u64.to_octal_string(), "62");
159    /// assert_eq!((-100i16).to_octal_string(), "177634");
160    /// ```
161    #[inline]
162    fn to_octal_string(&self) -> String {
163        ::alloc::format!("{self:o}")
164    }
165}
166
167/// A trait that provides an ergonomic way to create the string specified by a [`LowerHex`]
168/// implementation.
169pub trait ToLowerHexString: LowerHex {
170    fn to_lower_hex_string(&self) -> String;
171}
172
173impl<T: LowerHex> ToLowerHexString for T {
174    /// Returns the [`String`] produced by `T`s [`LowerHex`] implementation.
175    ///
176    /// # Examples
177    /// ```
178    /// use malachite_base::strings::ToLowerHexString;
179    ///
180    /// assert_eq!(50u64.to_lower_hex_string(), "32");
181    /// assert_eq!((-100i16).to_lower_hex_string(), "ff9c");
182    /// ```
183    #[inline]
184    fn to_lower_hex_string(&self) -> String {
185        ::alloc::format!("{self:x}")
186    }
187}
188
189/// A trait that provides an ergonomic way to create the string specified by an [`UpperHex`]
190/// implementation.
191pub trait ToUpperHexString: UpperHex {
192    fn to_upper_hex_string(&self) -> String;
193}
194
195impl<T: UpperHex> ToUpperHexString for T {
196    /// Returns the [`String`] produced by `T`s [`UpperHex`] implementation.
197    ///
198    /// # Examples
199    /// ```
200    /// use malachite_base::strings::ToUpperHexString;
201    ///
202    /// assert_eq!(50u64.to_upper_hex_string(), "32");
203    /// assert_eq!((-100i16).to_upper_hex_string(), "FF9C");
204    /// ```
205    #[inline]
206    fn to_upper_hex_string(&self) -> String {
207        ::alloc::format!("{self:X}")
208    }
209}
210
211/// Generates [`String`]s, given an iterator that generates `Vec<char>`s.
212///
213/// This `struct` is created by [`strings_from_char_vecs`]; see its documentation for more.
214#[derive(Clone, Debug)]
215pub struct StringsFromCharVecs<I: Iterator<Item = Vec<char>>> {
216    css: I,
217}
218
219impl<I: Iterator<Item = Vec<char>>> Iterator for StringsFromCharVecs<I> {
220    type Item = String;
221
222    #[inline]
223    fn next(&mut self) -> Option<String> {
224        self.css.next().map(|cs| cs.into_iter().collect())
225    }
226}
227
228/// Generates [`String`]s, given an iterator that generates `Vec<char>`s.
229///
230/// The elements appear in the same order as they do in the given iterator, but as [`String`]s.
231///
232/// The output length is `css.count()`.
233///
234/// # Worst-case complexity per iteration
235/// $T(i) = O(\ell + T^\prime(i))$
236///
237/// $M(i) = O(\ell + M^\prime(i))$
238///
239/// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, $T^\prime$ and
240/// $M^\prime$ are the time and memory functions of `css`, and $\ell$ is the length of the $i$th
241/// output string.
242///
243/// # Examples
244/// ```
245/// use itertools::Itertools;
246/// use malachite_base::strings::strings_from_char_vecs;
247///
248/// let ss =
249///     &strings_from_char_vecs([vec!['a', 'b'], vec!['c', 'd']].iter().cloned()).collect_vec();
250/// assert_eq!(
251///     ss.iter().map(|cs| cs.as_str()).collect_vec().as_slice(),
252///     &["ab", "cd"]
253/// );
254/// ```
255#[inline]
256pub const fn strings_from_char_vecs<I: Iterator<Item = Vec<char>>>(
257    css: I,
258) -> StringsFromCharVecs<I> {
259    StringsFromCharVecs { css }
260}
261
262/// Iterators that generate [`String`]s without repetition.
263pub mod exhaustive;
264/// The [`GmpConversionSpec`](gmp_format::GmpConversionSpec) struct, the
265/// [`GmpFormatArg`](gmp_format::GmpFormatArg) trait, and the [`gmp_format`](gmp_format::gmp_format)
266/// function, for formatting values according to GMP-style `printf` format strings; the
267/// [`gmp_format!`](crate::gmp_format) macro wraps them.
268pub mod gmp_format;
269#[cfg(feature = "random")]
270/// Iterators that generate [`String`]s randomly.
271pub mod random;