coremem_types: list: switch to parameter-based indexing; add apply method

This commit is contained in:
2022-07-20 14:31:20 -07:00
parent e029c8b3d9
commit d0ae25e28b

View File

@@ -154,24 +154,30 @@ impl<Output, F> ListOp<F, Null, Output> for Null {
}
}
pub trait SameType<T> { }
impl<T> SameType<T> for T { }
/// implemented on a list AND index, allowing potentially non-generic code to fetch a
/// compile-time-constant element.
trait IndexOp<List, Index, Elem> {
// TODO: would be nice to make idx a fn parameter
fn get(&self, idx: Index) -> &Elem;
fn get_mut(&mut self, idx: Index) -> &mut Elem;
fn set(&mut self, idx: Index, el: Elem) {
*self.get_mut(idx) = el;
pub trait IndexOp<List, Index, Elem> {
fn apply<I: SameType<Index>, R, F: Fn(&Elem) -> R>(&self, f: F) -> R;
fn get<I: SameType<Index>>(&self) -> &Elem;
fn get_mut<I: SameType<Index>>(&mut self) -> &mut Elem;
fn set<I: SameType<Index>>(&mut self, el: Elem) {
*self.get_mut::<I>() = el;
}
}
/// zero-index into Self
impl<H, T> IndexOp<Node<H, T>, P0, H> for Node<H, T>
{
fn get(&self, _idx: P0) -> &H {
fn apply<I: SameType<P0>, R, F: Fn(&H) -> R>(&self, f: F) -> R {
f(&self.head)
}
fn get<I: SameType<P0>>(&self) -> &H {
&self.head
}
fn get_mut(&mut self, _idx: P0) -> &mut H {
fn get_mut<I: SameType<P0>>(&mut self) -> &mut H {
&mut self.head
}
}
@@ -182,11 +188,14 @@ where
P: Peano,
T: IndexOp<T, P, ElemAtP>
{
fn get(&self, _idx: PNext<P>) -> &ElemAtP {
self.tail.get(P::default())
fn apply<I: SameType<PNext<P>>, R, F: Fn(&ElemAtP) -> R>(&self, f: F) -> R {
self.tail.apply::<P, R, F>(f)
}
fn get_mut(&mut self, _idx: PNext<P>) -> &mut ElemAtP {
self.tail.get_mut(P::default())
fn get<I: SameType<PNext<P>>>(&self) -> &ElemAtP {
self.tail.get::<P>()
}
fn get_mut<I: SameType<PNext<P>>>(&mut self) -> &mut ElemAtP {
self.tail.get_mut::<P>()
}
}
@@ -332,27 +341,27 @@ mod test {
let list = Node::new_terminal(3f32)
.prepend(4i32)
.prepend(5u32);
assert_eq!(list.get(P0), &5u32);
assert_eq!(list.get(P1::default()), &4i32);
assert_eq!(list.get(P2::default()), &3f32);
assert_eq!(list.get::<P0>(), &5u32);
assert_eq!(list.get::<P1>(), &4i32);
assert_eq!(list.get::<P2>(), &3f32);
}
#[test]
fn set() {
let mut list = List::<(u32, i32, f32)>::default();
list.set(P0, 5u32);
list.set::<P0>(5u32);
assert_eq!(list.get(P0), &5u32);
assert_eq!(list.get(P1::default()), &0i32);
assert_eq!(list.get(P2::default()), &0f32);
assert_eq!(list.get::<P0>(), &5u32);
assert_eq!(list.get::<P1>(), &0i32);
assert_eq!(list.get::<P2>(), &0f32);
list.set(P2::default(), 3f32);
list.set(P1::default(), 4i32);
list.set::<P2>(3f32);
list.set::<P1>(4i32);
assert_eq!(list.get(P0), &5u32);
assert_eq!(list.get(P1::default()), &4i32);
assert_eq!(list.get(P2::default()), &3f32);
assert_eq!(list.get::<P0>(), &5u32);
assert_eq!(list.get::<P1>(), &4i32);
assert_eq!(list.get::<P2>(), &3f32);
}
#[test]
@@ -369,8 +378,8 @@ mod test {
fn test_into_list() {
let list = (5u32, 4i32, 3f32).into_list();
assert_eq!(list.get(P0), &5u32);
assert_eq!(list.get(P1::default()), &4i32);
assert_eq!(list.get(P2::default()), &3f32);
assert_eq!(list.get::<P0>(), &5u32);
assert_eq!(list.get::<P1>(), &4i32);
assert_eq!(list.get::<P2>(), &3f32);
}
}