2022-04-30 12:01:31 -05:00
|
|
|
//! Utilities for the slice primitive type.
|
2014-08-04 22:48:39 +12:00
|
|
|
//!
|
2020-12-19 08:23:59 -05:00
|
|
|
//! *[See also the slice primitive type](slice).*
|
2018-05-09 18:03:56 -04:00
|
|
|
//!
|
2022-04-30 12:01:31 -05:00
|
|
|
//! Most of the structs in this module are iterator types which can only be created
|
|
|
|
|
//! using a certain function. For example, `slice.iter()` yields an [`Iter`].
|
2014-08-04 22:48:39 +12:00
|
|
|
//!
|
2022-04-30 12:01:31 -05:00
|
|
|
//! A few functions are provided to create a slice from a value reference
|
|
|
|
|
//! or from a raw pointer.
|
2015-01-23 21:48:20 -08:00
|
|
|
#![stable(feature = "rust1", since = "1.0.0")]
|
2015-05-30 19:49:56 -04:00
|
|
|
// 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.
|
2016-01-22 23:49:57 -08:00
|
|
|
#![cfg_attr(test, allow(unused_imports, dead_code))]
|
2015-05-30 19:49:56 -04:00
|
|
|
|
2019-02-03 08:27:44 +01:00
|
|
|
use core::borrow::{Borrow, BorrowMut};
|
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-16 20:18:04 -04:00
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2019-02-03 08:27:44 +01:00
|
|
|
use core::cmp::Ordering::{self, Less};
|
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-16 20:18:04 -04:00
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2024-04-16 20:24:21 +02:00
|
|
|
use core::mem::{self, MaybeUninit};
|
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-16 20:18:04 -04:00
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2019-02-03 08:27:44 +01:00
|
|
|
use core::ptr;
|
2022-11-20 20:35:40 +01:00
|
|
|
#[cfg(not(no_global_oom_handling))]
|
|
|
|
|
use core::slice::sort;
|
2014-06-06 16:33:44 -07: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-16 20:18:04 -04:00
|
|
|
use crate::alloc::Allocator;
|
|
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2024-04-16 20:24:21 +02:00
|
|
|
use crate::alloc::Global;
|
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-16 20:18:04 -04:00
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2019-02-03 08:27:44 +01:00
|
|
|
use crate::borrow::ToOwned;
|
|
|
|
|
use crate::boxed::Box;
|
|
|
|
|
use crate::vec::Vec;
|
2012-07-17 16:31:19 -07:00
|
|
|
|
2022-11-20 16:55:41 -08:00
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests;
|
|
|
|
|
|
2020-08-01 07:49:24 +02:00
|
|
|
#[unstable(feature = "array_chunks", issue = "74985")]
|
2020-05-18 23:14:55 +02:00
|
|
|
pub use core::slice::ArrayChunks;
|
2020-08-01 11:48:34 -07:00
|
|
|
#[unstable(feature = "array_chunks", issue = "74985")]
|
|
|
|
|
pub use core::slice::ArrayChunksMut;
|
2020-08-13 19:09:14 +00:00
|
|
|
#[unstable(feature = "array_windows", issue = "75027")]
|
|
|
|
|
pub use core::slice::ArrayWindows;
|
2022-02-10 21:09:05 -05:00
|
|
|
#[stable(feature = "inherent_ascii_escape", since = "1.60.0")]
|
2021-11-05 17:14:57 +10:00
|
|
|
pub use core::slice::EscapeAscii;
|
2019-11-29 19:30:49 -08:00
|
|
|
#[stable(feature = "slice_get_slice", since = "1.28.0")]
|
|
|
|
|
pub use core::slice::SliceIndex;
|
2024-02-03 16:37:58 -05:00
|
|
|
#[stable(feature = "slice_group_by", since = "1.77.0")]
|
2023-11-07 17:46:00 +01:00
|
|
|
pub use core::slice::{ChunkBy, ChunkByMut};
|
2015-11-16 19:54:28 +03:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2019-11-29 19:30:49 -08:00
|
|
|
pub use core::slice::{Chunks, Windows};
|
|
|
|
|
#[stable(feature = "chunks_exact", since = "1.31.0")]
|
|
|
|
|
pub use core::slice::{ChunksExact, ChunksExactMut};
|
2015-11-16 19:54:28 +03:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2019-11-29 19:30:49 -08:00
|
|
|
pub use core::slice::{ChunksMut, Split, SplitMut};
|
2015-11-16 19:54:28 +03:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2019-11-29 19:30:49 -08:00
|
|
|
pub use core::slice::{Iter, IterMut};
|
|
|
|
|
#[stable(feature = "rchunks", since = "1.31.0")]
|
|
|
|
|
pub use core::slice::{RChunks, RChunksExact, RChunksExactMut, RChunksMut};
|
2018-04-17 00:30:06 -04:00
|
|
|
#[stable(feature = "slice_rsplit", since = "1.27.0")]
|
2017-04-03 15:25:30 -05:00
|
|
|
pub use core::slice::{RSplit, RSplitMut};
|
2015-11-16 19:54:28 +03:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2019-11-29 19:30:49 -08:00
|
|
|
pub use core::slice::{RSplitN, RSplitNMut, SplitN, SplitNMut};
|
2021-11-05 15:44:43 +10:00
|
|
|
#[stable(feature = "split_inclusive", since = "1.51.0")]
|
|
|
|
|
pub use core::slice::{SplitInclusive, SplitInclusiveMut};
|
2019-11-29 19:30:49 -08:00
|
|
|
#[stable(feature = "from_ref", since = "1.28.0")]
|
|
|
|
|
pub use core::slice::{from_mut, from_ref};
|
2022-05-27 18:37:33 +04:00
|
|
|
#[unstable(feature = "slice_from_ptr_range", issue = "89792")]
|
|
|
|
|
pub use core::slice::{from_mut_ptr_range, from_ptr_range};
|
2015-11-16 19:54:28 +03:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2019-11-29 19:30:49 -08:00
|
|
|
pub use core::slice::{from_raw_parts, from_raw_parts_mut};
|
2024-02-15 10:13:47 -05:00
|
|
|
#[unstable(feature = "slice_range", issue = "76393")]
|
|
|
|
|
pub use core::slice::{range, try_range};
|
2011-12-13 16:25:51 -08:00
|
|
|
|
Second pass stabilization: slice
This commit takes a second pass through the `slice` module to
stabilize its API. The changes are as follows:
**Stable**:
* `as_mut_slice`
* `as_ptr`, `as_mut_ptr`
* `binary_search_by` (was: `binary_search`)
* `binary_search` (was: `binary_search_elem`)
* `chunks`, `chunks_mut`
* `contains`
* `ends_with`
* `first`, `first_mut` (was: `head`)
* `get_unchecked`, `get_unchecked_mut` (was: `unsafe_get`)
* `get`
* `is_empty`
* `iter`, `iter_mut`
* `len`
* `reverse`
* `sort_by`
* `sort`
* `split_at`, `split_at_mut`
* `split_mut`, `splitn_mut`, `rsplitn_mut`
* `split`, `splitn`, `rsplitn`
* `starts_with`
* `swap`
* `to_vec`
* `windows`
**Deprecated**:
* `head`, `head_mut` (renamed as above)
* `unsafe_get`, `unsafe_mut` (renamed as above)
* `binary_search_elem` (renamed as above)
* `partitioned`, deprecated in favor of a new, more
general iterator consumer called `partition`.
* `BinarySearchResult`, deprecated in favor of `Result<uint, uint>`
[breaking-change]
2014-12-17 20:50:16 -08:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Basic slice extension methods
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2013-06-03 13:19:37 +10:00
|
|
|
|
2015-03-13 19:44:02 -05:00
|
|
|
// HACK(japaric) needed for the implementation of `vec!` macro during testing
|
2019-03-26 17:34:32 +00:00
|
|
|
// N.B., see the `hack` module in this file for more details.
|
2015-03-11 19:44:02 -05:00
|
|
|
#[cfg(test)]
|
2019-02-02 11:05:20 +01:00
|
|
|
pub use hack::into_vec;
|
2015-03-13 19:44:02 -05:00
|
|
|
// HACK(japaric) needed for the implementation of `Vec::clone` during testing
|
2019-03-26 17:34:32 +00:00
|
|
|
// N.B., see the `hack` module in this file for more details.
|
2015-03-11 19:44:02 -05:00
|
|
|
#[cfg(test)]
|
2019-02-02 11:05:20 +01:00
|
|
|
pub use hack::to_vec;
|
2015-03-13 19:44:02 -05:00
|
|
|
|
2015-03-18 09:36:18 -07:00
|
|
|
// HACK(japaric): With cfg(test) `impl [T]` is not available, these three
|
|
|
|
|
// functions are actually methods that are in `impl [T]` but not in
|
|
|
|
|
// `core::slice::SliceExt` - we need to supply these functions for the
|
|
|
|
|
// `test_permutations` test
|
2022-02-16 19:23:37 +08:00
|
|
|
pub(crate) mod hack {
|
2020-12-04 14:47:15 +01:00
|
|
|
use core::alloc::Allocator;
|
2020-11-18 17:23:41 +01:00
|
|
|
|
2019-02-03 08:27:44 +01:00
|
|
|
use crate::boxed::Box;
|
2019-11-29 19:30:49 -08:00
|
|
|
use crate::vec::Vec;
|
2019-02-02 08:36:45 +01:00
|
|
|
|
2020-04-19 01:03:43 +09:00
|
|
|
// We shouldn't add inline attribute to this since this is used in
|
|
|
|
|
// `vec!` macro mostly and causes perf regression. See #71204 for
|
|
|
|
|
// discussion and perf results.
|
2024-09-06 13:48:17 +02:00
|
|
|
#[allow(missing_docs)]
|
2020-12-04 14:47:15 +01:00
|
|
|
pub fn into_vec<T, A: Allocator>(b: Box<[T], A>) -> Vec<T, A> {
|
2015-03-13 19:44:02 -05:00
|
|
|
unsafe {
|
2019-05-27 22:40:13 +02:00
|
|
|
let len = b.len();
|
2020-12-04 14:47:15 +01:00
|
|
|
let (b, alloc) = Box::into_raw_with_allocator(b);
|
2020-11-18 17:23:41 +01:00
|
|
|
Vec::from_raw_parts_in(b as *mut T, len, len, alloc)
|
2015-03-13 19:44:02 -05:00
|
|
|
}
|
2015-03-11 19:44:02 -05: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-16 20:18:04 -04:00
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2024-09-06 13:48:17 +02:00
|
|
|
#[allow(missing_docs)]
|
2015-03-13 19:44:02 -05:00
|
|
|
#[inline]
|
2020-12-04 14:47:15 +01:00
|
|
|
pub fn to_vec<T: ConvertVec, A: Allocator>(s: &[T], alloc: A) -> Vec<T, A> {
|
2020-11-18 22:59:47 +00:00
|
|
|
T::to_vec(s, alloc)
|
|
|
|
|
}
|
|
|
|
|
|
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-16 20:18:04 -04:00
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2020-11-18 22:59:47 +00:00
|
|
|
pub trait ConvertVec {
|
2020-12-04 14:47:15 +01:00
|
|
|
fn to_vec<A: Allocator>(s: &[Self], alloc: A) -> Vec<Self, A>
|
2020-11-18 22:59:47 +00:00
|
|
|
where
|
|
|
|
|
Self: Sized;
|
|
|
|
|
}
|
|
|
|
|
|
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-16 20:18:04 -04:00
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2020-11-18 22:59:47 +00:00
|
|
|
impl<T: Clone> ConvertVec for T {
|
|
|
|
|
#[inline]
|
2020-12-04 14:47:15 +01:00
|
|
|
default fn to_vec<A: Allocator>(s: &[Self], alloc: A) -> Vec<Self, A> {
|
|
|
|
|
struct DropGuard<'a, T, A: Allocator> {
|
2020-11-18 22:59:47 +00:00
|
|
|
vec: &'a mut Vec<T, A>,
|
|
|
|
|
num_init: usize,
|
|
|
|
|
}
|
2020-12-04 14:47:15 +01:00
|
|
|
impl<'a, T, A: Allocator> Drop for DropGuard<'a, T, A> {
|
2020-11-18 22:59:47 +00:00
|
|
|
#[inline]
|
|
|
|
|
fn drop(&mut self) {
|
|
|
|
|
// SAFETY:
|
|
|
|
|
// items were marked initialized in the loop below
|
|
|
|
|
unsafe {
|
|
|
|
|
self.vec.set_len(self.num_init);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
let mut vec = Vec::with_capacity_in(s.len(), alloc);
|
|
|
|
|
let mut guard = DropGuard { vec: &mut vec, num_init: 0 };
|
|
|
|
|
let slots = guard.vec.spare_capacity_mut();
|
|
|
|
|
// .take(slots.len()) is necessary for LLVM to remove bounds checks
|
|
|
|
|
// and has better codegen than zip.
|
|
|
|
|
for (i, b) in s.iter().enumerate().take(slots.len()) {
|
|
|
|
|
guard.num_init = i;
|
|
|
|
|
slots[i].write(b.clone());
|
|
|
|
|
}
|
|
|
|
|
core::mem::forget(guard);
|
|
|
|
|
// SAFETY:
|
|
|
|
|
// the vec was allocated and initialized above to at least this length.
|
|
|
|
|
unsafe {
|
|
|
|
|
vec.set_len(s.len());
|
|
|
|
|
}
|
|
|
|
|
vec
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
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-16 20:18:04 -04:00
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2020-11-18 22:59:47 +00:00
|
|
|
impl<T: Copy> ConvertVec for T {
|
|
|
|
|
#[inline]
|
2020-12-04 14:47:15 +01:00
|
|
|
fn to_vec<A: Allocator>(s: &[Self], alloc: A) -> Vec<Self, A> {
|
2020-11-18 22:59:47 +00:00
|
|
|
let mut v = Vec::with_capacity_in(s.len(), alloc);
|
|
|
|
|
// SAFETY:
|
|
|
|
|
// allocated above with the capacity of `s`, and initialize to `s.len()` in
|
|
|
|
|
// ptr::copy_to_non_overlapping below.
|
|
|
|
|
unsafe {
|
|
|
|
|
s.as_ptr().copy_to_nonoverlapping(v.as_mut_ptr(), s.len());
|
|
|
|
|
v.set_len(s.len());
|
|
|
|
|
}
|
|
|
|
|
v
|
|
|
|
|
}
|
2015-03-13 19:44:02 -05:00
|
|
|
}
|
2015-03-11 19:44:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(not(test))]
|
2015-03-10 23:13:29 -05:00
|
|
|
impl<T> [T] {
|
2024-04-16 20:24:21 +02:00
|
|
|
/// Sorts the slice, preserving initial order of equal elements.
|
2015-05-20 00:43:46 +02:00
|
|
|
///
|
2024-04-16 20:24:21 +02:00
|
|
|
/// This sort is stable (i.e., does not reorder equal elements) and *O*(*n* \* log(*n*))
|
|
|
|
|
/// worst-case.
|
|
|
|
|
///
|
2024-09-15 16:26:46 -06:00
|
|
|
/// If the implementation of [`Ord`] for `T` does not implement a [total order], the function
|
|
|
|
|
/// may panic; even if the function exits normally, the resulting order of elements in the slice
|
|
|
|
|
/// is unspecified. See also the note on panicking below.
|
2017-01-10 10:23:21 -05:00
|
|
|
///
|
2017-07-02 02:09:21 +02:00
|
|
|
/// When applicable, unstable sorting is preferred because it is generally faster than stable
|
2024-04-16 20:24:21 +02:00
|
|
|
/// sorting and it doesn't allocate auxiliary memory. See
|
|
|
|
|
/// [`sort_unstable`](slice::sort_unstable). The exception are partially sorted slices, which
|
|
|
|
|
/// may be better served with `slice::sort`.
|
2017-07-02 02:09:21 +02:00
|
|
|
///
|
2024-08-03 15:10:27 +02:00
|
|
|
/// Sorting types that only implement [`PartialOrd`] such as [`f32`] and [`f64`] require
|
|
|
|
|
/// additional precautions. For example, `f32::NAN != f32::NAN`, which doesn't fulfill the
|
|
|
|
|
/// reflexivity requirement of [`Ord`]. By using an alternative comparison function with
|
2024-08-09 15:05:37 +02:00
|
|
|
/// `slice::sort_by` such as [`f32::total_cmp`] or [`f64::total_cmp`] that defines a [total
|
2024-08-03 15:10:27 +02:00
|
|
|
/// order] users can sort slices containing floating-point values. Alternatively, if all values
|
|
|
|
|
/// in the slice are guaranteed to be in a subset for which [`PartialOrd::partial_cmp`] forms a
|
|
|
|
|
/// [total order], it's possible to sort the slice with `sort_by(|a, b|
|
|
|
|
|
/// a.partial_cmp(b).unwrap())`.
|
2024-07-31 11:28:11 +02:00
|
|
|
///
|
2017-01-14 01:46:30 +01:00
|
|
|
/// # Current implementation
|
2017-01-20 09:11:11 +01:00
|
|
|
///
|
2024-04-16 20:24:21 +02:00
|
|
|
/// The current implementation is based on [driftsort] by Orson Peters and Lukas Bergdoll, which
|
|
|
|
|
/// combines the fast average case of quicksort with the fast worst case and partial run
|
|
|
|
|
/// detection of mergesort, achieving linear time on fully sorted and reversed inputs. On inputs
|
2024-06-20 18:07:04 +02:00
|
|
|
/// with k distinct elements, the expected time to sort the data is *O*(*n* \* log(*k*)).
|
2024-04-16 20:24:21 +02:00
|
|
|
///
|
|
|
|
|
/// The auxiliary memory allocation behavior depends on the input length. Short slices are
|
|
|
|
|
/// handled without allocation, medium sized slices allocate `self.len()` and beyond that it
|
|
|
|
|
/// clamps at `self.len() / 2`.
|
2017-01-14 01:46:30 +01:00
|
|
|
///
|
2024-07-27 16:48:42 +02:00
|
|
|
/// # Panics
|
|
|
|
|
///
|
2024-09-15 16:26:46 -06:00
|
|
|
/// May panic if the implementation of [`Ord`] for `T` does not implement a [total order], or if
|
|
|
|
|
/// the [`Ord`] implementation itself panics.
|
|
|
|
|
///
|
|
|
|
|
/// All safe functions on slices preserve the invariant that even if the function panics, all
|
|
|
|
|
/// original elements will remain in the slice and any possible modifications via interior
|
|
|
|
|
/// mutability are observed in the input. This ensures that recovery code (for instance inside
|
|
|
|
|
/// of a `Drop` or following a `catch_unwind`) will still have access to all the original
|
|
|
|
|
/// elements. For instance, if the slice belongs to a `Vec`, the `Vec::drop` method will be able
|
|
|
|
|
/// to dispose of all contained elements.
|
2015-11-04 12:44:31 +01:00
|
|
|
///
|
2015-05-20 00:43:46 +02:00
|
|
|
/// # Examples
|
2015-03-10 23:13:29 -05:00
|
|
|
///
|
2016-09-21 17:07:45 +02:00
|
|
|
/// ```
|
2024-07-31 11:28:11 +02:00
|
|
|
/// let mut v = [4, -5, 1, -3, 2];
|
2015-05-20 00:43:46 +02:00
|
|
|
///
|
|
|
|
|
/// v.sort();
|
2024-07-31 11:28:11 +02:00
|
|
|
/// assert_eq!(v, [-5, -3, 1, 2, 4]);
|
2015-03-10 23:13:29 -05:00
|
|
|
/// ```
|
2024-04-16 20:24:21 +02:00
|
|
|
///
|
|
|
|
|
/// [driftsort]: https://github.com/Voultapher/driftsort
|
2024-07-31 11:28:11 +02:00
|
|
|
/// [total order]: https://en.wikipedia.org/wiki/Total_order
|
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-16 20:18:04 -04:00
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2022-04-05 22:42:23 +02:00
|
|
|
#[rustc_allow_incoherent_impl]
|
2015-03-10 23:13:29 -05:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
|
#[inline]
|
2015-11-24 11:23:48 +13:00
|
|
|
pub fn sort(&mut self)
|
2019-11-29 19:30:49 -08:00
|
|
|
where
|
|
|
|
|
T: Ord,
|
2015-11-24 11:23:48 +13:00
|
|
|
{
|
2022-11-20 20:35:40 +01:00
|
|
|
stable_sort(self, T::lt);
|
2015-03-10 23:13:29 -05:00
|
|
|
}
|
|
|
|
|
|
2024-07-31 11:28:11 +02:00
|
|
|
/// Sorts the slice with a comparison function, preserving initial order of equal elements.
|
2024-04-16 20:24:21 +02:00
|
|
|
///
|
|
|
|
|
/// This sort is stable (i.e., does not reorder equal elements) and *O*(*n* \* log(*n*))
|
|
|
|
|
/// worst-case.
|
2017-03-17 15:05:44 +01:00
|
|
|
///
|
2024-09-15 16:26:46 -06:00
|
|
|
/// If the comparison function `compare` does not implement a [total order], the function may
|
|
|
|
|
/// panic; even if the function exits normally, the resulting order of elements in the slice is
|
|
|
|
|
/// unspecified. See also the note on panicking below.
|
2018-09-02 22:26:38 -07:00
|
|
|
///
|
2024-07-31 11:28:11 +02:00
|
|
|
/// For example `|a, b| (a - b).cmp(a)` is a comparison function that is neither transitive nor
|
|
|
|
|
/// reflexive nor total, `a < b < c < a` with `a = 1, b = 2, c = 3`. For more information and
|
|
|
|
|
/// examples see the [`Ord`] documentation.
|
2018-09-09 22:07:17 -07:00
|
|
|
///
|
2017-03-17 15:05:44 +01:00
|
|
|
/// # Current implementation
|
|
|
|
|
///
|
2024-04-16 20:24:21 +02:00
|
|
|
/// The current implementation is based on [driftsort] by Orson Peters and Lukas Bergdoll, which
|
|
|
|
|
/// combines the fast average case of quicksort with the fast worst case and partial run
|
|
|
|
|
/// detection of mergesort, achieving linear time on fully sorted and reversed inputs. On inputs
|
2024-06-20 18:07:04 +02:00
|
|
|
/// with k distinct elements, the expected time to sort the data is *O*(*n* \* log(*k*)).
|
2024-04-16 20:24:21 +02:00
|
|
|
///
|
|
|
|
|
/// The auxiliary memory allocation behavior depends on the input length. Short slices are
|
|
|
|
|
/// handled without allocation, medium sized slices allocate `self.len()` and beyond that it
|
|
|
|
|
/// clamps at `self.len() / 2`.
|
2017-03-17 15:05:44 +01:00
|
|
|
///
|
2024-07-27 16:48:42 +02:00
|
|
|
/// # Panics
|
|
|
|
|
///
|
2024-09-15 16:26:46 -06:00
|
|
|
/// May panic if `compare` does not implement a [total order], or if `compare` itself panics.
|
|
|
|
|
///
|
|
|
|
|
/// All safe functions on slices preserve the invariant that even if the function panics, all
|
|
|
|
|
/// original elements will remain in the slice and any possible modifications via interior
|
|
|
|
|
/// mutability are observed in the input. This ensures that recovery code (for instance inside
|
|
|
|
|
/// of a `Drop` or following a `catch_unwind`) will still have access to all the original
|
|
|
|
|
/// elements. For instance, if the slice belongs to a `Vec`, the `Vec::drop` method will be able
|
|
|
|
|
/// to dispose of all contained elements.
|
2017-03-17 15:05:44 +01:00
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
2024-07-31 11:28:11 +02:00
|
|
|
/// let mut v = [4, -5, 1, -3, 2];
|
2017-03-17 15:05:44 +01:00
|
|
|
/// v.sort_by(|a, b| a.cmp(b));
|
2024-07-31 11:28:11 +02:00
|
|
|
/// assert_eq!(v, [-5, -3, 1, 2, 4]);
|
2017-03-17 15:05:44 +01:00
|
|
|
///
|
|
|
|
|
/// // reverse sorting
|
|
|
|
|
/// v.sort_by(|a, b| b.cmp(a));
|
2024-07-31 11:28:11 +02:00
|
|
|
/// assert_eq!(v, [4, 2, 1, -3, -5]);
|
2017-03-17 15:05:44 +01:00
|
|
|
/// ```
|
2024-04-16 20:24:21 +02:00
|
|
|
///
|
|
|
|
|
/// [driftsort]: https://github.com/Voultapher/driftsort
|
2024-07-31 11:28:11 +02:00
|
|
|
/// [total order]: https://en.wikipedia.org/wiki/Total_order
|
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-16 20:18:04 -04:00
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2022-04-05 22:42:23 +02:00
|
|
|
#[rustc_allow_incoherent_impl]
|
2017-03-17 15:05:44 +01:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn sort_by<F>(&mut self, mut compare: F)
|
2019-11-29 19:30:49 -08:00
|
|
|
where
|
|
|
|
|
F: FnMut(&T, &T) -> Ordering,
|
2017-03-17 15:05:44 +01:00
|
|
|
{
|
2022-11-20 20:35:40 +01:00
|
|
|
stable_sort(self, |a, b| compare(a, b) == Less);
|
2017-03-17 15:05:44 +01:00
|
|
|
}
|
|
|
|
|
|
2024-04-16 20:24:21 +02:00
|
|
|
/// Sorts the slice with a key extraction function, preserving initial order of equal elements.
|
2018-03-16 14:37:17 +00:00
|
|
|
///
|
2020-10-14 16:50:00 +11:00
|
|
|
/// This sort is stable (i.e., does not reorder equal elements) and *O*(*m* \* *n* \* log(*n*))
|
|
|
|
|
/// worst-case, where the key function is *O*(*m*).
|
2018-03-16 14:37:17 +00:00
|
|
|
///
|
2024-09-15 16:26:46 -06:00
|
|
|
/// If the implementation of [`Ord`] for `K` does not implement a [total order], the function
|
|
|
|
|
/// may panic; even if the function exits normally, the resulting order of elements in the slice
|
|
|
|
|
/// is unspecified. See also the note on panicking below.
|
2018-03-16 14:37:17 +00:00
|
|
|
///
|
|
|
|
|
/// # Current implementation
|
|
|
|
|
///
|
2024-04-16 20:24:21 +02:00
|
|
|
/// The current implementation is based on [driftsort] by Orson Peters and Lukas Bergdoll, which
|
|
|
|
|
/// combines the fast average case of quicksort with the fast worst case and partial run
|
|
|
|
|
/// detection of mergesort, achieving linear time on fully sorted and reversed inputs. On inputs
|
2024-06-20 18:07:04 +02:00
|
|
|
/// with k distinct elements, the expected time to sort the data is *O*(*n* \* log(*k*)).
|
2024-04-16 20:24:21 +02:00
|
|
|
///
|
|
|
|
|
/// The auxiliary memory allocation behavior depends on the input length. Short slices are
|
|
|
|
|
/// handled without allocation, medium sized slices allocate `self.len()` and beyond that it
|
|
|
|
|
/// clamps at `self.len() / 2`.
|
2018-03-16 14:37:17 +00:00
|
|
|
///
|
2024-07-27 16:48:42 +02:00
|
|
|
/// # Panics
|
|
|
|
|
///
|
2024-09-15 16:26:46 -06:00
|
|
|
/// May panic if the implementation of [`Ord`] for `K` does not implement a [total order], or if
|
|
|
|
|
/// the [`Ord`] implementation or the key-function `f` panics.
|
|
|
|
|
///
|
|
|
|
|
/// All safe functions on slices preserve the invariant that even if the function panics, all
|
|
|
|
|
/// original elements will remain in the slice and any possible modifications via interior
|
|
|
|
|
/// mutability are observed in the input. This ensures that recovery code (for instance inside
|
|
|
|
|
/// of a `Drop` or following a `catch_unwind`) will still have access to all the original
|
|
|
|
|
/// elements. For instance, if the slice belongs to a `Vec`, the `Vec::drop` method will be able
|
|
|
|
|
/// to dispose of all contained elements.
|
2018-03-16 14:37:17 +00:00
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
2024-07-31 11:28:11 +02:00
|
|
|
/// let mut v = [4i32, -5, 1, -3, 2];
|
2018-03-16 14:37:17 +00:00
|
|
|
///
|
|
|
|
|
/// v.sort_by_key(|k| k.abs());
|
2024-07-31 11:28:11 +02:00
|
|
|
/// assert_eq!(v, [1, 2, -3, 4, -5]);
|
2018-03-16 14:37:17 +00:00
|
|
|
/// ```
|
2024-04-16 20:24:21 +02:00
|
|
|
///
|
|
|
|
|
/// [driftsort]: https://github.com/Voultapher/driftsort
|
2024-07-31 11:28:11 +02:00
|
|
|
/// [total order]: https://en.wikipedia.org/wiki/Total_order
|
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-16 20:18:04 -04:00
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2022-04-05 22:42:23 +02:00
|
|
|
#[rustc_allow_incoherent_impl]
|
2018-03-16 14:37:17 +00:00
|
|
|
#[stable(feature = "slice_sort_by_key", since = "1.7.0")]
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn sort_by_key<K, F>(&mut self, mut f: F)
|
2019-11-29 19:30:49 -08:00
|
|
|
where
|
|
|
|
|
F: FnMut(&T) -> K,
|
|
|
|
|
K: Ord,
|
2018-03-16 14:37:17 +00:00
|
|
|
{
|
2022-11-20 20:35:40 +01:00
|
|
|
stable_sort(self, |a, b| f(a).lt(&f(b)));
|
2018-03-16 14:37:17 +00:00
|
|
|
}
|
|
|
|
|
|
2024-04-16 20:24:21 +02:00
|
|
|
/// Sorts the slice with a key extraction function, preserving initial order of equal elements.
|
2017-01-14 01:46:30 +01:00
|
|
|
///
|
2024-04-16 20:24:21 +02:00
|
|
|
/// This sort is stable (i.e., does not reorder equal elements) and *O*(*m* \* *n* + *n* \*
|
|
|
|
|
/// log(*n*)) worst-case, where the key function is *O*(*m*).
|
2018-03-01 12:22:11 +00:00
|
|
|
///
|
2024-04-16 20:24:21 +02:00
|
|
|
/// During sorting, the key function is called at most once per element, by using temporary
|
|
|
|
|
/// storage to remember the results of key evaluation. The order of calls to the key function is
|
|
|
|
|
/// unspecified and may change in future versions of the standard library.
|
|
|
|
|
///
|
2024-09-15 16:26:46 -06:00
|
|
|
/// If the implementation of [`Ord`] for `K` does not implement a [total order], the function
|
|
|
|
|
/// may panic; even if the function exits normally, the resulting order of elements in the slice
|
|
|
|
|
/// is unspecified. See also the note on panicking below.
|
2017-07-02 02:09:21 +02:00
|
|
|
///
|
2024-04-16 20:24:21 +02:00
|
|
|
/// For simple key functions (e.g., functions that are property accesses or basic operations),
|
|
|
|
|
/// [`sort_by_key`](slice::sort_by_key) is likely to be faster.
|
2018-03-16 14:37:17 +00:00
|
|
|
///
|
2017-01-14 01:46:30 +01:00
|
|
|
/// # Current implementation
|
|
|
|
|
///
|
2024-04-16 20:24:21 +02:00
|
|
|
/// The current implementation is based on [instruction-parallel-network sort][ipnsort] by Lukas
|
|
|
|
|
/// Bergdoll, which combines the fast average case of randomized quicksort with the fast worst
|
|
|
|
|
/// case of heapsort, while achieving linear time on fully sorted and reversed inputs. And
|
|
|
|
|
/// *O*(*k* \* log(*n*)) where *k* is the number of distinct elements in the input. It leverages
|
|
|
|
|
/// superscalar out-of-order execution capabilities commonly found in CPUs, to efficiently
|
|
|
|
|
/// perform the operation.
|
2015-12-02 17:31:49 -08:00
|
|
|
///
|
2018-03-17 20:18:08 +00:00
|
|
|
/// In the worst case, the algorithm allocates temporary storage in a `Vec<(K, usize)>` the
|
|
|
|
|
/// length of the slice.
|
2015-12-02 17:31:49 -08:00
|
|
|
///
|
2024-07-27 16:48:42 +02:00
|
|
|
/// # Panics
|
|
|
|
|
///
|
2024-09-15 16:26:46 -06:00
|
|
|
/// May panic if the implementation of [`Ord`] for `K` does not implement a [total order], or if
|
|
|
|
|
/// the [`Ord`] implementation panics.
|
|
|
|
|
///
|
|
|
|
|
/// All safe functions on slices preserve the invariant that even if the function panics, all
|
|
|
|
|
/// original elements will remain in the slice and any possible modifications via interior
|
|
|
|
|
/// mutability are observed in the input. This ensures that recovery code (for instance inside
|
|
|
|
|
/// of a `Drop` or following a `catch_unwind`) will still have access to all the original
|
|
|
|
|
/// elements. For instance, if the slice belongs to a `Vec`, the `Vec::drop` method will be able
|
|
|
|
|
/// to dispose of all contained elements.
|
2024-07-27 16:48:42 +02:00
|
|
|
///
|
2015-12-02 17:31:49 -08:00
|
|
|
/// # Examples
|
|
|
|
|
///
|
2016-09-21 17:07:45 +02:00
|
|
|
/// ```
|
2024-07-31 11:28:11 +02:00
|
|
|
/// let mut v = [4i32, -5, 1, -3, 2, 10];
|
2015-12-02 17:31:49 -08:00
|
|
|
///
|
2024-07-31 11:28:11 +02:00
|
|
|
/// // Strings are sorted by lexicographical order.
|
2018-03-17 20:18:08 +00:00
|
|
|
/// v.sort_by_cached_key(|k| k.to_string());
|
2024-07-31 11:28:11 +02:00
|
|
|
/// assert_eq!(v, [-3, -5, 1, 10, 2, 4]);
|
2015-12-02 17:31:49 -08:00
|
|
|
/// ```
|
2018-03-17 20:18:08 +00:00
|
|
|
///
|
2024-04-16 20:24:21 +02:00
|
|
|
/// [ipnsort]: https://github.com/Voultapher/sort-research-rs/tree/main/ipnsort
|
2024-07-31 11:28:11 +02:00
|
|
|
/// [total order]: https://en.wikipedia.org/wiki/Total_order
|
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-16 20:18:04 -04:00
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2022-04-05 22:42:23 +02:00
|
|
|
#[rustc_allow_incoherent_impl]
|
2019-01-31 12:47:31 -08:00
|
|
|
#[stable(feature = "slice_sort_by_cached_key", since = "1.34.0")]
|
2015-12-02 17:31:49 -08:00
|
|
|
#[inline]
|
2018-03-16 14:37:17 +00:00
|
|
|
pub fn sort_by_cached_key<K, F>(&mut self, f: F)
|
2019-11-29 19:30:49 -08:00
|
|
|
where
|
|
|
|
|
F: FnMut(&T) -> K,
|
|
|
|
|
K: Ord,
|
2015-12-02 17:31:49 -08:00
|
|
|
{
|
2018-03-02 16:28:55 +00:00
|
|
|
// Helper macro for indexing our vector by the smallest possible type, to reduce allocation.
|
|
|
|
|
macro_rules! sort_by_key {
|
2019-11-29 19:30:49 -08:00
|
|
|
($t:ty, $slice:ident, $f:ident) => {{
|
2018-03-02 16:28:55 +00:00
|
|
|
let mut indices: Vec<_> =
|
|
|
|
|
$slice.iter().map($f).enumerate().map(|(i, k)| (k, i as $t)).collect();
|
|
|
|
|
// The elements of `indices` are unique, as they are indexed, so any sort will be
|
2018-03-18 11:11:17 +00:00
|
|
|
// stable with respect to the original slice. We use `sort_unstable` here because
|
2024-04-16 20:24:21 +02:00
|
|
|
// it requires no memory allocation.
|
2018-03-02 16:28:55 +00:00
|
|
|
indices.sort_unstable();
|
|
|
|
|
for i in 0..$slice.len() {
|
|
|
|
|
let mut index = indices[i].1;
|
|
|
|
|
while (index as usize) < i {
|
|
|
|
|
index = indices[index as usize].1;
|
|
|
|
|
}
|
|
|
|
|
indices[i].1 = index;
|
|
|
|
|
$slice.swap(i, index as usize);
|
|
|
|
|
}
|
2019-11-29 19:30:49 -08:00
|
|
|
}};
|
2018-03-01 10:46:06 +00:00
|
|
|
}
|
2018-03-02 16:28:55 +00:00
|
|
|
|
|
|
|
|
let len = self.len();
|
2019-11-29 19:30:49 -08:00
|
|
|
if len < 2 {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2024-04-16 20:24:21 +02:00
|
|
|
|
|
|
|
|
// Avoids binary-size usage in cases where the alignment doesn't work out to make this
|
|
|
|
|
// beneficial or on 32-bit platforms.
|
|
|
|
|
let is_using_u32_as_idx_type_helpful =
|
|
|
|
|
const { mem::size_of::<(K, u32)>() < mem::size_of::<(K, usize)>() };
|
|
|
|
|
|
|
|
|
|
// It's possible to instantiate this for u8 and u16 but, doing so is very wasteful in terms
|
|
|
|
|
// of compile-times and binary-size, the peak saved heap memory for u16 is (u8 + u16) -> 4
|
|
|
|
|
// bytes * u16::MAX vs (u8 + u32) -> 8 bytes * u16::MAX, the saved heap memory is at peak
|
|
|
|
|
// ~262KB.
|
|
|
|
|
if is_using_u32_as_idx_type_helpful && len <= (u32::MAX as usize) {
|
2019-11-29 19:30:49 -08:00
|
|
|
return sort_by_key!(u32, self, f);
|
|
|
|
|
}
|
2024-04-16 20:24:21 +02:00
|
|
|
|
2018-03-02 16:28:55 +00:00
|
|
|
sort_by_key!(usize, self, f)
|
2015-12-02 17:31:49 -08:00
|
|
|
}
|
|
|
|
|
|
2015-05-20 00:43:46 +02:00
|
|
|
/// Copies `self` into a new `Vec`.
|
2016-07-08 17:21:16 +02:00
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let s = [10, 40, 30];
|
|
|
|
|
/// let x = s.to_vec();
|
|
|
|
|
/// // Here, `s` and `x` can be modified independently.
|
|
|
|
|
/// ```
|
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-16 20:18:04 -04:00
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2022-04-05 22:42:23 +02:00
|
|
|
#[rustc_allow_incoherent_impl]
|
type error method suggestions use whitelisted identity-like conversions
Previously, on a type mismatch (and if this wasn't preëmpted by a
higher-priority suggestion), we would look for argumentless methods
returning the expected type, and list them in a `help` note.
This had two major shortcomings. Firstly, a lot of the suggestions didn't
really make sense (if you used a &str where a String was expected,
`.to_ascii_uppercase()` is probably not the solution you were hoping
for). Secondly, we weren't generating suggestions from the most useful
traits!
We address the first problem with an internal
`#[rustc_conversion_suggestion]` attribute meant to mark methods that keep
the "same value" in the relevant sense, just converting the type. We
address the second problem by making `FnCtxt.probe_for_return_type` pass
the `ProbeScope::AllTraits` to `probe_op`: this would seem to be safe
because grep reveals no other callers of `probe_for_return_type`.
Also, structured suggestions are preferred (because they're pretty, but
also for RLS and friends).
Also also, we make the E0055 autoderef recursion limit error use the
one-time-diagnostics set, because we can potentially hit the limit a lot
during probing. (Without this,
test/ui/did_you_mean/recursion_limit_deref.rs would report "aborting due to
51 errors").
Unfortunately, the trait probing is still not all one would hope for: at a
minimum, we don't know how to rule out `into()` in cases where it wouldn't
actually work, and we don't know how to rule in `.to_owned()` where it
would. Issues #46459 and #46460 have been filed and are ref'd in a FIXME.
This is hoped to resolve #42929, #44672, and #45777.
2017-11-19 11:25:35 -08:00
|
|
|
#[rustc_conversion_suggestion]
|
2015-03-10 23:13:29 -05:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2015-05-20 00:43:46 +02:00
|
|
|
#[inline]
|
2015-11-24 11:23:48 +13:00
|
|
|
pub fn to_vec(&self) -> Vec<T>
|
2020-11-18 17:23:41 +01:00
|
|
|
where
|
|
|
|
|
T: Clone,
|
|
|
|
|
{
|
|
|
|
|
self.to_vec_in(Global)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Copies `self` into a new `Vec` with an allocator.
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// #![feature(allocator_api)]
|
|
|
|
|
///
|
|
|
|
|
/// use std::alloc::System;
|
|
|
|
|
///
|
|
|
|
|
/// let s = [10, 40, 30];
|
|
|
|
|
/// let x = s.to_vec_in(System);
|
|
|
|
|
/// // Here, `s` and `x` can be modified independently.
|
|
|
|
|
/// ```
|
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-16 20:18:04 -04:00
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2022-04-05 22:42:23 +02:00
|
|
|
#[rustc_allow_incoherent_impl]
|
2020-11-18 17:23:41 +01:00
|
|
|
#[inline]
|
|
|
|
|
#[unstable(feature = "allocator_api", issue = "32838")]
|
2020-12-04 14:47:15 +01:00
|
|
|
pub fn to_vec_in<A: Allocator>(&self, alloc: A) -> Vec<T, A>
|
2019-11-29 19:30:49 -08:00
|
|
|
where
|
|
|
|
|
T: Clone,
|
2015-11-24 11:23:48 +13:00
|
|
|
{
|
2019-03-26 17:34:32 +00:00
|
|
|
// N.B., see the `hack` module in this file for more details.
|
2020-11-18 17:23:41 +01:00
|
|
|
hack::to_vec(self, alloc)
|
2015-03-10 23:13:29 -05:00
|
|
|
}
|
|
|
|
|
|
2015-04-13 10:21:32 -04:00
|
|
|
/// Converts `self` into a vector without clones or allocation.
|
2016-07-08 17:21:16 +02:00
|
|
|
///
|
2017-05-22 05:23:47 -07:00
|
|
|
/// The resulting vector can be converted back into a box via
|
2017-05-22 16:39:31 -07:00
|
|
|
/// `Vec<T>`'s `into_boxed_slice` method.
|
2017-05-22 05:23:47 -07:00
|
|
|
///
|
2016-07-08 17:21:16 +02:00
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let s: Box<[i32]> = Box::new([10, 40, 30]);
|
|
|
|
|
/// let x = s.into_vec();
|
|
|
|
|
/// // `s` cannot be used anymore because it has been converted into `x`.
|
|
|
|
|
///
|
2016-10-29 22:54:04 +01:00
|
|
|
/// assert_eq!(x, vec![10, 40, 30]);
|
2016-07-08 17:21:16 +02:00
|
|
|
/// ```
|
2022-04-05 22:42:23 +02:00
|
|
|
#[rustc_allow_incoherent_impl]
|
2015-03-10 23:13:29 -05:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2015-03-13 19:44:02 -05:00
|
|
|
#[inline]
|
2024-09-18 21:42:38 +01:00
|
|
|
#[cfg_attr(not(test), rustc_diagnostic_item = "slice_into_vec")]
|
2020-12-04 14:47:15 +01:00
|
|
|
pub fn into_vec<A: Allocator>(self: Box<Self, A>) -> Vec<T, A> {
|
2019-03-26 17:34:32 +00:00
|
|
|
// N.B., see the `hack` module in this file for more details.
|
2015-03-13 19:44:02 -05:00
|
|
|
hack::into_vec(self)
|
2015-03-10 23:13:29 -05:00
|
|
|
}
|
2018-03-13 22:29:59 +01:00
|
|
|
|
2022-11-07 17:11:41 +01:00
|
|
|
/// Creates a vector by copying a slice `n` times.
|
2018-03-13 22:29:59 +01:00
|
|
|
///
|
2018-09-20 09:31:14 -07:00
|
|
|
/// # Panics
|
|
|
|
|
///
|
|
|
|
|
/// This function will panic if the capacity would overflow.
|
|
|
|
|
///
|
2018-03-13 22:29:59 +01:00
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// Basic usage:
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
2019-10-01 11:55:46 +00:00
|
|
|
/// assert_eq!([1, 2].repeat(3), vec![1, 2, 1, 2, 1, 2]);
|
2018-03-13 22:29:59 +01:00
|
|
|
/// ```
|
2018-09-20 09:31:14 -07:00
|
|
|
///
|
|
|
|
|
/// A panic upon overflow:
|
|
|
|
|
///
|
|
|
|
|
/// ```should_panic
|
2019-10-01 11:55:46 +00:00
|
|
|
/// // this will panic at runtime
|
2020-03-27 22:15:02 +01:00
|
|
|
/// b"0123456789abcdef".repeat(usize::MAX);
|
2018-09-20 09:31:14 -07:00
|
|
|
/// ```
|
2022-04-05 22:42:23 +02:00
|
|
|
#[rustc_allow_incoherent_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-16 20:18:04 -04:00
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2019-09-28 16:39:07 +00:00
|
|
|
#[stable(feature = "repeat_generic_slice", since = "1.40.0")]
|
2019-11-29 19:30:49 -08:00
|
|
|
pub fn repeat(&self, n: usize) -> Vec<T>
|
|
|
|
|
where
|
|
|
|
|
T: Copy,
|
|
|
|
|
{
|
2018-03-13 22:29:59 +01:00
|
|
|
if n == 0 {
|
|
|
|
|
return Vec::new();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If `n` is larger than zero, it can be split as
|
|
|
|
|
// `n = 2^expn + rem (2^expn > rem, expn >= 0, rem >= 0)`.
|
|
|
|
|
// `2^expn` is the number represented by the leftmost '1' bit of `n`,
|
|
|
|
|
// and `rem` is the remaining part of `n`.
|
|
|
|
|
|
|
|
|
|
// Using `Vec` to access `set_len()`.
|
2019-12-24 11:59:57 +08:00
|
|
|
let capacity = self.len().checked_mul(n).expect("capacity overflow");
|
|
|
|
|
let mut buf = Vec::with_capacity(capacity);
|
2018-03-13 22:29:59 +01:00
|
|
|
|
|
|
|
|
// `2^expn` repetition is done by doubling `buf` `expn`-times.
|
|
|
|
|
buf.extend(self);
|
|
|
|
|
{
|
|
|
|
|
let mut m = n >> 1;
|
|
|
|
|
// If `m > 0`, there are remaining bits up to the leftmost '1'.
|
|
|
|
|
while m > 0 {
|
|
|
|
|
// `buf.extend(buf)`:
|
|
|
|
|
unsafe {
|
2024-03-25 23:19:40 +03:00
|
|
|
ptr::copy_nonoverlapping::<T>(
|
2018-03-13 22:29:59 +01:00
|
|
|
buf.as_ptr(),
|
2024-03-25 23:19:40 +03:00
|
|
|
(buf.as_mut_ptr()).add(buf.len()),
|
2018-03-13 22:29:59 +01:00
|
|
|
buf.len(),
|
|
|
|
|
);
|
|
|
|
|
// `buf` has capacity of `self.len() * n`.
|
|
|
|
|
let buf_len = buf.len();
|
|
|
|
|
buf.set_len(buf_len * 2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m >>= 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// `rem` (`= n - 2^expn`) repetition is done by copying
|
|
|
|
|
// first `rem` repetitions from `buf` itself.
|
2019-12-24 11:59:57 +08:00
|
|
|
let rem_len = capacity - buf.len(); // `self.len() * rem`
|
2018-03-13 22:29:59 +01:00
|
|
|
if rem_len > 0 {
|
|
|
|
|
// `buf.extend(buf[0 .. rem_len])`:
|
|
|
|
|
unsafe {
|
|
|
|
|
// This is non-overlapping since `2^expn > rem`.
|
2024-03-25 23:19:40 +03:00
|
|
|
ptr::copy_nonoverlapping::<T>(
|
2018-03-13 22:29:59 +01:00
|
|
|
buf.as_ptr(),
|
2024-03-25 23:19:40 +03:00
|
|
|
(buf.as_mut_ptr()).add(buf.len()),
|
2018-03-13 22:29:59 +01:00
|
|
|
rem_len,
|
|
|
|
|
);
|
|
|
|
|
// `buf.len() + rem_len` equals to `buf.capacity()` (`= self.len() * n`).
|
2019-12-24 11:59:57 +08:00
|
|
|
buf.set_len(capacity);
|
2018-03-13 22:29:59 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
buf
|
|
|
|
|
}
|
2019-07-05 11:38:40 +02:00
|
|
|
|
|
|
|
|
/// Flattens a slice of `T` into a single value `Self::Output`.
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// assert_eq!(["hello", "world"].concat(), "helloworld");
|
|
|
|
|
/// assert_eq!([[1, 2], [3, 4]].concat(), [1, 2, 3, 4]);
|
|
|
|
|
/// ```
|
2022-04-05 22:42:23 +02:00
|
|
|
#[rustc_allow_incoherent_impl]
|
2019-07-05 11:38:40 +02:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2019-07-08 17:47:49 +02:00
|
|
|
pub fn concat<Item: ?Sized>(&self) -> <Self as Concat<Item>>::Output
|
2019-11-29 19:30:49 -08:00
|
|
|
where
|
|
|
|
|
Self: Concat<Item>,
|
2019-07-05 11:38:40 +02:00
|
|
|
{
|
2019-07-08 17:47:49 +02:00
|
|
|
Concat::concat(self)
|
2019-07-05 11:38:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Flattens a slice of `T` into a single value `Self::Output`, placing a
|
|
|
|
|
/// given separator between each.
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// assert_eq!(["hello", "world"].join(" "), "hello world");
|
|
|
|
|
/// assert_eq!([[1, 2], [3, 4]].join(&0), [1, 2, 0, 3, 4]);
|
2019-07-08 18:08:54 +02:00
|
|
|
/// assert_eq!([[1, 2], [3, 4]].join(&[0, 0][..]), [1, 2, 0, 0, 3, 4]);
|
2019-07-05 11:38:40 +02:00
|
|
|
/// ```
|
2022-04-05 22:42:23 +02:00
|
|
|
#[rustc_allow_incoherent_impl]
|
2019-07-05 11:38:40 +02:00
|
|
|
#[stable(feature = "rename_connect_to_join", since = "1.3.0")]
|
2019-07-08 17:50:27 +02:00
|
|
|
pub fn join<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Output
|
2019-11-29 19:30:49 -08:00
|
|
|
where
|
|
|
|
|
Self: Join<Separator>,
|
2019-07-05 11:38:40 +02:00
|
|
|
{
|
2019-07-08 17:47:49 +02:00
|
|
|
Join::join(self, sep)
|
2019-07-05 11:38:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Flattens a slice of `T` into a single value `Self::Output`, placing a
|
|
|
|
|
/// given separator between each.
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// # #![allow(deprecated)]
|
|
|
|
|
/// assert_eq!(["hello", "world"].connect(" "), "hello world");
|
|
|
|
|
/// assert_eq!([[1, 2], [3, 4]].connect(&0), [1, 2, 0, 3, 4]);
|
|
|
|
|
/// ```
|
2022-04-05 22:42:23 +02:00
|
|
|
#[rustc_allow_incoherent_impl]
|
2019-07-05 11:38:40 +02:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2023-08-21 12:51:51 +03:00
|
|
|
#[deprecated(since = "1.3.0", note = "renamed to join", suggestion = "join")]
|
2019-07-08 17:50:27 +02:00
|
|
|
pub fn connect<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Output
|
2019-11-29 19:30:49 -08:00
|
|
|
where
|
|
|
|
|
Self: Join<Separator>,
|
2019-07-05 11:38:40 +02:00
|
|
|
{
|
2019-07-08 17:47:49 +02:00
|
|
|
Join::join(self, sep)
|
2019-07-05 11:38:40 +02:00
|
|
|
}
|
2015-03-10 23:13:29 -05:00
|
|
|
}
|
|
|
|
|
|
2017-11-29 12:14:03 -08:00
|
|
|
#[cfg(not(test))]
|
2017-10-01 21:13:49 +02:00
|
|
|
impl [u8] {
|
|
|
|
|
/// Returns a vector containing a copy of this slice where each byte
|
|
|
|
|
/// 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`].
|
|
|
|
|
///
|
2021-03-27 14:15:42 -04:00
|
|
|
/// [`make_ascii_uppercase`]: slice::make_ascii_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-16 20:18:04 -04:00
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2022-04-05 22:42:23 +02:00
|
|
|
#[rustc_allow_incoherent_impl]
|
2021-10-09 01:01:40 -04:00
|
|
|
#[must_use = "this returns the uppercase bytes as a new Vec, \
|
|
|
|
|
without modifying the original"]
|
2017-11-30 11:20:11 -08:00
|
|
|
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
|
2017-10-01 21:13:49 +02:00
|
|
|
#[inline]
|
|
|
|
|
pub fn to_ascii_uppercase(&self) -> Vec<u8> {
|
|
|
|
|
let mut me = self.to_vec();
|
|
|
|
|
me.make_ascii_uppercase();
|
|
|
|
|
me
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns a vector containing a copy of this slice where each byte
|
|
|
|
|
/// 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`].
|
|
|
|
|
///
|
2021-03-27 14:15:42 -04:00
|
|
|
/// [`make_ascii_lowercase`]: slice::make_ascii_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-16 20:18:04 -04:00
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2022-04-05 22:42:23 +02:00
|
|
|
#[rustc_allow_incoherent_impl]
|
2021-10-09 01:01:40 -04:00
|
|
|
#[must_use = "this returns the lowercase bytes as a new Vec, \
|
|
|
|
|
without modifying the original"]
|
2017-11-30 11:20:11 -08:00
|
|
|
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
|
2017-10-01 21:13:49 +02:00
|
|
|
#[inline]
|
|
|
|
|
pub fn to_ascii_lowercase(&self) -> Vec<u8> {
|
|
|
|
|
let mut me = self.to_vec();
|
|
|
|
|
me.make_ascii_lowercase();
|
|
|
|
|
me
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-05 19:08:37 -08:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-01-06 20:53:18 -05:00
|
|
|
// Extension traits for slices over specific kinds of data
|
2015-01-05 19:08:37 -08:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2019-07-05 11:38:40 +02:00
|
|
|
|
2020-12-19 08:23:59 -05:00
|
|
|
/// Helper trait for [`[T]::concat`](slice::concat).
|
2019-07-08 17:47:49 +02:00
|
|
|
///
|
|
|
|
|
/// Note: the `Item` type parameter is not used in this trait,
|
|
|
|
|
/// but it allows impls to be more generic.
|
|
|
|
|
/// Without it, we get this error:
|
|
|
|
|
///
|
|
|
|
|
/// ```error
|
|
|
|
|
/// error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predica
|
2022-11-03 15:59:23 -07:00
|
|
|
/// --> library/alloc/src/slice.rs:608:6
|
2019-07-08 17:47:49 +02:00
|
|
|
/// |
|
|
|
|
|
/// 608 | impl<T: Clone, V: Borrow<[T]>> Concat for [V] {
|
|
|
|
|
/// | ^ unconstrained type parameter
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// This is because there could exist `V` types with multiple `Borrow<[_]>` impls,
|
|
|
|
|
/// such that multiple `T` types would apply:
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// # #[allow(dead_code)]
|
|
|
|
|
/// pub struct Foo(Vec<u32>, Vec<String>);
|
|
|
|
|
///
|
|
|
|
|
/// impl std::borrow::Borrow<[u32]> for Foo {
|
|
|
|
|
/// fn borrow(&self) -> &[u32] { &self.0 }
|
|
|
|
|
/// }
|
|
|
|
|
///
|
|
|
|
|
/// impl std::borrow::Borrow<[String]> for Foo {
|
|
|
|
|
/// fn borrow(&self) -> &[String] { &self.1 }
|
|
|
|
|
/// }
|
|
|
|
|
/// ```
|
2019-07-05 11:38:40 +02:00
|
|
|
#[unstable(feature = "slice_concat_trait", issue = "27747")]
|
2019-07-08 17:47:49 +02:00
|
|
|
pub trait Concat<Item: ?Sized> {
|
2019-07-05 11:38:40 +02:00
|
|
|
#[unstable(feature = "slice_concat_trait", issue = "27747")]
|
2015-05-05 16:34:35 +02:00
|
|
|
/// The resulting type after concatenation
|
|
|
|
|
type Output;
|
|
|
|
|
|
2020-12-19 08:23:59 -05:00
|
|
|
/// Implementation of [`[T]::concat`](slice::concat)
|
2019-07-05 11:38:40 +02:00
|
|
|
#[unstable(feature = "slice_concat_trait", issue = "27747")]
|
2019-07-08 17:47:49 +02:00
|
|
|
fn concat(slice: &Self) -> Self::Output;
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-19 08:23:59 -05:00
|
|
|
/// Helper trait for [`[T]::join`](slice::join)
|
2019-07-08 17:47:49 +02:00
|
|
|
#[unstable(feature = "slice_concat_trait", issue = "27747")]
|
2019-07-08 17:50:27 +02:00
|
|
|
pub trait Join<Separator> {
|
2019-07-08 17:47:49 +02:00
|
|
|
#[unstable(feature = "slice_concat_trait", issue = "27747")]
|
|
|
|
|
/// The resulting type after concatenation
|
|
|
|
|
type Output;
|
2014-12-11 09:44:17 -08:00
|
|
|
|
2020-12-19 08:23:59 -05:00
|
|
|
/// Implementation of [`[T]::join`](slice::join)
|
2019-07-05 11:38:40 +02:00
|
|
|
#[unstable(feature = "slice_concat_trait", issue = "27747")]
|
2019-07-08 17:50:27 +02:00
|
|
|
fn join(slice: &Self, sep: Separator) -> Self::Output;
|
Second pass stabilization: slice
This commit takes a second pass through the `slice` module to
stabilize its API. The changes are as follows:
**Stable**:
* `as_mut_slice`
* `as_ptr`, `as_mut_ptr`
* `binary_search_by` (was: `binary_search`)
* `binary_search` (was: `binary_search_elem`)
* `chunks`, `chunks_mut`
* `contains`
* `ends_with`
* `first`, `first_mut` (was: `head`)
* `get_unchecked`, `get_unchecked_mut` (was: `unsafe_get`)
* `get`
* `is_empty`
* `iter`, `iter_mut`
* `len`
* `reverse`
* `sort_by`
* `sort`
* `split_at`, `split_at_mut`
* `split_mut`, `splitn_mut`, `rsplitn_mut`
* `split`, `splitn`, `rsplitn`
* `starts_with`
* `swap`
* `to_vec`
* `windows`
**Deprecated**:
* `head`, `head_mut` (renamed as above)
* `unsafe_get`, `unsafe_mut` (renamed as above)
* `binary_search_elem` (renamed as above)
* `partitioned`, deprecated in favor of a new, more
general iterator consumer called `partition`.
* `BinarySearchResult`, deprecated in favor of `Result<uint, uint>`
[breaking-change]
2014-12-17 20:50:16 -08:00
|
|
|
}
|
2014-12-11 09:44:17 -08: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-16 20:18:04 -04:00
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2019-07-08 18:12:06 +02:00
|
|
|
#[unstable(feature = "slice_concat_ext", issue = "27747")]
|
2019-07-08 17:47:49 +02:00
|
|
|
impl<T: Clone, V: Borrow<[T]>> Concat<T> for [V] {
|
2015-05-05 16:34:35 +02:00
|
|
|
type Output = Vec<T>;
|
|
|
|
|
|
2019-07-08 17:47:49 +02:00
|
|
|
fn concat(slice: &Self) -> Vec<T> {
|
2019-07-05 11:38:40 +02:00
|
|
|
let size = slice.iter().map(|slice| slice.borrow().len()).sum();
|
Second pass stabilization: slice
This commit takes a second pass through the `slice` module to
stabilize its API. The changes are as follows:
**Stable**:
* `as_mut_slice`
* `as_ptr`, `as_mut_ptr`
* `binary_search_by` (was: `binary_search`)
* `binary_search` (was: `binary_search_elem`)
* `chunks`, `chunks_mut`
* `contains`
* `ends_with`
* `first`, `first_mut` (was: `head`)
* `get_unchecked`, `get_unchecked_mut` (was: `unsafe_get`)
* `get`
* `is_empty`
* `iter`, `iter_mut`
* `len`
* `reverse`
* `sort_by`
* `sort`
* `split_at`, `split_at_mut`
* `split_mut`, `splitn_mut`, `rsplitn_mut`
* `split`, `splitn`, `rsplitn`
* `starts_with`
* `swap`
* `to_vec`
* `windows`
**Deprecated**:
* `head`, `head_mut` (renamed as above)
* `unsafe_get`, `unsafe_mut` (renamed as above)
* `binary_search_elem` (renamed as above)
* `partitioned`, deprecated in favor of a new, more
general iterator consumer called `partition`.
* `BinarySearchResult`, deprecated in favor of `Result<uint, uint>`
[breaking-change]
2014-12-17 20:50:16 -08:00
|
|
|
let mut result = Vec::with_capacity(size);
|
2019-07-05 11:38:40 +02:00
|
|
|
for v in slice {
|
2015-12-02 17:31:49 -08:00
|
|
|
result.extend_from_slice(v.borrow())
|
Second pass stabilization: slice
This commit takes a second pass through the `slice` module to
stabilize its API. The changes are as follows:
**Stable**:
* `as_mut_slice`
* `as_ptr`, `as_mut_ptr`
* `binary_search_by` (was: `binary_search`)
* `binary_search` (was: `binary_search_elem`)
* `chunks`, `chunks_mut`
* `contains`
* `ends_with`
* `first`, `first_mut` (was: `head`)
* `get_unchecked`, `get_unchecked_mut` (was: `unsafe_get`)
* `get`
* `is_empty`
* `iter`, `iter_mut`
* `len`
* `reverse`
* `sort_by`
* `sort`
* `split_at`, `split_at_mut`
* `split_mut`, `splitn_mut`, `rsplitn_mut`
* `split`, `splitn`, `rsplitn`
* `starts_with`
* `swap`
* `to_vec`
* `windows`
**Deprecated**:
* `head`, `head_mut` (renamed as above)
* `unsafe_get`, `unsafe_mut` (renamed as above)
* `binary_search_elem` (renamed as above)
* `partitioned`, deprecated in favor of a new, more
general iterator consumer called `partition`.
* `BinarySearchResult`, deprecated in favor of `Result<uint, uint>`
[breaking-change]
2014-12-17 20:50:16 -08:00
|
|
|
}
|
|
|
|
|
result
|
2014-12-11 09:44:17 -08:00
|
|
|
}
|
2019-07-08 17:47:49 +02: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-16 20:18:04 -04:00
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2019-07-08 17:47:49 +02:00
|
|
|
#[unstable(feature = "slice_concat_ext", issue = "27747")]
|
2019-07-09 18:19:01 +02:00
|
|
|
impl<T: Clone, V: Borrow<[T]>> Join<&T> for [V] {
|
2019-07-08 17:47:49 +02:00
|
|
|
type Output = Vec<T>;
|
2014-12-11 09:44:17 -08:00
|
|
|
|
2019-07-08 17:47:49 +02:00
|
|
|
fn join(slice: &Self, sep: &T) -> Vec<T> {
|
2019-07-05 11:38:40 +02:00
|
|
|
let mut iter = slice.iter();
|
2018-05-25 23:53:22 +02:00
|
|
|
let first = match iter.next() {
|
|
|
|
|
Some(first) => first,
|
|
|
|
|
None => return vec![],
|
|
|
|
|
};
|
2019-07-08 18:08:54 +02:00
|
|
|
let size = slice.iter().map(|v| v.borrow().len()).sum::<usize>() + slice.len() - 1;
|
2018-12-03 16:22:27 +01:00
|
|
|
let mut result = Vec::with_capacity(size);
|
2018-05-25 23:53:22 +02:00
|
|
|
result.extend_from_slice(first.borrow());
|
|
|
|
|
|
|
|
|
|
for v in iter {
|
|
|
|
|
result.push(sep.clone());
|
|
|
|
|
result.extend_from_slice(v.borrow())
|
|
|
|
|
}
|
|
|
|
|
result
|
2014-12-11 09:44:17 -08:00
|
|
|
}
|
Second pass stabilization: slice
This commit takes a second pass through the `slice` module to
stabilize its API. The changes are as follows:
**Stable**:
* `as_mut_slice`
* `as_ptr`, `as_mut_ptr`
* `binary_search_by` (was: `binary_search`)
* `binary_search` (was: `binary_search_elem`)
* `chunks`, `chunks_mut`
* `contains`
* `ends_with`
* `first`, `first_mut` (was: `head`)
* `get_unchecked`, `get_unchecked_mut` (was: `unsafe_get`)
* `get`
* `is_empty`
* `iter`, `iter_mut`
* `len`
* `reverse`
* `sort_by`
* `sort`
* `split_at`, `split_at_mut`
* `split_mut`, `splitn_mut`, `rsplitn_mut`
* `split`, `splitn`, `rsplitn`
* `starts_with`
* `swap`
* `to_vec`
* `windows`
**Deprecated**:
* `head`, `head_mut` (renamed as above)
* `unsafe_get`, `unsafe_mut` (renamed as above)
* `binary_search_elem` (renamed as above)
* `partitioned`, deprecated in favor of a new, more
general iterator consumer called `partition`.
* `BinarySearchResult`, deprecated in favor of `Result<uint, uint>`
[breaking-change]
2014-12-17 20:50:16 -08:00
|
|
|
}
|
2014-12-11 09:44:17 -08: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-16 20:18:04 -04:00
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2019-07-08 18:08:54 +02:00
|
|
|
#[unstable(feature = "slice_concat_ext", issue = "27747")]
|
2019-07-09 18:19:10 +02:00
|
|
|
impl<T: Clone, V: Borrow<[T]>> Join<&[T]> for [V] {
|
2019-07-08 18:08:54 +02:00
|
|
|
type Output = Vec<T>;
|
|
|
|
|
|
|
|
|
|
fn join(slice: &Self, sep: &[T]) -> Vec<T> {
|
|
|
|
|
let mut iter = slice.iter();
|
|
|
|
|
let first = match iter.next() {
|
|
|
|
|
Some(first) => first,
|
|
|
|
|
None => return vec![],
|
|
|
|
|
};
|
2019-11-29 19:30:49 -08:00
|
|
|
let size =
|
|
|
|
|
slice.iter().map(|v| v.borrow().len()).sum::<usize>() + sep.len() * (slice.len() - 1);
|
2019-07-08 18:08:54 +02:00
|
|
|
let mut result = Vec::with_capacity(size);
|
|
|
|
|
result.extend_from_slice(first.borrow());
|
|
|
|
|
|
|
|
|
|
for v in iter {
|
|
|
|
|
result.extend_from_slice(sep);
|
|
|
|
|
result.extend_from_slice(v.borrow())
|
|
|
|
|
}
|
|
|
|
|
result
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
Second pass stabilization: slice
This commit takes a second pass through the `slice` module to
stabilize its API. The changes are as follows:
**Stable**:
* `as_mut_slice`
* `as_ptr`, `as_mut_ptr`
* `binary_search_by` (was: `binary_search`)
* `binary_search` (was: `binary_search_elem`)
* `chunks`, `chunks_mut`
* `contains`
* `ends_with`
* `first`, `first_mut` (was: `head`)
* `get_unchecked`, `get_unchecked_mut` (was: `unsafe_get`)
* `get`
* `is_empty`
* `iter`, `iter_mut`
* `len`
* `reverse`
* `sort_by`
* `sort`
* `split_at`, `split_at_mut`
* `split_mut`, `splitn_mut`, `rsplitn_mut`
* `split`, `splitn`, `rsplitn`
* `starts_with`
* `swap`
* `to_vec`
* `windows`
**Deprecated**:
* `head`, `head_mut` (renamed as above)
* `unsafe_get`, `unsafe_mut` (renamed as above)
* `binary_search_elem` (renamed as above)
* `partitioned`, deprecated in favor of a new, more
general iterator consumer called `partition`.
* `BinarySearchResult`, deprecated in favor of `Result<uint, uint>`
[breaking-change]
2014-12-17 20:50:16 -08:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Standard trait implementations for slices
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2015-02-11 23:16:32 -08:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2022-07-16 11:58:26 +02:00
|
|
|
impl<T, A: Allocator> Borrow<[T]> for Vec<T, A> {
|
2015-11-24 11:23:48 +13:00
|
|
|
fn borrow(&self) -> &[T] {
|
|
|
|
|
&self[..]
|
|
|
|
|
}
|
Second pass stabilization: slice
This commit takes a second pass through the `slice` module to
stabilize its API. The changes are as follows:
**Stable**:
* `as_mut_slice`
* `as_ptr`, `as_mut_ptr`
* `binary_search_by` (was: `binary_search`)
* `binary_search` (was: `binary_search_elem`)
* `chunks`, `chunks_mut`
* `contains`
* `ends_with`
* `first`, `first_mut` (was: `head`)
* `get_unchecked`, `get_unchecked_mut` (was: `unsafe_get`)
* `get`
* `is_empty`
* `iter`, `iter_mut`
* `len`
* `reverse`
* `sort_by`
* `sort`
* `split_at`, `split_at_mut`
* `split_mut`, `splitn_mut`, `rsplitn_mut`
* `split`, `splitn`, `rsplitn`
* `starts_with`
* `swap`
* `to_vec`
* `windows`
**Deprecated**:
* `head`, `head_mut` (renamed as above)
* `unsafe_get`, `unsafe_mut` (renamed as above)
* `binary_search_elem` (renamed as above)
* `partitioned`, deprecated in favor of a new, more
general iterator consumer called `partition`.
* `BinarySearchResult`, deprecated in favor of `Result<uint, uint>`
[breaking-change]
2014-12-17 20:50:16 -08:00
|
|
|
}
|
|
|
|
|
|
2015-02-11 23:16:32 -08:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2022-07-16 11:58:26 +02:00
|
|
|
impl<T, A: Allocator> BorrowMut<[T]> for Vec<T, A> {
|
2015-11-24 11:23:48 +13:00
|
|
|
fn borrow_mut(&mut self) -> &mut [T] {
|
|
|
|
|
&mut self[..]
|
|
|
|
|
}
|
Second pass stabilization: slice
This commit takes a second pass through the `slice` module to
stabilize its API. The changes are as follows:
**Stable**:
* `as_mut_slice`
* `as_ptr`, `as_mut_ptr`
* `binary_search_by` (was: `binary_search`)
* `binary_search` (was: `binary_search_elem`)
* `chunks`, `chunks_mut`
* `contains`
* `ends_with`
* `first`, `first_mut` (was: `head`)
* `get_unchecked`, `get_unchecked_mut` (was: `unsafe_get`)
* `get`
* `is_empty`
* `iter`, `iter_mut`
* `len`
* `reverse`
* `sort_by`
* `sort`
* `split_at`, `split_at_mut`
* `split_mut`, `splitn_mut`, `rsplitn_mut`
* `split`, `splitn`, `rsplitn`
* `starts_with`
* `swap`
* `to_vec`
* `windows`
**Deprecated**:
* `head`, `head_mut` (renamed as above)
* `unsafe_get`, `unsafe_mut` (renamed as above)
* `binary_search_elem` (renamed as above)
* `partitioned`, deprecated in favor of a new, more
general iterator consumer called `partition`.
* `BinarySearchResult`, deprecated in favor of `Result<uint, uint>`
[breaking-change]
2014-12-17 20:50:16 -08:00
|
|
|
}
|
|
|
|
|
|
2023-01-28 14:19:01 +01:00
|
|
|
// Specializable trait for implementing ToOwned::clone_into. This is
|
|
|
|
|
// public in the crate and has the Allocator parameter so that
|
|
|
|
|
// vec::clone_from use it too.
|
|
|
|
|
#[cfg(not(no_global_oom_handling))]
|
|
|
|
|
pub(crate) trait SpecCloneIntoVec<T, A: Allocator> {
|
|
|
|
|
fn clone_into(&self, target: &mut Vec<T, A>);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(not(no_global_oom_handling))]
|
|
|
|
|
impl<T: Clone, A: Allocator> SpecCloneIntoVec<T, A> for [T] {
|
|
|
|
|
default fn clone_into(&self, target: &mut Vec<T, A>) {
|
|
|
|
|
// drop anything in target that will not be overwritten
|
|
|
|
|
target.truncate(self.len());
|
|
|
|
|
|
|
|
|
|
// target.len <= self.len due to the truncate above, so the
|
|
|
|
|
// slices here are always in-bounds.
|
|
|
|
|
let (init, tail) = self.split_at(target.len());
|
|
|
|
|
|
|
|
|
|
// reuse the contained values' allocations/resources.
|
|
|
|
|
target.clone_from_slice(init);
|
|
|
|
|
target.extend_from_slice(tail);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(not(no_global_oom_handling))]
|
|
|
|
|
impl<T: Copy, A: Allocator> SpecCloneIntoVec<T, A> for [T] {
|
|
|
|
|
fn clone_into(&self, target: &mut Vec<T, A>) {
|
|
|
|
|
target.clear();
|
|
|
|
|
target.extend_from_slice(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-16 20:18:04 -04:00
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2015-02-11 23:16:32 -08:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
|
impl<T: Clone> ToOwned for [T] {
|
|
|
|
|
type Owned = Vec<T>;
|
2015-03-11 19:44:02 -05:00
|
|
|
#[cfg(not(test))]
|
2015-11-24 11:23:48 +13:00
|
|
|
fn to_owned(&self) -> Vec<T> {
|
|
|
|
|
self.to_vec()
|
|
|
|
|
}
|
2015-03-11 19:44:02 -05:00
|
|
|
|
|
|
|
|
#[cfg(test)]
|
2015-11-24 11:23:48 +13:00
|
|
|
fn to_owned(&self) -> Vec<T> {
|
2020-11-18 17:23:41 +01:00
|
|
|
hack::to_vec(self, Global)
|
2015-11-24 11:23:48 +13:00
|
|
|
}
|
2017-04-01 19:33:45 -07:00
|
|
|
|
|
|
|
|
fn clone_into(&self, target: &mut Vec<T>) {
|
2023-01-28 14:19:01 +01:00
|
|
|
SpecCloneIntoVec::clone_into(self, target);
|
2017-04-01 19:33:45 -07:00
|
|
|
}
|
Second pass stabilization: slice
This commit takes a second pass through the `slice` module to
stabilize its API. The changes are as follows:
**Stable**:
* `as_mut_slice`
* `as_ptr`, `as_mut_ptr`
* `binary_search_by` (was: `binary_search`)
* `binary_search` (was: `binary_search_elem`)
* `chunks`, `chunks_mut`
* `contains`
* `ends_with`
* `first`, `first_mut` (was: `head`)
* `get_unchecked`, `get_unchecked_mut` (was: `unsafe_get`)
* `get`
* `is_empty`
* `iter`, `iter_mut`
* `len`
* `reverse`
* `sort_by`
* `sort`
* `split_at`, `split_at_mut`
* `split_mut`, `splitn_mut`, `rsplitn_mut`
* `split`, `splitn`, `rsplitn`
* `starts_with`
* `swap`
* `to_vec`
* `windows`
**Deprecated**:
* `head`, `head_mut` (renamed as above)
* `unsafe_get`, `unsafe_mut` (renamed as above)
* `binary_search_elem` (renamed as above)
* `partitioned`, deprecated in favor of a new, more
general iterator consumer called `partition`.
* `BinarySearchResult`, deprecated in favor of `Result<uint, uint>`
[breaking-change]
2014-12-17 20:50:16 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Sorting
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2022-11-20 20:35:40 +01:00
|
|
|
#[inline]
|
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-16 20:18:04 -04:00
|
|
|
#[cfg(not(no_global_oom_handling))]
|
2022-11-20 20:35:40 +01:00
|
|
|
fn stable_sort<T, F>(v: &mut [T], mut is_less: F)
|
2019-11-29 19:30:49 -08:00
|
|
|
where
|
|
|
|
|
F: FnMut(&T, &T) -> bool,
|
2016-12-06 12:05:16 +01:00
|
|
|
{
|
2024-04-16 20:59:17 +02:00
|
|
|
sort::stable::sort::<T, F, Vec<T>>(v, &mut is_less);
|
|
|
|
|
}
|
2016-12-06 12:05:16 +01:00
|
|
|
|
2024-04-16 20:59:17 +02:00
|
|
|
#[cfg(not(no_global_oom_handling))]
|
|
|
|
|
#[unstable(issue = "none", feature = "std_internals")]
|
|
|
|
|
impl<T> sort::stable::BufGuard<T> for Vec<T> {
|
|
|
|
|
fn with_capacity(capacity: usize) -> Self {
|
|
|
|
|
Vec::with_capacity(capacity)
|
2024-04-16 20:24:21 +02:00
|
|
|
}
|
2014-11-12 12:01:26 -08:00
|
|
|
|
2024-04-16 20:59:17 +02:00
|
|
|
fn as_uninit_slice_mut(&mut self) -> &mut [MaybeUninit<T>] {
|
|
|
|
|
self.spare_capacity_mut()
|
|
|
|
|
}
|
2014-11-20 08:43:37 -08:00
|
|
|
}
|