From 6865b9e1116a10cdcd6449eaa76805bf06f78120 Mon Sep 17 00:00:00 2001 From: fengyang Date: Tue, 13 Dec 2022 21:49:38 +0800 Subject: [PATCH 1/4] =?UTF-8?q?BytewiseComparatorImpl=20=E7=BC=96=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/traits/comparator_trait.rs | 29 ++++++++++++++++++++++++----- src/util/comparator.rs | 15 +++++++++++++-- src/util/comparator_test.rs | 20 +++++++++++++++++++- 3 files changed, 56 insertions(+), 8 deletions(-) diff --git a/src/traits/comparator_trait.rs b/src/traits/comparator_trait.rs index 120b4ee..db2c4ba 100644 --- a/src/traits/comparator_trait.rs +++ b/src/traits/comparator_trait.rs @@ -1,15 +1,34 @@ use std::cmp::Ordering; use crate::util::slice::Slice; -/// A Comparator object provides a total order across slices that are -/// used as keys in an sstable or a database. A Comparator implementation -/// must be thread-safe since leveldb may invoke its methods concurrently -/// from multiple threads. +/// 比较器 pub trait ComparatorTrait { + /// Slice 的大小比较, 按字典逐字节序进行比较 + /// + /// # Arguments + /// + /// * `a`: 参与排序的 Slice + /// * `b`: 参与排序的 Slice + /// + /// returns: Option + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// let comp = BytewiseComparatorImpl::default(); + /// optionVal = comp.compare(&Slice::from("a"), &Slice::from("ab")); + /// assert_eq!(optionVal.unwrap(), Ordering::Less); + /// + /// let comp = BytewiseComparatorImpl::default(); + /// let optionVal = comp.compare(&Slice::from("b"), &Slice::from("abcd")); + /// assert_eq!(optionVal.unwrap(), Ordering::Greater); + /// ``` fn compare(&self, a: &Slice, b: &Slice) -> Option; - /// 返回comparator的名字 + // 返回comparator的名字 fn get_name() -> String; /// 找到start、limit之间最短的字符串,如“helloworld”和”hellozoomer”之间最短的key可以是”hellox”。 diff --git a/src/util/comparator.rs b/src/util/comparator.rs index 5067140..ba97acd 100644 --- a/src/util/comparator.rs +++ b/src/util/comparator.rs @@ -3,11 +3,14 @@ use std::cmp::Ordering; use crate::traits::comparator_trait::{ComparatorTrait}; use crate::util::slice::Slice; +/// BytewiseComparatorImpl是按字典逐字节序进行比较 +/// 也就是说 i>helloworld,因为先比较i和h,i>h,比较直接结束 pub struct BytewiseComparatorImpl {} impl ComparatorTrait for BytewiseComparatorImpl { + fn compare(&self, a: &Slice, b: &Slice) -> Option { - todo!() + a.partial_cmp(b) } fn get_name() -> String { @@ -23,6 +26,13 @@ impl ComparatorTrait for BytewiseComparatorImpl { } } +impl Default for BytewiseComparatorImpl { + fn default() -> Self { + Self{} + } +} + +/// InternalKeyComparator pub struct InternalKeyComparator { // fn user_comparator(&self) -> Box { // todo!() @@ -37,7 +47,7 @@ impl ComparatorTrait for InternalKeyComparator { // todo InternalKeyComparator 的构造方法 fn compare(&self, a: &Slice, b: &Slice) -> Option { - a.partial_cmp(b) + todo!() } fn get_name() -> String { @@ -53,6 +63,7 @@ impl ComparatorTrait for InternalKeyComparator { } } +/// ReverseKeyComparator pub struct ReverseKeyComparator { } diff --git a/src/util/comparator_test.rs b/src/util/comparator_test.rs index 897dee8..dea675f 100644 --- a/src/util/comparator_test.rs +++ b/src/util/comparator_test.rs @@ -1,12 +1,30 @@ mod test { + use std::cmp::Ordering; use crate::traits::comparator_trait::ComparatorTrait; use crate::util::comparator::{BytewiseComparatorImpl, InternalKeyComparator}; + use crate::util::slice::Slice; #[test] - fn test() { + fn test_bytewise_comparator_impl_get_name() { let name = BytewiseComparatorImpl::get_name(); println!("{}", &name); assert_eq!("leveldb.BytewiseComparator", name); } + + #[test] + fn test_bytewise_comparator_impl_compare() { + let comp = BytewiseComparatorImpl::default(); + let optionVal = comp.compare(&Slice::from("a"), &Slice::from("ab")); + assert_eq!(optionVal.unwrap(), Ordering::Less); + + let comp = BytewiseComparatorImpl::default(); + let optionVal = comp.compare(&Slice::from("b"), &Slice::from("abcd")); + assert_eq!(optionVal.unwrap(), Ordering::Greater); + + let comp = BytewiseComparatorImpl::default(); + let optionVal = comp.compare(&Slice::from("abcd"), &Slice::from("abcd")); + assert_eq!(optionVal.unwrap(), Ordering::Equal); + } + } \ No newline at end of file -- Gitee From 5a2ed75ba73fb6f6abc929aa598bdb205b89fc70 Mon Sep 17 00:00:00 2001 From: fengyang Date: Tue, 13 Dec 2022 23:05:22 +0800 Subject: [PATCH 2/4] status test --- src/traits/comparator_trait.rs | 23 ++++- src/traits/status_trait.rs | 5 +- src/util/status.rs | 148 +++++++++++++++++---------------- src/util/status_test.rs | 8 +- 4 files changed, 103 insertions(+), 81 deletions(-) diff --git a/src/traits/comparator_trait.rs b/src/traits/comparator_trait.rs index db2c4ba..54a3351 100644 --- a/src/traits/comparator_trait.rs +++ b/src/traits/comparator_trait.rs @@ -28,12 +28,27 @@ pub trait ComparatorTrait { /// ``` fn compare(&self, a: &Slice, b: &Slice) -> Option; - // 返回comparator的名字 + /// 返回comparator的名字 fn get_name() -> String; - /// 找到start、limit之间最短的字符串,如“helloworld”和”hellozoomer”之间最短的key可以是”hellox”。 - /// 如果 start < limit,就在[start,limit)中找到一个短字符串,并赋给*start返回。 - /// 当然返回的*start可能没变化(start==limit),此时这个函数相当于啥都没干,这也是正确的。 + /// 函数:用于减少像index blocks这样的内部数据结构占用的空间, 其中的*start和*key参数都是IN OUT的。 + /// + /// 这个函数的作用就是: + /// 如果*start < limit,就在[startlimit,)中找到一个短字符串,并赋给*start返回. 如“helloworld”和”hellozoomer”之间最短的key可以是”hellox”。 + /// 简单的comparator实现可能不改变*start(start==limit),这也是正确的 + /// + /// # Arguments + /// + /// * `start`: + /// * `limit`: + /// + /// returns: String + /// + /// # Examples + /// + /// ``` + /// + /// ``` fn find_shortest_separator(&self, start: &String, limit:&Slice) -> String; /// 减少像index blocks这样的内部数据结构占用的空间 diff --git a/src/traits/status_trait.rs b/src/traits/status_trait.rs index e25ac1c..9edcc8e 100644 --- a/src/traits/status_trait.rs +++ b/src/traits/status_trait.rs @@ -1,6 +1,9 @@ use crate::util::slice::Slice; use crate::util::status::LevelError; +/// db 中的返回状态,将错误号和错误信息封装成Status类,统一进行处理。 +/// 在 leveldb的实现里, 为了节省空间Status将返回码(code), 错误信息message及长度打包存储于一个字符串数组中, 来存储错误信息。 +/// 在该项目中, 使用LevelError 和 Slice 存储错误信息 pub trait StatusTrait { /// 判断 状态是否为默认值 @@ -17,8 +20,6 @@ pub trait StatusTrait { /// ``` fn is_default(&self) -> bool; - fn into_code(&self) -> u32; - fn into_msg(self) -> Option; fn is_ok(&self) -> bool; diff --git a/src/util/status.rs b/src/util/status.rs index 77726c4..e8e47ff 100644 --- a/src/util/status.rs +++ b/src/util/status.rs @@ -1,4 +1,5 @@ use std::fmt::Error; +use std::ops::Deref; use crate::traits::status_trait::StatusTrait; use crate::util::r#const::COLON_WHITE_SPACE; use crate::util::slice::Slice; @@ -14,13 +15,32 @@ pub enum LevelError { KIOError(Option), } -impl Default for LevelError { - fn default() -> LevelError { - KOk +impl StatusTrait for LevelError { + fn is_default(&self) -> bool { + self.is_ok() } -} -impl StatusTrait for LevelError { + fn into_msg(self) -> Option { + match self { + KOk => None, + /// 以后可能会差异化处理,因此不做 _ 的默认输出 + KNotFound(slice) => { + slice + }, + KCorruption(slice) => { + slice + }, + KNotSupported(slice) => { + slice + }, + KInvalidArgument(slice) => { + slice + }, + KIOError(slice) => { + slice + }, + } + } fn is_ok(&self) -> bool { match self { @@ -64,104 +84,72 @@ impl StatusTrait for LevelError { } } + #[inline] + fn to_string(self) -> String { + if self.is_default() { + return String::from("OK") + } + + let msg_type = match self { + KOk => "OK", + KNotFound(_) => "NotFound: ", + KCorruption(_) => "Corruption: ", + KNotSupported(_) => "Not implemented: ", + KInvalidArgument(_) => "Invalid argument: ", + KIOError(_) => "IO error: " + }; + + let error_msg = String::from(self.into_msg().unwrap()); + + format!("{}{}", msg_type, error_msg) + } + fn ok() -> LevelError { KOk } fn not_found(mut msg: Slice, msg2: Slice) -> LevelError { - &msg.merge(msg2, Some(String::from(COLON_WHITE_SPACE))); + let _ = &msg.merge(msg2, Some(String::from(COLON_WHITE_SPACE))); KNotFound(Some(msg)) } fn corruption(mut msg: Slice, msg2: Slice) -> LevelError { - &msg.merge(msg2, Some(String::from(COLON_WHITE_SPACE))); + let _ = &msg.merge(msg2, Some(String::from(COLON_WHITE_SPACE))); KCorruption(Some(msg)) } fn not_supported(mut msg: Slice, msg2: Slice) -> LevelError { - &msg.merge(msg2, Some(String::from(COLON_WHITE_SPACE))); + let _ = &msg.merge(msg2, Some(String::from(COLON_WHITE_SPACE))); KNotSupported(Some(msg)) } fn invalid_argument(mut msg: Slice, msg2: Slice) -> LevelError { - &msg.merge(msg2, Some(String::from(COLON_WHITE_SPACE))); + let _ = &msg.merge(msg2, Some(String::from(COLON_WHITE_SPACE))); KInvalidArgument(Some(msg)) } fn io_error(mut msg: Slice, msg2: Slice) -> LevelError { - &msg.merge(msg2, Some(String::from(COLON_WHITE_SPACE))); + let _ = &msg.merge(msg2, Some(String::from(COLON_WHITE_SPACE))); KIOError(Some(msg)) } +} - fn is_default(&self) -> bool { - self.is_ok() - } - - fn into_code(&self) -> u32 { - match self { - KOk => {0}, - KNotFound(_) => {1}, - KCorruption(_) => {2}, - KNotSupported(_) => {3}, - KInvalidArgument(_) => {4}, - KIOError(_) => {5}, - } - } - - fn into_msg(self) -> Option { - match self { - KOk => None, - /// 以后可能会差异化处理,因此不做 _ 的默认输出 - KNotFound(slice) => { - slice - }, - KCorruption(slice) => { - slice - }, - KNotSupported(slice) => { - slice - }, - KInvalidArgument(slice) => { - slice - }, - KIOError(slice) => { - slice - }, - } - } - - #[inline] - fn to_string(self) -> String { - if self.is_default() { - return String::from("OK") - } - - let msg_type = match self { - KOk => "OK", - KNotFound(_) => "NotFound: ", - KCorruption(_) => "Corruption: ", - KNotSupported(_) => "Not implemented: ", - KInvalidArgument(_) => "Invalid argument: ", - KIOError(_) => "IO error: " - }; - - let error_msg = String::from(self.into_msg().unwrap()); - - format!("{}{}", msg_type, error_msg) +impl Default for LevelError { + fn default() -> LevelError { + KOk } } - -impl TryFrom for LevelError { +impl TryFrom for LevelError { type Error = String; - /// 错误码转 LevelError + /// i32 错误码转 LevelError /// /// # Arguments /// /// * `value`: 错误码的值 /// - /// returns: Result>::Error> + /// returns: Result>::Error> /// /// # Examples /// @@ -169,7 +157,7 @@ impl TryFrom for LevelError { /// let rs: LevelError = LevelError::try_from(3)?; /// assert!(&rs.is_not_supported_error()); /// ``` - fn try_from(value: u32) -> Result { + fn try_from(value: i32) -> Result { match value { 0 => Ok(KOk), 1 => Ok(KNotFound(None)), @@ -181,4 +169,22 @@ impl TryFrom for LevelError { _ => Err(String::from(format!("Unknown code: {}", value))) } } -} \ No newline at end of file +} + +// impl Deref for LevelError { +// type Target = i32; +// +// /// StatusTrait 解引用到 i32 +// fn deref(&self) -> &Self::Target { +// let le = match self { +// KOk => 0, +// KNotFound(_) => 1, +// KCorruption(_) => 2, +// KNotSupported(_) => 3, +// KInvalidArgument(_) => 4, +// KIOError(_) => 5, +// }; +// +// &*le +// } +// } \ No newline at end of file diff --git a/src/util/status_test.rs b/src/util/status_test.rs index c63b0e9..bcfb993 100644 --- a/src/util/status_test.rs +++ b/src/util/status_test.rs @@ -68,12 +68,12 @@ mod test { String::from(msg2).into()); let binding = error.to_string(); - let errorMsg = binding.as_str(); - println!("{}", errorMsg); + let error_msg = binding.as_str(); + println!("{}", error_msg); - let expectString: String = format!("Invalid argument: {}{}{}", String::from(msg1), COLON_WHITE_SPACE, + let expect_string: String = format!("Invalid argument: {}{}{}", String::from(msg1), COLON_WHITE_SPACE, String::from(msg2)); - assert_eq!(expectString, errorMsg); + assert_eq!(expect_string, error_msg); } #[test] -- Gitee From fd0a0b0b575e414dc02511c64b1025a2d3ce3dcb Mon Sep 17 00:00:00 2001 From: fengyang Date: Tue, 13 Dec 2022 23:09:13 +0800 Subject: [PATCH 3/4] test_bytewise_comparator_impl_get_name --- src/traits/comparator_trait.rs | 16 ++++++++++++++-- src/util/comparator.rs | 23 ----------------------- src/util/comparator_test.rs | 14 +++++++------- 3 files changed, 21 insertions(+), 32 deletions(-) diff --git a/src/traits/comparator_trait.rs b/src/traits/comparator_trait.rs index 54a3351..2d82ba6 100644 --- a/src/traits/comparator_trait.rs +++ b/src/traits/comparator_trait.rs @@ -51,8 +51,20 @@ pub trait ComparatorTrait { /// ``` fn find_shortest_separator(&self, start: &String, limit:&Slice) -> String; - /// 减少像index blocks这样的内部数据结构占用的空间 - /// 将 key变成一个比原*key大的短字符串,并赋值给 key返回。 + /// 找一个 >= key的短字符串, key变成一个比原*key大的短字符串,并返回。 + /// 简单的comparator实现可能不改变 key,这也是正确的 + /// + /// # Arguments + /// + /// * `key`: + /// + /// returns: String + /// + /// # Examples + /// + /// ``` + /// + /// ``` fn find_short_successor(&self, key: &String) -> String; } \ No newline at end of file diff --git a/src/util/comparator.rs b/src/util/comparator.rs index ba97acd..51d0123 100644 --- a/src/util/comparator.rs +++ b/src/util/comparator.rs @@ -62,26 +62,3 @@ impl ComparatorTrait for InternalKeyComparator { todo!() } } - -/// ReverseKeyComparator -pub struct ReverseKeyComparator { - -} - -impl ComparatorTrait for ReverseKeyComparator { - fn compare(&self, a: &Slice, b: &Slice) -> Option { - todo!() - } - - fn get_name() -> String { - String::from("leveldb.ReverseBytewiseComparator") - } - - fn find_shortest_separator(&self, start: &String, limit: &Slice) -> String { - todo!() - } - - fn find_short_successor(&self, key: &String) -> String { - todo!() - } -} \ No newline at end of file diff --git a/src/util/comparator_test.rs b/src/util/comparator_test.rs index dea675f..b7f3af3 100644 --- a/src/util/comparator_test.rs +++ b/src/util/comparator_test.rs @@ -15,16 +15,16 @@ mod test { #[test] fn test_bytewise_comparator_impl_compare() { let comp = BytewiseComparatorImpl::default(); - let optionVal = comp.compare(&Slice::from("a"), &Slice::from("ab")); - assert_eq!(optionVal.unwrap(), Ordering::Less); + let option_val = comp.compare(&Slice::from("a"), &Slice::from("ab")); + assert_eq!(option_val.unwrap(), Ordering::Less); - let comp = BytewiseComparatorImpl::default(); - let optionVal = comp.compare(&Slice::from("b"), &Slice::from("abcd")); - assert_eq!(optionVal.unwrap(), Ordering::Greater); + // let comp = BytewiseComparatorImpl::default(); + // let option_val = comp.compare(&Slice::from("b"), &Slice::from("abcd")); + // assert_eq!(option_val.unwrap(), Ordering::Greater); let comp = BytewiseComparatorImpl::default(); - let optionVal = comp.compare(&Slice::from("abcd"), &Slice::from("abcd")); - assert_eq!(optionVal.unwrap(), Ordering::Equal); + let option_val = comp.compare(&Slice::from("abcd"), &Slice::from("abcd")); + assert_eq!(option_val.unwrap(), Ordering::Equal); } } \ No newline at end of file -- Gitee From 58c1ddf99393ed8d2dc4c7f1fae4fbc68d4244e0 Mon Sep 17 00:00:00 2001 From: fengyang Date: Wed, 14 Dec 2022 00:17:55 +0800 Subject: [PATCH 4/4] =?UTF-8?q?Status=E9=87=8D=E5=86=99=EF=BC=8C=E5=B0=86e?= =?UTF-8?q?rror=20code=20=E4=B8=8EStatus=20=E6=8B=86=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/traits/mod.rs | 1 - src/traits/status_trait.rs | 92 ---------- src/util/bloom_filter_test.rs | 8 + src/util/mod.rs | 2 +- src/util/status.rs | 305 +++++++++++++++++++++++++--------- src/util/status_test.rs | 54 +++--- 6 files changed, 259 insertions(+), 203 deletions(-) delete mode 100644 src/traits/status_trait.rs diff --git a/src/traits/mod.rs b/src/traits/mod.rs index 4193fa3..ffe5726 100644 --- a/src/traits/mod.rs +++ b/src/traits/mod.rs @@ -3,5 +3,4 @@ pub mod iterator; pub mod comparator_trait; pub mod coding_trait; pub mod filter_policy_trait; -pub mod status_trait; diff --git a/src/traits/status_trait.rs b/src/traits/status_trait.rs deleted file mode 100644 index 9edcc8e..0000000 --- a/src/traits/status_trait.rs +++ /dev/null @@ -1,92 +0,0 @@ -use crate::util::slice::Slice; -use crate::util::status::LevelError; - -/// db 中的返回状态,将错误号和错误信息封装成Status类,统一进行处理。 -/// 在 leveldb的实现里, 为了节省空间Status将返回码(code), 错误信息message及长度打包存储于一个字符串数组中, 来存储错误信息。 -/// 在该项目中, 使用LevelError 和 Slice 存储错误信息 -pub trait StatusTrait { - - /// 判断 状态是否为默认值 - /// - /// # Arguments - /// - /// returns: bool, true 为默认值, false 为不是默认值 - /// - /// # Examples - /// - /// ``` - /// let err: LevelError = LevelError::ok(); - /// assert!(err.is_default()); - /// ``` - fn is_default(&self) -> bool; - - fn into_msg(self) -> Option; - - fn is_ok(&self) -> bool; - - fn is_not_found(&self) -> bool; - - fn is_corruption(&self) -> bool; - - fn is_io_error(&self) -> bool; - - fn is_not_supported_error(&self) -> bool; - - fn is_invalid_argument(&self) -> bool; - - /// LevelError 转 String - /// - /// # Arguments - /// - /// returns: LevelError - /// - /// # Examples - /// - /// ``` - /// let error: LevelError = LevelError::invalid_argument(String::from("aa"), String::from("bb")); - /// let data = error.to_string(); - /// assert_eq!("Invalid argument: aa: bb", data); - /// ``` - fn to_string(self) -> String; - - fn ok() -> LevelError; - - fn not_found(msg: Slice, msg2: Slice) -> LevelError; - - /// 生成 LevelError.KCorruption - /// - /// # Arguments - /// - /// * `msg`: Slice - /// * `msg2`: Slice - /// - /// returns: LevelError - /// - /// # Examples - /// - /// ``` - /// LevelError::corruption(String::from(msg1).into(), String::from(msg2).into()) - /// ``` - fn corruption(msg: Slice, msg2: Slice) -> LevelError; - - fn not_supported(msg: Slice, msg2: Slice) -> LevelError; - fn invalid_argument(msg: Slice, msg2: Slice) -> LevelError; - - /// 生成 LevelError.KIOError - /// - /// # Arguments - /// - /// * `msg`: Slice - /// * `msg2`: Slice - /// - /// returns: LevelError - /// - /// # Examples - /// - /// ``` - /// let err: LevelError = LevelError::io_error(String::from("aa"), String::from("bb")); - /// assert!(&err.is_io_error()); - /// ``` - fn io_error(msg: Slice, msg2: Slice) -> LevelError; - -} \ No newline at end of file diff --git a/src/util/bloom_filter_test.rs b/src/util/bloom_filter_test.rs index e69de29..d148c51 100644 --- a/src/util/bloom_filter_test.rs +++ b/src/util/bloom_filter_test.rs @@ -0,0 +1,8 @@ + +mod test { + + #[test] + fn test_by() { + println!("{}", "a"); + } +} \ No newline at end of file diff --git a/src/util/mod.rs b/src/util/mod.rs index b8de60d..fa3512d 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -22,4 +22,4 @@ mod bloom_filter_test; pub mod filter_policy; /// 定义别名 -pub type Result = result::Result; +pub type ResultT = result::Result; diff --git a/src/util/status.rs b/src/util/status.rs index e8e47ff..051a424 100644 --- a/src/util/status.rs +++ b/src/util/status.rs @@ -1,136 +1,252 @@ -use std::fmt::Error; +use std::fmt::{Display, Error, Formatter}; use std::ops::Deref; -use crate::traits::status_trait::StatusTrait; use crate::util::r#const::COLON_WHITE_SPACE; +use crate::util::ResultT; use crate::util::slice::Slice; use crate::util::status::LevelError::{KCorruption, KIOError, KInvalidArgument, KNotSupported, KNotFound, KOk}; +/// db 中的返回状态,将错误号和错误信息封装成Status类,统一进行处理。 +/// 在 leveldb的实现里, 为了节省空间Status将返回码(code), 错误信息message及长度打包存储于一个字符串数组中, 来存储错误信息。 +/// 在该项目中, 使用LevelError 和 Slice 存储错误信息 +pub struct Status { + err: LevelError, + msg: Slice +} + +impl Default for Status { + fn default() -> Self { + LevelError::ok() + } +} + +impl Status { + /// + /// + /// # Arguments + /// + /// * `err`: + /// * `slice`: + /// + /// returns: Status + /// + /// # Examples + /// + /// ``` + /// + /// ``` + pub fn wrapper(err: LevelError, slice: Slice) -> Status { + Self { + err, + msg: slice + } + } + + pub fn wrappers(err: LevelError, mut slice1: Slice, slice2: Slice) -> Status { + slice1.merge(slice2, Some(String::from(COLON_WHITE_SPACE))); + + Self { + err, + msg: slice1 + } + } + + pub fn get_error(self) -> LevelError { + self.err + } + + /// 得到 LevelError 中的错误信息: Slice + /// + /// # Arguments + /// + /// returns: Option + /// + /// # Examples + /// + /// ``` + /// let msg1 = "abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc"; + /// let msg2 = "456456456456456456456456456456456456456456456456"; + /// + /// let status: Status = LevelError::io_error(String::from(msg1).into(), String::from(msg2).into()); + /// assert!(&status.get_error().is_io_error()); + /// + /// let slice: Option = status.into_msg(); + /// assert_eq!("abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc: 456456456456456456456456456456456456456456456456", + /// String::from(slice.unwrap())); + /// ``` + pub fn into_msg(self) -> Option { + Some(self.msg) + } + + + /// LevelError 转 String + /// + /// # Arguments + /// + /// returns: LevelError + /// + /// # Examples + /// + /// ``` + /// let err: Status = LevelError::invalid_argument(String::from("aa"), String::from("bb")); + /// let data = err.to_string(); + /// assert_eq!("Invalid argument: aa: bb", data); + /// ``` + #[inline] + pub fn to_string(self) -> String { + let err = self.err; + + let msg_type = match &err { + KOk => "OK", + KNotFound => "NotFound: ", + KCorruption => "Corruption: ", + KNotSupported => "Not implemented: ", + KInvalidArgument => "Invalid argument: ", + KIOError => "IO error: " + }; + + if err.is_ok() { + return String::from(msg_type); + } + + let msg = self.msg; + let error_msg = String::from(msg); + + format!("{}{}", msg_type, error_msg) + } +} + /// Status 的状态 pub enum LevelError { KOk, - KNotFound(Option), - KCorruption(Option), - KNotSupported(Option), - KInvalidArgument(Option), - KIOError(Option), + KNotFound, + KCorruption, + KNotSupported, + KInvalidArgument, + KIOError, } -impl StatusTrait for LevelError { - fn is_default(&self) -> bool { - self.is_ok() - } - - fn into_msg(self) -> Option { - match self { - KOk => None, - /// 以后可能会差异化处理,因此不做 _ 的默认输出 - KNotFound(slice) => { - slice - }, - KCorruption(slice) => { - slice - }, - KNotSupported(slice) => { - slice - }, - KInvalidArgument(slice) => { - slice - }, - KIOError(slice) => { - slice - }, - } - } - - fn is_ok(&self) -> bool { +impl LevelError { + pub fn is_ok(self) -> bool { match self { KOk => true, _ => false } } - fn is_not_found(&self) -> bool { + pub fn is_not_found(&self) -> bool { match self { - KNotFound(_) => true, + KNotFound => true, _ => false } } - fn is_corruption(&self) -> bool { + pub fn is_corruption(&self) -> bool { match self { - KCorruption(_) => true, + KCorruption => true, _ => false } } - fn is_io_error(&self) -> bool { + pub fn is_io_error(&self) -> bool { match self { - KIOError(_) => true, + KIOError => true, _ => false } } - fn is_not_supported_error(&self) -> bool { + pub fn is_not_supported_error(&self) -> bool { match self { - KNotSupported(_) => true, + KNotSupported => true, _ => false } } - fn is_invalid_argument(&self) -> bool { + pub fn is_invalid_argument(&self) -> bool { match self { - KInvalidArgument(_) => true, + KInvalidArgument => true, _ => false } } - #[inline] - fn to_string(self) -> String { - if self.is_default() { - return String::from("OK") + pub fn ok() -> Status { + Status{ + err: Default::default(), + msg: Default::default() } - - let msg_type = match self { - KOk => "OK", - KNotFound(_) => "NotFound: ", - KCorruption(_) => "Corruption: ", - KNotSupported(_) => "Not implemented: ", - KInvalidArgument(_) => "Invalid argument: ", - KIOError(_) => "IO error: " - }; - - let error_msg = String::from(self.into_msg().unwrap()); - - format!("{}{}", msg_type, error_msg) - } - - fn ok() -> LevelError { - KOk } - fn not_found(mut msg: Slice, msg2: Slice) -> LevelError { + pub fn not_found(mut msg: Slice, msg2: Slice) -> Status { let _ = &msg.merge(msg2, Some(String::from(COLON_WHITE_SPACE))); - KNotFound(Some(msg)) + + Status{ + err: KNotFound, + msg: msg + } } - fn corruption(mut msg: Slice, msg2: Slice) -> LevelError { + /// 生成 LevelError.KCorruption + /// + /// # Arguments + /// + /// * `msg`: Slice + /// * `msg2`: Slice + /// + /// returns: LevelError + /// + /// # Examples + /// + /// ``` + /// LevelError::corruption(String::from(msg1).into(), String::from(msg2).into()) + /// ``` + pub fn corruption(mut msg: Slice, msg2: Slice) -> Status { let _ = &msg.merge(msg2, Some(String::from(COLON_WHITE_SPACE))); - KCorruption(Some(msg)) + + Status{ + err: KCorruption, + msg: msg + } } - fn not_supported(mut msg: Slice, msg2: Slice) -> LevelError { + pub fn not_supported(mut msg: Slice, msg2: Slice) -> Status { let _ = &msg.merge(msg2, Some(String::from(COLON_WHITE_SPACE))); - KNotSupported(Some(msg)) + + Status{ + err: KNotSupported, + msg: msg + } } - fn invalid_argument(mut msg: Slice, msg2: Slice) -> LevelError { + pub fn invalid_argument(mut msg: Slice, msg2: Slice) -> Status { let _ = &msg.merge(msg2, Some(String::from(COLON_WHITE_SPACE))); - KInvalidArgument(Some(msg)) + + Status{ + err: KInvalidArgument, + msg: msg + } } - fn io_error(mut msg: Slice, msg2: Slice) -> LevelError { + /// 生成 LevelError.KIOError + /// + /// # Arguments + /// + /// * `msg`: Slice + /// * `msg2`: Slice + /// + /// returns: LevelError + /// + /// # Examples + /// + /// ``` + /// let err: LevelError = LevelError::io_error(String::from("aa"), String::from("bb")); + /// assert!(&err.is_io_error()); + /// ``` + pub fn io_error(mut msg: Slice, msg2: Slice) -> Status { let _ = &msg.merge(msg2, Some(String::from(COLON_WHITE_SPACE))); - KIOError(Some(msg)) + + Status{ + err: KIOError, + msg: msg + } } } @@ -160,17 +276,44 @@ impl TryFrom for LevelError { fn try_from(value: i32) -> Result { match value { 0 => Ok(KOk), - 1 => Ok(KNotFound(None)), - 2 => Ok(KCorruption(None)), - 3 => Ok(KNotSupported(None)), - 4 => Ok(KInvalidArgument(None)), - 5 => Ok(KIOError(None)), + 1 => Ok(KNotFound), + 2 => Ok(KCorruption), + 3 => Ok(KNotSupported), + 4 => Ok(KInvalidArgument), + 5 => Ok(KIOError), // all other numbers _ => Err(String::from(format!("Unknown code: {}", value))) } } } +// /// 实现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 Deref for LevelError { // type Target = i32; // diff --git a/src/util/status_test.rs b/src/util/status_test.rs index bcfb993..8b6fa1f 100644 --- a/src/util/status_test.rs +++ b/src/util/status_test.rs @@ -1,56 +1,54 @@ mod test { - use crate::traits::status_trait::StatusTrait; use crate::util::r#const::COLON_WHITE_SPACE; use crate::util::slice::Slice; - use crate::util::status::LevelError; + use crate::util::status::{LevelError, Status}; #[test] fn test_error_code() { let msg1 = "abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc"; let msg2 = "456456456456456456456456456456456456456456456456"; - let err: LevelError = LevelError::io_error(String::from(msg1).into(), String::from(msg2).into()); - assert!(&err.is_io_error()); - // assert!(&err.into_code() == 5); - let slice: Option = err.into_msg(); + let err: Status = LevelError::io_error(String::from(msg1).into(), String::from(msg2).into()); + assert!(&err.get_error().is_io_error()); + + let status = Status::default(); + assert!(&status.get_error().is_ok()); + + let status = Status::wrappers(LevelError::KIOError, String::from(msg1).into(), String::from(msg2).into()); + let slice: Option = status.into_msg(); assert_eq!("abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc: 456456456456456456456456456456456456456456456456", String::from(slice.unwrap())); - let err: LevelError = LevelError::ok(); - assert!(&err.is_ok()); - let slice: Option = err.into_msg(); - assert!(Option::None == slice); - - let err: LevelError = LevelError::invalid_argument(String::from(msg1).into(), + let err: Status = LevelError::invalid_argument(String::from(msg1).into(), String::from(msg2).into()); - assert!(&err.is_invalid_argument()); + assert!(&err.get_error().is_invalid_argument()); // assert_eq!(err.into_code(), 4); - let err: LevelError = LevelError::corruption(String::from(msg1).into(), + let err: Status = LevelError::corruption(String::from(msg1).into(), String::from(msg2).into()); - assert!(&err.is_corruption()); + assert!(&err.get_error().is_corruption()); // assert_eq!(err.into_code(), 2); - let err: LevelError = LevelError::not_found(String::from(msg1).into(), + let err: Status = LevelError::not_found(String::from(msg1).into(), String::from(msg2).into()); - assert!(&err.is_not_found()); - // assert_eq!(err.into_code(), 1); + assert!(&err.get_error().is_not_found()); - let err: LevelError = LevelError::not_supported(String::from(msg1).into(), + let err: Status = LevelError::not_supported(String::from(msg1).into(), String::from(msg2).into()); - assert!(&err.is_not_supported_error()); - // assert_eq!(err.into_code(), 3); + assert!(&err.get_error().is_not_supported_error()); + + let err: LevelError = LevelError::KOk; + assert!(&err.is_ok()); let err: LevelError = LevelError::default(); assert!(&err.is_ok()); - // assert_eq!(err.into_code(), 0); } #[test] fn test_toString() { // ok - let status: LevelError = LevelError::ok(); + let status: Status = LevelError::ok(); assert_eq!("OK", status.to_string()); let msg1 = "abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc\ @@ -64,7 +62,7 @@ mod test { 456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456\ 456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456"; - let error: LevelError = LevelError::invalid_argument(String::from(msg1).into(), + let error: Status = LevelError::invalid_argument(String::from(msg1).into(), String::from(msg2).into()); let binding = error.to_string(); @@ -78,12 +76,12 @@ mod test { #[test] fn test_is_default() { - let err: LevelError = LevelError::ok(); - assert!(err.is_default()); + let err: Status = LevelError::ok(); + assert!(err.get_error().is_ok()); - let err: LevelError = LevelError::io_error(String::from("a").into(), + let err: Status = LevelError::io_error(String::from("a").into(), String::from("b").into()); - assert!(!err.is_default()); + assert!(!err.get_error().is_ok()); // let err: LevelError = LevelError::ok(); // let a = err.into(); -- Gitee