// This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. use std::ops::Index; use std::marker::PhantomData; trait Map { type Value; fn get(&self, key: Key) -> Self::Value; fn cloned<'a, T>(&'a self) -> ClonedMap<'a, Self, Key, T> where Self: Sized + Map, T: 'a { ClonedMap(self, PhantomData, PhantomData) } } pub struct ClonedMap<'a, M: 'a, Key, Value: 'a>(&'a M, PhantomData, PhantomData); impl<'a, M, Key, Value> Map for ClonedMap<'a, M, Key, Value> where M: Map, 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 for IndexMap<'a, I> where I: 'a + Index, 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 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); }