It's kind of messy to do, but you can use the generalizing borrows via dyn Trait
trick to make this work:
use std::ops::Bound;
use std::ops::RangeBounds;
use std::borrow::Borrow;
use std::any::TypeId;
use std::collections::BTreeMap;
use std::cmp::Ordering;
#[derive(Copy,Clone,Eq,PartialEq,Ord,PartialOrd)]
pub enum Scale<T> {
OffScaleLow,
Value(T),
OffScaleHigh
}
trait CmpIndex {
fn cmp_key(&self)->(Scale<usize>, Scale<TypeId>, Scale<usize>);
}
impl CmpIndex for (usize,TypeId,usize) {
fn cmp_key(&self)->(Scale<usize>, Scale<TypeId>, Scale<usize>) {
(Scale::Value(self.0), Scale::Value(self.1), Scale::Value(self.2))
}
}
impl CmpIndex for (Scale<usize>,Scale<TypeId>,Scale<usize>) {
fn cmp_key(&self)->(Scale<usize>, Scale<TypeId>, Scale<usize>) {
*self
}
}
impl PartialEq for dyn CmpIndex+'_ {
fn eq(&self, other:&Self)->bool {
self.cmp_key().eq(&other.cmp_key())
}
}
impl Eq for dyn CmpIndex+'_ {}
impl PartialOrd for dyn CmpIndex+'_ {
fn partial_cmp(&self, other:&Self)->Option<Ordering> {
self.cmp_key().partial_cmp(&other.cmp_key())
}
}
impl Ord for dyn CmpIndex+'_ {
fn cmp(&self, other:&Self)->Ordering {
self.cmp_key().cmp(&other.cmp_key())
}
}
impl<'a> Borrow<dyn CmpIndex+'a> for (usize, TypeId, usize) {
fn borrow(&self)->&(dyn CmpIndex+'a) { self }
}
impl<'a, T:CmpIndex+'a> RangeBounds<dyn CmpIndex+'a> for (Bound<T>, Bound<T>) {
fn start_bound(&self) -> Bound<&(dyn CmpIndex+'a)> {
self.0.as_ref().map(|b| b as &dyn CmpIndex)
}
fn end_bound(&self) -> Bound<&(dyn CmpIndex+'a)> {
self.1.as_ref().map(|b| b as &dyn CmpIndex)
}
}
pub fn select_primary<T>(map: &BTreeMap<(usize,TypeId,usize), T>, i:usize)
->std::collections::btree_map::Range<'_, (usize,TypeId,usize), T> {
use Scale::*;
map.range::<dyn CmpIndex,_>((
Bound::Included((Value(i), OffScaleLow, OffScaleLow)),
Bound::Included((Value(i), OffScaleHigh, OffScaleHigh))
))
}
pub fn select_primary_and_type<T>(
map: &BTreeMap<(usize,TypeId,usize), T>,
i:usize,
ty: TypeId
) -> std::collections::btree_map::Range<'_, (usize,TypeId,usize), T> {
use Scale::*;
map.range::<dyn CmpIndex,_>((
Bound::Included((Value(i), Value(ty), OffScaleLow)),
Bound::Included((Value(i), Value(ty), OffScaleHigh))
))
}