How can I ensure that a Rust vector only contains alternating types?
To store alternating types in a way that the type system enforces and has reasonable efficiency, you can use a tuple: Vec<(X, Y)>
.
Your situation also requires
- Storing an extra leading value in an
Option
to handle starting withY
- Storing an extra trailing value in an
Option
to handle ending withX
use either::Either; // 1.5.2
use std::iter;
#[derive(Debug, Default)]
struct Data<X, Y> {
head: Option<Y>,
pairs: Vec<(X, Y)>,
tail: Option<X>,
}
impl<X, Y> Data<X, Y> {
fn iter(&self) -> impl Iterator<Item = Either<&X, &Y>> {
let head = self.head.iter().map(Either::Right);
let pairs = self.pairs.iter().flat_map(|(a, b)| {
let a = iter::once(Either::Left(a));
let b = iter::once(Either::Right(b));
a.chain(b)
});
let tail = self.tail.iter().map(Either::Left);
head.chain(pairs).chain(tail)
}
}
That being said, you are going to have ergonomic issues somewhere. For example, you can't just push
an Either<X, Y>
because the previously pushed value might be of the same type. Creating the entire structure at once might be the simplest direction:
#[derive(Debug)]
struct A;
#[derive(Debug)]
struct B;
fn main() {
let data = Data {
head: Some(B),
pairs: vec![(A, B)],
tail: None,
};
println!("{:?}", data.iter().collect::<Vec<_>>());
}