extern crate collections;
pub trait AsOption<T> {
fn as_option(&self) -> Option<T>;
}
impl AsOption<usize> for usize {
fn as_option(&self) -> Option<usize> {
Some(*self)
}
}
impl AsOption<usize> for Option<usize> {
fn as_option(&self) -> Option<usize> {
*self
}
}
use self::collections::range::RangeArgument;
use std::ops::Range;
use std::cmp;
pub trait GetSlice {
fn get_slice<T: AsOption<usize>, U: RangeArgument<T>>(&self, a: U) -> &Self;
fn get_slice_mut<T: AsOption<usize>, U: RangeArgument<T>>(&mut self, a: U) -> &mut Self;
}
fn bound<T: AsOption<usize>, U: RangeArgument<T>>(len: usize, a: U) -> Range<usize> {
let start = cmp::min(a.start().and_then(|x| x.as_option()).unwrap_or(0), len);
let end = cmp::min(a.end().and_then(|x| x.as_option()).unwrap_or(len), len);
if start <= end {
start..end
} else {
0..0
}
}
impl GetSlice for str {
fn get_slice<T: AsOption<usize>, U: RangeArgument<T>>(&self, a: U) -> &Self {
&self[bound(self.len(), a)]
}
fn get_slice_mut<T: AsOption<usize>, U: RangeArgument<T>>(&mut self, a: U) -> &mut Self {
let len = self.len();
&mut self[bound(len, a)]
}
}
impl<T> GetSlice for [T] {
fn get_slice<U: AsOption<usize>, V: RangeArgument<U>>(&self, a: V) -> &Self {
&self[bound(self.len(), a)]
}
fn get_slice_mut<U: AsOption<usize>, V: RangeArgument<U>>(&mut self, a: V) -> &mut Self {
let len = self.len();
&mut self[bound(len, a)]
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_get_slice() {
let arr = [1, 2, 3];
assert_eq!(arr.get_slice(1..42), &[2, 3]);
assert_eq!(arr.get_slice(20..42), &[]);
assert_eq!(arr.get_slice(0..), &arr);
assert_eq!(arr.get_slice::<usize, _>(..), &arr);
assert_eq!(arr.get_slice(..42), &arr);
assert_eq!(arr.get_slice(Some(1)..None), &[2, 3]);
assert_eq!(arr.get_slice(Some(1)..Some(2)), &[2]);
let mut vec = Vec::new();
assert!(vec.get_slice(Some(1)..Some(2)).is_empty());
vec.push(3);
assert_eq!(vec.get_slice(0..2), &[3]);
assert!(vec.get_slice(1..2).is_empty());
}
}