bronzedb_util/
types.rs

1use libc::memcmp;
2use std::cmp::{Eq, Ordering, PartialEq, PartialOrd};
3use std::hash::{Hash, Hasher};
4use std::mem::transmute;
5use std::ops::Deref;
6use std::os::raw::c_void;
7
8pub type Value = Vec<u8>;
9pub type Entry = (Key, Value);
10pub type EntryRef<'a> = (&'a Key, &'a Value);
11
12#[derive(Debug, Clone, Default)]
13pub struct Key {
14    data: Vec<u8>,
15}
16
17pub struct RawKey {
18    data: [u8],
19}
20
21impl Deref for RawKey {
22    type Target = [u8];
23    fn deref(&self) -> &Self::Target {
24        &self.data
25    }
26}
27
28impl Deref for Key {
29    type Target = Vec<u8>;
30    fn deref(&self) -> &Self::Target {
31        &self.data
32    }
33}
34
35impl AsRef<[u8]> for Key {
36    fn as_ref(&self) -> &[u8] {
37        self.as_slice()
38    }
39}
40
41impl From<&[u8]> for &RawKey {
42    fn from(data: &[u8]) -> Self {
43        unsafe { transmute(data) }
44    }
45}
46
47impl From<Vec<u8>> for Key {
48    fn from(data: Vec<u8>) -> Self {
49        Self { data }
50    }
51}
52
53impl PartialEq for RawKey {
54    fn eq(&self, other: &Self) -> bool {
55        self.len() == other.len()
56            && unsafe {
57                0 == memcmp(
58                    &self.data as *const [u8] as *const c_void,
59                    &other.data as *const [u8] as *const c_void,
60                    self.len(),
61                )
62            }
63    }
64}
65
66impl PartialOrd for RawKey {
67    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
68        match unsafe {
69            memcmp(
70                &self.data as *const [u8] as *const c_void,
71                &other.data as *const [u8] as *const c_void,
72                self.len(),
73            )
74        } {
75            x if x < 0 => Some(Ordering::Less),
76            x if x > 0 => Some(Ordering::Greater),
77            _ => {
78                if self.len() == other.len() {
79                    Some(Ordering::Equal)
80                } else if self.len() < other.len() {
81                    Some(Ordering::Less)
82                } else {
83                    Some(Ordering::Greater)
84                }
85            }
86        }
87    }
88}
89
90impl PartialEq for Key {
91    fn eq(&self, other: &Self) -> bool {
92        <RawKey as PartialEq>::eq(self.as_slice().into(), other.as_slice().into())
93    }
94}
95
96impl PartialOrd for Key {
97    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
98        <RawKey as PartialOrd>::partial_cmp(self.as_slice().into(), other.as_slice().into())
99    }
100}
101
102impl Eq for Key {}
103
104impl Hash for Key {
105    fn hash<H: Hasher>(&self, state: &mut H) {
106        <u8 as Hash>::hash_slice(self.as_slice(), state)
107    }
108}
109
110#[cfg(test)]
111mod tests {
112    use std::cmp::Ordering::*;
113    use std::cmp::PartialOrd;
114
115    #[test]
116    fn key_cmp() {
117        for (former, latter, order) in vec![
118            ("xixi", "haha", Greater),
119            ("haa", "haha", Less),
120            ("haha", "haha", Equal),
121            ("hah", "haha", Less),
122            ("hahah", "haha", Greater),
123        ] {
124            let former_key = former.to_owned().into_bytes();
125            let latter_key = latter.to_owned().into_bytes();
126            assert_eq!(order, former_key.partial_cmp(&latter_key).unwrap());
127        }
128    }
129}