Class Subspace :: sus :: collections :: Slice
A dynamically-sized const view into a contiguous sequence of objects of type
const T
.
Contiguous here means that elements are laid out so that every element is
the same distance from its neighbors, where there are
sus::mem::size_of<T>()
many bytes between the start
of each element.
Slices are a view into a block of memory represented as a pointer and a length.
Static Methods
Constructs an empty Slice
.
This constructor is implicit so that using the EmptyMarker
allows the caller to avoid spelling out the
full Slice
type.
Constructs an empty Slice, which has no elements.
sus::construct::From<T[N]> trait.
Returns a Slice that refers to all elements of the data
array.
Constructs a slice from its raw parts with iterator invalidation tracking. Iterators produced from this slice will interact with the collection to allow it to know when they are being invalidated by the collection.
For building a Slice from primitive pointer, use from_raw_parts()
.
Safety
The following must be upheld or Undefined Behaviour may result:
- The
len
must be no more than the number of elements in the allocation at and after the position ofdata
. - The pointer
data
must be a valid pointer to an allocation, not a dangling pointer, at any point during the Slice's lifetime. This must be true even iflen
is 0. - The
refs
will besus::iter::IterRefCounter::empty_for_view()
unless theSlice
is being constructed from a context that owns an IterRefCounter and wants to be able to observe when it invalidates theSlice
by tracking its lifetime.
In some other langages such as Rust, the slice may hold an invalid pointer
when the length is zero. But Slice
must not hold a dangling pointer.
Otherwise addition on the dangling pointer may happen in Slice methods,
which is Undefined Behaviour in C++. To support dangling pointers, those
methods would need length == 0
branches. Care must be applied when
converting slices between languages as a result.
Constructs a slice from its raw parts.
For building a Slice from a collection, use from_raw_collection()
in order to participate in iterator invalidation tracking.
Safety
The following must be upheld or Undefined Behaviour may result:
- The
len
must be no more than the number of elements in the allocation at and after the position ofdata
. - The pointer
data
must be a valid pointer to an allocation, not a dangling pointer, at any point during the Slice's lifetime. This must be true even iflen
is 0. - The
refs
will besus::iter::IterRefCounter::empty_for_view()
unless theSlice
is being constructed from a context that owns an IterRefCounter and wants to be able to observe when it invalidates theSlice
by tracking its lifetime.
In some other langages such as Rust, the slice may hold an invalid pointer
when the length is zero. But Slice
must not hold a dangling pointer.
Otherwise addition on the dangling pointer may happen in Slice methods,
which is Undefined Behaviour in C++. To support dangling pointers, those
methods would need length == 0
branches. Care must be applied when
converting slices between languages as a result.
Methods
Returns a const pointer to the first element in the slice.
The caller must ensure that the collection outlives the pointer this function returns, or else it will end up pointing to garbage.
Modifying the collection referenced by this slice may cause its buffer to be reallocated, which would also make any pointers to it invalid.
Returns the two const pointers spanning the slice.
The returned range is half-open, which means that the end pointer points one past the last element of the slice. This way, an empty slice is represented by two equal pointers, and the difference between the two pointers represents the size of the slice.
The end pointer requires caution, as it does not point to a valid element in the slice.
This function is useful for interacting with interfaces which use two
pointers to refer to a range of elements in memory, as is common in C++
stdlib algorthms. Note that the pointers can be unpacked from the Range
with structured bindings as in auto [a, b] = s.as_ptr_range();
.
Binary searches this slice for a given element. This behaves similarly to contains if this slice is sorted.
If the value is found then sus::Ok
is returned, with the index
of the matching element. If there are multiple matches, then any one of
the matches could be returned. The index is chosen deterministically, but
is subject to change in future versions of Subspace. If the value is not
found then sus::Err
is returned, with the index where a matching
element could be inserted while maintaining sorted order.
Binary searches this slice with a comparator function. This behaves
similarly to contains
if this slice is sorted.
The comparator function should implement an order consistent with the
sort order of the underlying slice, returning a std::strong_ordering
that indicates whether its argument is less than, equal to or greater
than the desired target.
If the value is found then sus::Ok
is returned, with the index
of the matching element. If there are multiple matches, then any one of
the matches could be returned. The index is chosen deterministically, but
is subject to change in future versions of Subspace. If the value is not
found then sus::Err
is returned, with the index where a matching
element could be inserted while maintaining sorted order.
Binary searches this slice with a key extraction function. This behaves
similarly to contains
if this slice is sorted.
Assumes that the slice is sorted by the key, for instance with sort_by_key using the same key extraction function.
If the value is found then sus::Ok
is returned, with the index
of the matching element. If there are multiple matches, then any one of
the matches could be returned. The index is chosen deterministically, but
is subject to change in future versions of Subspace. If the value is not
found then sus::Err
is returned, with the index where a matching
element could be inserted while maintaining sorted order.
Returns an iterator over chunk_size
elements of the slice at a time,
starting at the beginning of the slice.
The chunks are slices and do not overlap. If chunk_size
does not divide
the length of the slice, then the last chunk will not have length
chunk_size
.
See chunks_exact()
for a variant of this iterator that returns chunks
of always exactly chunk_size
elements, and rchunks()
for the same
iterator but starting at the end of the slice.
Panics
Panics if chunk_size is 0.
Returns an iterator over chunk_size
elements of the slice at a time,
starting at the beginning of the slice.
The chunks are slices and do not overlap. If chunk_size
does not divide
the length of the slice, then the last up to chunk_size-1
elements will
be omitted and can be retrieved from the remainder
function of the
iterator.
TODO: Verify if: due to each chunk having exactly chunk_size
elements,
the compiler can often optimize the resulting code better than in the
case of chunks()
.
See chunks()
for a variant of this iterator that also returns the
remainder as a smaller chunk, and rchunks_exact()
for the same iterator
but starting at the end of the slice.
Panics
Panics if chunk_size
is 0.
Flattens and concatenates the items in the Slice.
The items of type T
are flattened into a collection of type
T::ConcatOutputType
. This method is only supported for types that
satisfy the sus::collections::Concat<T>
concept.
Slice
itself satisfies Concat
, with its output being Vec
, so that a
Slice
of Slice<T>
s can be concat()
together into a single Vec<T>
.
Example
i32 a1[] = {1, 2}, a2[] = {3, 4};
Slice<i32> as[] = {Slice<i32>::from(a1), Slice<i32>::from(a2)};
Vec<i32> v = Slice<Slice<i32>>::from(as).concat();
sus_check(v == Slice<i32>::from({1, 2, 3, 4}));
Concatenates a clone of each element in the slice into vec
.
This method exists to satisfy sus::collections::Concat<Slice<T>>
, for
concat()
to append the elements in each Slice onto vec
.
Returns true
if the slice contains an element with the given value.
This operation is O(n).
Note that if you have a sorted slice, binary_search()
may be faster.
Stops tracking iterator invalidation.
Safety
If the Slice points into a collection and that collection is invalidated,
it will no longer be caught. The caller must provide conditions that can
ensure the Slice
's pointer into the collection will remain valid.
Iterator invalidation tracking also tracks the stability of the collection object itself, not just its contents, which can be overly strict.
This function can be used when the collection's contents will remain valid, but the collection itself may be moved, which would invalidate the tracking and be treated as invalidating the iterator. There is no way to restore tracking.
Returns true
if suffix
is a suffix of the slice.
Returns the first element of the slice, or None
if it is empty.
Returns a const reference to the element at index i
, or None
if
i
is beyond the end of the Slice.
Returns a subslice which contains elements in range
, which specifies a
start and a length.
The start is the index of the first element to be returned in the
subslice, and the length is the number of elements in the output slice.
As such, r.get_range(Range(0u, r.len()))
returns a slice over the full
set of elements in r
.
Returns None if the Range would otherwise contain an element that is out of bounds.
Returns a subslice which contains elements in range
, which specifies a
start and a length.
The start is the index of the first element to be returned in the
subslice, and the length is the number of elements in the output slice.
As such, r.get_range(Range(0u, r.len()))
returns a slice over the full
set of elements in r
.
Safety
It is possible to specify a Range contains an element that is out of bounds of the Slice, which can result in Undefined Behaviour.
Returns a const reference to the element at index i
.
Safety
The index i
must be inside the bounds of the slice or Undefined
Behaviour results. The size of the slice must therefore also have a
length of at least 1.
Converts the slice into an iterator that consumes the slice and returns each element in the same order they appear in the slice.
Returns true if the slice has a length of 0.
Returns an iterator over all the elements in the slice, visited in the same order they appear in the slice. The iterator gives const access to each element.
Flattens and concatenates the items in the Slice, cloning a separator
between each item.
The items of type T
are flattened into a collection of type
T::JoinOutputType
. This method is only supported for types that
satisfy the sus::collections::Join<T>
concept.
Slice
itself satisfies Join
, with its output being Vec
, so that a
Slice
of Slice<T>
s can be join()
together into a single Vec<T>
.
Example
i32 a1[] = {1, 2}, a2[] = {3, 4}, asep[] = {10, 11, 12};
Slice<i32> as[] = {Slice<i32>::from(a1), Slice<i32>::from(a2)};
// Join slices with a slice between.
Vec<i32> v = Slice<Slice<i32>>::from(as).join(Slice<i32>::from(asep));
sus_check(v == sus::Vec<i32>(1, 2, 10, 11, 12, 3, 4));
// Join slices with a single item between.
Vec<i32> v2 = Slice<Slice<i32>>::from(as).join(99);
sus_check(v2 == sus::Vec<i32>(1, 2, 99, 3, 4));
Joins a clone of each element in the slice into vec
.
This method exists to satisfy sus::collections::Join<Slice<T>, U>
,
for join() to append the elements in each Slice onto vec
.
Returns the last element of the slice, or None
if it is empty.
Returns the number of elements in the slice.
Returns the index of the partition point according to the given predicate (the index of the first element of the second partition).
The slice is assumed to be partitioned according to the given predicate.
This means that all elements for which the predicate returns true are at the
start of the slice and all elements for which the predicate returns false
are at the end. For example, [7, 15, 3, 5, 4, 12, 6]
is partitioned under
the predicate x % 2 != 0
(all odd numbers are at the start, all even at
the end).
If this slice is not partitioned, the returned result is unspecified and meaningless, as this method performs a kind of binary search.
See also binary_search()
, binary_search_by()
, and
binary_search_by_key()
.
Returns an iterator over chunk_size
elements of the slice at a time,
starting at the end of the slice.
The chunks are slices and do not overlap. If chunk_size
does not divide
the length of the slice, then the last chunk will not have length
chunk_size
.
See rchunks_exact()
for a variant of this iterator that returns chunks of
always exactly chunk_size
elements, and chunks()
for the same iterator
but starting at the beginning of the slice.
Panics
Panics if chunk_size
is 0.
Returns an iterator over chunk_size
elements of the slice at a time,
starting at the end of the slice.
The chunks are slices and do not overlap. If chunk_size
does not divide
the length of the slice, then the last up to chunk_size-1
elements will be
omitted and can be retrieved from the remainder()
function of the
iterator.
TODO: Verify if: Due to each chunk having exactly chunk_size
elements, the
compiler can often optimize the resulting code better than in the case of
rchunks()
.
See rchunks()
for a variant of this iterator that also returns the
remainder as a smaller chunk, and chunks_exact()
for the same iterator but
starting at the beginning of the slice.
Panics
Panics if chunk_size
is 0.
Creates a vector by copying a slice n times.
Panics
This function will panic if the capacity would become larger than
isize::MAX
.
Examples
auto v = sus::Vec<i32>(1, 2);
sus_check(v[".."_r].repeat(3) == sus::vec(1, 2, 1, 2, 1, 2).construct<i32>());
Returns an iterator over subslices separated by elements that match pred
,
starting at the end of the slice and working backwards. The matched element
is not contained in the subslices.
As with split()
, if the first or last element is matched, an empty slice
will be the first (or last) item returned by the iterator.
Returns an iterator over subslices separated by elements that match pred
limited to returning at most n
items. This starts at the end of the slice
and works backwards. The matched element is not contained in the subslices.
The last element returned, if any, will contain the remainder of the slice.
Returns an iterator over subslices separated by elements that match pred
.
The matched element is not contained in the subslices.
If the first element is matched, an empty slice will be the first item returned by the iterator. Similarly, if the last element in the slice is matched, an empty slice will be the last item returned by the iterator.
Divides one slice into two at an index.
The first will contain all indices from [0, mid)
(excluding the index
mid
itself) and the second will contain all indices from [mid, len())
(excluding the index len()
itself).
Panics
Panics if mid > len()
.
Divides one slice into two at an index, without doing bounds checking.
The first will contain all indices from [0, mid) (excluding the index mid itself) and the second will contain all indices from [mid, len) (excluding the index len itself).
For a safe alternative see split_at()
.
Safety
Calling this method with an out-of-bounds index is undefined behavior
even if the resulting reference is not used. The caller has to ensure
that 0 <= mid <= len()
.
Returns the first and all the rest of the elements of the slice, or None
if it is empty.
sus::fn::FnMut<Pred, _Bool (const T &)>
Returns an iterator over subslices separated by elements that match pred
.
The matched element is contained in the end of the previous subslice as a
terminator.
If the last element of the slice is matched, that element will be considered the terminator of the preceding slice. That slice will be the last item returned by the iterator.
Returns the last and all the rest of the elements of the slice, or None
if
it is empty.
Returns an iterator over subslices separated by elements that match pred
,
limited to returning at most n
items. The matched element is not contained
in the subslices.
The last element returned, if any, will contain the remainder of the slice.
Returns true
if needle
is a prefix of the slice.
Returns a subslice with the prefix
removed.
If the slice starts with prefix
, returns the subslice after the prefix
,
wrapped in Some
. If prefix
is empty, simply returns the original slice.
If the slice does not start with prefix
, returns None
.
TODO: Accept a SlicePattern<T>
concept instead of just a Slice<T>
.
Returns a subslice with the suffix
removed.
If the slice ends with suffix
, returns the subslice before the suffix
,
wrapped in Some
. If suffix
is empty, simply returns the original slice.
If the slice does not end with suffix
, returns None
.
Returns a subslice which contains elements in the range which is specified
by a start
and an end
.
This is an alias for the subscript operator with a RangeBounds
argument, but without the need to construct a
RangeBounds
.
The returned slice contains all indices in start <= x < end
. It is
empty if start >= end
.
NOTE: This is different from std::span::subspan which uses a start and a
length. Instead, this matches the construction of a
Range
in C++ and a Range
in Rust.
Panics
If the Range would otherwise contain an element that is out of bounds, the function will panic.
Constructs a Vec<T>
by cloning each value in the Slice.
The caller can choose traits for the Vec by specifying the trait type.
Returns an iterator over all contiguous windows of length size
. The
windows overlap. If the slice is shorter than size
, the iterator returns
no values.
Panics
Panics if size
is 0.
Operators
Returns a reference to the element at position i
in the Slice.
Panics
If the index i
is beyond the end of the slice, the function will panic.
Returns a subslice which contains elements in range
, which specifies a
start and an end.
The start is the index of the first element to be returned in the
subslice, and the end one past the last element in the output slice.
As such, r.get_range(Range(0u, r.len()))
returns a slice over the
full set of elements in r
.
Panics
If the Range would otherwise contain an element that is out of bounds, the function will panic.