use core::marker::PhantomData;
#[doc(hidden)]
pub struct Here;
#[doc(hidden)]
pub struct There<I>(PhantomData<fn() -> I>);
#[doc(hidden)]
pub trait Get<T, I> {
fn get(&self) -> T;
}
impl<T, Tail> Get<T, Here> for (T, Tail)
where
T: Clone,
{
fn get(&self) -> T {
self.0.clone()
}
}
impl<T, Head, Tail, I> Get<T, There<I>> for (Head, Tail)
where
Tail: Get<T, I>,
{
fn get(&self) -> T {
self.1.get()
}
}
#[doc(hidden)]
pub fn get<T, I, R>(resources: &R) -> T
where
R: Get<T, I>,
{
resources.get()
}
#[cfg(test)]
mod tests {
use super::get;
#[derive(Clone, Debug, Eq, PartialEq)]
struct Repository(&'static str);
#[derive(Clone, Debug, Eq, PartialEq)]
struct Clock(u64);
#[test]
fn gets_head_resource() {
let resources = (Repository("users"), (Clock(42), ()));
let repository: Repository = get(&resources);
assert_eq!(repository, Repository("users"));
}
#[test]
fn gets_nested_resource() {
let resources = (Repository("users"), (Clock(42), ()));
let clock: Clock = get(&resources);
assert_eq!(clock, Clock(42));
}
}