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}