clickhouse_driver_cth/
lib.rs

1#![no_std]
2extern crate libc;
3#[cfg(test)]
4#[macro_use]
5extern crate std;
6
7use core::mem::size_of;
8use core::ops::Deref;
9use core::ptr::read_unaligned;
10pub use libc::c_char;
11
12#[repr(C)]
13#[derive(Debug, PartialEq)]
14pub struct Hash128(pub u64, pub u64);
15
16impl Hash128 {
17    #[cfg(int128)]
18    #[inline(always)]
19    fn to_u128(self) -> u128 {
20        (self.0 as u128) << 64 | self.1 as u128
21    }
22}
23
24impl Deref for Hash128 {
25    type Target = [u8; 16];
26    #[inline]
27    fn deref(&self) -> &Self::Target {
28        unsafe { &*(self as *const Hash128 as *const [u8; 16]) }
29    }
30}
31
32#[allow(clippy::cast_ptr_alignment)]
33#[inline]
34pub fn fetch64(src: &[u8]) -> u64 {
35    debug_assert!(src.len() >= size_of::<u64>());
36    let ptr = src.as_ptr() as *const u64;
37    unsafe { read_unaligned(ptr) }
38}
39
40#[allow(clippy::cast_ptr_alignment)]
41#[inline]
42pub fn fetch128(src: &[u8]) -> u128 {
43    debug_assert!(src.len() >= size_of::<u128>());
44    let ptr = src.as_ptr() as *const u128;
45    unsafe { read_unaligned(ptr) }
46}
47
48#[cfg(not(int128))]
49impl PartialEq<&[u8]> for Hash128 {
50    fn eq(&self, other: &&[u8]) -> bool {
51        other.len() == 16 && (self.0 == fetch64(*other)) && (self.1 == fetch64(&other[8..]))
52    }
53}
54
55#[cfg(int128)]
56impl PartialEq<&[u8]> for Pair {
57    fn eq(&self, other: &&[u8]) -> bool {
58        (other.len() == 16) && (self.to_u128() == fetch128(other))
59    }
60}
61
62extern "C" {
63    pub fn _CityHash128(s: *const c_char, len: usize) -> Hash128;
64    pub fn _CityHash64(s: *const c_char, len: usize) -> u64;
65    pub fn _CityMurmur(s: *const c_char, len: usize, seed: Hash128) -> Hash128;
66}
67
68#[cfg(test)]
69extern "C" {
70    // pub fn _HashLen16(u: u64, v: u64) -> u64;
71    // pub fn _Fetch64(s: *const c_char) -> u64;
72    // pub fn _HashLen0to16(s: *const c_char, len: usize) -> u64;
73}
74
75pub fn city_hash_128(source: &[u8]) -> Hash128 {
76    unsafe { _CityHash128(source.as_ptr() as *const c_char, source.len()) }
77}
78
79pub fn city_hash_64(source: &[u8]) -> u64 {
80    unsafe { _CityHash64(source.as_ptr() as *const c_char, source.len()) }
81}
82
83#[cfg(test)]
84mod test {
85    use crate::*;
86
87    #[test]
88    fn test_city_hash_128() {
89        assert_eq!(
90            city_hash_128(b"abc"),
91            [
92                0xfe, 0x48, 0x77, 0x57, 0x95, 0xf1, 0x0f, 0x90, 0x7e, 0x0d, 0xb2, 0x55, 0x63, 0x17,
93                0xa9, 0x13
94            ]
95            .as_ref()
96        );
97        assert_ne!(
98            city_hash_128(b"abc"),
99            [
100                0x00, 0x48, 0x77, 0x57, 0x95, 0xf1, 0x0f, 0x90, 0x7e, 0x0d, 0xb2, 0x55, 0x63, 0x17,
101                0xa9, 0x13
102            ]
103            .as_ref()
104        );
105        assert_eq!(
106            city_hash_128(b"01234567890abc"),
107            [
108                0x36, 0x20, 0xe9, 0x1b, 0x54, 0x23, 0x04, 0xbe, 0x2d, 0xc7, 0x32, 0x8d, 0x93, 0xd2,
109                0x3b, 0x89
110            ]
111            .as_ref()
112        );
113        assert_eq!(
114            city_hash_128(b"01234567890123456789012345678901234567890123456789012345678901234"),
115            [
116                0x24, 0xd7, 0xd5, 0xdc, 0x8e, 0xb6, 0x85, 0xb2, 0xb1, 0xd9, 0x78, 0x15, 0xa2, 0x2a,
117                0xb0, 0x3d
118            ]
119            .as_ref()
120        );
121        assert_eq!(
122            city_hash_128(b""),
123            [
124                0x2b, 0x9a, 0xc0, 0x64, 0xfc, 0x9d, 0xf0, 0x3d, 0x29, 0x1e, 0xe5, 0x92, 0xc3, 0x40,
125                0xb5, 0x3c
126            ]
127            .as_ref()
128        );
129
130        assert_ne!(
131            city_hash_128(b"abc"),
132            [
133                0xfe, 0x48, 0x77, 0x57, 0x95, 0xf1, 0x0f, 0x90, 0x7e, 0x0d, 0xb2, 0x55, 0x63, 0x17,
134                0xa9, 0x11
135            ]
136            .as_ref()
137        );
138    }
139}