Reputation:
Is it possible to use custom structs as ranges?
For example:
struct Wrap(u32);
fn main() {
let x = Wrap(0);
(x..).take(10);
}
gives me
1 | struct Wrap(u32);
| ----------- doesn't satisfy `Wrap: Step`
And Step
is an experimental API. Not possible in normal Rust, then?
Upvotes: 3
Views: 183
Reputation: 834
The ..
syntax uses Range
, which implements iterator only if the underlying type implements Step, which in turn requires you to implement Clone
and PartialOrd
, and thus also PartialEq
.
Possible, but implementing Step
is currently nightly-only.
#![feature(step_trait)]
use std::iter;
#[derive(Clone, PartialEq, PartialOrd, Debug)]
struct Wrap(u32);
// Forward implementation to underlying u32
impl iter::Step for Wrap {
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
u32::steps_between(&start.0, &end.0)
}
fn forward_checked(start: Self, count: usize) -> Option<Self> {
u32::forward_checked(start.0, count).map(Wrap)
}
fn backward_checked(start: Self, count: usize) -> Option<Self> {
u32::backward_checked(start.0, count).map(Wrap)
}
}
fn main() {
let x = Wrap(0);
let values = (x..).take(10).collect::<Vec<_>>();
assert_eq!(values, vec![Wrap(0), Wrap(1), Wrap(2), Wrap(3), Wrap(4), Wrap(5), Wrap(6), Wrap(7), Wrap(8), Wrap(9)]);
}
Upvotes: 2