use std::{ops, range::Range};
pub trait MapExt: Sized {
type Val;
type This<R>;
fn map<R>(self, f: impl FnMut(Self::Val) -> R) -> Self::This<R>;
fn mutate(&mut self, f: impl FnMut(&mut Self::Val));
}
impl<T> MapExt for ops::Range<T> {
type Val = T;
type This<R> = ops::Range<R>;
fn map<R>(self, mut f: impl FnMut(Self::Val) -> R) -> Self::This<R> {
f(self.start)..f(self.end)
}
fn mutate(&mut self, mut f: impl FnMut(&mut Self::Val)) {
f(&mut self.start);
f(&mut self.end);
}
}
impl<T> MapExt for Range<T> {
type Val = T;
type This<R> = Range<R>;
fn map<R>(self, mut f: impl FnMut(Self::Val) -> R) -> Self::This<R> {
Range {
start: f(self.start),
end: f(self.end),
}
}
fn mutate(&mut self, mut f: impl FnMut(&mut Self::Val)) {
f(&mut self.start);
f(&mut self.end);
}
}
impl<T> MapExt for (T, T) {
type Val = T;
type This<R> = (R, R);
fn map<R>(self, mut f: impl FnMut(Self::Val) -> R) -> Self::This<R> {
(f(self.0), f(self.1))
}
fn mutate(&mut self, mut f: impl FnMut(&mut Self::Val)) {
f(&mut self.0);
f(&mut self.1);
}
}