I’m working on a draft RFC to finish up .drain()
and .drain(a..b)
for collections so that we can get them stabilized.
I’m having trouble with the range trait, currently called RangeArgument. How should it be designed to best support index ranges; including inclusive ranges in the future?
One headache is that inclusive ranges may actually overflow if you try to convert them to a half-open range with both upper and lower bound, so not even that is a good common representation (even if that’s the only thing the Vec really works with).
I’d be happy to see ideas how it should be implemented. The draft drain rfc is below, including a sketch Range trait.
Right now I’m leaning towards just the basic Range
trait, but that will lead to duplication of logic every place where it is used.
Summary
Implement .drain(range)
and .drain()
respectively as appropriate on collections.
Motivation
The drain
methods and their draining iterators serve to mass remove elements
from a collection, receieving them by value in an iterator, while the collection
keeps its allocation intact (if applicable).
The range parameterized variants of drain are a generalization of drain
, to
affect just a subrange of the collection, for example removing just an index range
from a vector.
drain
thus serves both to consume all or some elements from a collection without
consuming the collection itself. The ranged drain
allows bulk removal of
elements, more efficently than any other safe API.
Detailed design
- Implement
.drain(a..b)
wherea
andb
are indices or keys, for all collections that have meaningful order. - Implement
.drain()
for other collections. This is just like.drain(..)
would be (drain the whole collection). - Ranged drain accepts all range types, currently …, a…, …b, a…b, and drain will accept inclusive end ranges if they are implemented.
- Drain removes every element in the range.
- Drain returns a lazy iterator that produces the removed items in the range, by value.
- Drain removes the whole range, regardless if you iterate the draining iterator or not.
RangeArgument
trait
Currently called collections::range::RangeArgument
, to be called IndexRange
.
Use case:
impl Vec<T> {
fn drain<R>(&mut self, range: R) -> Drain<T> where R: IndexRange
}
/// Implemented by Range, RangeFrom, RangeTo, RangeFull and
/// future inclusive range types
pub trait Range<T> {
fn start(&self) -> Option<&T>;
fn end(&self) -> Option<&T>;
fn includes_start(&self) -> bool;
fn includes_end(&self) -> bool;
}
/// Implemented by ranges with usize index
pub trait IndexRange : Range<usize> {
/// Start value (exclusive)
///
/// Return if start value is present, else `None`.
fn exclusive_start(&self) -> Option<usize>;
/// Start value (inclusive)
///
/// Return if start value is present, else `None`.
fn inclusive_start(&self) -> Option<usize>;
/// End value (exclusive)
///
/// Return if end value is present, else `None`.
fn exclusive_end(&self) -> Option<usize>;
/// End value (inclusive)
/// Return if end value is present, else `None`.
fn inclusive_end(&self) -> Option<usize>;
}