diff --git a/README.md b/README.md index 725b3742f0042e0e7527cdcbbbe8f727571c57c7..b7d8eb048e93d12fb311db0d718cdbb1174b36f0 100644 --- a/README.md +++ b/README.md @@ -37,18 +37,18 @@ LevelDB for rust 1. 1.0.0 版本, 完成 util 相关的内容 -| 功能模块 | 完成人 | -|-------------------------------|-------------| -| Arena (Memory Management) | wangboo | -| Slice | wangboo | -| Random | colagy | -| Cache | colagy | -| Coding (Primitive Type SerDe) | colagy | -| Comparator | fengyang | -| Status | fengyang | -| BloomFilter | fengyang | -| CRC | lxd5866 | -| Env | lxd5866 | -| Hash | lxd5866 | -| MutexLock | kazeseiriou | -| Histgram | kazeseiriou | \ No newline at end of file +| 功能模块 | 完成人 | 进度 | +|-------------------------------|-----------------|------| +| Arena (Memory Management) | wangboo | | +| Slice | wangboo | | +| Random | colagy | | +| Cache | colagy | | +| Coding (Primitive Type SerDe) | colagy | | +| Comparator | fengyang | 85% | +| Status | fengyang | 100% | +| BloomFilter | fengyang | 0% | +| CRC | wangboo、lxd5866 | | +| Env | lxd5866 | | +| Hash | fengyang | 30% | +| MutexLock | kazeseiriou | | +| Histgram | kazeseiriou | | \ No newline at end of file diff --git a/src/traits/comparator_trait.rs b/src/traits/comparator_trait.rs index 2d82ba61e3015c65c5a62f3b895a370fe4b43045..47388a276f6f79912f5cbba844eeaf54f882aa61 100644 --- a/src/traits/comparator_trait.rs +++ b/src/traits/comparator_trait.rs @@ -31,28 +31,46 @@ pub trait ComparatorTrait { /// 返回comparator的名字 fn get_name() -> String; - /// 函数:用于减少像index blocks这样的内部数据结构占用的空间, 其中的*start和*key参数都是IN OUT的。 + /// 函数:找到start、limit之间最短的字符串,如“helloworld”和”hellozoomer”之间最短的key可以是”hellox” /// - /// 这个函数的作用就是: - /// 如果*start < limit,就在[startlimit,)中找到一个短字符串,并赋给*start返回. 如“helloworld”和”hellozoomer”之间最短的key可以是”hellox”。 - /// 简单的comparator实现可能不改变*start(start==limit),这也是正确的 + /// 作用是, + /// 如果start < limit,就把start修改为 start和limit的共同前缀, 后面多一个字符加1 + /// + /// 例如: + /// start: helloWorld + /// limit: helloZookeeper + /// 由于 start < limit, 所以调用 FindShortSuccessor(start, limit)之后, + /// start变成: helloX (保留前缀,第一个不相同的字符+1) /// /// # Arguments /// - /// * `start`: - /// * `limit`: + /// * `start`: String + /// * `limit`: Slice /// /// returns: String /// /// # Examples /// /// ``` - /// + /// let comp = BytewiseComparatorImpl::default(); + /// let find_shortest_separator_val = comp.find_shortest_separator( + /// &String::from("abcdefghijklimA"), + /// &Slice::from("abcdefghijklimNy")); + /// /// A < N + /// assert_eq!(find_shortest_separator_val, "abcdefghijklimB"); + /// + /// let comp = BytewiseComparatorImpl::default(); + /// let find_shortest_separator_val = comp.find_shortest_separator( + /// &String::from("abcdefghijklima"), + /// &Slice::from("abcdefghijklimNy")); + /// /// a > N + /// assert_eq!(find_shortest_separator_val, "abcdefghijklima"); /// ``` fn find_shortest_separator(&self, start: &String, limit:&Slice) -> String; - /// 找一个 >= key的短字符串, key变成一个比原*key大的短字符串,并返回。 - /// 简单的comparator实现可能不改变 key,这也是正确的 + /// 用于找到比key大的最短字符串,如传入“helloworld”,返回的key可能是“i” + /// + /// 找一个 >= key的短字符串, key变成一个比原key大的短字符串,并返回。 /// /// # Arguments /// diff --git a/src/util/comparator.rs b/src/util/comparator.rs index 51d0123401b905707ea0e210c3f534021311860a..173c68a6ab8a098de67c6c6c721b40e4eafaa2cb 100644 --- a/src/util/comparator.rs +++ b/src/util/comparator.rs @@ -1,12 +1,20 @@ -use std::cmp::Ordering; +use std::cmp::{min, Ordering}; use crate::traits::comparator_trait::{ComparatorTrait}; use crate::util::slice::Slice; -/// BytewiseComparatorImpl是按字典逐字节序进行比较 -/// 也就是说 i>helloworld,因为先比较i和h,i>h,比较直接结束 pub struct BytewiseComparatorImpl {} +/// +/// compare: +/// 按字典逐字节序进行比较 +/// 也就是说 i>helloworld,因为先比较i和h,i>h,比较直接结束 +impl Default for BytewiseComparatorImpl { + fn default() -> Self { + Self{} + } +} + impl ComparatorTrait for BytewiseComparatorImpl { fn compare(&self, a: &Slice, b: &Slice) -> Option { @@ -18,17 +26,66 @@ impl ComparatorTrait for BytewiseComparatorImpl { } fn find_shortest_separator(&self, start: &String, limit: &Slice) -> String { - todo!() + // 首先计算共同前缀字符串的长度 + let min_length: usize = min(start.len(), limit.len()); + + let mut diff_index: usize = 0; + let mut start_char_vec: Vec = start.as_bytes().to_vec(); + let limit_char_vec: &Vec = &limit.to_vec(); + // or use + // let start_char_vec: Vec = start.chars().collect::>(); + // let limit_char_vec: Vec = limit.to_vec().iter().map(|b| *b as char).collect::>(); + + assert_eq!(u8::MAX, 255); + while diff_index < min_length && + start_char_vec[diff_index] == limit_char_vec[diff_index] + { + // Increment counter + diff_index += 1; + } + + // 如果一个字符串是另个一字符串的前缀,无需做截短操作,否则进入 else。 + if diff_index >= min_length { + // 说明 start是limit的前缀,或者反之,此时不作修改,直接返回 + } else{ + // 尝试执行字符start[diff_index]++, 设置start长度为diff_index+1,并返回 + // ++条件:字符 < oxff 并且字符+1 < limit上该index的字符 + let diff_byte: u8 = start_char_vec[diff_index]; + // let diff_char = diff_byte as char; + + if diff_byte < u8::MAX && + // 且 start 中的差异字符的next 小于 limit中的diff_index的字符, + // 则将 start 差异字符位置+1的元素变更为 差异字符的next + (diff_byte + 1) < limit_char_vec[diff_index] { + start_char_vec[diff_index] = diff_byte + 1; + } + } + + let shortest_separator: &[u8] = &start_char_vec[0..diff_index+1]; + + let shortest_separator_val: String= Slice::from_buf(shortest_separator).into(); + shortest_separator_val } fn find_short_successor(&self, key: &String) -> String { - todo!() - } -} + // 找到第一个可以++的字符,执行++后,截断字符串; + // 如果找不到说明 key的字符都是 u8::MAX,直接返回 + let key_len = key.len(); -impl Default for BytewiseComparatorImpl { - fn default() -> Self { - Self{} + let mut key_char_vec: Vec = key.as_bytes().to_vec(); + for i in 0..key_len { + let byte_val: u8 = key_char_vec[i]; + if byte_val != u8::MAX { + key_char_vec[i] = byte_val + 1; + + let short_successor: &[u8] = &key_char_vec[0..i+1]; + + let short_successor_val: String= Slice::from_buf(short_successor).into(); + return short_successor_val; + } + } + + Slice::from_buf(key.as_bytes()).into() } } @@ -46,7 +103,7 @@ pub struct InternalKeyComparator { impl ComparatorTrait for InternalKeyComparator { // todo InternalKeyComparator 的构造方法 - fn compare(&self, a: &Slice, b: &Slice) -> Option { + fn compare(&self, _a: &Slice, _b: &Slice) -> Option { todo!() } @@ -54,11 +111,11 @@ impl ComparatorTrait for InternalKeyComparator { String::from("leveldb.InternalKeyComparator") } - fn find_shortest_separator(&self, start: &String, limit: &Slice) -> String { + fn find_shortest_separator(&self, _start: &String, _limit: &Slice) -> String { todo!() } - fn find_short_successor(&self, key: &String) -> String { + fn find_short_successor(&self, _key: &String) -> String { todo!() } } diff --git a/src/util/comparator_test.rs b/src/util/comparator_test.rs index b7f3af3f607e412d6f037a15ba560bb0f41e5ba1..a9b28072864bafda6df6746c3cf8e86916aea592 100644 --- a/src/util/comparator_test.rs +++ b/src/util/comparator_test.rs @@ -1,6 +1,7 @@ mod test { use std::cmp::Ordering; + use std::io::Write; use crate::traits::comparator_trait::ComparatorTrait; use crate::util::comparator::{BytewiseComparatorImpl, InternalKeyComparator}; use crate::util::slice::Slice; @@ -8,7 +9,7 @@ mod test { #[test] fn test_bytewise_comparator_impl_get_name() { let name = BytewiseComparatorImpl::get_name(); - println!("{}", &name); + println!("get_name: {}", &name); assert_eq!("leveldb.BytewiseComparator", name); } @@ -18,6 +19,7 @@ mod test { let option_val = comp.compare(&Slice::from("a"), &Slice::from("ab")); assert_eq!(option_val.unwrap(), Ordering::Less); + // todo Slice 存在 bug 未修复 // let comp = BytewiseComparatorImpl::default(); // let option_val = comp.compare(&Slice::from("b"), &Slice::from("abcd")); // assert_eq!(option_val.unwrap(), Ordering::Greater); @@ -27,4 +29,103 @@ mod test { assert_eq!(option_val.unwrap(), Ordering::Equal); } + #[test] + fn test_bytewise_comparator_impl_find_shortest_separator() { + let comp = BytewiseComparatorImpl::default(); + let find_shortest_separator_val = comp.find_shortest_separator( + &String::from("helloWorld"), + &Slice::from("helloZookeeper")); + // W < Z + assert_eq!(find_shortest_separator_val, "helloX"); + + let comp = BytewiseComparatorImpl::default(); + let find_shortest_separator_val = comp.find_shortest_separator( + &String::from("abcdefghijklimx"), + &Slice::from("abcdefghijklimNy")); + // x(!X) > N + assert_eq!(find_shortest_separator_val, "abcdefghijklimx"); + + let comp = BytewiseComparatorImpl::default(); + let find_shortest_separator_val = comp.find_shortest_separator( + &String::from("abcdefghijklimA"), + &Slice::from("abcdefghijklimNy")); + // A < N + assert_eq!(find_shortest_separator_val, "abcdefghijklimB"); + + let comp = BytewiseComparatorImpl::default(); + let find_shortest_separator_val = comp.find_shortest_separator( + &String::from("abcdefghijklima"), + &Slice::from("abcdefghijklimNy")); + // a > N + assert_eq!(find_shortest_separator_val, "abcdefghijklima"); + + let comp = BytewiseComparatorImpl::default(); + let find_shortest_separator_val = comp.find_shortest_separator( + &String::from("abcdefghijklima"), + &Slice::from("abcdefghijklimny")); + // a < n + assert_eq!(find_shortest_separator_val, "abcdefghijklimb"); + } + + #[test] + fn test_bytewise_comparator_impl_find_short_successor() { + let comp = BytewiseComparatorImpl::default(); + let find_short_successor_val = comp.find_short_successor(&String::from("helloWorld")); + assert_eq!(find_short_successor_val, "i"); + + + let comp = BytewiseComparatorImpl::default(); + let find_short_successor_val = comp.find_short_successor(&String::from("a")); + assert_eq!(find_short_successor_val, "b"); + + + let comp = BytewiseComparatorImpl::default(); + let find_short_successor_val = comp.find_short_successor(&String::from("123")); + assert_eq!(find_short_successor_val, "2"); + + + // 只有 u8::MAX + let u8_max_vec: Vec = vec![u8::MAX]; + let u8_max_str = String::from(Slice::from_buf(u8_max_vec.as_slice())); + + let comp = BytewiseComparatorImpl::default(); + let find_short_successor_val = comp.find_short_successor(&u8_max_str); + assert_eq!(u8_max_str, find_short_successor_val); + + + // u8max 结尾 + let mut u8_vec: Vec = vec![]; + u8_vec.write(&String::from("helloWorld").as_bytes().to_vec()); + u8_vec.push(u8::MAX); + + let u8_array_str = String::from(Slice::from_buf(u8_vec.as_slice())); + + let comp = BytewiseComparatorImpl::default(); + let find_short_successor_val = comp.find_short_successor(&u8_array_str); + assert_eq!(find_short_successor_val, "i"); + + + // u8max 开头 + let mut u8_vec: Vec = vec![]; + u8_vec.push(u8::MAX); + u8_vec.write(&String::from("helloWorld").as_bytes().to_vec()); + let u8_max_str = String::from(Slice::from_buf(u8_vec.as_slice())); + + let comp = BytewiseComparatorImpl::default(); + let find_short_successor_val = comp.find_short_successor(&u8_max_str); + + // 只有 u8::MAX + let mut expect_u8_max_vec: Vec = vec![]; + expect_u8_max_vec.push(u8::MAX); + expect_u8_max_vec.write("i".as_bytes()).expect("panic message"); + assert_eq!(find_short_successor_val, + String::from(Slice::from_buf(expect_u8_max_vec.as_slice()))); + } + + #[test] + fn test_internal_key_comparator_get_name() { + let name = InternalKeyComparator::get_name(); + assert_eq!("leveldb.InternalKeyComparator", name); + } + } \ No newline at end of file diff --git a/src/util/hash.rs b/src/util/hash.rs new file mode 100644 index 0000000000000000000000000000000000000000..d383f2b80c66a6fef143d61dc3e40d8c17eaa93b --- /dev/null +++ b/src/util/hash.rs @@ -0,0 +1,21 @@ + +pub trait AsHash { + /// + /// + /// # Arguments + /// + /// * `data`: + /// * `n`: data 的长度 + /// * `seed`: 随机数种子 + /// + /// returns: u32 + /// + /// # Examples + /// + /// ``` + /// + /// ``` + fn hash(data: String, n: usize, seed: u32) -> u32; +} + +pub struct Hash {} \ No newline at end of file diff --git a/src/util/hash_test.rs b/src/util/hash_test.rs new file mode 100644 index 0000000000000000000000000000000000000000..0384579bac614a1d033fd08d59a0f40e9b67e2b8 --- /dev/null +++ b/src/util/hash_test.rs @@ -0,0 +1,6 @@ + +#[test] +fn test_hash() { + + +} \ No newline at end of file diff --git a/src/util/mod.rs b/src/util/mod.rs index b56627f691d2bb32cdbfa868f2e8f128cb856218..dab1d24d297957f4e18ca59351f54c9339b2759f 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1,5 +1,6 @@ use crate::util::status::LevelError; use std::result; +pub use arena::Arena; /// 常量定义 pub mod r#const; @@ -11,13 +12,12 @@ mod coding_test; pub mod arena; mod arena_test; -pub use arena::Arena; - pub mod status; mod status_test; pub mod comparator; mod comparator_test; mod crc; +mod crc_test; pub mod bloom_filter; mod bloom_filter_test; pub mod filter_policy; @@ -27,4 +27,5 @@ pub type ResultT = result::Result; pub mod histogram; mod histogram_test; -mod crc_test; +mod hash; +mod hash_test; diff --git a/src/util/status.rs b/src/util/status.rs index 9b534bda30f4f936a2ee7e70a7268fc016f5c52f..9bb66623c243973f9ded34923e2748f59a5350c3 100644 --- a/src/util/status.rs +++ b/src/util/status.rs @@ -1,5 +1,4 @@ use std::fmt::{Display, Error, Formatter}; -use std::ops::Deref; use crate::util::r#const::COLON_WHITE_SPACE; use crate::util::ResultT; use crate::util::slice::Slice; @@ -78,6 +77,10 @@ impl Status { self.err.is_invalid_argument() } + pub fn get_error_string(&self) -> String { + self.err.to_string() + } + /// 请注意, err 的所有权会发生转移!!! pub fn get_error(self) -> LevelError { self.err @@ -102,8 +105,8 @@ impl Status { /// assert_eq!("abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc: 456456456456456456456456456456456456456456456456", /// String::from(slice.unwrap())); /// ``` - pub fn into_msg(self) -> Option { - Some(self.msg) + pub fn into_msg(self) -> Slice { + self.msg } @@ -144,6 +147,29 @@ impl Status { } } +// impl Display for Status { +// fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { +// let mut print = String::new(); +// +// if self.is_ok() { +// print.push_str("OK"); +// write!(f, "{}", print); +// +// return Ok(()); +// } +// +// print.push_str(&self.get_error_string()); +// +// let slice: &Slice = &self.msg; +// let errMsg = String::from(slice); +// print.push_str(errMsg.as_str()); +// +// write!(f, "{}", print); +// +// Ok(()) +// } +// } + /// Status 的状态 pub enum LevelError { KOk, @@ -316,32 +342,23 @@ impl TryFrom for LevelError { } } -// /// 实现Display,自动提供to_string -// impl Display for LevelError { -// fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { -// let mut print = String::new(); -// -// if self.is_default() { -// print.push_str("OK"); -// return write!(f, "{}", print); -// } -// -// let msg_type = match self { -// KOk => "OK", -// KNotFound(_) => "NotFound: ", -// KCorruption(_) => "Corruption: ", -// KNotSupported(_) => "Not implemented: ", -// KInvalidArgument(_) => "Invalid argument: ", -// KIOError(_) => "IO error: " -// }; -// print.push_str(msg_type); -// -// let mut msg_err: Slice = self.into_msg().unwrap(); -// print.push_str(msg_err.borrow_data().as_str()); -// -// write!(f, "{}", print) -// } -// } +impl Display for LevelError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + let mut print = String::new(); + + let msg_type = match &self { + KOk => "OK", + KNotFound => "NotFound: ", + KCorruption => "Corruption: ", + KNotSupported => "Not implemented: ", + KInvalidArgument => "Invalid argument: ", + KIOError => "IO error: " + }; + print.push_str(msg_type); + + write!(f, "{}", print) + } +} // impl Deref for LevelError { // type Target = i32; diff --git a/src/util/status_test.rs b/src/util/status_test.rs index af745d0092f04023f07ccda66736d11eb0862202..eadccd312caf906153172263fc0ed1140f825d80 100644 --- a/src/util/status_test.rs +++ b/src/util/status_test.rs @@ -1,5 +1,6 @@ mod test { + use std::borrow::Cow; use crate::util::r#const::COLON_WHITE_SPACE; use crate::util::slice::Slice; use crate::util::status::{LevelError, Status}; @@ -10,9 +11,9 @@ mod test { let status = Status::wrapper(LevelError::KIOError, String::from(msg1).into()); assert!(&status.is_io_error()); - let slice: Option = status.into_msg(); + let slice: Slice = status.into_msg(); assert_eq!("abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc", - String::from(slice.unwrap())); + String::from(slice)); let ss = Status::wrapper(LevelError::KOk, String::from(msg1).into()); assert!(&ss.is_ok()); @@ -25,27 +26,27 @@ mod test { let msg2 = "456456456456456456456456456456456456456456456456"; let status = Status::wrappers(LevelError::KIOError, String::from(msg1).into(), String::from(msg2).into()); - let slice: Option = status.into_msg(); + let slice: Slice = status.into_msg(); assert_eq!("abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc: 456456456456456456456456456456456456456456456456", - String::from(slice.unwrap())); + String::from(slice)); let err: Status = LevelError::invalid_argument(String::from(msg1).into(), String::from(msg2).into()); - assert!(&err.get_error().is_invalid_argument()); + assert!(&err.is_invalid_argument()); // assert_eq!(err.into_code(), 4); let err: Status = LevelError::corruption(String::from(msg1).into(), String::from(msg2).into()); - assert!(&err.get_error().is_corruption()); + assert!(&err.is_corruption()); // assert_eq!(err.into_code(), 2); let err: Status = LevelError::not_found(String::from(msg1).into(), String::from(msg2).into()); - assert!(&err.get_error().is_not_found()); + assert!(&err.is_not_found()); let err: Status = LevelError::not_supported(String::from(msg1).into(), String::from(msg2).into()); - assert!(&err.get_error().is_not_supported_error()); + assert!(&err.is_not_supported_error()); let err: LevelError = LevelError::KOk; assert!(&err.is_ok()); @@ -55,7 +56,22 @@ mod test { } #[test] - fn test_toString() { + fn test_is_default() { + let err: Status = LevelError::ok(); + assert!(err.is_ok()); + + let err: Status = LevelError::io_error(String::from("a").into(), + String::from("b").into()); + assert!(!err.is_ok()); + + let status: Status = LevelError::not_found(String::from("a").into(), + String::from("b").into()); + assert!(status.is_not_found()); + assert!(status.get_error().is_not_found()); + } + + #[test] + fn test_status_to_string() { // ok let status: Status = LevelError::ok(); assert_eq!("OK", status.to_string()); @@ -84,21 +100,26 @@ mod test { } #[test] - fn test_is_default() { - let err: Status = LevelError::ok(); - assert!(err.get_error().is_ok()); + fn test_level_error_toString() { + // ok + let status: Status = LevelError::ok(); + assert_eq!("OK", status.to_string()); - let err: Status = LevelError::io_error(String::from("a").into(), - String::from("b").into()); - assert!(!err.get_error().is_ok()); + // err invalid_argument + let msg1 = "bcabcabcabcabcabcbc"; + let msg2 = "56"; + let error: Status = LevelError::invalid_argument(String::from(msg1).into(), + String::from(msg2).into()); + + let le_err: LevelError = error.get_error(); + println!("{}", &le_err); - // let err: LevelError = LevelError::ok(); - // let a = err.into(); - // print!("{}", a); + // Display + assert_eq!(String::from("Invalid argument: "), le_err.to_string()); } #[test] - fn test_try_from() -> Result<(), String> { + fn test_level_error_try_from() -> Result<(), String> { let rs = LevelError::try_from(1)?; assert!(&rs.is_not_found()); let rs: Result = 1.try_into();