user1002430
user1002430

Reputation:

Ranges on Rust wrapper types?

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

Answers (1)

linuskmr
linuskmr

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)]);
}

Playground

Upvotes: 2

Related Questions