jammdb/
bytes.rs

1use std::{
2    cmp::Ordering,
3    hash::{Hash, Hasher},
4    rc::Rc,
5};
6
7pub trait ToBytes<'a> {
8    fn to_bytes(self) -> Bytes<'a>;
9}
10
11impl<'a> ToBytes<'a> for &'a [u8] {
12    fn to_bytes(self) -> Bytes<'a> {
13        Bytes::Slice(self)
14    }
15}
16
17impl<'a> ToBytes<'a> for &'a str {
18    fn to_bytes(self) -> Bytes<'a> {
19        Bytes::Slice(self.as_bytes())
20    }
21}
22
23macro_rules! byte_array_to_bytes {
24    ($($n:expr),*) => (
25    $(
26        impl<'a> ToBytes<'a> for [u8; $n] {
27            fn to_bytes(self) -> Bytes<'a> {
28                Bytes::Bytes(bytes::Bytes::copy_from_slice(&self))
29            }
30        }
31    )*
32)
33}
34
35// We don't want to automatically copy arrays of any length,
36// but for concenience, we'll copy arrays for integer sizes
37// so that if you do i.to_be_bytes() it will work for any int.
38byte_array_to_bytes!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
39
40impl<'a> ToBytes<'a> for String {
41    fn to_bytes(self) -> Bytes<'a> {
42        Bytes::String(Rc::new(self))
43    }
44}
45
46impl<'a> ToBytes<'a> for Vec<u8> {
47    fn to_bytes(self) -> Bytes<'a> {
48        Bytes::Vec(Rc::new(self))
49    }
50}
51
52impl<'a> ToBytes<'a> for bytes::Bytes {
53    fn to_bytes(self) -> Bytes<'a> {
54        Bytes::Bytes(self)
55    }
56}
57
58impl<'a> ToBytes<'a> for &bytes::Bytes {
59    fn to_bytes(self) -> Bytes<'a> {
60        Bytes::Bytes(self.clone())
61    }
62}
63
64impl<'a> ToBytes<'a> for Bytes<'a> {
65    fn to_bytes(self) -> Bytes<'a> {
66        self
67    }
68}
69
70impl<'a> ToBytes<'a> for &Bytes<'a> {
71    fn to_bytes(self) -> Bytes<'a> {
72        self.clone()
73    }
74}
75
76#[derive(Debug, Clone)]
77pub enum Bytes<'a> {
78    Slice(&'a [u8]),
79    Bytes(bytes::Bytes),
80    Vec(Rc<Vec<u8>>),
81    String(Rc<String>),
82}
83
84impl<'a> Bytes<'a> {
85    pub fn size(&self) -> usize {
86        match self {
87            Self::Slice(s) => s.len(),
88            Self::Bytes(b) => b.len(),
89            Self::Vec(v) => v.len(),
90            Self::String(s) => s.len(),
91        }
92    }
93}
94
95impl<'a> AsRef<[u8]> for Bytes<'a> {
96    fn as_ref(&self) -> &[u8] {
97        match self {
98            Self::Slice(s) => s,
99            Self::Bytes(b) => b,
100            Self::Vec(v) => v.as_slice(),
101            Self::String(s) => s.as_bytes(),
102        }
103    }
104}
105
106impl<'a> Ord for Bytes<'a> {
107    fn cmp(&self, other: &Self) -> Ordering {
108        let a = self.as_ref();
109        let b = other.as_ref();
110        a.cmp(b)
111    }
112}
113
114impl<'a> PartialOrd for Bytes<'a> {
115    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
116        Some(self.cmp(other))
117    }
118}
119
120impl<'a> PartialEq for Bytes<'a> {
121    fn eq(&self, other: &Self) -> bool {
122        let a = self.as_ref();
123        let b = other.as_ref();
124        a.eq(b)
125    }
126}
127
128impl<'a> Eq for Bytes<'a> {}
129
130impl<'a> Hash for Bytes<'a> {
131    fn hash<H: Hasher>(&self, state: &mut H) {
132        let a = self.as_ref();
133        a.hash(state);
134    }
135}
136
137#[cfg(test)]
138mod tests {
139    use super::*;
140
141    #[test]
142    fn from_vec() {
143        let vec: Vec<u8> = vec![0, 0, 0];
144        let ptr = vec.as_slice()[0] as *const u8;
145        let b: Bytes = vec.to_bytes();
146        let ptr2 = b.as_ref()[0] as *const u8;
147        assert!(ptr == ptr2);
148    }
149
150    #[test]
151    fn from_str() {
152        let s = "abc";
153        let ptr = s.as_bytes()[0] as *const u8;
154        let b: Bytes = s.to_bytes();
155        let ptr2 = b.as_ref()[0] as *const u8;
156        assert!(ptr == ptr2);
157    }
158}