1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
use super::*;

/// A trait object used in method that access map entries without replacing them.
#[derive(StableAbi)]
#[repr(C)]
pub struct MapQuery<'a,K>{
    _marker:NotCopyNotClone,
    is_equal:extern "C" fn(&K,&ErasedObject)->bool,
    hash    :extern "C" fn(&ErasedObject,HasherObject<'_>),
    query:&'a ErasedObject,
}

impl<'a,K> MapQuery<'a,K>{
    #[inline]
    pub(super) fn new<Q>(query:&'a &'a Q)->Self
    where 
        K:Borrow<Q>,
        Q:Hash + Eq + 'a+?Sized,
    {
        MapQuery{
            _marker:NotCopyNotClone,
            is_equal:is_equal::<K,Q>,
            hash    :hash::<Q>,
            query:unsafe{ transmute_reference(query) },
        }
    }

    // #[inline]
    // pub(super) unsafe fn to_static(self)->MapQuery<'static,K>{
    //     mem::transmute::<MapQuery<'a,K>,MapQuery<'static,K>>(self)
    // }
    
    #[inline]
    pub(super) unsafe fn as_static(&self)->&MapQuery<'static,K>{
        transmute_reference(self)
    }
}

impl<'a,K> MapQuery<'a,K>{
    #[inline]
    pub(super) fn is_equal(&self,other:&K)->bool{
        (self.is_equal)(other,self.query)
    }

    #[inline]
    pub(super) unsafe fn as_mapkey(&self)->MapKey<K>{
        MapKey::Query(NonNull::from(self.as_static()))
    }
}


impl<'a,K> Hash for MapQuery<'a,K>{
    #[inline]
    fn hash<H>(&self,hasher:&mut H)
    where
        H: Hasher,
    {
        (self.hash)(&self.query,HasherObject::new(hasher))
    }
}


extern "C" fn is_equal<K,Q>(key:&K,query:&ErasedObject)->bool
where
    K:Borrow<Q>,
    Q:Eq+?Sized,
{
    extern_fn_panic_handling!{
        let query =unsafe{ transmute_reference::<ErasedObject,&Q>(query) };
        key.borrow()==*query
    }
}


extern "C" fn hash<Q>(query:&ErasedObject,mut hasher:HasherObject<'_>)
where
    Q:Hash+?Sized,
{
    extern_fn_panic_handling!{
        let query =unsafe{ transmute_reference::<ErasedObject,&Q>(query) };
        query.hash(&mut hasher);
    }
}