2022-04-30 17:01:31 +00:00
|
|
|
|
//! Utilities for the `str` primitive type.
|
2017-06-13 22:52:59 +00:00
|
|
|
|
//!
|
2020-12-19 13:23:59 +00:00
|
|
|
|
//! *[See also the `str` primitive type](str).*
|
2017-06-13 22:52:59 +00:00
|
|
|
|
|
|
|
|
|
#![stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
|
// Many of the usings in this module are only used in the test configuration.
|
|
|
|
|
// It's cleaner to just turn off the unused_imports warning than to fix them.
|
|
|
|
|
#![allow(unused_imports)]
|
|
|
|
|
|
2019-04-30 06:52:07 +00:00
|
|
|
|
use core::borrow::{Borrow, BorrowMut};
|
2019-02-03 07:27:44 +00:00
|
|
|
|
use core::iter::FusedIterator;
|
2017-04-11 20:02:43 +00:00
|
|
|
|
use core::mem;
|
2018-03-02 04:50:59 +00:00
|
|
|
|
use core::ptr;
|
2017-06-13 22:52:59 +00:00
|
|
|
|
use core::str::pattern::{DoubleEndedSearcher, Pattern, ReverseSearcher, Searcher};
|
2018-07-06 15:20:39 +00:00
|
|
|
|
use core::unicode::conversions;
|
2017-04-11 20:02:43 +00:00
|
|
|
|
|
2019-02-03 07:27:44 +00:00
|
|
|
|
use crate::borrow::ToOwned;
|
|
|
|
|
use crate::boxed::Box;
|
2019-07-08 15:47:49 +00:00
|
|
|
|
use crate::slice::{Concat, Join, SliceIndex};
|
2019-02-03 07:27:44 +00:00
|
|
|
|
use crate::string::String;
|
|
|
|
|
use crate::vec::Vec;
|
2017-04-11 20:02:43 +00:00
|
|
|
|
|
2017-06-13 22:52:59 +00:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
|
pub use core::str::pattern;
|
|
|
|
|
#[stable(feature = "encode_utf16", since = "1.8.0")]
|
|
|
|
|
pub use core::str::EncodeUtf16;
|
|
|
|
|
#[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
|
2018-05-05 04:33:20 +00:00
|
|
|
|
pub use core::str::SplitAsciiWhitespace;
|
2021-11-05 07:46:58 +00:00
|
|
|
|
#[stable(feature = "split_inclusive", since = "1.51.0")]
|
2021-03-23 11:57:03 +00:00
|
|
|
|
pub use core::str::SplitInclusive;
|
2017-06-13 22:52:59 +00:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
|
pub use core::str::SplitWhitespace;
|
2024-01-26 02:11:54 +00:00
|
|
|
|
#[unstable(feature = "str_from_raw_parts", issue = "119206")]
|
|
|
|
|
pub use core::str::{from_raw_parts, from_raw_parts_mut};
|
2017-06-13 22:52:59 +00:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
|
pub use core::str::{from_utf8, from_utf8_mut, Bytes, CharIndices, Chars};
|
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
|
pub use core::str::{from_utf8_unchecked, from_utf8_unchecked_mut, ParseBoolError};
|
2019-04-12 05:18:36 +00:00
|
|
|
|
#[stable(feature = "str_escape", since = "1.34.0")]
|
|
|
|
|
pub use core::str::{EscapeDebug, EscapeDefault, EscapeUnicode};
|
2017-06-13 22:52:59 +00:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
|
pub use core::str::{FromStr, Utf8Error};
|
|
|
|
|
#[allow(deprecated)]
|
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
|
pub use core::str::{Lines, LinesAny};
|
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
|
pub use core::str::{MatchIndices, RMatchIndices};
|
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
|
pub use core::str::{Matches, RMatches};
|
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
|
pub use core::str::{RSplit, Split};
|
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2018-04-05 17:00:48 +00:00
|
|
|
|
pub use core::str::{RSplitN, SplitN};
|
2017-06-13 22:52:59 +00:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2018-05-05 04:33:20 +00:00
|
|
|
|
pub use core::str::{RSplitTerminator, SplitTerminator};
|
2024-04-28 13:28:27 +00:00
|
|
|
|
#[stable(feature = "utf8_chunks", since = "1.79.0")]
|
2022-08-20 16:49:20 +00:00
|
|
|
|
pub use core::str::{Utf8Chunk, Utf8Chunks};
|
2017-06-13 22:52:59 +00:00
|
|
|
|
|
2019-07-08 15:47:49 +00:00
|
|
|
|
/// Note: `str` in `Concat<str>` is not meaningful here.
|
|
|
|
|
/// This type parameter of the trait only exists to enable another impl.
|
alloc: Add unstable Cfg feature `no-global_oom_handling`
For certain sorts of systems, programming, it's deemed essential that
all allocation failures be explicitly handled where they occur. For
example, see Linus Torvald's opinion in [1]. Merely not calling global
panic handlers, or always `try_reserving` first (for vectors), is not
deemed good enough, because the mere presence of the global OOM handlers
is burdens static analysis.
One option for these projects to use rust would just be to skip `alloc`,
rolling their own allocation abstractions. But this would, in my
opinion be a real shame. `alloc` has a few `try_*` methods already, and
we could easily have more. Features like custom allocator support also
demonstrate and existing to support diverse use-cases with the same
abstractions.
A natural way to add such a feature flag would a Cargo feature, but
there are currently uncertainties around how std library crate's Cargo
features may or not be stable, so to avoid any risk of stabilizing by
mistake we are going with a more low-level "raw cfg" token, which
cannot be interacted with via Cargo alone.
Note also that since there is no notion of "default cfg tokens" outside
of Cargo features, we have to invert the condition from
`global_oom_handling` to to `not(no_global_oom_handling)`. This breaks
the monotonicity that would be important for a Cargo feature (i.e.
turning on more features should never break compatibility), but it
doesn't matter for raw cfg tokens which are not intended to be
"constraint solved" by Cargo or anything else.
To support this use-case we create a new feature, "global-oom-handling",
on by default, and put the global OOM handler infra and everything else
it that depends on it behind it. By default, nothing is changed, but
users concerned about global handling can make sure it is disabled, and
be confident that all OOM handling is local and explicit.
For this first iteration, non-flat collections are outright disabled.
`Vec` and `String` don't yet have `try_*` allocation methods, but are
kept anyways since they can be oom-safely created "from parts", and we
hope to add those `try_` methods in the future.
[1]: https://lore.kernel.org/lkml/CAHk-=wh_sNLoz84AUUzuqXEsYH35u=8HV3vK-jbRbJ_B-JjGrg@mail.gmail.com/
2021-04-17 00:18:04 +00:00
|
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2019-07-08 16:12:06 +00:00
|
|
|
|
#[unstable(feature = "slice_concat_ext", issue = "27747")]
|
2019-07-08 15:47:49 +00:00
|
|
|
|
impl<S: Borrow<str>> Concat<str> for [S] {
|
2017-06-13 22:52:59 +00:00
|
|
|
|
type Output = String;
|
|
|
|
|
|
2019-07-08 15:47:49 +00:00
|
|
|
|
fn concat(slice: &Self) -> String {
|
|
|
|
|
Join::join(slice, "")
|
2017-06-13 22:52:59 +00:00
|
|
|
|
}
|
2019-07-08 15:47:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
alloc: Add unstable Cfg feature `no-global_oom_handling`
For certain sorts of systems, programming, it's deemed essential that
all allocation failures be explicitly handled where they occur. For
example, see Linus Torvald's opinion in [1]. Merely not calling global
panic handlers, or always `try_reserving` first (for vectors), is not
deemed good enough, because the mere presence of the global OOM handlers
is burdens static analysis.
One option for these projects to use rust would just be to skip `alloc`,
rolling their own allocation abstractions. But this would, in my
opinion be a real shame. `alloc` has a few `try_*` methods already, and
we could easily have more. Features like custom allocator support also
demonstrate and existing to support diverse use-cases with the same
abstractions.
A natural way to add such a feature flag would a Cargo feature, but
there are currently uncertainties around how std library crate's Cargo
features may or not be stable, so to avoid any risk of stabilizing by
mistake we are going with a more low-level "raw cfg" token, which
cannot be interacted with via Cargo alone.
Note also that since there is no notion of "default cfg tokens" outside
of Cargo features, we have to invert the condition from
`global_oom_handling` to to `not(no_global_oom_handling)`. This breaks
the monotonicity that would be important for a Cargo feature (i.e.
turning on more features should never break compatibility), but it
doesn't matter for raw cfg tokens which are not intended to be
"constraint solved" by Cargo or anything else.
To support this use-case we create a new feature, "global-oom-handling",
on by default, and put the global OOM handler infra and everything else
it that depends on it behind it. By default, nothing is changed, but
users concerned about global handling can make sure it is disabled, and
be confident that all OOM handling is local and explicit.
For this first iteration, non-flat collections are outright disabled.
`Vec` and `String` don't yet have `try_*` allocation methods, but are
kept anyways since they can be oom-safely created "from parts", and we
hope to add those `try_` methods in the future.
[1]: https://lore.kernel.org/lkml/CAHk-=wh_sNLoz84AUUzuqXEsYH35u=8HV3vK-jbRbJ_B-JjGrg@mail.gmail.com/
2021-04-17 00:18:04 +00:00
|
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2019-07-08 15:47:49 +00:00
|
|
|
|
#[unstable(feature = "slice_concat_ext", issue = "27747")]
|
2019-07-09 16:19:18 +00:00
|
|
|
|
impl<S: Borrow<str>> Join<&str> for [S] {
|
2019-07-08 15:47:49 +00:00
|
|
|
|
type Output = String;
|
2017-06-13 22:52:59 +00:00
|
|
|
|
|
2019-07-08 15:47:49 +00:00
|
|
|
|
fn join(slice: &Self, sep: &str) -> String {
|
2019-07-05 09:38:40 +00:00
|
|
|
|
unsafe { String::from_utf8_unchecked(join_generic_copy(slice, sep.as_bytes())) }
|
2018-04-30 11:09:10 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2017-06-13 22:52:59 +00:00
|
|
|
|
|
alloc: Add unstable Cfg feature `no-global_oom_handling`
For certain sorts of systems, programming, it's deemed essential that
all allocation failures be explicitly handled where they occur. For
example, see Linus Torvald's opinion in [1]. Merely not calling global
panic handlers, or always `try_reserving` first (for vectors), is not
deemed good enough, because the mere presence of the global OOM handlers
is burdens static analysis.
One option for these projects to use rust would just be to skip `alloc`,
rolling their own allocation abstractions. But this would, in my
opinion be a real shame. `alloc` has a few `try_*` methods already, and
we could easily have more. Features like custom allocator support also
demonstrate and existing to support diverse use-cases with the same
abstractions.
A natural way to add such a feature flag would a Cargo feature, but
there are currently uncertainties around how std library crate's Cargo
features may or not be stable, so to avoid any risk of stabilizing by
mistake we are going with a more low-level "raw cfg" token, which
cannot be interacted with via Cargo alone.
Note also that since there is no notion of "default cfg tokens" outside
of Cargo features, we have to invert the condition from
`global_oom_handling` to to `not(no_global_oom_handling)`. This breaks
the monotonicity that would be important for a Cargo feature (i.e.
turning on more features should never break compatibility), but it
doesn't matter for raw cfg tokens which are not intended to be
"constraint solved" by Cargo or anything else.
To support this use-case we create a new feature, "global-oom-handling",
on by default, and put the global OOM handler infra and everything else
it that depends on it behind it. By default, nothing is changed, but
users concerned about global handling can make sure it is disabled, and
be confident that all OOM handling is local and explicit.
For this first iteration, non-flat collections are outright disabled.
`Vec` and `String` don't yet have `try_*` allocation methods, but are
kept anyways since they can be oom-safely created "from parts", and we
hope to add those `try_` methods in the future.
[1]: https://lore.kernel.org/lkml/CAHk-=wh_sNLoz84AUUzuqXEsYH35u=8HV3vK-jbRbJ_B-JjGrg@mail.gmail.com/
2021-04-17 00:18:04 +00:00
|
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2021-02-03 21:36:33 +00:00
|
|
|
|
macro_rules! specialize_for_lengths {
|
|
|
|
|
($separator:expr, $target:expr, $iter:expr; $($num:expr),*) => {{
|
2018-04-30 11:09:10 +00:00
|
|
|
|
let mut target = $target;
|
|
|
|
|
let iter = $iter;
|
|
|
|
|
let sep_bytes = $separator;
|
|
|
|
|
match $separator.len() {
|
|
|
|
|
$(
|
|
|
|
|
// loops with hardcoded sizes run much faster
|
|
|
|
|
// specialize the cases with small separator lengths
|
|
|
|
|
$num => {
|
|
|
|
|
for s in iter {
|
2018-05-23 05:20:37 +00:00
|
|
|
|
copy_slice_and_advance!(target, sep_bytes);
|
2021-02-03 21:36:33 +00:00
|
|
|
|
let content_bytes = s.borrow().as_ref();
|
|
|
|
|
copy_slice_and_advance!(target, content_bytes);
|
2018-04-30 11:09:10 +00:00
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
)*
|
|
|
|
|
_ => {
|
|
|
|
|
// arbitrary non-zero size fallback
|
|
|
|
|
for s in iter {
|
2018-05-23 05:20:37 +00:00
|
|
|
|
copy_slice_and_advance!(target, sep_bytes);
|
2021-02-03 21:36:33 +00:00
|
|
|
|
let content_bytes = s.borrow().as_ref();
|
|
|
|
|
copy_slice_and_advance!(target, content_bytes);
|
2018-04-30 11:09:10 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-04-07 19:56:02 +00:00
|
|
|
|
}
|
2021-02-03 21:36:33 +00:00
|
|
|
|
target
|
|
|
|
|
}}
|
2018-04-30 11:09:10 +00:00
|
|
|
|
}
|
2017-06-13 22:52:59 +00:00
|
|
|
|
|
alloc: Add unstable Cfg feature `no-global_oom_handling`
For certain sorts of systems, programming, it's deemed essential that
all allocation failures be explicitly handled where they occur. For
example, see Linus Torvald's opinion in [1]. Merely not calling global
panic handlers, or always `try_reserving` first (for vectors), is not
deemed good enough, because the mere presence of the global OOM handlers
is burdens static analysis.
One option for these projects to use rust would just be to skip `alloc`,
rolling their own allocation abstractions. But this would, in my
opinion be a real shame. `alloc` has a few `try_*` methods already, and
we could easily have more. Features like custom allocator support also
demonstrate and existing to support diverse use-cases with the same
abstractions.
A natural way to add such a feature flag would a Cargo feature, but
there are currently uncertainties around how std library crate's Cargo
features may or not be stable, so to avoid any risk of stabilizing by
mistake we are going with a more low-level "raw cfg" token, which
cannot be interacted with via Cargo alone.
Note also that since there is no notion of "default cfg tokens" outside
of Cargo features, we have to invert the condition from
`global_oom_handling` to to `not(no_global_oom_handling)`. This breaks
the monotonicity that would be important for a Cargo feature (i.e.
turning on more features should never break compatibility), but it
doesn't matter for raw cfg tokens which are not intended to be
"constraint solved" by Cargo or anything else.
To support this use-case we create a new feature, "global-oom-handling",
on by default, and put the global OOM handler infra and everything else
it that depends on it behind it. By default, nothing is changed, but
users concerned about global handling can make sure it is disabled, and
be confident that all OOM handling is local and explicit.
For this first iteration, non-flat collections are outright disabled.
`Vec` and `String` don't yet have `try_*` allocation methods, but are
kept anyways since they can be oom-safely created "from parts", and we
hope to add those `try_` methods in the future.
[1]: https://lore.kernel.org/lkml/CAHk-=wh_sNLoz84AUUzuqXEsYH35u=8HV3vK-jbRbJ_B-JjGrg@mail.gmail.com/
2021-04-17 00:18:04 +00:00
|
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2018-05-23 05:20:37 +00:00
|
|
|
|
macro_rules! copy_slice_and_advance {
|
|
|
|
|
($target:expr, $bytes:expr) => {
|
|
|
|
|
let len = $bytes.len();
|
2018-05-25 21:53:22 +00:00
|
|
|
|
let (head, tail) = { $target }.split_at_mut(len);
|
|
|
|
|
head.copy_from_slice($bytes);
|
|
|
|
|
$target = tail;
|
2018-05-23 05:20:37 +00:00
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-30 11:09:10 +00:00
|
|
|
|
// Optimized join implementation that works for both Vec<T> (T: Copy) and String's inner vec
|
|
|
|
|
// Currently (2018-05-13) there is a bug with type inference and specialization (see issue #36262)
|
2019-07-05 09:38:40 +00:00
|
|
|
|
// For this reason SliceConcat<T> is not specialized for T: Copy and SliceConcat<str> is the
|
2018-04-30 11:09:10 +00:00
|
|
|
|
// only user of this function. It is left in place for the time when that is fixed.
|
|
|
|
|
//
|
|
|
|
|
// the bounds for String-join are S: Borrow<str> and for Vec-join Borrow<[T]>
|
|
|
|
|
// [T] and str both impl AsRef<[T]> for some T
|
|
|
|
|
// => s.borrow().as_ref() and we always have slices
|
alloc: Add unstable Cfg feature `no-global_oom_handling`
For certain sorts of systems, programming, it's deemed essential that
all allocation failures be explicitly handled where they occur. For
example, see Linus Torvald's opinion in [1]. Merely not calling global
panic handlers, or always `try_reserving` first (for vectors), is not
deemed good enough, because the mere presence of the global OOM handlers
is burdens static analysis.
One option for these projects to use rust would just be to skip `alloc`,
rolling their own allocation abstractions. But this would, in my
opinion be a real shame. `alloc` has a few `try_*` methods already, and
we could easily have more. Features like custom allocator support also
demonstrate and existing to support diverse use-cases with the same
abstractions.
A natural way to add such a feature flag would a Cargo feature, but
there are currently uncertainties around how std library crate's Cargo
features may or not be stable, so to avoid any risk of stabilizing by
mistake we are going with a more low-level "raw cfg" token, which
cannot be interacted with via Cargo alone.
Note also that since there is no notion of "default cfg tokens" outside
of Cargo features, we have to invert the condition from
`global_oom_handling` to to `not(no_global_oom_handling)`. This breaks
the monotonicity that would be important for a Cargo feature (i.e.
turning on more features should never break compatibility), but it
doesn't matter for raw cfg tokens which are not intended to be
"constraint solved" by Cargo or anything else.
To support this use-case we create a new feature, "global-oom-handling",
on by default, and put the global OOM handler infra and everything else
it that depends on it behind it. By default, nothing is changed, but
users concerned about global handling can make sure it is disabled, and
be confident that all OOM handling is local and explicit.
For this first iteration, non-flat collections are outright disabled.
`Vec` and `String` don't yet have `try_*` allocation methods, but are
kept anyways since they can be oom-safely created "from parts", and we
hope to add those `try_` methods in the future.
[1]: https://lore.kernel.org/lkml/CAHk-=wh_sNLoz84AUUzuqXEsYH35u=8HV3vK-jbRbJ_B-JjGrg@mail.gmail.com/
2021-04-17 00:18:04 +00:00
|
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2018-04-30 11:09:10 +00:00
|
|
|
|
fn join_generic_copy<B, T, S>(slice: &[S], sep: &[T]) -> Vec<T>
|
|
|
|
|
where
|
|
|
|
|
T: Copy,
|
|
|
|
|
B: AsRef<[T]> + ?Sized,
|
|
|
|
|
S: Borrow<B>,
|
|
|
|
|
{
|
|
|
|
|
let sep_len = sep.len();
|
|
|
|
|
let mut iter = slice.iter();
|
2018-05-25 21:53:22 +00:00
|
|
|
|
|
|
|
|
|
// the first slice is the only one without a separator preceding it
|
|
|
|
|
let first = match iter.next() {
|
|
|
|
|
Some(first) => first,
|
|
|
|
|
None => return vec![],
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// compute the exact total length of the joined Vec
|
|
|
|
|
// if the `len` calculation overflows, we'll panic
|
|
|
|
|
// we would have run out of memory anyway and the rest of the function requires
|
|
|
|
|
// the entire Vec pre-allocated for safety
|
2021-02-03 21:36:33 +00:00
|
|
|
|
let reserved_len = sep_len
|
2018-05-25 21:53:22 +00:00
|
|
|
|
.checked_mul(iter.len())
|
|
|
|
|
.and_then(|n| {
|
|
|
|
|
slice.iter().map(|s| s.borrow().as_ref().len()).try_fold(n, usize::checked_add)
|
2018-04-30 11:09:10 +00:00
|
|
|
|
})
|
|
|
|
|
.expect("attempt to join into collection with len > usize::MAX");
|
|
|
|
|
|
2021-03-20 17:42:54 +00:00
|
|
|
|
// prepare an uninitialized buffer
|
2021-02-03 21:36:33 +00:00
|
|
|
|
let mut result = Vec::with_capacity(reserved_len);
|
|
|
|
|
debug_assert!(result.capacity() >= reserved_len);
|
2018-04-30 11:09:10 +00:00
|
|
|
|
|
2018-05-25 21:53:22 +00:00
|
|
|
|
result.extend_from_slice(first.borrow().as_ref());
|
2018-04-30 11:09:10 +00:00
|
|
|
|
|
2018-05-25 21:53:22 +00:00
|
|
|
|
unsafe {
|
2021-02-03 21:36:33 +00:00
|
|
|
|
let pos = result.len();
|
2021-12-08 22:55:50 +00:00
|
|
|
|
let target = result.spare_capacity_mut().get_unchecked_mut(..reserved_len - pos);
|
|
|
|
|
|
|
|
|
|
// Convert the separator and slices to slices of MaybeUninit
|
|
|
|
|
// to simplify implementation in specialize_for_lengths
|
|
|
|
|
let sep_uninit = core::slice::from_raw_parts(sep.as_ptr().cast(), sep.len());
|
|
|
|
|
let iter_uninit = iter.map(|it| {
|
|
|
|
|
let it = it.borrow().as_ref();
|
|
|
|
|
core::slice::from_raw_parts(it.as_ptr().cast(), it.len())
|
|
|
|
|
});
|
2021-02-03 21:36:33 +00:00
|
|
|
|
|
|
|
|
|
// copy separator and slices over without bounds checks
|
|
|
|
|
// generate loops with hardcoded offsets for small separators
|
|
|
|
|
// massive improvements possible (~ x2)
|
2021-12-08 22:55:50 +00:00
|
|
|
|
let remain = specialize_for_lengths!(sep_uninit, target, iter_uninit; 0, 1, 2, 3, 4);
|
2021-02-03 21:36:33 +00:00
|
|
|
|
|
2021-03-20 17:42:54 +00:00
|
|
|
|
// A weird borrow implementation may return different
|
|
|
|
|
// slices for the length calculation and the actual copy.
|
|
|
|
|
// Make sure we don't expose uninitialized bytes to the caller.
|
2021-02-03 21:36:33 +00:00
|
|
|
|
let result_len = reserved_len - remain.len();
|
|
|
|
|
result.set_len(result_len);
|
2018-05-25 21:53:22 +00:00
|
|
|
|
}
|
|
|
|
|
result
|
2018-04-07 19:56:02 +00:00
|
|
|
|
}
|
2017-06-13 22:52:59 +00:00
|
|
|
|
|
2018-04-07 19:56:02 +00:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
|
impl Borrow<str> for String {
|
|
|
|
|
#[inline]
|
|
|
|
|
fn borrow(&self) -> &str {
|
|
|
|
|
&self[..]
|
2017-06-13 22:52:59 +00:00
|
|
|
|
}
|
2018-04-07 19:56:02 +00:00
|
|
|
|
}
|
2017-06-13 22:52:59 +00:00
|
|
|
|
|
2019-04-30 06:52:07 +00:00
|
|
|
|
#[stable(feature = "string_borrow_mut", since = "1.36.0")]
|
|
|
|
|
impl BorrowMut<str> for String {
|
|
|
|
|
#[inline]
|
|
|
|
|
fn borrow_mut(&mut self) -> &mut str {
|
|
|
|
|
&mut self[..]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
alloc: Add unstable Cfg feature `no-global_oom_handling`
For certain sorts of systems, programming, it's deemed essential that
all allocation failures be explicitly handled where they occur. For
example, see Linus Torvald's opinion in [1]. Merely not calling global
panic handlers, or always `try_reserving` first (for vectors), is not
deemed good enough, because the mere presence of the global OOM handlers
is burdens static analysis.
One option for these projects to use rust would just be to skip `alloc`,
rolling their own allocation abstractions. But this would, in my
opinion be a real shame. `alloc` has a few `try_*` methods already, and
we could easily have more. Features like custom allocator support also
demonstrate and existing to support diverse use-cases with the same
abstractions.
A natural way to add such a feature flag would a Cargo feature, but
there are currently uncertainties around how std library crate's Cargo
features may or not be stable, so to avoid any risk of stabilizing by
mistake we are going with a more low-level "raw cfg" token, which
cannot be interacted with via Cargo alone.
Note also that since there is no notion of "default cfg tokens" outside
of Cargo features, we have to invert the condition from
`global_oom_handling` to to `not(no_global_oom_handling)`. This breaks
the monotonicity that would be important for a Cargo feature (i.e.
turning on more features should never break compatibility), but it
doesn't matter for raw cfg tokens which are not intended to be
"constraint solved" by Cargo or anything else.
To support this use-case we create a new feature, "global-oom-handling",
on by default, and put the global OOM handler infra and everything else
it that depends on it behind it. By default, nothing is changed, but
users concerned about global handling can make sure it is disabled, and
be confident that all OOM handling is local and explicit.
For this first iteration, non-flat collections are outright disabled.
`Vec` and `String` don't yet have `try_*` allocation methods, but are
kept anyways since they can be oom-safely created "from parts", and we
hope to add those `try_` methods in the future.
[1]: https://lore.kernel.org/lkml/CAHk-=wh_sNLoz84AUUzuqXEsYH35u=8HV3vK-jbRbJ_B-JjGrg@mail.gmail.com/
2021-04-17 00:18:04 +00:00
|
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2018-04-07 19:56:02 +00:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
|
impl ToOwned for str {
|
|
|
|
|
type Owned = String;
|
2018-08-29 10:30:54 +00:00
|
|
|
|
#[inline]
|
2018-04-07 19:56:02 +00:00
|
|
|
|
fn to_owned(&self) -> String {
|
|
|
|
|
unsafe { String::from_utf8_unchecked(self.as_bytes().to_owned()) }
|
2017-06-13 22:52:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-04-07 19:56:02 +00:00
|
|
|
|
fn clone_into(&self, target: &mut String) {
|
2019-06-30 18:30:01 +00:00
|
|
|
|
let mut b = mem::take(target).into_bytes();
|
2018-04-07 19:56:02 +00:00
|
|
|
|
self.as_bytes().clone_into(&mut b);
|
|
|
|
|
*target = unsafe { String::from_utf8_unchecked(b) }
|
2017-06-13 22:52:59 +00:00
|
|
|
|
}
|
2018-04-07 19:56:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Methods for string slices.
|
|
|
|
|
#[cfg(not(test))]
|
|
|
|
|
impl str {
|
2017-06-13 22:52:59 +00:00
|
|
|
|
/// Converts a `Box<str>` into a `Box<[u8]>` without copying or allocating.
|
2017-09-11 06:28:14 +00:00
|
|
|
|
///
|
2017-09-11 06:13:57 +00:00
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let s = "this is a string";
|
|
|
|
|
/// let boxed_str = s.to_owned().into_boxed_str();
|
|
|
|
|
/// let boxed_bytes = boxed_str.into_boxed_bytes();
|
|
|
|
|
/// assert_eq!(*boxed_bytes, *s.as_bytes());
|
|
|
|
|
/// ```
|
2022-04-05 20:42:23 +00:00
|
|
|
|
#[rustc_allow_incoherent_impl]
|
2017-07-20 22:52:12 +00:00
|
|
|
|
#[stable(feature = "str_box_extras", since = "1.20.0")]
|
2021-10-14 23:56:53 +00:00
|
|
|
|
#[must_use = "`self` will be dropped if the result is not used"]
|
2018-03-31 21:19:02 +00:00
|
|
|
|
#[inline]
|
2017-06-13 22:52:59 +00:00
|
|
|
|
pub fn into_boxed_bytes(self: Box<str>) -> Box<[u8]> {
|
|
|
|
|
self.into()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Replaces all matches of a pattern with another string.
|
|
|
|
|
///
|
|
|
|
|
/// `replace` creates a new [`String`], and copies the data from this string slice into it.
|
|
|
|
|
/// While doing so, it attempts to find matches of a pattern. If it finds any, it
|
|
|
|
|
/// replaces them with the replacement string slice.
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// Basic usage:
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let s = "this is old";
|
|
|
|
|
///
|
|
|
|
|
/// assert_eq!("this is new", s.replace("old", "new"));
|
2022-06-09 16:28:46 +00:00
|
|
|
|
/// assert_eq!("than an old", s.replace("is", "an"));
|
2017-06-13 22:52:59 +00:00
|
|
|
|
/// ```
|
|
|
|
|
///
|
2023-03-25 15:41:00 +00:00
|
|
|
|
/// When the pattern doesn't match, it returns this string slice as [`String`]:
|
2017-06-13 22:52:59 +00:00
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let s = "this is old";
|
|
|
|
|
/// assert_eq!(s, s.replace("cookie monster", "little lamb"));
|
|
|
|
|
/// ```
|
alloc: Add unstable Cfg feature `no-global_oom_handling`
For certain sorts of systems, programming, it's deemed essential that
all allocation failures be explicitly handled where they occur. For
example, see Linus Torvald's opinion in [1]. Merely not calling global
panic handlers, or always `try_reserving` first (for vectors), is not
deemed good enough, because the mere presence of the global OOM handlers
is burdens static analysis.
One option for these projects to use rust would just be to skip `alloc`,
rolling their own allocation abstractions. But this would, in my
opinion be a real shame. `alloc` has a few `try_*` methods already, and
we could easily have more. Features like custom allocator support also
demonstrate and existing to support diverse use-cases with the same
abstractions.
A natural way to add such a feature flag would a Cargo feature, but
there are currently uncertainties around how std library crate's Cargo
features may or not be stable, so to avoid any risk of stabilizing by
mistake we are going with a more low-level "raw cfg" token, which
cannot be interacted with via Cargo alone.
Note also that since there is no notion of "default cfg tokens" outside
of Cargo features, we have to invert the condition from
`global_oom_handling` to to `not(no_global_oom_handling)`. This breaks
the monotonicity that would be important for a Cargo feature (i.e.
turning on more features should never break compatibility), but it
doesn't matter for raw cfg tokens which are not intended to be
"constraint solved" by Cargo or anything else.
To support this use-case we create a new feature, "global-oom-handling",
on by default, and put the global OOM handler infra and everything else
it that depends on it behind it. By default, nothing is changed, but
users concerned about global handling can make sure it is disabled, and
be confident that all OOM handling is local and explicit.
For this first iteration, non-flat collections are outright disabled.
`Vec` and `String` don't yet have `try_*` allocation methods, but are
kept anyways since they can be oom-safely created "from parts", and we
hope to add those `try_` methods in the future.
[1]: https://lore.kernel.org/lkml/CAHk-=wh_sNLoz84AUUzuqXEsYH35u=8HV3vK-jbRbJ_B-JjGrg@mail.gmail.com/
2021-04-17 00:18:04 +00:00
|
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2022-04-05 20:42:23 +00:00
|
|
|
|
#[rustc_allow_incoherent_impl]
|
2018-05-07 16:30:11 +00:00
|
|
|
|
#[must_use = "this returns the replaced string as a new allocation, \
|
|
|
|
|
without modifying the original"]
|
2017-06-13 22:52:59 +00:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn replace<'a, P: Pattern<'a>>(&'a self, from: P, to: &str) -> String {
|
|
|
|
|
let mut result = String::new();
|
|
|
|
|
let mut last_end = 0;
|
|
|
|
|
for (start, part) in self.match_indices(from) {
|
2018-06-26 10:34:42 +00:00
|
|
|
|
result.push_str(unsafe { self.get_unchecked(last_end..start) });
|
2017-06-13 22:52:59 +00:00
|
|
|
|
result.push_str(to);
|
|
|
|
|
last_end = start + part.len();
|
|
|
|
|
}
|
2018-06-26 10:34:42 +00:00
|
|
|
|
result.push_str(unsafe { self.get_unchecked(last_end..self.len()) });
|
2017-06-13 22:52:59 +00:00
|
|
|
|
result
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Replaces first N matches of a pattern with another string.
|
|
|
|
|
///
|
|
|
|
|
/// `replacen` creates a new [`String`], and copies the data from this string slice into it.
|
|
|
|
|
/// While doing so, it attempts to find matches of a pattern. If it finds any, it
|
|
|
|
|
/// replaces them with the replacement string slice at most `count` times.
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// Basic usage:
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let s = "foo foo 123 foo";
|
|
|
|
|
/// assert_eq!("new new 123 foo", s.replacen("foo", "new", 2));
|
|
|
|
|
/// assert_eq!("faa fao 123 foo", s.replacen('o', "a", 3));
|
|
|
|
|
/// assert_eq!("foo foo new23 foo", s.replacen(char::is_numeric, "new", 1));
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
2023-03-25 15:41:00 +00:00
|
|
|
|
/// When the pattern doesn't match, it returns this string slice as [`String`]:
|
2017-06-13 22:52:59 +00:00
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let s = "this is old";
|
|
|
|
|
/// assert_eq!(s, s.replacen("cookie monster", "little lamb", 10));
|
|
|
|
|
/// ```
|
alloc: Add unstable Cfg feature `no-global_oom_handling`
For certain sorts of systems, programming, it's deemed essential that
all allocation failures be explicitly handled where they occur. For
example, see Linus Torvald's opinion in [1]. Merely not calling global
panic handlers, or always `try_reserving` first (for vectors), is not
deemed good enough, because the mere presence of the global OOM handlers
is burdens static analysis.
One option for these projects to use rust would just be to skip `alloc`,
rolling their own allocation abstractions. But this would, in my
opinion be a real shame. `alloc` has a few `try_*` methods already, and
we could easily have more. Features like custom allocator support also
demonstrate and existing to support diverse use-cases with the same
abstractions.
A natural way to add such a feature flag would a Cargo feature, but
there are currently uncertainties around how std library crate's Cargo
features may or not be stable, so to avoid any risk of stabilizing by
mistake we are going with a more low-level "raw cfg" token, which
cannot be interacted with via Cargo alone.
Note also that since there is no notion of "default cfg tokens" outside
of Cargo features, we have to invert the condition from
`global_oom_handling` to to `not(no_global_oom_handling)`. This breaks
the monotonicity that would be important for a Cargo feature (i.e.
turning on more features should never break compatibility), but it
doesn't matter for raw cfg tokens which are not intended to be
"constraint solved" by Cargo or anything else.
To support this use-case we create a new feature, "global-oom-handling",
on by default, and put the global OOM handler infra and everything else
it that depends on it behind it. By default, nothing is changed, but
users concerned about global handling can make sure it is disabled, and
be confident that all OOM handling is local and explicit.
For this first iteration, non-flat collections are outright disabled.
`Vec` and `String` don't yet have `try_*` allocation methods, but are
kept anyways since they can be oom-safely created "from parts", and we
hope to add those `try_` methods in the future.
[1]: https://lore.kernel.org/lkml/CAHk-=wh_sNLoz84AUUzuqXEsYH35u=8HV3vK-jbRbJ_B-JjGrg@mail.gmail.com/
2021-04-17 00:18:04 +00:00
|
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2022-04-05 20:42:23 +00:00
|
|
|
|
#[rustc_allow_incoherent_impl]
|
2018-05-07 16:30:11 +00:00
|
|
|
|
#[must_use = "this returns the replaced string as a new allocation, \
|
|
|
|
|
without modifying the original"]
|
2017-06-13 22:52:59 +00:00
|
|
|
|
#[stable(feature = "str_replacen", since = "1.16.0")]
|
|
|
|
|
pub fn replacen<'a, P: Pattern<'a>>(&'a self, pat: P, to: &str, count: usize) -> String {
|
|
|
|
|
// Hope to reduce the times of re-allocation
|
|
|
|
|
let mut result = String::with_capacity(32);
|
|
|
|
|
let mut last_end = 0;
|
|
|
|
|
for (start, part) in self.match_indices(pat).take(count) {
|
2018-06-26 10:34:42 +00:00
|
|
|
|
result.push_str(unsafe { self.get_unchecked(last_end..start) });
|
2017-06-13 22:52:59 +00:00
|
|
|
|
result.push_str(to);
|
|
|
|
|
last_end = start + part.len();
|
|
|
|
|
}
|
2018-06-26 10:34:42 +00:00
|
|
|
|
result.push_str(unsafe { self.get_unchecked(last_end..self.len()) });
|
2017-06-13 22:52:59 +00:00
|
|
|
|
result
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns the lowercase equivalent of this string slice, as a new [`String`].
|
|
|
|
|
///
|
|
|
|
|
/// 'Lowercase' is defined according to the terms of the Unicode Derived Core Property
|
|
|
|
|
/// `Lowercase`.
|
|
|
|
|
///
|
|
|
|
|
/// Since some characters can expand into multiple characters when changing
|
|
|
|
|
/// the case, this function returns a [`String`] instead of modifying the
|
|
|
|
|
/// parameter in-place.
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// Basic usage:
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let s = "HELLO";
|
|
|
|
|
///
|
|
|
|
|
/// assert_eq!("hello", s.to_lowercase());
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// A tricky example, with sigma:
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let sigma = "Σ";
|
|
|
|
|
///
|
|
|
|
|
/// assert_eq!("σ", sigma.to_lowercase());
|
|
|
|
|
///
|
|
|
|
|
/// // but at the end of a word, it's ς, not σ:
|
|
|
|
|
/// let odysseus = "ὈΔΥΣΣΕΎΣ";
|
|
|
|
|
///
|
|
|
|
|
/// assert_eq!("ὀδυσσεύς", odysseus.to_lowercase());
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// Languages without case are not changed:
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let new_year = "农历新年";
|
|
|
|
|
///
|
|
|
|
|
/// assert_eq!(new_year, new_year.to_lowercase());
|
|
|
|
|
/// ```
|
alloc: Add unstable Cfg feature `no-global_oom_handling`
For certain sorts of systems, programming, it's deemed essential that
all allocation failures be explicitly handled where they occur. For
example, see Linus Torvald's opinion in [1]. Merely not calling global
panic handlers, or always `try_reserving` first (for vectors), is not
deemed good enough, because the mere presence of the global OOM handlers
is burdens static analysis.
One option for these projects to use rust would just be to skip `alloc`,
rolling their own allocation abstractions. But this would, in my
opinion be a real shame. `alloc` has a few `try_*` methods already, and
we could easily have more. Features like custom allocator support also
demonstrate and existing to support diverse use-cases with the same
abstractions.
A natural way to add such a feature flag would a Cargo feature, but
there are currently uncertainties around how std library crate's Cargo
features may or not be stable, so to avoid any risk of stabilizing by
mistake we are going with a more low-level "raw cfg" token, which
cannot be interacted with via Cargo alone.
Note also that since there is no notion of "default cfg tokens" outside
of Cargo features, we have to invert the condition from
`global_oom_handling` to to `not(no_global_oom_handling)`. This breaks
the monotonicity that would be important for a Cargo feature (i.e.
turning on more features should never break compatibility), but it
doesn't matter for raw cfg tokens which are not intended to be
"constraint solved" by Cargo or anything else.
To support this use-case we create a new feature, "global-oom-handling",
on by default, and put the global OOM handler infra and everything else
it that depends on it behind it. By default, nothing is changed, but
users concerned about global handling can make sure it is disabled, and
be confident that all OOM handling is local and explicit.
For this first iteration, non-flat collections are outright disabled.
`Vec` and `String` don't yet have `try_*` allocation methods, but are
kept anyways since they can be oom-safely created "from parts", and we
hope to add those `try_` methods in the future.
[1]: https://lore.kernel.org/lkml/CAHk-=wh_sNLoz84AUUzuqXEsYH35u=8HV3vK-jbRbJ_B-JjGrg@mail.gmail.com/
2021-04-17 00:18:04 +00:00
|
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2022-04-05 20:42:23 +00:00
|
|
|
|
#[rustc_allow_incoherent_impl]
|
2021-10-09 05:01:40 +00:00
|
|
|
|
#[must_use = "this returns the lowercase string as a new String, \
|
|
|
|
|
without modifying the original"]
|
2017-06-13 22:52:59 +00:00
|
|
|
|
#[stable(feature = "unicode_case_mapping", since = "1.2.0")]
|
|
|
|
|
pub fn to_lowercase(&self) -> String {
|
2022-05-14 17:44:31 +00:00
|
|
|
|
let out = convert_while_ascii(self.as_bytes(), u8::to_ascii_lowercase);
|
|
|
|
|
|
|
|
|
|
// Safety: we know this is a valid char boundary since
|
|
|
|
|
// out.len() is only progressed if ascii bytes are found
|
|
|
|
|
let rest = unsafe { self.get_unchecked(out.len()..) };
|
|
|
|
|
|
|
|
|
|
// Safety: We have written only valid ASCII to our vec
|
|
|
|
|
let mut s = unsafe { String::from_utf8_unchecked(out) };
|
|
|
|
|
|
2024-05-05 21:01:09 +00:00
|
|
|
|
for (i, c) in rest.char_indices() {
|
2017-06-13 22:52:59 +00:00
|
|
|
|
if c == 'Σ' {
|
|
|
|
|
// Σ maps to σ, except at the end of a word where it maps to ς.
|
|
|
|
|
// This is the only conditional (contextual) but language-independent mapping
|
|
|
|
|
// in `SpecialCasing.txt`,
|
|
|
|
|
// so hard-code it rather than have a generic "condition" mechanism.
|
|
|
|
|
// See https://github.com/rust-lang/rust/issues/26035
|
2024-05-05 21:01:09 +00:00
|
|
|
|
let out_len = self.len() - rest.len();
|
|
|
|
|
let sigma_lowercase = map_uppercase_sigma(&self, i + out_len);
|
|
|
|
|
s.push(sigma_lowercase);
|
2017-06-13 22:52:59 +00:00
|
|
|
|
} else {
|
2018-07-06 15:20:39 +00:00
|
|
|
|
match conversions::to_lower(c) {
|
|
|
|
|
[a, '\0', _] => s.push(a),
|
|
|
|
|
[a, b, '\0'] => {
|
|
|
|
|
s.push(a);
|
|
|
|
|
s.push(b);
|
|
|
|
|
}
|
|
|
|
|
[a, b, c] => {
|
|
|
|
|
s.push(a);
|
|
|
|
|
s.push(b);
|
|
|
|
|
s.push(c);
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-06-13 22:52:59 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return s;
|
|
|
|
|
|
2024-05-05 21:01:09 +00:00
|
|
|
|
fn map_uppercase_sigma(from: &str, i: usize) -> char {
|
2021-06-23 20:26:46 +00:00
|
|
|
|
// See https://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992
|
2017-06-13 22:52:59 +00:00
|
|
|
|
// for the definition of `Final_Sigma`.
|
|
|
|
|
debug_assert!('Σ'.len_utf8() == 2);
|
2023-04-11 04:49:38 +00:00
|
|
|
|
let is_word_final = case_ignorable_then_cased(from[..i].chars().rev())
|
|
|
|
|
&& !case_ignorable_then_cased(from[i + 2..].chars());
|
2024-05-05 21:01:09 +00:00
|
|
|
|
if is_word_final { 'ς' } else { 'σ' }
|
2017-06-13 22:52:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-04-11 04:49:38 +00:00
|
|
|
|
fn case_ignorable_then_cased<I: Iterator<Item = char>>(iter: I) -> bool {
|
2020-12-07 13:16:42 +00:00
|
|
|
|
use core::unicode::{Case_Ignorable, Cased};
|
2017-06-13 22:52:59 +00:00
|
|
|
|
match iter.skip_while(|&c| Case_Ignorable(c)).next() {
|
|
|
|
|
Some(c) => Cased(c),
|
|
|
|
|
None => false,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns the uppercase equivalent of this string slice, as a new [`String`].
|
|
|
|
|
///
|
|
|
|
|
/// 'Uppercase' is defined according to the terms of the Unicode Derived Core Property
|
|
|
|
|
/// `Uppercase`.
|
|
|
|
|
///
|
|
|
|
|
/// Since some characters can expand into multiple characters when changing
|
|
|
|
|
/// the case, this function returns a [`String`] instead of modifying the
|
|
|
|
|
/// parameter in-place.
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// Basic usage:
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let s = "hello";
|
|
|
|
|
///
|
|
|
|
|
/// assert_eq!("HELLO", s.to_uppercase());
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// Scripts without case are not changed:
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let new_year = "农历新年";
|
|
|
|
|
///
|
|
|
|
|
/// assert_eq!(new_year, new_year.to_uppercase());
|
|
|
|
|
/// ```
|
2019-06-01 07:23:26 +00:00
|
|
|
|
///
|
|
|
|
|
/// One character can become multiple:
|
|
|
|
|
/// ```
|
|
|
|
|
/// let s = "tschüß";
|
|
|
|
|
///
|
|
|
|
|
/// assert_eq!("TSCHÜSS", s.to_uppercase());
|
|
|
|
|
/// ```
|
alloc: Add unstable Cfg feature `no-global_oom_handling`
For certain sorts of systems, programming, it's deemed essential that
all allocation failures be explicitly handled where they occur. For
example, see Linus Torvald's opinion in [1]. Merely not calling global
panic handlers, or always `try_reserving` first (for vectors), is not
deemed good enough, because the mere presence of the global OOM handlers
is burdens static analysis.
One option for these projects to use rust would just be to skip `alloc`,
rolling their own allocation abstractions. But this would, in my
opinion be a real shame. `alloc` has a few `try_*` methods already, and
we could easily have more. Features like custom allocator support also
demonstrate and existing to support diverse use-cases with the same
abstractions.
A natural way to add such a feature flag would a Cargo feature, but
there are currently uncertainties around how std library crate's Cargo
features may or not be stable, so to avoid any risk of stabilizing by
mistake we are going with a more low-level "raw cfg" token, which
cannot be interacted with via Cargo alone.
Note also that since there is no notion of "default cfg tokens" outside
of Cargo features, we have to invert the condition from
`global_oom_handling` to to `not(no_global_oom_handling)`. This breaks
the monotonicity that would be important for a Cargo feature (i.e.
turning on more features should never break compatibility), but it
doesn't matter for raw cfg tokens which are not intended to be
"constraint solved" by Cargo or anything else.
To support this use-case we create a new feature, "global-oom-handling",
on by default, and put the global OOM handler infra and everything else
it that depends on it behind it. By default, nothing is changed, but
users concerned about global handling can make sure it is disabled, and
be confident that all OOM handling is local and explicit.
For this first iteration, non-flat collections are outright disabled.
`Vec` and `String` don't yet have `try_*` allocation methods, but are
kept anyways since they can be oom-safely created "from parts", and we
hope to add those `try_` methods in the future.
[1]: https://lore.kernel.org/lkml/CAHk-=wh_sNLoz84AUUzuqXEsYH35u=8HV3vK-jbRbJ_B-JjGrg@mail.gmail.com/
2021-04-17 00:18:04 +00:00
|
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2022-04-05 20:42:23 +00:00
|
|
|
|
#[rustc_allow_incoherent_impl]
|
2021-10-09 05:01:40 +00:00
|
|
|
|
#[must_use = "this returns the uppercase string as a new String, \
|
|
|
|
|
without modifying the original"]
|
2017-06-13 22:52:59 +00:00
|
|
|
|
#[stable(feature = "unicode_case_mapping", since = "1.2.0")]
|
|
|
|
|
pub fn to_uppercase(&self) -> String {
|
2022-05-14 17:44:31 +00:00
|
|
|
|
let out = convert_while_ascii(self.as_bytes(), u8::to_ascii_uppercase);
|
|
|
|
|
|
|
|
|
|
// Safety: we know this is a valid char boundary since
|
|
|
|
|
// out.len() is only progressed if ascii bytes are found
|
|
|
|
|
let rest = unsafe { self.get_unchecked(out.len()..) };
|
|
|
|
|
|
|
|
|
|
// Safety: We have written only valid ASCII to our vec
|
|
|
|
|
let mut s = unsafe { String::from_utf8_unchecked(out) };
|
|
|
|
|
|
|
|
|
|
for c in rest.chars() {
|
2018-07-06 15:20:39 +00:00
|
|
|
|
match conversions::to_upper(c) {
|
|
|
|
|
[a, '\0', _] => s.push(a),
|
|
|
|
|
[a, b, '\0'] => {
|
|
|
|
|
s.push(a);
|
|
|
|
|
s.push(b);
|
|
|
|
|
}
|
|
|
|
|
[a, b, c] => {
|
|
|
|
|
s.push(a);
|
|
|
|
|
s.push(b);
|
|
|
|
|
s.push(c);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-09-05 11:30:30 +00:00
|
|
|
|
s
|
2017-06-13 22:52:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Converts a [`Box<str>`] into a [`String`] without copying or allocating.
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let string = String::from("birthday gift");
|
|
|
|
|
/// let boxed_str = string.clone().into_boxed_str();
|
|
|
|
|
///
|
|
|
|
|
/// assert_eq!(boxed_str.into_string(), string);
|
|
|
|
|
/// ```
|
|
|
|
|
#[stable(feature = "box_str", since = "1.4.0")]
|
2022-04-05 20:42:23 +00:00
|
|
|
|
#[rustc_allow_incoherent_impl]
|
2021-10-14 23:56:53 +00:00
|
|
|
|
#[must_use = "`self` will be dropped if the result is not used"]
|
2018-03-31 21:19:02 +00:00
|
|
|
|
#[inline]
|
2017-06-13 22:52:59 +00:00
|
|
|
|
pub fn into_string(self: Box<str>) -> String {
|
2017-09-27 18:56:20 +00:00
|
|
|
|
let slice = Box::<[u8]>::from(self);
|
|
|
|
|
unsafe { String::from_utf8_unchecked(slice.into_vec()) }
|
2017-06-13 22:52:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-08-22 06:06:39 +00:00
|
|
|
|
/// Creates a new [`String`] by repeating a string `n` times.
|
2017-06-13 22:52:59 +00:00
|
|
|
|
///
|
2018-09-20 16:31:14 +00:00
|
|
|
|
/// # Panics
|
|
|
|
|
///
|
|
|
|
|
/// This function will panic if the capacity would overflow.
|
|
|
|
|
///
|
2017-06-13 22:52:59 +00:00
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// Basic usage:
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// assert_eq!("abc".repeat(4), String::from("abcabcabcabc"));
|
|
|
|
|
/// ```
|
2018-09-20 16:31:14 +00:00
|
|
|
|
///
|
|
|
|
|
/// A panic upon overflow:
|
|
|
|
|
///
|
|
|
|
|
/// ```should_panic
|
2019-10-01 11:55:46 +00:00
|
|
|
|
/// // this will panic at runtime
|
2021-10-14 23:56:53 +00:00
|
|
|
|
/// let huge = "0123456789abcdef".repeat(usize::MAX);
|
2018-09-20 16:31:14 +00:00
|
|
|
|
/// ```
|
alloc: Add unstable Cfg feature `no-global_oom_handling`
For certain sorts of systems, programming, it's deemed essential that
all allocation failures be explicitly handled where they occur. For
example, see Linus Torvald's opinion in [1]. Merely not calling global
panic handlers, or always `try_reserving` first (for vectors), is not
deemed good enough, because the mere presence of the global OOM handlers
is burdens static analysis.
One option for these projects to use rust would just be to skip `alloc`,
rolling their own allocation abstractions. But this would, in my
opinion be a real shame. `alloc` has a few `try_*` methods already, and
we could easily have more. Features like custom allocator support also
demonstrate and existing to support diverse use-cases with the same
abstractions.
A natural way to add such a feature flag would a Cargo feature, but
there are currently uncertainties around how std library crate's Cargo
features may or not be stable, so to avoid any risk of stabilizing by
mistake we are going with a more low-level "raw cfg" token, which
cannot be interacted with via Cargo alone.
Note also that since there is no notion of "default cfg tokens" outside
of Cargo features, we have to invert the condition from
`global_oom_handling` to to `not(no_global_oom_handling)`. This breaks
the monotonicity that would be important for a Cargo feature (i.e.
turning on more features should never break compatibility), but it
doesn't matter for raw cfg tokens which are not intended to be
"constraint solved" by Cargo or anything else.
To support this use-case we create a new feature, "global-oom-handling",
on by default, and put the global OOM handler infra and everything else
it that depends on it behind it. By default, nothing is changed, but
users concerned about global handling can make sure it is disabled, and
be confident that all OOM handling is local and explicit.
For this first iteration, non-flat collections are outright disabled.
`Vec` and `String` don't yet have `try_*` allocation methods, but are
kept anyways since they can be oom-safely created "from parts", and we
hope to add those `try_` methods in the future.
[1]: https://lore.kernel.org/lkml/CAHk-=wh_sNLoz84AUUzuqXEsYH35u=8HV3vK-jbRbJ_B-JjGrg@mail.gmail.com/
2021-04-17 00:18:04 +00:00
|
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2022-04-05 20:42:23 +00:00
|
|
|
|
#[rustc_allow_incoherent_impl]
|
2021-10-14 23:56:53 +00:00
|
|
|
|
#[must_use]
|
2017-06-13 22:52:59 +00:00
|
|
|
|
#[stable(feature = "repeat_str", since = "1.16.0")]
|
|
|
|
|
pub fn repeat(&self, n: usize) -> String {
|
2018-03-13 21:29:59 +00:00
|
|
|
|
unsafe { String::from_utf8_unchecked(self.as_bytes().repeat(n)) }
|
2017-06-13 22:52:59 +00:00
|
|
|
|
}
|
2018-03-26 13:25:31 +00:00
|
|
|
|
|
2017-10-01 19:46:17 +00:00
|
|
|
|
/// Returns a copy of this string where each character is mapped to its
|
|
|
|
|
/// ASCII upper case equivalent.
|
|
|
|
|
///
|
|
|
|
|
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
|
|
|
|
|
/// but non-ASCII letters are unchanged.
|
|
|
|
|
///
|
|
|
|
|
/// To uppercase the value in-place, use [`make_ascii_uppercase`].
|
|
|
|
|
///
|
|
|
|
|
/// To uppercase ASCII characters in addition to non-ASCII characters, use
|
|
|
|
|
/// [`to_uppercase`].
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let s = "Grüße, Jürgen ❤";
|
|
|
|
|
///
|
|
|
|
|
/// assert_eq!("GRüßE, JüRGEN ❤", s.to_ascii_uppercase());
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
2020-07-18 17:14:00 +00:00
|
|
|
|
/// [`make_ascii_uppercase`]: str::make_ascii_uppercase
|
2017-10-01 19:46:17 +00:00
|
|
|
|
/// [`to_uppercase`]: #method.to_uppercase
|
alloc: Add unstable Cfg feature `no-global_oom_handling`
For certain sorts of systems, programming, it's deemed essential that
all allocation failures be explicitly handled where they occur. For
example, see Linus Torvald's opinion in [1]. Merely not calling global
panic handlers, or always `try_reserving` first (for vectors), is not
deemed good enough, because the mere presence of the global OOM handlers
is burdens static analysis.
One option for these projects to use rust would just be to skip `alloc`,
rolling their own allocation abstractions. But this would, in my
opinion be a real shame. `alloc` has a few `try_*` methods already, and
we could easily have more. Features like custom allocator support also
demonstrate and existing to support diverse use-cases with the same
abstractions.
A natural way to add such a feature flag would a Cargo feature, but
there are currently uncertainties around how std library crate's Cargo
features may or not be stable, so to avoid any risk of stabilizing by
mistake we are going with a more low-level "raw cfg" token, which
cannot be interacted with via Cargo alone.
Note also that since there is no notion of "default cfg tokens" outside
of Cargo features, we have to invert the condition from
`global_oom_handling` to to `not(no_global_oom_handling)`. This breaks
the monotonicity that would be important for a Cargo feature (i.e.
turning on more features should never break compatibility), but it
doesn't matter for raw cfg tokens which are not intended to be
"constraint solved" by Cargo or anything else.
To support this use-case we create a new feature, "global-oom-handling",
on by default, and put the global OOM handler infra and everything else
it that depends on it behind it. By default, nothing is changed, but
users concerned about global handling can make sure it is disabled, and
be confident that all OOM handling is local and explicit.
For this first iteration, non-flat collections are outright disabled.
`Vec` and `String` don't yet have `try_*` allocation methods, but are
kept anyways since they can be oom-safely created "from parts", and we
hope to add those `try_` methods in the future.
[1]: https://lore.kernel.org/lkml/CAHk-=wh_sNLoz84AUUzuqXEsYH35u=8HV3vK-jbRbJ_B-JjGrg@mail.gmail.com/
2021-04-17 00:18:04 +00:00
|
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2022-04-05 20:42:23 +00:00
|
|
|
|
#[rustc_allow_incoherent_impl]
|
2021-10-12 12:53:54 +00:00
|
|
|
|
#[must_use = "to uppercase the value in-place, use `make_ascii_uppercase()`"]
|
2017-11-30 19:20:11 +00:00
|
|
|
|
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
|
2017-10-01 19:46:17 +00:00
|
|
|
|
#[inline]
|
|
|
|
|
pub fn to_ascii_uppercase(&self) -> String {
|
2023-01-15 23:15:06 +00:00
|
|
|
|
let mut s = self.to_owned();
|
|
|
|
|
s.make_ascii_uppercase();
|
|
|
|
|
s
|
2017-10-01 19:46:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns a copy of this string where each character is mapped to its
|
|
|
|
|
/// ASCII lower case equivalent.
|
|
|
|
|
///
|
|
|
|
|
/// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
|
|
|
|
|
/// but non-ASCII letters are unchanged.
|
|
|
|
|
///
|
|
|
|
|
/// To lowercase the value in-place, use [`make_ascii_lowercase`].
|
|
|
|
|
///
|
|
|
|
|
/// To lowercase ASCII characters in addition to non-ASCII characters, use
|
|
|
|
|
/// [`to_lowercase`].
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let s = "Grüße, Jürgen ❤";
|
|
|
|
|
///
|
|
|
|
|
/// assert_eq!("grüße, jürgen ❤", s.to_ascii_lowercase());
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
2020-07-18 17:14:00 +00:00
|
|
|
|
/// [`make_ascii_lowercase`]: str::make_ascii_lowercase
|
2017-10-01 19:46:17 +00:00
|
|
|
|
/// [`to_lowercase`]: #method.to_lowercase
|
alloc: Add unstable Cfg feature `no-global_oom_handling`
For certain sorts of systems, programming, it's deemed essential that
all allocation failures be explicitly handled where they occur. For
example, see Linus Torvald's opinion in [1]. Merely not calling global
panic handlers, or always `try_reserving` first (for vectors), is not
deemed good enough, because the mere presence of the global OOM handlers
is burdens static analysis.
One option for these projects to use rust would just be to skip `alloc`,
rolling their own allocation abstractions. But this would, in my
opinion be a real shame. `alloc` has a few `try_*` methods already, and
we could easily have more. Features like custom allocator support also
demonstrate and existing to support diverse use-cases with the same
abstractions.
A natural way to add such a feature flag would a Cargo feature, but
there are currently uncertainties around how std library crate's Cargo
features may or not be stable, so to avoid any risk of stabilizing by
mistake we are going with a more low-level "raw cfg" token, which
cannot be interacted with via Cargo alone.
Note also that since there is no notion of "default cfg tokens" outside
of Cargo features, we have to invert the condition from
`global_oom_handling` to to `not(no_global_oom_handling)`. This breaks
the monotonicity that would be important for a Cargo feature (i.e.
turning on more features should never break compatibility), but it
doesn't matter for raw cfg tokens which are not intended to be
"constraint solved" by Cargo or anything else.
To support this use-case we create a new feature, "global-oom-handling",
on by default, and put the global OOM handler infra and everything else
it that depends on it behind it. By default, nothing is changed, but
users concerned about global handling can make sure it is disabled, and
be confident that all OOM handling is local and explicit.
For this first iteration, non-flat collections are outright disabled.
`Vec` and `String` don't yet have `try_*` allocation methods, but are
kept anyways since they can be oom-safely created "from parts", and we
hope to add those `try_` methods in the future.
[1]: https://lore.kernel.org/lkml/CAHk-=wh_sNLoz84AUUzuqXEsYH35u=8HV3vK-jbRbJ_B-JjGrg@mail.gmail.com/
2021-04-17 00:18:04 +00:00
|
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2022-04-05 20:42:23 +00:00
|
|
|
|
#[rustc_allow_incoherent_impl]
|
2021-10-09 05:01:40 +00:00
|
|
|
|
#[must_use = "to lowercase the value in-place, use `make_ascii_lowercase()`"]
|
2017-11-30 19:20:11 +00:00
|
|
|
|
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
|
2017-10-01 19:46:17 +00:00
|
|
|
|
#[inline]
|
|
|
|
|
pub fn to_ascii_lowercase(&self) -> String {
|
2023-01-15 23:15:06 +00:00
|
|
|
|
let mut s = self.to_owned();
|
|
|
|
|
s.make_ascii_lowercase();
|
|
|
|
|
s
|
2017-10-01 19:46:17 +00:00
|
|
|
|
}
|
2017-06-13 22:52:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-04-11 20:02:43 +00:00
|
|
|
|
/// Converts a boxed slice of bytes to a boxed string slice without checking
|
|
|
|
|
/// that the string contains valid UTF-8.
|
2017-09-11 16:28:28 +00:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let smile_utf8 = Box::new([226, 152, 186]);
|
|
|
|
|
/// let smile = unsafe { std::str::from_boxed_utf8_unchecked(smile_utf8) };
|
|
|
|
|
///
|
|
|
|
|
/// assert_eq!("☺", &*smile);
|
|
|
|
|
/// ```
|
2017-07-20 22:52:12 +00:00
|
|
|
|
#[stable(feature = "str_box_extras", since = "1.20.0")]
|
2021-10-10 22:22:40 +00:00
|
|
|
|
#[must_use]
|
2018-03-31 21:19:02 +00:00
|
|
|
|
#[inline]
|
2017-04-11 20:02:43 +00:00
|
|
|
|
pub unsafe fn from_boxed_utf8_unchecked(v: Box<[u8]>) -> Box<str> {
|
2020-05-28 21:27:00 +00:00
|
|
|
|
unsafe { Box::from_raw(Box::into_raw(v) as *mut str) }
|
2017-04-11 20:02:43 +00:00
|
|
|
|
}
|
2022-05-14 17:44:31 +00:00
|
|
|
|
|
|
|
|
|
/// Converts the bytes while the bytes are still ascii.
|
2023-08-15 19:26:14 +00:00
|
|
|
|
/// For better average performance, this happens in chunks of `2*size_of::<usize>()`.
|
2022-05-14 17:44:31 +00:00
|
|
|
|
/// Returns a vec with the converted bytes.
|
|
|
|
|
#[inline]
|
|
|
|
|
#[cfg(not(test))]
|
|
|
|
|
#[cfg(not(no_global_oom_handling))]
|
|
|
|
|
fn convert_while_ascii(b: &[u8], convert: fn(&u8) -> u8) -> Vec<u8> {
|
|
|
|
|
let mut out = Vec::with_capacity(b.len());
|
|
|
|
|
|
|
|
|
|
const USIZE_SIZE: usize = mem::size_of::<usize>();
|
|
|
|
|
const MAGIC_UNROLL: usize = 2;
|
|
|
|
|
const N: usize = USIZE_SIZE * MAGIC_UNROLL;
|
|
|
|
|
const NONASCII_MASK: usize = usize::from_ne_bytes([0x80; USIZE_SIZE]);
|
|
|
|
|
|
|
|
|
|
let mut i = 0;
|
|
|
|
|
unsafe {
|
|
|
|
|
while i + N <= b.len() {
|
|
|
|
|
// Safety: we have checks the sizes `b` and `out` to know that our
|
|
|
|
|
let in_chunk = b.get_unchecked(i..i + N);
|
|
|
|
|
let out_chunk = out.spare_capacity_mut().get_unchecked_mut(i..i + N);
|
|
|
|
|
|
|
|
|
|
let mut bits = 0;
|
|
|
|
|
for j in 0..MAGIC_UNROLL {
|
|
|
|
|
// read the bytes 1 usize at a time (unaligned since we haven't checked the alignment)
|
|
|
|
|
// safety: in_chunk is valid bytes in the range
|
|
|
|
|
bits |= in_chunk.as_ptr().cast::<usize>().add(j).read_unaligned();
|
|
|
|
|
}
|
|
|
|
|
// if our chunks aren't ascii, then return only the prior bytes as init
|
|
|
|
|
if bits & NONASCII_MASK != 0 {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// perform the case conversions on N bytes (gets heavily autovec'd)
|
|
|
|
|
for j in 0..N {
|
|
|
|
|
// safety: in_chunk and out_chunk is valid bytes in the range
|
|
|
|
|
let out = out_chunk.get_unchecked_mut(j);
|
|
|
|
|
out.write(convert(in_chunk.get_unchecked(j)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// mark these bytes as initialised
|
|
|
|
|
i += N;
|
|
|
|
|
}
|
|
|
|
|
out.set_len(i);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
out
|
|
|
|
|
}
|