From 9f2ee41424fd89ae36386c4c34c2af62290a33ac Mon Sep 17 00:00:00 2001 From: fengyang Date: Fri, 16 Dec 2022 01:03:38 +0800 Subject: [PATCH 01/13] =?UTF-8?q?=E5=88=9D=E6=AD=A5hash=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.toml | 5 +++ src/util/hash.rs | 71 ++++++++++++++++++++++++++++++++++++++++--- src/util/hash_test.rs | 11 +++++++ 3 files changed, 83 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7b77544..6f688ef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,3 +10,8 @@ path = "src/lib.rs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] + + +[profile.dev] + +[profile.release] diff --git a/src/util/hash.rs b/src/util/hash.rs index d383f2b..5a311c0 100644 --- a/src/util/hash.rs +++ b/src/util/hash.rs @@ -1,5 +1,11 @@ +use std::ops::{BitXor, Mul}; +use crate::traits::coding_trait::CodingTrait; +use crate::util::coding::Coding; -pub trait AsHash { +/// 本方案中,采用的是MurMurHash的一种变体,是一种高效低碰撞的非加密型哈希函数。具有较高的平衡性与低碰撞率 +pub struct Hash {} + +impl<'a> Hash { /// /// /// # Arguments @@ -15,7 +21,64 @@ pub trait AsHash { /// ``` /// /// ``` - fn hash(data: String, n: usize, seed: u32) -> u32; -} + pub fn hash(data: String, data_size: usize, seed: u32) -> u32 { + let murmur_hash : u32 = 0xc6a4a793; + let r : u32 = 24; + + let limit: usize = data_size; + let mul_first = data_size.mul(murmur_hash as usize); // x = data_size * murmur_hash + let mut h: usize = seed.bitxor(mul_first as u32) as usize; // h = seed ^ x + + // 每次按照四字节长度读取字节流中的数据 w,并使用普通的哈希函数计算哈希值。 + let mut position: usize = 0; + while position + 4 <= limit { + //每次解码前4个字节,直到最后剩下小于4个字节 + // rust的 &[u8] 是胖指针,带长度信息的,会做range check,所以是安全的。 + let slice_str: &[u8] = data[position..(position + 4)].as_ref(); + let w: u32 = Coding::decode_fixed32(slice_str); + + // 向后移动4个字节 + position += 4; + + // /计算过程中使用了自然溢出特性 + // h += w + h = h.wrapping_add(w as usize); + // h *= m + h = h.wrapping_mul(murmur_hash as usize); + // ^ 按位异或 bitxor , >> 右移位 shr, << 左移位 shl + // h ^= (h >> 16) == h ^= h.shr(16); + h = h.bitxor(h.wrapping_shr(16)); + } + + // 四字节读取则为了加速,最终可能剩下 3/2/1 个多余的字节, + // 将剩下的字节转化到 h 里面 + let cu = limit - position; + match cu { + 3 => { + let us: &[u8] = data[position..].as_ref(); + h = h.wrapping_add((us[2] as u32).wrapping_shl(16) as usize); + h = h.wrapping_add((us[1] as u32).wrapping_shl(8) as usize); + h = h.wrapping_add(us[0].into()); + }, + 2 => { + let us: &[u8] = data[position..].as_ref(); + h = h.wrapping_add((us[1] as u32).wrapping_shl(8) as usize); + h = h.wrapping_add(us[0].into()); + }, + 1 => { + let us: &[u8] = data[position..].as_ref(); + h = h.wrapping_add(us[0].into()); + // h *= m + h = h.wrapping_mul(murmur_hash as usize); + // h ^= (h >> r) == h ^= h.shr(r); + h = h.bitxor(h.wrapping_shr(r)); + }, + _ => {} + }; + + println!("hash usize: {}", h); + println!("hash u32: {}", h as u32); -pub struct Hash {} \ No newline at end of file + h as u32 + } +} \ No newline at end of file diff --git a/src/util/hash_test.rs b/src/util/hash_test.rs index 0384579..e2564a0 100644 --- a/src/util/hash_test.rs +++ b/src/util/hash_test.rs @@ -1,6 +1,17 @@ +use crate::util::hash::{Hash}; #[test] fn test_hash() { + let val = "aabbccd"; + let hash_val = Hash::hash(String::from(val), val.len(), 3); + println!("hash:{}", hash_val); + let val = "aabbcc"; + let hash_val = Hash::hash(String::from(val), val.len(), 3); + println!("hash:{}", hash_val); + + let val = "aabbc"; + let hash_val = Hash::hash(String::from(val), val.len(), 3); + println!("hash:{}", hash_val); } \ No newline at end of file -- Gitee From bff8833b7dba6058bcbc11e2bb215a133fba91b4 Mon Sep 17 00:00:00 2001 From: fengyang Date: Fri, 16 Dec 2022 14:03:42 +0800 Subject: [PATCH 02/13] =?UTF-8?q?=E5=88=9D=E6=AD=A5hash=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/hash.rs | 13 +++++++++++-- src/util/hash_test.rs | 9 +++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/util/hash.rs b/src/util/hash.rs index 5a311c0..17aea26 100644 --- a/src/util/hash.rs +++ b/src/util/hash.rs @@ -21,14 +21,23 @@ impl<'a> Hash { /// ``` /// /// ``` - pub fn hash(data: String, data_size: usize, seed: u32) -> u32 { + pub fn hash(mut data: String, data_size: usize, seed: u32) -> u32 { + let data_u8_vec; + unsafe { + data_u8_vec = data.as_mut_vec(); + } + + Hash::hash_char(data_u8_vec, data_size, seed) + } + + pub fn hash_char(data: &Vec, data_size: usize, seed: u32) -> u32 { let murmur_hash : u32 = 0xc6a4a793; let r : u32 = 24; let limit: usize = data_size; let mul_first = data_size.mul(murmur_hash as usize); // x = data_size * murmur_hash let mut h: usize = seed.bitxor(mul_first as u32) as usize; // h = seed ^ x - + // 每次按照四字节长度读取字节流中的数据 w,并使用普通的哈希函数计算哈希值。 let mut position: usize = 0; while position + 4 <= limit { diff --git a/src/util/hash_test.rs b/src/util/hash_test.rs index e2564a0..29ece53 100644 --- a/src/util/hash_test.rs +++ b/src/util/hash_test.rs @@ -13,5 +13,14 @@ fn test_hash() { let val = "aabbc"; let hash_val = Hash::hash(String::from(val), val.len(), 3); println!("hash:{}", hash_val); +} +#[test] +fn test_hash_code() { + let data4: Vec = vec![0xe1, 0x80, 0xb9, 0x32]; + + let hash_val = Hash::hash_char(&data4, data4.len(), 3); + println!("hash:{}", hash_val); + // 3978388282 + // assert_eq!(0xed21633a, hash_val); } \ No newline at end of file -- Gitee From 7f5cef6fa5f234da367525f381f7c78f0dfa03b6 Mon Sep 17 00:00:00 2001 From: fengyang Date: Fri, 16 Dec 2022 22:13:34 +0800 Subject: [PATCH 03/13] =?UTF-8?q?hash=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/hash.rs | 69 ++++++++++++++++++++++++------------------- src/util/hash_test.rs | 37 +++++++++++++++++++---- 2 files changed, 71 insertions(+), 35 deletions(-) diff --git a/src/util/hash.rs b/src/util/hash.rs index 17aea26..a134fc7 100644 --- a/src/util/hash.rs +++ b/src/util/hash.rs @@ -19,7 +19,9 @@ impl<'a> Hash { /// # Examples /// /// ``` - /// + /// let data3: Vec = vec![0xe2, 0x99, 0xa5]; + /// let hash_val = Hash::hash_char(&data3, data3.len(), 0xbc9f1d34); /// + /// assert_eq!(0x323c078f, hash_val); /// ``` pub fn hash(mut data: String, data_size: usize, seed: u32) -> u32 { let data_u8_vec; @@ -36,7 +38,7 @@ impl<'a> Hash { let limit: usize = data_size; let mul_first = data_size.mul(murmur_hash as usize); // x = data_size * murmur_hash - let mut h: usize = seed.bitxor(mul_first as u32) as usize; // h = seed ^ x + let mut h: u32 = seed.bitxor(mul_first as u32); // h = seed ^ x // 每次按照四字节长度读取字节流中的数据 w,并使用普通的哈希函数计算哈希值。 let mut position: usize = 0; @@ -51,9 +53,9 @@ impl<'a> Hash { // /计算过程中使用了自然溢出特性 // h += w - h = h.wrapping_add(w as usize); + h = h.wrapping_add(w); // h *= m - h = h.wrapping_mul(murmur_hash as usize); + h = h.wrapping_mul(murmur_hash); // ^ 按位异或 bitxor , >> 右移位 shr, << 左移位 shl // h ^= (h >> 16) == h ^= h.shr(16); h = h.bitxor(h.wrapping_shr(16)); @@ -61,33 +63,40 @@ impl<'a> Hash { // 四字节读取则为了加速,最终可能剩下 3/2/1 个多余的字节, // 将剩下的字节转化到 h 里面 - let cu = limit - position; - match cu { - 3 => { - let us: &[u8] = data[position..].as_ref(); - h = h.wrapping_add((us[2] as u32).wrapping_shl(16) as usize); - h = h.wrapping_add((us[1] as u32).wrapping_shl(8) as usize); - h = h.wrapping_add(us[0].into()); - }, - 2 => { - let us: &[u8] = data[position..].as_ref(); - h = h.wrapping_add((us[1] as u32).wrapping_shl(8) as usize); - h = h.wrapping_add(us[0].into()); - }, - 1 => { - let us: &[u8] = data[position..].as_ref(); - h = h.wrapping_add(us[0].into()); - // h *= m - h = h.wrapping_mul(murmur_hash as usize); - // h ^= (h >> r) == h ^= h.shr(r); - h = h.bitxor(h.wrapping_shr(r)); - }, - _ => {} - }; + let mut mark: usize = 0; + while limit - position - mark != 0 { + match limit - position - mark { + 3 => { + let us: &[u8] = data[position..].as_ref(); + let as_us: u32 = us[2] as u32; + h = h.wrapping_add(as_us.wrapping_shl(16)); + + mark += 1; + }, + 2 => { + let us: &[u8] = data[position..].as_ref(); + let as_us: u32 = us[1] as u32; + h = h.wrapping_add( as_us.wrapping_shl(8)); - println!("hash usize: {}", h); - println!("hash u32: {}", h as u32); + mark += 1; + }, + 1 => { + let us: &[u8] = data[position..].as_ref(); + let as_us: u32 = us[0] as u32; + h = h.wrapping_add(as_us); + // h *= m + h = h.wrapping_mul(murmur_hash); + // h ^= (h >> r) ==> h ^= h.shr(r); + h = h.bitxor(h.wrapping_shr(r)); + + mark += 1; + }, + _ => { + println!("0") + } + }; + } - h as u32 + h } } \ No newline at end of file diff --git a/src/util/hash_test.rs b/src/util/hash_test.rs index 29ece53..770192b 100644 --- a/src/util/hash_test.rs +++ b/src/util/hash_test.rs @@ -17,10 +17,37 @@ fn test_hash() { #[test] fn test_hash_code() { + let data1: Vec = vec![0x62]; + let data2: Vec = vec![0xc3, 0x97]; + let data3: Vec = vec![0xe2, 0x99, 0xa5]; let data4: Vec = vec![0xe1, 0x80, 0xb9, 0x32]; + let data5: Vec = vec![0x01, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x14, + 0x00, 0x00, 0x00, 0x18, + 0x28, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00]; - let hash_val = Hash::hash_char(&data4, data4.len(), 3); - println!("hash:{}", hash_val); - // 3978388282 - // assert_eq!(0xed21633a, hash_val); -} \ No newline at end of file + let hash_val = Hash::hash_char(&vec![0], 0, 0xbc9f1d34); + assert_eq!(0xbc9f1d34, hash_val); + + let hash_val = Hash::hash_char(&data1, data1.len(), 0xbc9f1d34); + assert_eq!(0xef1345c4, hash_val); + + let hash_val = Hash::hash_char(&data2, data2.len(), 0xbc9f1d34); + assert_eq!(0x5b663814, hash_val); + let hash_val = Hash::hash_char(&data3, data3.len(), 0xbc9f1d34); + assert_eq!(0x323c078f, hash_val); + + let hash_val = Hash::hash_char(&data4, data4.len(), 0xbc9f1d34); + assert_eq!(0xed21633a, hash_val); + + let hash_val = Hash::hash_char(&data5, data5.len(), 0x12345678); + assert_eq!(0xf333dabb, hash_val); +} -- Gitee From 8a71d815a72a28a1c0af2913851af6980b24f499 Mon Sep 17 00:00:00 2001 From: fengyang Date: Fri, 16 Dec 2022 22:24:03 +0800 Subject: [PATCH 04/13] =?UTF-8?q?FilterPolicy=20=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/traits/filter_policy_trait.rs | 7 +++++++ src/util/filter_policy.rs | 4 ++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b7d8eb0..dc51f61 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,6 @@ LevelDB for rust | BloomFilter | fengyang | 0% | | CRC | wangboo、lxd5866 | | | Env | lxd5866 | | -| Hash | fengyang | 30% | +| Hash | fengyang | 100% | | MutexLock | kazeseiriou | | | Histgram | kazeseiriou | | \ No newline at end of file diff --git a/src/traits/filter_policy_trait.rs b/src/traits/filter_policy_trait.rs index fcfd19d..c751282 100644 --- a/src/traits/filter_policy_trait.rs +++ b/src/traits/filter_policy_trait.rs @@ -1,9 +1,16 @@ use crate::util::slice::Slice; +/// 用于key过滤,可以快速的排除不存在的key pub trait FilterPolicy { + /// filter的名字 + /// Return the name of this policy. Note that if the filter encoding + /// changes in an incompatible way, the name returned by this method + /// must be changed. Otherwise, old incompatible filters may be + /// passed to methods of this type. fn name() -> String; fn create_filter(&self, keys: Slice, n: u32) -> String; + fn key_may_match(key: &Slice, filter: &Slice) -> bool; } \ No newline at end of file diff --git a/src/util/filter_policy.rs b/src/util/filter_policy.rs index 9e9811e..ca88fa3 100644 --- a/src/util/filter_policy.rs +++ b/src/util/filter_policy.rs @@ -15,4 +15,8 @@ impl FilterPolicy for BloomFilterPolicy { fn create_filter(&self, keys: Slice, n: u32) -> String { todo!() } + + fn key_may_match(key: &Slice, filter: &Slice) -> bool { + todo!() + } } \ No newline at end of file -- Gitee From a4f1e02eb60070ed401cbd03da70f87414d895de Mon Sep 17 00:00:00 2001 From: fengyang Date: Fri, 16 Dec 2022 22:33:01 +0800 Subject: [PATCH 05/13] =?UTF-8?q?FilterPolicy=20=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/traits/filter_policy_trait.rs | 26 +++++++++++++++++++++++++- src/util/filter_policy.rs | 2 +- src/util/hash.rs | 2 +- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/traits/filter_policy_trait.rs b/src/traits/filter_policy_trait.rs index c751282..2ec339d 100644 --- a/src/traits/filter_policy_trait.rs +++ b/src/traits/filter_policy_trait.rs @@ -10,7 +10,31 @@ pub trait FilterPolicy { /// passed to methods of this type. fn name() -> String; - fn create_filter(&self, keys: Slice, n: u32) -> String; + /// 根据指定的参数创建过滤器,并返回结果, 结果为dst的原始内容 + append结果。 + /// 参数keys[0,n-1]包含依据用户提供的comparator排序的key列表--可重复, + /// 并把根据这些key创建的filter追加到 dst中。 + /// + /// keys[0,n-1] contains a list of keys (potentially with duplicates) + /// that are ordered according to the user supplied comparator. + /// Append a filter that summarizes keys[0,n-1] to *dst. + /// + /// Warning: do not change the initial contents of dst. Instead, + /// append the newly constructed filter to dst. + /// + /// # Arguments + /// + /// * `keys`: + /// * `n`: + /// * `dst`: + /// + /// returns: String + /// + /// # Examples + /// + /// ``` + /// + /// ``` + fn create_filter(&self, keys: Slice, n: u32, dst: String) -> String; fn key_may_match(key: &Slice, filter: &Slice) -> bool; } \ No newline at end of file diff --git a/src/util/filter_policy.rs b/src/util/filter_policy.rs index ca88fa3..b40e0dd 100644 --- a/src/util/filter_policy.rs +++ b/src/util/filter_policy.rs @@ -12,7 +12,7 @@ impl FilterPolicy for BloomFilterPolicy { String::from("leveldb.BuiltinBloomFilter2") } - fn create_filter(&self, keys: Slice, n: u32) -> String { + fn create_filter(&self, keys: Slice, n: u32, dst: String) -> String { todo!() } diff --git a/src/util/hash.rs b/src/util/hash.rs index a134fc7..ea82575 100644 --- a/src/util/hash.rs +++ b/src/util/hash.rs @@ -6,7 +6,7 @@ use crate::util::coding::Coding; pub struct Hash {} impl<'a> Hash { - /// + /// 计算 data 的 hash /// /// # Arguments /// -- Gitee From 4026c7e469079ada35f1f3afc14e7e58b682dc5c Mon Sep 17 00:00:00 2001 From: wangboo <5417808+wangboa@user.noreply.gitee.com> Date: Sat, 17 Dec 2022 11:01:35 +0800 Subject: [PATCH 06/13] fix some code, add ToHash trait --- src/util/hash.rs | 98 ++++++++++++++++++++++++------------------- src/util/hash_test.rs | 18 ++++---- 2 files changed, 64 insertions(+), 52 deletions(-) diff --git a/src/util/hash.rs b/src/util/hash.rs index ea82575..2fd4e0b 100644 --- a/src/util/hash.rs +++ b/src/util/hash.rs @@ -1,43 +1,59 @@ use std::ops::{BitXor, Mul}; + use crate::traits::coding_trait::CodingTrait; use crate::util::coding::Coding; +use crate::util::slice::Slice; -/// 本方案中,采用的是MurMurHash的一种变体,是一种高效低碰撞的非加密型哈希函数。具有较高的平衡性与低碰撞率 -pub struct Hash {} +/// 一种可以计算 hash 的特质 +pub trait ToHash { + fn to_hash(&self) -> u32; +} -impl<'a> Hash { - /// 计算 data 的 hash - /// - /// # Arguments - /// - /// * `data`: - /// * `n`: data 的长度 - /// * `seed`: 随机数种子 - /// - /// returns: u32 - /// - /// # Examples - /// - /// ``` - /// let data3: Vec = vec![0xe2, 0x99, 0xa5]; - /// let hash_val = Hash::hash_char(&data3, data3.len(), 0xbc9f1d34); /// - /// assert_eq!(0x323c078f, hash_val); - /// ``` - pub fn hash(mut data: String, data_size: usize, seed: u32) -> u32 { - let data_u8_vec; - unsafe { - data_u8_vec = data.as_mut_vec(); - } +/// 所有基本类型 u8, i8, u16, u32 ... 的数组都可以实现 hash 值计算 +/// Sample: +/// ``` +/// let hash = vec!['a','b','c'].to_hash(); +/// ``` +impl ToHash for Vec { + fn to_hash(&self) -> u32 { + todo!() + } +} + +/// 所有基本类型 u8, i8, u16, u32 ... 的slice都可以实现 hash 值计算 +/// Sample: +/// ``` +/// let buf = ['a','b','c']; +/// let hash = &buf.to_hash(); +/// ``` +impl ToHash for &[T] { + fn to_hash(&self) -> u32 { + todo!() + } +} - Hash::hash_char(data_u8_vec, data_size, seed) +impl ToHash for Slice { + fn to_hash(&self) -> u32 { + todo!() } +} - pub fn hash_char(data: &Vec, data_size: usize, seed: u32) -> u32 { - let murmur_hash : u32 = 0xc6a4a793; - let r : u32 = 24; +impl ToHash for String { + fn to_hash(&self) -> u32 { + todo!() + } +} - let limit: usize = data_size; - let mul_first = data_size.mul(murmur_hash as usize); // x = data_size * murmur_hash +/// 本方案中,采用的是MurMurHash的一种变体,是一种高效低碰撞的非加密型哈希函数。具有较高的平衡性与低碰撞率 +pub struct Hash {} + +impl Hash { + pub fn hash_char(data: &[u8], seed: u32) -> u32 { + let murmur_hash: u32 = 0xc6a4a793; + let r: u32 = 24; + + let limit: usize = data.len(); + let mul_first = limit.mul(murmur_hash as usize); // x = data_size * murmur_hash let mut h: u32 = seed.bitxor(mul_first as u32); // h = seed ^ x // 每次按照四字节长度读取字节流中的数据 w,并使用普通的哈希函数计算哈希值。 @@ -45,8 +61,7 @@ impl<'a> Hash { while position + 4 <= limit { //每次解码前4个字节,直到最后剩下小于4个字节 // rust的 &[u8] 是胖指针,带长度信息的,会做range check,所以是安全的。 - let slice_str: &[u8] = data[position..(position + 4)].as_ref(); - let w: u32 = Coding::decode_fixed32(slice_str); + let w = Coding::decode_fixed32(&data[position..]); // 向后移动4个字节 position += 4; @@ -67,22 +82,19 @@ impl<'a> Hash { while limit - position - mark != 0 { match limit - position - mark { 3 => { - let us: &[u8] = data[position..].as_ref(); - let as_us: u32 = us[2] as u32; + let as_us: u32 = data[position + 2] as u32; h = h.wrapping_add(as_us.wrapping_shl(16)); mark += 1; - }, + } 2 => { - let us: &[u8] = data[position..].as_ref(); - let as_us: u32 = us[1] as u32; - h = h.wrapping_add( as_us.wrapping_shl(8)); + let as_us: u32 = data[position + 1] as u32; + h = h.wrapping_add(as_us.wrapping_shl(8)); mark += 1; - }, + } 1 => { - let us: &[u8] = data[position..].as_ref(); - let as_us: u32 = us[0] as u32; + let as_us: u32 = data[position] as u32; h = h.wrapping_add(as_us); // h *= m h = h.wrapping_mul(murmur_hash); @@ -90,7 +102,7 @@ impl<'a> Hash { h = h.bitxor(h.wrapping_shr(r)); mark += 1; - }, + } _ => { println!("0") } diff --git a/src/util/hash_test.rs b/src/util/hash_test.rs index 770192b..e02bd4b 100644 --- a/src/util/hash_test.rs +++ b/src/util/hash_test.rs @@ -3,15 +3,15 @@ use crate::util::hash::{Hash}; #[test] fn test_hash() { let val = "aabbccd"; - let hash_val = Hash::hash(String::from(val), val.len(), 3); + let hash_val = Hash::hash_char(val.as_bytes(), 3); println!("hash:{}", hash_val); let val = "aabbcc"; - let hash_val = Hash::hash(String::from(val), val.len(), 3); + let hash_val = Hash::hash_char(val.as_bytes(), 3); println!("hash:{}", hash_val); let val = "aabbc"; - let hash_val = Hash::hash(String::from(val), val.len(), 3); + let hash_val = Hash::hash_char(val.as_bytes(), 3); println!("hash:{}", hash_val); } @@ -34,20 +34,20 @@ fn test_hash_code() { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; - let hash_val = Hash::hash_char(&vec![0], 0, 0xbc9f1d34); + let hash_val = Hash::hash_char(&vec![0],0xbc9f1d34); assert_eq!(0xbc9f1d34, hash_val); - let hash_val = Hash::hash_char(&data1, data1.len(), 0xbc9f1d34); + let hash_val = Hash::hash_char(&data1, 0xbc9f1d34); assert_eq!(0xef1345c4, hash_val); - let hash_val = Hash::hash_char(&data2, data2.len(), 0xbc9f1d34); + let hash_val = Hash::hash_char(&data2, 0xbc9f1d34); assert_eq!(0x5b663814, hash_val); - let hash_val = Hash::hash_char(&data3, data3.len(), 0xbc9f1d34); + let hash_val = Hash::hash_char(&data3, 0xbc9f1d34); assert_eq!(0x323c078f, hash_val); - let hash_val = Hash::hash_char(&data4, data4.len(), 0xbc9f1d34); + let hash_val = Hash::hash_char(&data4, 0xbc9f1d34); assert_eq!(0xed21633a, hash_val); - let hash_val = Hash::hash_char(&data5, data5.len(), 0x12345678); + let hash_val = Hash::hash_char(&data5, 0x12345678); assert_eq!(0xf333dabb, hash_val); } -- Gitee From 8b2d857e28525bf9056059c24a1830150bc3d999 Mon Sep 17 00:00:00 2001 From: wangboo <5417808+wangboa@user.noreply.gitee.com> Date: Sat, 17 Dec 2022 11:04:11 +0800 Subject: [PATCH 07/13] add &str to impl ToHash trait --- src/util/hash.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/util/hash.rs b/src/util/hash.rs index 2fd4e0b..ec6ef7e 100644 --- a/src/util/hash.rs +++ b/src/util/hash.rs @@ -32,6 +32,17 @@ impl ToHash for &[T] { } } +/// 实现了 &str 转 ToHash 的特质 +/// Sample: +/// ``` +/// let hash = "abc".to_hash(); +/// ``` +impl ToHash for &str { + fn to_hash(&self) -> u32 { + todo!() + } +} + impl ToHash for Slice { fn to_hash(&self) -> u32 { todo!() -- Gitee From 891b28136c29337063f68cb8ec7ce064776d439e Mon Sep 17 00:00:00 2001 From: zhengcheng Date: Sat, 17 Dec 2022 11:10:57 +0800 Subject: [PATCH 08/13] =?UTF-8?q?=E8=A1=A5=E5=85=85=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/histogram.rs | 114 +++++++++++++++++++++++++++++++------ src/util/histogram_test.rs | 7 ++- 2 files changed, 101 insertions(+), 20 deletions(-) diff --git a/src/util/histogram.rs b/src/util/histogram.rs index 5a0145b..f5d76ca 100644 --- a/src/util/histogram.rs +++ b/src/util/histogram.rs @@ -164,7 +164,7 @@ pub struct Histogram { max: f64, num: f64, sum: f64, - sumSquares: f64, + sum_squares: f64, buckets: [f64; K_NUM_BUCKETS] } @@ -175,7 +175,7 @@ impl Default for Histogram { max: 0.0, num: 0.0, sum: 0.0, - sumSquares: 0.0, + sum_squares: 0.0, buckets: [0.0; K_NUM_BUCKETS] } } @@ -231,7 +231,7 @@ impl Histogram { self.max = 0.0; self.num = 0.0; self.sum = 0.0; - self.sumSquares = 0.0; + self.sum_squares = 0.0; for i in 0..K_NUM_BUCKETS { self.buckets[i] = 0.0; } @@ -265,7 +265,7 @@ impl Histogram { } self.num += 1.0; self.sum += value; - self.sumSquares += value * value; + self.sum_squares += value * value; } /// 合并另一个直方图的数据到当前直方图 /// @@ -291,17 +291,17 @@ impl Histogram { } self.num += other.num; self.sum += other.sum; - self.sumSquares += other.sumSquares; + self.sum_squares += other.sum_squares; for i in 0..K_NUM_BUCKETS { self.buckets[i] += other.buckets[i]; } } - /// + /// 计算处于p%位置的值既第p百分位数 /// /// # Arguments /// - /// * `p`: + /// * `p`:百分位 /// /// returns: f64 /// @@ -311,17 +311,17 @@ impl Histogram { /// /// ``` fn percentile(&self, p :f64) -> f64 { - let threhold = self.num * ( p / 100.0); + let threshold = self.num * ( p / 100.0); let mut sum :f64 = 0.0; for i in 0..K_NUM_BUCKETS { sum += self.buckets[i]; - if sum >= threhold { - let leftPoint :f64 = if i == 0 {0.0} else {K_BUCKET_LIMIT[i - 1]}; - let rightPoint :f64 = K_BUCKET_LIMIT[i]; - let leftSum :f64 = sum - self.buckets[i]; - let rightSum :f64 = sum; - let pos :f64 = (threhold - leftSum) / (rightSum - leftSum); - let mut r :f64 = leftPoint + (rightPoint - leftPoint) * pos; + if sum >= threshold { + let left_point :f64 = if i == 0 {0.0} else {K_BUCKET_LIMIT[i - 1]}; + let right_point :f64 = K_BUCKET_LIMIT[i]; + let left_sum :f64 = sum - self.buckets[i]; + let right_sum :f64 = sum; + let pos :f64 = (threshold - left_sum) / (right_sum - left_sum); + let mut r :f64 = left_point + (right_point - left_point) * pos; if r < self.min { r = self.min; } @@ -334,11 +334,35 @@ impl Histogram { return self.max; } + /// 计算中位数 + /// + /// # Arguments + /// + /// + /// returns: f64 + /// + /// # Examples + /// + /// ``` + /// + /// ``` + #[inline] fn median(&self) -> f64 { return self.percentile(50.0); } - /// 求平均值 + /// 计算平均值 + /// + /// # Arguments + /// + /// + /// returns: f64 + /// + /// # Examples + /// + /// ``` + /// + /// ``` fn average(&self) -> f64 { if self.sum == 0.0 { return 0.0; @@ -346,11 +370,67 @@ impl Histogram { return self.sum / self.num; } + /// 计算标准偏差 + /// + /// # Arguments + /// + /// + /// returns: f64 + /// + /// # Examples + /// + /// ``` + /// + /// ``` fn standard_deviation(&self) -> f64 { if self.sum == 0.0 { return 0.0; } - let variance = (self.sumSquares * self.num - self.sum * self.sum) / (self.num * self.num); + let variance = (self.sum_squares * self.num - self.sum * self.sum) / (self.num * self.num); return variance.sqrt(); } +} + +#[test] +fn test_add() { + let mut histogram = Histogram::default(); + histogram.add(2.0); + histogram.add(20.0); + assert_eq!(2.0, histogram.num); + assert_eq!(22.0, histogram.sum); + assert_eq!(2.0, histogram.min); + assert_eq!(20.0, histogram.max); + assert_eq!(404.0, histogram.sum_squares); + assert_eq!(1.0, histogram.buckets[2]); + assert_eq!(1.0, histogram.buckets[15]); + assert_eq!(11.0, histogram.average()); + assert_eq!(2.6, histogram.percentile(30.0)); + assert_eq!(3.0, histogram.median()); + assert_eq!(11.0, histogram.average()); + assert_eq!(9.0, histogram.standard_deviation()); + print!("{}", histogram.to_string()); +} + +#[test] +fn test_merge() { + let mut histogram = Histogram::default(); + histogram.add(2.0); + let mut other = Histogram::default(); + other.add(20.0); + histogram.merge(&other); + assert_eq!(2.0, histogram.num); + assert_eq!(22.0, histogram.sum); + assert_eq!(2.0, histogram.min); + assert_eq!(20.0, histogram.max); + assert_eq!(404.0, histogram.sum_squares); + assert_eq!(1.0, histogram.buckets[2]); + assert_eq!(1.0, histogram.buckets[15]); + histogram.clear(); + assert_eq!(0.0, histogram.num); + assert_eq!(0.0, histogram.sum); + assert_eq!(1e200, histogram.min); + assert_eq!(0.0, histogram.max); + assert_eq!(0.0, histogram.sum_squares); + assert_eq!(0.0, histogram.buckets[2]); + assert_eq!(0.0, histogram.buckets[15]); } \ No newline at end of file diff --git a/src/util/histogram_test.rs b/src/util/histogram_test.rs index 50c5a58..a4f01e7 100644 --- a/src/util/histogram_test.rs +++ b/src/util/histogram_test.rs @@ -5,9 +5,10 @@ mod test{ #[test] fn test_add() { let mut histogram = Histogram::default(); - histogram.add(1.0); - histogram.add(0.2); - histogram.add(6.0); + histogram.add(2.0); + let mut other = Histogram::default(); + other.add(20.0); print!("{}", histogram.to_string()); + print!("{}", other.to_string()); } } -- Gitee From a96294a65c4ed792b6041020fd678c47eb278865 Mon Sep 17 00:00:00 2001 From: fengyang Date: Sat, 17 Dec 2022 12:09:59 +0800 Subject: [PATCH 09/13] hash test fix --- src/util/hash.rs | 3 ++- src/util/hash_test.rs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/util/hash.rs b/src/util/hash.rs index ec6ef7e..c60f0c1 100644 --- a/src/util/hash.rs +++ b/src/util/hash.rs @@ -72,7 +72,8 @@ impl Hash { while position + 4 <= limit { //每次解码前4个字节,直到最后剩下小于4个字节 // rust的 &[u8] 是胖指针,带长度信息的,会做range check,所以是安全的。 - let w = Coding::decode_fixed32(&data[position..]); + // 虽然decode_fixed32 中也是解码4字节,但传入整个data在方法上不明确,因此传 [position..(position + 4)], 可以更加方便理解,对性能无影响 + let w = Coding::decode_fixed32(&data[position..(position + 4)]); // 向后移动4个字节 position += 4; diff --git a/src/util/hash_test.rs b/src/util/hash_test.rs index e02bd4b..06b6168 100644 --- a/src/util/hash_test.rs +++ b/src/util/hash_test.rs @@ -34,7 +34,7 @@ fn test_hash_code() { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; - let hash_val = Hash::hash_char(&vec![0],0xbc9f1d34); + let hash_val = Hash::hash_char(&vec![],0xbc9f1d34); assert_eq!(0xbc9f1d34, hash_val); let hash_val = Hash::hash_char(&data1, 0xbc9f1d34); -- Gitee From 973200a921b871530f032d958773113f305b909e Mon Sep 17 00:00:00 2001 From: zhengcheng Date: Sat, 17 Dec 2022 12:51:54 +0800 Subject: [PATCH 10/13] =?UTF-8?q?=E4=BA=92=E6=96=A5=E9=94=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/mod.rs | 2 + src/util/mutex_lock.rs | 75 +++++++++++++++++++++++++++++++++++++ src/util/mutex_lock_test.rs | 27 +++++++++++++ 3 files changed, 104 insertions(+) create mode 100644 src/util/mutex_lock.rs create mode 100644 src/util/mutex_lock_test.rs diff --git a/src/util/mod.rs b/src/util/mod.rs index dab1d24..d2f931c 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -29,3 +29,5 @@ pub mod histogram; mod histogram_test; mod hash; mod hash_test; +mod mutex_lock; +mod mutex_lock_test; diff --git a/src/util/mutex_lock.rs b/src/util/mutex_lock.rs new file mode 100644 index 0000000..02efe82 --- /dev/null +++ b/src/util/mutex_lock.rs @@ -0,0 +1,75 @@ +use std::ops::Deref; +use std::sync::{Arc, LockResult, Mutex, MutexGuard, TryLockResult}; + +pub struct Lock { + lock: Arc>, +} + +/// 线程内使用的锁对象 +impl Lock { + #[inline] + fn new(t: Arc>) -> Self { + Self { + lock: t + } + } + + #[inline] + pub fn lock(&self) -> LockResult> { + self.lock.lock() + } + + #[inline] + pub fn try_lock(&self) -> TryLockResult> { + self.lock.try_lock() + } +} + +/// 互斥锁 +pub struct MutexLock { + mutex_hold: Arc>, +} + +impl MutexLock { + /// 构建互斥锁 + /// + /// # Arguments + /// + /// * `t`: 锁对象 + /// + /// returns: MutexLock + /// + /// # Examples + /// + /// ``` + /// let mutex_lock = MutexLock::new(0); + /// ``` + #[inline] + pub fn new(t: T) -> Self { + Self { + mutex_hold: Arc::new(Mutex::new(t)) + } + } + + /// 获取用于move的锁对象 + /// + /// # Arguments + /// + /// + /// returns: MutexLock + /// + /// # Examples + /// + /// ``` + /// let mutex_lock = MutexLock::new(0); + /// let lock = mutex_lock.get_lock(); /// + /// let handle = thread::spawn(move || { + /// let mut num = lock.lock().unwrap(); + /// *num += 1; + /// }); + /// ``` + #[inline] + pub fn get_lock(&self) -> Lock { + return Lock::new(Arc::clone(&self.mutex_hold)); + } +} diff --git a/src/util/mutex_lock_test.rs b/src/util/mutex_lock_test.rs new file mode 100644 index 0000000..7273a71 --- /dev/null +++ b/src/util/mutex_lock_test.rs @@ -0,0 +1,27 @@ +mod test { + use std::thread; + + use crate::util::mutex_lock::MutexLock; + + #[test] + fn test() { + let mutex_lock = MutexLock::new(0); + let mut handles = vec![]; + + for _ in 0..10 { + let lock = mutex_lock.get_lock(); + let handle = thread::spawn(move || { + let mut num = lock.lock().unwrap(); + + *num += 1; + }); + handles.push(handle); + } + + for handle in handles { + handle.join().unwrap(); + } + + println!("Result: {}", mutex_lock.get_lock().lock().unwrap()); + } +} \ No newline at end of file -- Gitee From 2abe4ffeeea6795b96b59b9e939477f4dc6fd9de Mon Sep 17 00:00:00 2001 From: zhengcheng Date: Sat, 17 Dec 2022 12:54:23 +0800 Subject: [PATCH 11/13] =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/mutex_lock.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/mutex_lock.rs b/src/util/mutex_lock.rs index 02efe82..84e6d65 100644 --- a/src/util/mutex_lock.rs +++ b/src/util/mutex_lock.rs @@ -62,7 +62,7 @@ impl MutexLock { /// /// ``` /// let mutex_lock = MutexLock::new(0); - /// let lock = mutex_lock.get_lock(); /// + /// let lock = mutex_lock.get_lock(); /// let handle = thread::spawn(move || { /// let mut num = lock.lock().unwrap(); /// *num += 1; -- Gitee From dcee6c20f6195dec93050627c382b0fb64ca7705 Mon Sep 17 00:00:00 2001 From: fengyang Date: Sat, 17 Dec 2022 14:34:35 +0800 Subject: [PATCH 12/13] =?UTF-8?q?ToHash=20=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +- src/util/const.rs | 3 ++ src/util/hash.rs | 28 +++++++++---- src/util/hash_test.rs | 93 ++++++++++++++++++++++++++++++++++++++----- 4 files changed, 109 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index dc51f61..da9d596 100644 --- a/README.md +++ b/README.md @@ -46,9 +46,9 @@ LevelDB for rust | Coding (Primitive Type SerDe) | colagy | | | Comparator | fengyang | 85% | | Status | fengyang | 100% | -| BloomFilter | fengyang | 0% | +| BloomFilter | fengyang | 10% | | CRC | wangboo、lxd5866 | | | Env | lxd5866 | | -| Hash | fengyang | 100% | +| Hash | fengyang | 100% | | MutexLock | kazeseiriou | | | Histgram | kazeseiriou | | \ No newline at end of file diff --git a/src/util/const.rs b/src/util/const.rs index e7d7eac..b57d833 100644 --- a/src/util/const.rs +++ b/src/util/const.rs @@ -2,3 +2,6 @@ /// 冒号 + 空格 pub const COLON_WHITE_SPACE: &'static str = ": "; + +/// hash 的默认seed +pub const HASH_DEFAULT_SEED: u32 = 0xbc9f1d34; diff --git a/src/util/hash.rs b/src/util/hash.rs index c60f0c1..bc8c601 100644 --- a/src/util/hash.rs +++ b/src/util/hash.rs @@ -1,7 +1,12 @@ use std::ops::{BitXor, Mul}; +use std::mem::size_of; +use std::slice as stds; use crate::traits::coding_trait::CodingTrait; use crate::util::coding::Coding; +use crate::util::crc::AsCrc; +use crate::util::r#const::HASH_DEFAULT_SEED; +use crate::util::slice; use crate::util::slice::Slice; /// 一种可以计算 hash 的特质 @@ -16,7 +21,9 @@ pub trait ToHash { /// ``` impl ToHash for Vec { fn to_hash(&self) -> u32 { - todo!() + let v_v = self.as_slice(); + + v_v.to_hash() } } @@ -24,11 +31,18 @@ impl ToHash for Vec { /// Sample: /// ``` /// let buf = ['a','b','c']; -/// let hash = &buf.to_hash(); +/// let hash_val = &buf.as_slice().to_hash(); /// ``` impl ToHash for &[T] { + #[inline] fn to_hash(&self) -> u32 { - todo!() + let ptr_u8 = self.as_ptr() as *const _ as *const u8; + + let data = unsafe { + stds::from_raw_parts(ptr_u8, size_of::() * self.len()) + }; + + Hash::hash_code(data, HASH_DEFAULT_SEED) } } @@ -39,19 +53,19 @@ impl ToHash for &[T] { /// ``` impl ToHash for &str { fn to_hash(&self) -> u32 { - todo!() + Hash::hash_code(self.as_bytes(), HASH_DEFAULT_SEED) } } impl ToHash for Slice { fn to_hash(&self) -> u32 { - todo!() + Hash::hash_code(self.to_vec().as_slice(), HASH_DEFAULT_SEED) } } impl ToHash for String { fn to_hash(&self) -> u32 { - todo!() + Hash::hash_code(self.as_bytes(), HASH_DEFAULT_SEED) } } @@ -59,7 +73,7 @@ impl ToHash for String { pub struct Hash {} impl Hash { - pub fn hash_char(data: &[u8], seed: u32) -> u32 { + pub fn hash_code(data: &[u8], seed: u32) -> u32 { let murmur_hash: u32 = 0xc6a4a793; let r: u32 = 24; diff --git a/src/util/hash_test.rs b/src/util/hash_test.rs index 06b6168..81dce89 100644 --- a/src/util/hash_test.rs +++ b/src/util/hash_test.rs @@ -1,17 +1,20 @@ -use crate::util::hash::{Hash}; +use crate::util::hash::{Hash, ToHash}; +use crate::util::r#const::HASH_DEFAULT_SEED; +use crate::util::slice::Slice; +use std::slice; #[test] fn test_hash() { let val = "aabbccd"; - let hash_val = Hash::hash_char(val.as_bytes(), 3); + let hash_val = Hash::hash_code(val.as_bytes(), 3); println!("hash:{}", hash_val); let val = "aabbcc"; - let hash_val = Hash::hash_char(val.as_bytes(), 3); + let hash_val = Hash::hash_code(val.as_bytes(), 3); println!("hash:{}", hash_val); let val = "aabbc"; - let hash_val = Hash::hash_char(val.as_bytes(), 3); + let hash_val = Hash::hash_code(val.as_bytes(), 3); println!("hash:{}", hash_val); } @@ -34,20 +37,90 @@ fn test_hash_code() { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; - let hash_val = Hash::hash_char(&vec![],0xbc9f1d34); + let hash_val = Hash::hash_code(&vec![], 0xbc9f1d34); assert_eq!(0xbc9f1d34, hash_val); - let hash_val = Hash::hash_char(&data1, 0xbc9f1d34); + let hash_val = Hash::hash_code(&data1, 0xbc9f1d34); assert_eq!(0xef1345c4, hash_val); - let hash_val = Hash::hash_char(&data2, 0xbc9f1d34); + let hash_val = Hash::hash_code(&data2, 0xbc9f1d34); assert_eq!(0x5b663814, hash_val); - let hash_val = Hash::hash_char(&data3, 0xbc9f1d34); + let hash_val = Hash::hash_code(&data3, 0xbc9f1d34); assert_eq!(0x323c078f, hash_val); - let hash_val = Hash::hash_char(&data4, 0xbc9f1d34); + let hash_val = Hash::hash_code(&data4, 0xbc9f1d34); assert_eq!(0xed21633a, hash_val); - let hash_val = Hash::hash_char(&data5, 0x12345678); + let hash_val = Hash::hash_code(&data5, 0x12345678); assert_eq!(0xf333dabb, hash_val); } + +#[test] +fn test_string_to_hash() { + let val = "aabbccd"; + let hash_val_get = Hash::hash_code(val.as_bytes(), HASH_DEFAULT_SEED); + println!("hash_val_get:{}", hash_val_get); + + let val_s = String::from(val); + let string_hash_val = val_s.to_hash(); + println!("string_hash_val:{}", string_hash_val); + + assert_eq!(hash_val_get, string_hash_val); +} + +#[test] +fn test_slice_to_hash() { + let val = "aabbccd"; + let slice: Slice = Slice::from_buf(val.as_bytes()); + let slice_hash_val = slice.to_hash(); + println!("slice_hash_val:{}", slice_hash_val); + + let hash_val_get = Hash::hash_code(slice.to_vec().as_slice(), HASH_DEFAULT_SEED); + println!("hash_code:{}", hash_val_get); + + assert_eq!(hash_val_get, slice_hash_val); +} + +#[test] +fn test_str_to_hash() { + let str = "aabbccd"; + let str_hash_val = str.to_hash(); + println!("str_hash_val:{}", str_hash_val); + + let hash_val_get = Hash::hash_code(str.as_bytes(), HASH_DEFAULT_SEED); + println!("hash_code:{}", hash_val_get); + + assert_eq!(hash_val_get, str_hash_val); +} + +#[test] +fn test_size_base_to_hash() { + // 所有基本类型 u8, i8, u16, u32 + + let buf = ['a','b','c']; + let char_hash_val = &buf.as_slice().to_hash(); + println!("char_hash_val:{}", char_hash_val); + + let buf = ["aa", "bb", "cc"].as_slice(); + let string_hash_val = &buf.to_hash(); + println!("string_hash_val:{}", string_hash_val); + + let buf = [1, 2, u32::MAX].as_slice(); + let u32_hash_val = &buf.to_hash(); + println!("u32_hash_val:{}", u32_hash_val); +} + +#[test] +fn test_size_vec_to_hash() { + let buf = vec!['a','b','c']; + let char_hash_val = buf.to_hash(); + println!("char_hash_val:{}", char_hash_val); + + let buf = ["aa", "bb", "cc"].as_slice(); + let string_hash_val = &buf.to_hash(); + println!("string_hash_val:{}", string_hash_val); + + let buf = [1, 2, u32::MAX].as_slice(); + let u32_hash_val = &buf.to_hash(); + println!("u32_hash_val:{}", u32_hash_val); +} -- Gitee From 49aac72cc39d37e76422d1af0fff52bf25d4e5f8 Mon Sep 17 00:00:00 2001 From: fengyang Date: Sat, 17 Dec 2022 14:38:52 +0800 Subject: [PATCH 13/13] ToHash doc --- README.md | 2 +- src/util/hash.rs | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index da9d596..cb49cd3 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ LevelDB for rust | Random | colagy | | | Cache | colagy | | | Coding (Primitive Type SerDe) | colagy | | -| Comparator | fengyang | 85% | +| Comparator | fengyang | 90% | | Status | fengyang | 100% | | BloomFilter | fengyang | 10% | | CRC | wangboo、lxd5866 | | diff --git a/src/util/hash.rs b/src/util/hash.rs index bc8c601..fef5dc5 100644 --- a/src/util/hash.rs +++ b/src/util/hash.rs @@ -57,12 +57,26 @@ impl ToHash for &str { } } +/// 实现了 Slice 转 ToHash 的特质 +/// Sample: +/// ``` +/// let val = "aabbccd"; +/// let slice: Slice = Slice::from_buf(val.as_bytes()); +/// let slice_hash_val = slice.to_hash(); +/// ``` impl ToHash for Slice { fn to_hash(&self) -> u32 { Hash::hash_code(self.to_vec().as_slice(), HASH_DEFAULT_SEED) } } +/// 实现了 String 转 ToHash 的特质 +/// Sample: +/// ``` +/// let val = "aabbccd"; +/// let val_s = String::from(val); +/// let string_hash_val = val_s.to_hash(); +/// ``` impl ToHash for String { fn to_hash(&self) -> u32 { Hash::hash_code(self.as_bytes(), HASH_DEFAULT_SEED) -- Gitee