use std::ops::Index;
use std::marker::PhantomData;
trait Map<Key> {
type Value;
fn get(&self, key: Key) -> Self::Value;
fn cloned<'a, T>(&'a self) -> ClonedMap<'a, Self, Key, T>
where Self: Sized + Map<Key, Value = &'a T>,
T: 'a
{
ClonedMap(self, PhantomData, PhantomData)
}
}
pub struct ClonedMap<'a, M: 'a, Key, Value: 'a>(&'a M, PhantomData<Key>, PhantomData<Value>);
impl<'a, M, Key, Value> Map<Key> for ClonedMap<'a, M, Key, Value>
where M: Map<Key, Value = &'a Value>,
T: Clone
{
type Value = Value;
fn get(&self, key: Key) -> Self::Value {
T::clone(self.0.get(key))
}
}
pub struct IndexMap<'a, I: 'a>(&'a I);
impl<'a, I, Key> Map<Key> for IndexMap<'a, I>
where I: 'a + Index<Key>,
I::Output: 'a
{
type Value = &'a I::Output;
fn get(&self, key: Key) -> Self::Value {
unsafe { ::std::mem::transmute(&self.0[key]) }
}
}
pub struct ConstMap<'a, T: 'a>(&'a T);
impl<'a, T: 'a> Map<usize> for ConstMap<'a, T> {
type Value = &'a T;
fn get(&self, _key: usize) -> Self::Value {
&self.0
}
}
#[test]
fn x() {
let x = 10;
let c = ConstMap(&x);
assert_eq!(c.get(2), &x);
assert_eq!(c.cloned().get(2), x);
let v = vec![false];
let c = IndexMap(&v);
assert_eq!(c.get(0), &false);
assert_eq!(c.cloned().get(0), false);
}