From ac45c11e0187faa6d76f9a1714823ca9755831fd Mon Sep 17 00:00:00 2001 From: fengyang Date: Wed, 7 Dec 2022 21:32:41 +0800 Subject: [PATCH 01/16] =?UTF-8?q?=E4=BF=AE=E6=94=B9readme=E7=9A=84?= =?UTF-8?q?=E5=88=86=E6=94=AF=E8=A7=84=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- doc/TODOList.md | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 84ebc1b..ff45216 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ LevelDB for rust #### 参与贡献 1. Fork 本仓库 -2. 新建 Feat_xxx 分支 +2. 新建 feat/1.0.0_util_xxx 分支 3. 提交代码 4. 新建 Pull Request diff --git a/doc/TODOList.md b/doc/TODOList.md index 5b36362..e0b7c83 100644 --- a/doc/TODOList.md +++ b/doc/TODOList.md @@ -16,6 +16,7 @@ 5. Table Build 6. Recovery 7. SStable +8. # Util 1. Arena (Memory Management) 2. BloomFilter @@ -31,6 +32,7 @@ 12. Status 13. Random 14. Slice + ## Traits 1. public trait defined in leveldb include dir -- Gitee From dcf2a134f5024305f06302ab43bd5f375101f5eb Mon Sep 17 00:00:00 2001 From: colagy Date: Thu, 8 Dec 2022 21:03:05 +0800 Subject: [PATCH 02/16] add varint32() to coding.rs; fixed mod bug; --- README.md | 30 +++++++++++++------------- src/traits/iterator.rs | 7 ++---- src/traits/mod.rs | 2 +- src/util/coding.rs | 47 +++++++++++++++++++++++++++++++++++++++++ src/util/coding_test.rs | 20 ++++++++++++++++++ src/util/mod.rs | 8 ++++--- 6 files changed, 90 insertions(+), 24 deletions(-) create mode 100644 src/util/coding.rs create mode 100644 src/util/coding_test.rs diff --git a/README.md b/README.md index 84ebc1b..8868118 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 | -| BloomFilter | colagy | -| Cache | colagy | -| Coding (Primitive Type SerDe) | colagy | -| Comparator | fengyang | -| Status | fengyang | -| Random | 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 | +| Status | fengyang | +| BloomFilter | fengyang | +| CRC | lxd5866 | +| Env | lxd5866 | +| Hash | lxd5866 | +| MutexLock | kazeseiriou | +| Histgram | kazeseiriou | \ No newline at end of file diff --git a/src/traits/iterator.rs b/src/traits/iterator.rs index 319650a..a985e81 100644 --- a/src/traits/iterator.rs +++ b/src/traits/iterator.rs @@ -1,7 +1,6 @@ -use crate::util::Slice; +use crate::util::slice::Slice; pub trait Iterator { - fn valid(&self) -> bool; fn seek_to_first(&mut self); @@ -19,6 +18,4 @@ pub trait Iterator { fn value(&self) -> &Slice; } -trait AAA { - -} +trait AAA {} diff --git a/src/traits/mod.rs b/src/traits/mod.rs index fb4a7b1..74f6e80 100644 --- a/src/traits/mod.rs +++ b/src/traits/mod.rs @@ -1,4 +1,4 @@ -use crate::util::Slice; +use crate::util::slice::Slice; mod iterator; mod comparator; diff --git a/src/util/coding.rs b/src/util/coding.rs new file mode 100644 index 0000000..74f2492 --- /dev/null +++ b/src/util/coding.rs @@ -0,0 +1,47 @@ +const B: u8 = 128; + +/// +/// +/// +pub trait Coding { + fn varint32(self, buf: &mut [u8]); +} + +impl Coding for u32 +{ + fn varint32(self, buf: &mut [u8]) { + // if self < 1 << 7 { + // buf[0] = self as u8; + // } else if self < 1 << 14 { + // buf[0] = self | B; + // println!("{:b}", buf[0]); + // buf[1] = buf[0] >> 7; + // println!("{:b}", buf[1]); + // } else if self < 1 << 21 { + // buf[0] = (self | B as u8) as u8; + // println!("{:b}", buf[0]); + // buf[1] = (buf[0] >> 7) | B; + // println!("{:b}", buf[1]); + // buf[2] = buf[1] >> 14; + // println!("{:b}", buf[2]); + // } else if self < 1 << 28 { + // buf[0] = (self | B as u8) as u8; + // println!("{:b}", buf[0]); + // buf[1] = (buf[0] >> 7) | B; + // println!("{:b}", buf[1]); + // buf[2] = (buf[1] >> 14) | B; + // println!("{:b}", buf[2]); + // buf[3] = buf[2] >> 21; + // } else { + // buf[0] = (self | B as u8) as u8; + // println!("{:b}", buf[0]); + // buf[1] = (buf[0] >> 7) | B; + // println!("{:b}", buf[1]); + // buf[2] = (buf[1] >> 14) | B; + // println!("{:b}", buf[2]); + // buf[3] = (buf[2] >> 21) | B; + // println!("{:b}", buf[3]); + // buf[4] = buf[3] >> 28; + // } + } +} \ No newline at end of file diff --git a/src/util/coding_test.rs b/src/util/coding_test.rs new file mode 100644 index 0000000..3c4184f --- /dev/null +++ b/src/util/coding_test.rs @@ -0,0 +1,20 @@ +mod test { + use crate::util::coding::Coding; + + #[test] + fn test_i32() { + let mut buf: [u8; 8] = [0, 0, 0, 0, 0, 0, 0, 0]; + let x = 127.varint32(&mut buf); + println!("{:?}", buf); + println!("{:?}", x); + println!("{:b}", buf[0]); + } + + #[test] + fn test_offset() { + let buf: [u8; 3] = [0, 1, 2]; + let mut offset: usize = 0; + offset += 1; + println!("{:?}", buf[offset]) + } +} diff --git a/src/util/mod.rs b/src/util/mod.rs index 3f159e6..fe7c884 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1,3 +1,5 @@ -mod slice; -mod status; -mod slice_test; \ No newline at end of file +pub mod slice; +pub mod status; +mod slice_test; +pub mod coding; +mod coding_test; \ No newline at end of file -- Gitee From b7110a1e72901f390527a40ac9d8176e9693a6c1 Mon Sep 17 00:00:00 2001 From: wangboo <5417808+wangboa@user.noreply.gitee.com> Date: Thu, 8 Dec 2022 21:07:53 +0800 Subject: [PATCH 03/16] =?UTF-8?q?=E6=96=B0=E5=A2=9Eslice=E7=9A=84=E4=B8=80?= =?UTF-8?q?=E4=BA=9B=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/slice.rs | 133 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) diff --git a/src/util/slice.rs b/src/util/slice.rs index da59ff7..71f2d71 100644 --- a/src/util/slice.rs +++ b/src/util/slice.rs @@ -1,11 +1,144 @@ +use std::alloc::{alloc, Layout}; +use std::borrow::{Borrow, Cow}; +use std::ptr; +use std::ptr::{copy, NonNull}; pub struct Slice { + data: NonNull, + len: usize, +} +#[allow(improper_ctypes)] +extern { + fn memcmp(s1: *const i8, s2: *const i8, n: usize) -> i32; } impl Default for Slice { + /// 构造一个空的 Slice fn default() -> Self { + unsafe { + Self { + data: NonNull::new_unchecked(ptr::null_mut()), + len: 0, + } + } + } +} + +impl Slice { + /// 获取 slice 长度 + #[inline] + pub fn size(&self) -> usize { + self.len + } + + /// 判断 slice 是否为空 + #[inline] + pub fn empty(&self) -> bool { + self.len == 0 + } + + /// 移除头部 n 个元素 + pub fn remove_prefix(&self, n: usize) -> Slice { + assert!(self.len >= n); + if self.len == 0 { + return Slice::default(); + } + let len = self.len - n; + unsafe { + let data = alloc(Layout::array(len).unwrap()); + copy(self.data.as_ptr().offset(n as isize), data, len); + Self { + data: NonNull::new_unchecked(data), + len, + } + } + } + + /// 判断本 Slice 是否以 other 为开始 + pub fn starts_with(&self, other: &Self) -> bool { + assert!(other.len <= self.len); + if other.len == 0 { + return true; + } + return self.len >= other.len && unsafe { + memcmp( + self.data.as_ptr() as *const i8, + other.data.as_ptr() as *const i8, + other.len) == 0 + }; + } +} + +impl<'a> Slice { + /// 借取 Slice 中的数据, 调用方只拥有读权限 + pub fn borrow_data(&self) -> Cow<'a, String> { + let str = unsafe { + String::from_raw_parts(self.data.as_ptr(), self.len, self.len) + }; + Cow::Borrowed(&str) + } +} + +impl Into for Slice { + /// 将 Slice 内数据的所有权移交给 String + fn into(self) -> String { + unsafe { + String::from_raw_parts(self.data.as_ptr(), self.len, self.len) + } + } +} + +impl Into for String { + /// 通过 String 构造一个 Slice + fn into(mut self) -> Slice { + unsafe { + Slice { + data: NonNull::new_unchecked(self.as_mut_ptr()), + len: str.len(), + } + } + } +} + +impl Into for &str { + /// 通过 &str 构造一个 Slice + fn into(mut self) -> Slice { + unsafe { + Slice { + data: NonNull::new_unchecked(self.as_mut_ptr()), + len: slice.len(), + } + } + } +} + +impl PartialEq for Slice { + /// 判断两个 Slice 是否相同 + fn eq(&self, other: &Self) -> bool { todo!() } } +impl core::ops::Index for Slice { + type Output = u8; + + /// 获取某个下标的数据 + fn index(&self, index: isize) -> &Self::Output { + if index < self.len as isize { + unsafe { + &self.data.as_ptr().offset(index).read() + } + } else { + &0_u8 + } + } +} + +impl Drop for Slice { + /// 释放内存 + fn drop(&mut self) { + let _: String = self.into(); + } +} + -- Gitee From f0e044f650db8e1e9a38354c323be2b816032f41 Mon Sep 17 00:00:00 2001 From: wangboo <5417808+wangboa@user.noreply.gitee.com> Date: Thu, 8 Dec 2022 22:27:15 +0800 Subject: [PATCH 04/16] =?UTF-8?q?=E5=A2=9E=E5=8A=A0Slice?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/slice.rs | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/src/util/slice.rs b/src/util/slice.rs index 71f2d71..a4945cd 100644 --- a/src/util/slice.rs +++ b/src/util/slice.rs @@ -1,6 +1,7 @@ use std::alloc::{alloc, Layout}; -use std::borrow::{Borrow, Cow}; -use std::ptr; +use std::borrow::Cow; +use std::ops::Deref; +use std::{ptr, slice}; use std::ptr::{copy, NonNull}; pub struct Slice { @@ -46,7 +47,7 @@ impl Slice { } let len = self.len - n; unsafe { - let data = alloc(Layout::array(len).unwrap()); + let data = alloc(Layout::array::(len).unwrap()); copy(self.data.as_ptr().offset(n as isize), data, len); Self { data: NonNull::new_unchecked(data), @@ -76,7 +77,7 @@ impl<'a> Slice { let str = unsafe { String::from_raw_parts(self.data.as_ptr(), self.len, self.len) }; - Cow::Borrowed(&str) + Cow::Owned(str) } } @@ -95,19 +96,19 @@ impl Into for String { unsafe { Slice { data: NonNull::new_unchecked(self.as_mut_ptr()), - len: str.len(), + len: self.len(), } } } } -impl Into for &str { +impl Into for &mut str { /// 通过 &str 构造一个 Slice - fn into(mut self) -> Slice { + fn into(self) -> Slice { unsafe { Slice { data: NonNull::new_unchecked(self.as_mut_ptr()), - len: slice.len(), + len: self.len(), } } } @@ -115,22 +116,27 @@ impl Into for &str { impl PartialEq for Slice { /// 判断两个 Slice 是否相同 - fn eq(&self, other: &Self) -> bool { + fn eq(&self, _other: &Self) -> bool { todo!() } } -impl core::ops::Index for Slice { +impl core::ops::Index for Slice { type Output = u8; /// 获取某个下标的数据 - fn index(&self, index: isize) -> &Self::Output { - if index < self.len as isize { - unsafe { - &self.data.as_ptr().offset(index).read() - } - } else { - &0_u8 + fn index(&self, index: usize) -> &Self::Output { + assert!(index < self.len); + &(**self)[index] + } +} + +impl Deref for Slice { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { + unsafe { + slice::from_raw_parts(self.data.as_ptr(), self.len) } } } @@ -138,7 +144,9 @@ impl core::ops::Index for Slice { impl Drop for Slice { /// 释放内存 fn drop(&mut self) { - let _: String = self.into(); + unsafe { + let _ = String::from_raw_parts(self.data.as_ptr(), self.len, self.len); + } } } -- Gitee From 4985c4dd1408b8aa2a41fe6149e8bf1d69a39e4f Mon Sep 17 00:00:00 2001 From: wangboo <5417808+wangboa@user.noreply.gitee.com> Date: Thu, 8 Dec 2022 22:30:35 +0800 Subject: [PATCH 05/16] =?UTF-8?q?=E5=A2=9E=E5=8A=A0Slice=20cmp=20=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/slice.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/util/slice.rs b/src/util/slice.rs index a4945cd..9f1cd72 100644 --- a/src/util/slice.rs +++ b/src/util/slice.rs @@ -2,6 +2,7 @@ use std::alloc::{alloc, Layout}; use std::borrow::Cow; use std::ops::Deref; use std::{ptr, slice}; +use std::cmp::Ordering; use std::ptr::{copy, NonNull}; pub struct Slice { @@ -121,6 +122,14 @@ impl PartialEq for Slice { } } +impl PartialOrd for Slice { + /// 判断两个 slice 的大小关系 + fn partial_cmp(&self, other: &Self) -> Option { + todo!() + } + +} + impl core::ops::Index for Slice { type Output = u8; -- Gitee From c54960e1b7b61d74213008fa7ca8edc8261290bf Mon Sep 17 00:00:00 2001 From: wangboo <5417808+wangboa@user.noreply.gitee.com> Date: Thu, 8 Dec 2022 23:03:47 +0800 Subject: [PATCH 06/16] =?UTF-8?q?=E5=AE=8C=E5=96=84=E6=AF=94=E8=BE=83?= =?UTF-8?q?=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/slice.rs | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/src/util/slice.rs b/src/util/slice.rs index 9f1cd72..b5cd383 100644 --- a/src/util/slice.rs +++ b/src/util/slice.rs @@ -1,8 +1,8 @@ +use std::{ptr, slice}; use std::alloc::{alloc, Layout}; use std::borrow::Cow; -use std::ops::Deref; -use std::{ptr, slice}; use std::cmp::Ordering; +use std::ops::Deref; use std::ptr::{copy, NonNull}; pub struct Slice { @@ -117,17 +117,40 @@ impl Into for &mut str { impl PartialEq for Slice { /// 判断两个 Slice 是否相同 - fn eq(&self, _other: &Self) -> bool { - todo!() + fn eq(&self, other: &Self) -> bool { + return self.len == other.len && unsafe { + memcmp( + self.data.as_ptr() as *const i8, + other.data.as_ptr() as *const i8, + self.len, + ) == 0 + }; } } impl PartialOrd for Slice { /// 判断两个 slice 的大小关系 fn partial_cmp(&self, other: &Self) -> Option { - todo!() + match self.len.partial_cmp(&other.len) { + Some(Ordering::Equal) => { + let cmp = unsafe { + memcmp( + self.data.as_ptr() as *const i8, + other.data.as_ptr() as *const i8, + self.len, + ) + }; + if cmp == 0 { + Some(Ordering::Equal) + } else if cmp > 0 { + Some(Ordering::Greater) + } else { + Some(Ordering::Less) + } + } + op => op + } } - } impl core::ops::Index for Slice { @@ -143,6 +166,7 @@ impl core::ops::Index for Slice { impl Deref for Slice { type Target = [u8]; + /// Slice 解引用到 &[u8] fn deref(&self) -> &Self::Target { unsafe { slice::from_raw_parts(self.data.as_ptr(), self.len) -- Gitee From 449c058ec0aadb993e1b536f508dd43b15697421 Mon Sep 17 00:00:00 2001 From: wangboo <5417808+wangboa@user.noreply.gitee.com> Date: Fri, 9 Dec 2022 20:08:19 +0800 Subject: [PATCH 07/16] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=83=A8=E5=88=86?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E4=BB=A3=E7=A0=81,=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E4=B8=80=E5=A4=84=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/slice.rs | 35 +++++++++++++++++++++++++---------- src/util/slice_test.rs | 29 +++++++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 12 deletions(-) diff --git a/src/util/slice.rs b/src/util/slice.rs index b5cd383..58a22d5 100644 --- a/src/util/slice.rs +++ b/src/util/slice.rs @@ -103,12 +103,24 @@ impl Into for String { } } -impl Into for &mut str { +impl Into for &str { /// 通过 &str 构造一个 Slice fn into(self) -> Slice { unsafe { Slice { - data: NonNull::new_unchecked(self.as_mut_ptr()), + data: NonNull::new_unchecked(self.as_ptr() as *mut u8), + len: self.len(), + } + } + } +} + +impl Into for Vec { + /// 通过 &str 构造一个 Slice + fn into(self) -> Slice { + unsafe { + Slice { + data: NonNull::new_unchecked(self.as_ptr() as *mut u8), len: self.len(), } } @@ -174,12 +186,15 @@ impl Deref for Slice { } } -impl Drop for Slice { - /// 释放内存 - fn drop(&mut self) { - unsafe { - let _ = String::from_raw_parts(self.data.as_ptr(), self.len, self.len); - } - } -} +// impl Drop for Slice { +// /// 释放内存 +// fn drop(&mut self) { +// if self.len > 0 { +// unsafe { +// let str = Vec::from_raw_parts(self.data.as_ptr(), self.len, self.len); +// println!("drop: {:?}", &str); +// } +// } +// } +// } diff --git a/src/util/slice_test.rs b/src/util/slice_test.rs index 02d05e2..69e8ccd 100644 --- a/src/util/slice_test.rs +++ b/src/util/slice_test.rs @@ -3,8 +3,33 @@ mod test { use crate::util::slice::Slice; #[test] - fn test() { - let slice = Slice::default(); + fn test_size() { + let slice: Slice = String::from("123").into(); + assert_eq!(3, slice.size()); + } + + #[test] + fn test_memory_leak() { + // 申请 100G 内存, 查看是否内存泄漏。如果内存泄漏,程序会OOM + (0..100_000_000).for_each(|_| { + unsafe { + // 1k + let str = "0123012301230123012301230123012301230123012301230123012301230123012\ + 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ + 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ + 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ + 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ + 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ + 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ + 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ + 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ + 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ + 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ + 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ + 301230123012301230123012301230123"; + let _: Slice = str.into(); + } + }) } } \ No newline at end of file -- Gitee From 0bc58c76270583db179a4351256383305b206b99 Mon Sep 17 00:00:00 2001 From: wangboo <5417808+wangboa@user.noreply.gitee.com> Date: Fri, 9 Dec 2022 21:38:43 +0800 Subject: [PATCH 08/16] v1 version --- src/util/slice.rs | 3 ++- src/util/slice_test.rs | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/util/slice.rs b/src/util/slice.rs index 58a22d5..e1fc885 100644 --- a/src/util/slice.rs +++ b/src/util/slice.rs @@ -2,6 +2,7 @@ use std::{ptr, slice}; use std::alloc::{alloc, Layout}; use std::borrow::Cow; use std::cmp::Ordering; +use std::mem::ManuallyDrop; use std::ops::Deref; use std::ptr::{copy, NonNull}; @@ -108,7 +109,7 @@ impl Into for &str { fn into(self) -> Slice { unsafe { Slice { - data: NonNull::new_unchecked(self.as_ptr() as *mut u8), + data: NonNull::new_unchecked(self.to_owned().as_ptr().to_owned() as *mut u8), len: self.len(), } } diff --git a/src/util/slice_test.rs b/src/util/slice_test.rs index 69e8ccd..037994d 100644 --- a/src/util/slice_test.rs +++ b/src/util/slice_test.rs @@ -2,6 +2,22 @@ mod test { use crate::util::slice::Slice; + #[test] + fn test_new() { + let mut a: Slice = "abc".into(); + unsafe { + let str = String::from_raw_parts((*a).as_mut_ptr(), 3, 3); + println!("str: {}", str); + } + // let str: &[u8] = &*a; + // println!("str: {:?}", String::from_utf8_lossy(str)); + // assert_eq!("123".as_bytes(), str); + + // let b: Slice = "abc".into(); + // let str1: String = b.into(); + // assert_eq!(String::from("abc"), str1); + } + #[test] fn test_size() { let slice: Slice = String::from("123").into(); -- Gitee From 300c4d5ad9ef085096e81f8adbe2ed5d72cdfeec Mon Sep 17 00:00:00 2001 From: wangboo <5417808+wangboa@user.noreply.gitee.com> Date: Fri, 9 Dec 2022 23:33:17 +0800 Subject: [PATCH 09/16] =?UTF-8?q?slice=20=E6=9B=B4=E6=8D=A2=E4=BA=86?= =?UTF-8?q?=E4=B8=80=E4=B8=AA=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/slice.rs | 99 ++++++++++++------------------------------ src/util/slice_test.rs | 53 ++++++++++++++++------ 2 files changed, 67 insertions(+), 85 deletions(-) diff --git a/src/util/slice.rs b/src/util/slice.rs index e1fc885..573d4e2 100644 --- a/src/util/slice.rs +++ b/src/util/slice.rs @@ -7,8 +7,7 @@ use std::ops::Deref; use std::ptr::{copy, NonNull}; pub struct Slice { - data: NonNull, - len: usize, + data: Vec, } #[allow(improper_ctypes)] @@ -21,8 +20,7 @@ impl Default for Slice { fn default() -> Self { unsafe { Self { - data: NonNull::new_unchecked(ptr::null_mut()), - len: 0, + data: Vec::new() } } } @@ -32,98 +30,67 @@ impl Slice { /// 获取 slice 长度 #[inline] pub fn size(&self) -> usize { - self.len + self.data.len() } /// 判断 slice 是否为空 #[inline] pub fn empty(&self) -> bool { - self.len == 0 + self.data.is_empty() } /// 移除头部 n 个元素 pub fn remove_prefix(&self, n: usize) -> Slice { - assert!(self.len >= n); - if self.len == 0 { + assert!(self.size() >= n); + if self.size() == 0 { return Slice::default(); } - let len = self.len - n; unsafe { - let data = alloc(Layout::array::(len).unwrap()); - copy(self.data.as_ptr().offset(n as isize), data, len); + let sub_data = &(*self.data)[n..self.size()]; Self { - data: NonNull::new_unchecked(data), - len, + data: Vec::from(sub_data) } } } /// 判断本 Slice 是否以 other 为开始 pub fn starts_with(&self, other: &Self) -> bool { - assert!(other.len <= self.len); - if other.len == 0 { + assert!(other.size() <= self.size()); + if other.size() == 0 { return true; } - return self.len >= other.len && unsafe { + return self.size() >= other.size() && unsafe { memcmp( self.data.as_ptr() as *const i8, other.data.as_ptr() as *const i8, - other.len) == 0 + other.size()) == 0 }; } } impl<'a> Slice { /// 借取 Slice 中的数据, 调用方只拥有读权限 - pub fn borrow_data(&self) -> Cow<'a, String> { + pub fn borrow_data(&mut self) -> Cow<'a, String> { let str = unsafe { - String::from_raw_parts(self.data.as_ptr(), self.len, self.len) + String::from_raw_parts(self.data.as_mut_ptr(), self.size(), self.size()) }; Cow::Owned(str) } } -impl Into for Slice { +impl From for String { /// 将 Slice 内数据的所有权移交给 String - fn into(self) -> String { + fn from(s: Slice) -> Self { unsafe { - String::from_raw_parts(self.data.as_ptr(), self.len, self.len) + String::from_utf8_unchecked(s.data) } } } -impl Into for String { - /// 通过 String 构造一个 Slice - fn into(mut self) -> Slice { - unsafe { - Slice { - data: NonNull::new_unchecked(self.as_mut_ptr()), - len: self.len(), - } - } - } -} - -impl Into for &str { - /// 通过 &str 构造一个 Slice - fn into(self) -> Slice { - unsafe { - Slice { - data: NonNull::new_unchecked(self.to_owned().as_ptr().to_owned() as *mut u8), - len: self.len(), - } - } - } -} - -impl Into for Vec { - /// 通过 &str 构造一个 Slice - fn into(self) -> Slice { - unsafe { - Slice { - data: NonNull::new_unchecked(self.as_ptr() as *mut u8), - len: self.len(), - } +impl > From for Slice { + fn from(r: R) -> Self { + Self { + data: Vec::from(r.as_ref()) } } } @@ -131,11 +98,11 @@ impl Into for Vec { impl PartialEq for Slice { /// 判断两个 Slice 是否相同 fn eq(&self, other: &Self) -> bool { - return self.len == other.len && unsafe { + return self.size() == other.size() && unsafe { memcmp( self.data.as_ptr() as *const i8, other.data.as_ptr() as *const i8, - self.len, + self.size(), ) == 0 }; } @@ -144,13 +111,13 @@ impl PartialEq for Slice { impl PartialOrd for Slice { /// 判断两个 slice 的大小关系 fn partial_cmp(&self, other: &Self) -> Option { - match self.len.partial_cmp(&other.len) { + match self.size().partial_cmp(&other.size()) { Some(Ordering::Equal) => { let cmp = unsafe { memcmp( self.data.as_ptr() as *const i8, other.data.as_ptr() as *const i8, - self.len, + self.size(), ) }; if cmp == 0 { @@ -171,7 +138,7 @@ impl core::ops::Index for Slice { /// 获取某个下标的数据 fn index(&self, index: usize) -> &Self::Output { - assert!(index < self.len); + assert!(index < self.size()); &(**self)[index] } } @@ -182,20 +149,8 @@ impl Deref for Slice { /// Slice 解引用到 &[u8] fn deref(&self) -> &Self::Target { unsafe { - slice::from_raw_parts(self.data.as_ptr(), self.len) + self.data.deref() } } } -// impl Drop for Slice { -// /// 释放内存 -// fn drop(&mut self) { -// if self.len > 0 { -// unsafe { -// let str = Vec::from_raw_parts(self.data.as_ptr(), self.len, self.len); -// println!("drop: {:?}", &str); -// } -// } -// } -// } - diff --git a/src/util/slice_test.rs b/src/util/slice_test.rs index 037994d..9bb11d8 100644 --- a/src/util/slice_test.rs +++ b/src/util/slice_test.rs @@ -3,25 +3,52 @@ mod test { use crate::util::slice::Slice; #[test] - fn test_new() { - let mut a: Slice = "abc".into(); + fn test_from() { + let mut a = Slice::from("123"); + assert_eq!(String::from("123"), String::from(a)) + + } + + #[test] + fn test_addr() { + let a = 123_u32; + let slice = a.to_le_bytes(); unsafe { - let str = String::from_raw_parts((*a).as_mut_ptr(), 3, 3); - println!("str: {}", str); + let a_addr = &a as *const u32 as usize; + let slice_addr = slice.as_ptr() as usize; + println!("a_addr: {}, slice_addr: {}", a_addr, slice_addr); } - // let str: &[u8] = &*a; - // println!("str: {:?}", String::from_utf8_lossy(str)); - // assert_eq!("123".as_bytes(), str); - - // let b: Slice = "abc".into(); - // let str1: String = b.into(); - // assert_eq!(String::from("abc"), str1); } #[test] fn test_size() { - let slice: Slice = String::from("123").into(); - assert_eq!(3, slice.size()); + let mut a: Vec = Vec::with_capacity(4); + // 把 u32 编码到4个byte中, 在内存中结构为 [a0, a1, a2, a3, ....] + // 方式1, 用位移来编码 + let len = 12_u32; // 长度 + a.push(len as u8); + a.push((len >> 8) as u8); + a.push((len >> 16) as u8); + a.push((len >> 24) as u8); + + // 方式2, 获取到内存地址直接写 + // unsafe { + // a.as_mut_ptr().cast::().write(12); + // 指针待偏移量可以这样写 + // a.as_mut_ptr().cast::().offset(0).write(12); + // a.set_len(4); + // } + + + // 取出数据校验, a 这个 vec 指针指向的数据为 [a0, a1, a2, a3, ....], + // 读取地址前4个byte到u32中, 比较原始值 + let value = unsafe { + a.as_ptr().cast::().read() + }; + assert_eq!(12, value); + + // let slice: Slice = String::from("123").into(); + // assert_eq!(3, slice.size()); } #[test] -- Gitee From c17da77a93369518863296e9232c464124c42d79 Mon Sep 17 00:00:00 2001 From: fengyang Date: Sat, 10 Dec 2022 00:20:19 +0800 Subject: [PATCH 10/16] =?UTF-8?q?Status=20=E6=9E=84=E9=80=A0=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/mod.rs | 3 +- src/util/status.rs | 157 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 157 insertions(+), 3 deletions(-) diff --git a/src/util/mod.rs b/src/util/mod.rs index fe7c884..3be3ed1 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -2,4 +2,5 @@ pub mod slice; pub mod status; mod slice_test; pub mod coding; -mod coding_test; \ No newline at end of file +mod coding_test; +mod status_test; \ No newline at end of file diff --git a/src/util/status.rs b/src/util/status.rs index ae9e509..968bb88 100644 --- a/src/util/status.rs +++ b/src/util/status.rs @@ -1,4 +1,157 @@ +/// 使用 Status 这个类来得到你的函数的返回的状态 +/// +use std::borrow::{Borrow, Cow}; +use std::io::Write; +use std::ptr; +use std::ptr::{NonNull, null}; +use crate::util::slice::Slice; +use crate::util::status::Code::kOk; -pub enum Status { +#[derive(Debug)] +pub struct Status { + /// state_[0, 3] 字节代表消息的长度,这个长度是从 state_[5, ...] 开始的,前面的 5 个字节不算。 + /// state_[4] 字节代表消息的类型,就是上面介绍的 enum Code 的 6 种类型。 + /// state_[5, ...] 代表实际的消息体。 -} \ No newline at end of file + /// OK status has a null state_. Otherwise, state_ is a new[] array + /// of the following form: + /// state_[0..3] == length of message + /// state_[4] == code + /// state_[5..] == message + pub state_: String, +} + +impl Default for Status { + fn default() -> Self { + unsafe { + Self { + state_: String::new() + } + } + } +} + +impl Status { + /// 构造一个 Status + fn off(state: String) -> Status { + unsafe { + Status { + state_: state + } + } + } + + /// 构造一个 Status + pub fn of(code: Code, msg: Slice, msg2:Slice) -> Status { + let len2: usize = msg2.len(); + let msgSize: usize = msg.len() + (2 + len2); + + let mut vecStatus: Vec = Vec::with_capacity(msgSize); + + let msgSizeV: u32 = msgSize.try_into().unwrap(); + + // 0,1,2,3 + // unsafe { + // vecStatus.as_mut_ptr().cast::().offset(0) + // .write(msgSizeV); + // } + vecStatus.push(msgSizeV as u8); + vecStatus.push((msgSizeV >> 8) as u8); + vecStatus.push((msgSizeV >> 16) as u8); + vecStatus.push((msgSizeV >> 24) as u8); + + // 4 + vecStatus.push(code as u8); + + // data 1 + vecStatus.write(msg.as_ref()); + + if len2 > 0 { + vecStatus.write(":".as_bytes()); + vecStatus.write(" ".as_bytes()); + vecStatus.write(msg2.as_ref()); + } + + unsafe { + return Status::off(String::from_utf8_unchecked(vecStatus)); + } + } + +// fn code(&self) -> Code { +// if self.state_ == nullptr +// return Code::kOk; +// +// +// return () ? : self.state_[4]; +// } +// +// /// Returns true iff the status indicates success. +// pub fn ok(&self) -> bool { +// self.state_ == NonNull +// // let code: Cow = Slice::borrow_data(&Slice::from(String::from("123").into())); +// // true +// } +// +// /// Returns true iff the status indicates a NotFound error. +// pub fn is_not_found(&self) -> bool { +// true +// } +// +// /// Returns true iff the status indicates a Corruption error. +// pub fn is_corruption(&self) -> bool { +// true +// } +// +// /// Returns true iff the status indicates an IOError. +// pub fn is_io_error(&self) -> bool { +// true +// } +// +// /// Returns true iff the status indicates a NotSupportedError. +// pub fn is_not_supported_error(&self) -> bool { +// true +// } +// +// /// Returns true iff the status indicates an InvalidArgument. +// pub fn is_invalid_argument(&self) -> bool { +// true +// } +// +// /// Return a string representation of this status suitable for printing. +// /// Returns the string "OK" for success. +// pub fn to_string(&self) -> String { +// format!("{}", "") +// } +} + +impl<'a> Status { + /// 返回 ok的 Status + pub fn ok(&self) -> Status { + Status::default() + } + + // /// 返回 ok的 Status + // pub fn not_found(msg: Slice) -> Status { + // Status::default() + // } + // + // /// 借取 Slice 中的数据, 调用方只拥有读权限 + // pub fn copy_state(&self) -> Cow<'a, String> { + // let size : u32; + // let str = unsafe { + // String::from_raw_parts(self.data.as_ptr(), self.len, self.len) + // }; + // Cow::Owned(str) + // } +} + +/// Status 的状态 +#[derive(Debug, PartialEq)] +pub enum Code { + kOk = 0, + kNotFound = 1, + kCorruption = 2, + kNotSupported = 3, + kInvalidArgument = 4, + kIOError = 5, +} -- Gitee From f0b7647dd6fd3162736a57e9d9b050118905bbef Mon Sep 17 00:00:00 2001 From: wangboo <5417808+wangboa@user.noreply.gitee.com> Date: Mon, 12 Dec 2022 14:54:21 +0800 Subject: [PATCH 11/16] =?UTF-8?q?=E5=AE=8C=E5=96=84slice=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E6=A1=88=E4=BE=8B,=20=E8=B0=83=E6=95=B4=E4=BB=A3=E7=A0=81,=20?= =?UTF-8?q?=E5=8E=BB=E9=99=A4=E8=AD=A6=E5=91=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/slice.rs | 32 +++++------ src/util/slice_test.rs | 120 ++++++++++++++++++++++------------------- 2 files changed, 78 insertions(+), 74 deletions(-) diff --git a/src/util/slice.rs b/src/util/slice.rs index 573d4e2..6f07e61 100644 --- a/src/util/slice.rs +++ b/src/util/slice.rs @@ -1,10 +1,7 @@ -use std::{ptr, slice}; -use std::alloc::{alloc, Layout}; +use std::mem; use std::borrow::Cow; use std::cmp::Ordering; -use std::mem::ManuallyDrop; use std::ops::Deref; -use std::ptr::{copy, NonNull}; pub struct Slice { data: Vec, @@ -18,10 +15,8 @@ extern { impl Default for Slice { /// 构造一个空的 Slice fn default() -> Self { - unsafe { - Self { - data: Vec::new() - } + Self { + data: Vec::new() } } } @@ -45,11 +40,9 @@ impl Slice { if self.size() == 0 { return Slice::default(); } - unsafe { - let sub_data = &(*self.data)[n..self.size()]; - Self { - data: Vec::from(sub_data) - } + let sub_data = &(*self.data)[n..self.size()]; + Self { + data: Vec::from(sub_data) } } @@ -71,10 +64,11 @@ impl Slice { impl<'a> Slice { /// 借取 Slice 中的数据, 调用方只拥有读权限 pub fn borrow_data(&mut self) -> Cow<'a, String> { - let str = unsafe { - String::from_raw_parts(self.data.as_mut_ptr(), self.size(), self.size()) - }; - Cow::Owned(str) + unsafe { + // String & Vec has the same layout + let s: &String = mem::transmute(&self.data); + Cow::Borrowed(s) + } } } @@ -148,9 +142,7 @@ impl Deref for Slice { /// Slice 解引用到 &[u8] fn deref(&self) -> &Self::Target { - unsafe { - self.data.deref() - } + &*self.data } } diff --git a/src/util/slice_test.rs b/src/util/slice_test.rs index 9bb11d8..9eabf59 100644 --- a/src/util/slice_test.rs +++ b/src/util/slice_test.rs @@ -1,78 +1,90 @@ - mod test { + use std::cmp::Ordering; use crate::util::slice::Slice; #[test] fn test_from() { - let mut a = Slice::from("123"); - assert_eq!(String::from("123"), String::from(a)) - + // from &str + let a0 = Slice::from("123"); + assert_eq!(String::from("123"), String::from(a0)); + // from String + let a1 = Slice::from(String::from("123")); + assert_eq!(String::from("123"), String::from(a1)); } #[test] - fn test_addr() { - let a = 123_u32; - let slice = a.to_le_bytes(); - unsafe { - let a_addr = &a as *const u32 as usize; - let slice_addr = slice.as_ptr() as usize; - println!("a_addr: {}, slice_addr: {}", a_addr, slice_addr); - } + fn test_empty() { + let a0 = Slice::default(); + assert_eq!(true, a0.empty()); + + let a1 = Slice::from("123"); + assert_eq!(false, a1.empty()); } #[test] - fn test_size() { - let mut a: Vec = Vec::with_capacity(4); - // 把 u32 编码到4个byte中, 在内存中结构为 [a0, a1, a2, a3, ....] - // 方式1, 用位移来编码 - let len = 12_u32; // 长度 - a.push(len as u8); - a.push((len >> 8) as u8); - a.push((len >> 16) as u8); - a.push((len >> 24) as u8); + fn test_remove_prefix() { + let a0 = Slice::from("123"); + let a1 = a0.remove_prefix(1); + assert_eq!(2, a1.len()); + } - // 方式2, 获取到内存地址直接写 - // unsafe { - // a.as_mut_ptr().cast::().write(12); - // 指针待偏移量可以这样写 - // a.as_mut_ptr().cast::().offset(0).write(12); - // a.set_len(4); - // } + #[test] + fn test_starts_with() { + let a0 = Slice::from("12345"); + let a1 = a0.remove_prefix(2); + assert_eq!(String::from("345"), String::from(a1)); + } + #[test] + fn test_borrow_data() { + let mut a0 = Slice::from("123"); + let borrowed = a0.borrow_data(); + assert_eq!(3, borrowed.len()); + let owned = borrowed.to_owned(); + assert_eq!(3, owned.len()); + } - // 取出数据校验, a 这个 vec 指针指向的数据为 [a0, a1, a2, a3, ....], - // 读取地址前4个byte到u32中, 比较原始值 - let value = unsafe { - a.as_ptr().cast::().read() - }; - assert_eq!(12, value); + #[test] + fn test_partial_eq() { + let a0 = Slice::from("123"); + let a1 = Slice::from("123"); + let a2 = Slice::from("234"); + let a3 = Slice::from("012"); + assert_eq!(true, a0 == a1); + assert_eq!(true, a0 < a2); + assert_eq!(true, a0 > a3); + } - // let slice: Slice = String::from("123").into(); - // assert_eq!(3, slice.size()); + #[test] + fn test_partial_ord() { + let a0 = Slice::from("123"); + let a1 = Slice::from("123"); + let a2 = Slice::from("234"); + let a3 = Slice::from("012"); + assert_eq!(Ordering::Equal, a0.partial_cmp(&a1).unwrap()); + assert_eq!(Ordering::Less, a0.partial_cmp(&a2).unwrap()); + assert_eq!(Ordering::Greater, a0.partial_cmp(&a3).unwrap()); } #[test] fn test_memory_leak() { // 申请 100G 内存, 查看是否内存泄漏。如果内存泄漏,程序会OOM (0..100_000_000).for_each(|_| { - unsafe { - // 1k - let str = "0123012301230123012301230123012301230123012301230123012301230123012\ - 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ - 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ - 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ - 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ - 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ - 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ - 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ - 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ - 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ - 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ - 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ - 301230123012301230123012301230123"; - let _: Slice = str.into(); - } + // 1k + let str = "0123012301230123012301230123012301230123012301230123012301230123012\ + 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ + 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ + 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ + 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ + 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ + 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ + 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ + 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ + 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ + 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ + 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ + 301230123012301230123012301230123"; + let _: Slice = str.into(); }) } - } \ No newline at end of file -- Gitee From ae767e1db9413363844c8081abd1b994bcbb54c6 Mon Sep 17 00:00:00 2001 From: wangboo <5417808+wangboa@user.noreply.gitee.com> Date: Mon, 12 Dec 2022 17:42:12 +0800 Subject: [PATCH 12/16] =?UTF-8?q?=E5=A2=9E=E5=8A=A0Arena=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?,=20DataPtr=E5=AE=9A=E4=B9=89,=20Encoding=20=E7=89=B9=E8=B4=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/arena.rs | 36 +++++++++++++++++ src/util/coding.rs | 58 +++++++-------------------- src/util/coding_test.rs | 16 -------- src/util/data_ptr.rs | 84 +++++++++++++++++++++++++++++++++++++++ src/util/data_ptr_test.rs | 14 +++++++ src/util/mod.rs | 5 ++- 6 files changed, 153 insertions(+), 60 deletions(-) create mode 100644 src/util/arena.rs create mode 100644 src/util/data_ptr.rs create mode 100644 src/util/data_ptr_test.rs diff --git a/src/util/arena.rs b/src/util/arena.rs new file mode 100644 index 0000000..7263060 --- /dev/null +++ b/src/util/arena.rs @@ -0,0 +1,36 @@ +use std::ptr::NonNull; +use crate::util::data_ptr::DataPtr; + +// Arena block size +const ARENA_BLOCK_SIZE: usize = 4096; + +struct Arena { + +} + +impl Arena { + + pub fn allocate(_bytes: usize) -> NonNull { + todo!() + } + + pub fn allocate_align(_bytes: usize) -> NonNull { + todo!() + } + + fn allocate_fallback(_bytes: usize) -> DataPtr { + todo!() + } + + fn allocate_new_block(_block_size: usize) -> DataPtr { + todo!() + } + +} + +impl Drop for Arena { + + fn drop(&mut self) { + todo!() + } +} \ No newline at end of file diff --git a/src/util/coding.rs b/src/util/coding.rs index 74f2492..99a5c67 100644 --- a/src/util/coding.rs +++ b/src/util/coding.rs @@ -1,47 +1,19 @@ -const B: u8 = 128; +use std::mem::size_of; -/// -/// -/// -pub trait Coding { - fn varint32(self, buf: &mut [u8]); -} +use crate::util::data_ptr::DataPtr; -impl Coding for u32 -{ - fn varint32(self, buf: &mut [u8]) { - // if self < 1 << 7 { - // buf[0] = self as u8; - // } else if self < 1 << 14 { - // buf[0] = self | B; - // println!("{:b}", buf[0]); - // buf[1] = buf[0] >> 7; - // println!("{:b}", buf[1]); - // } else if self < 1 << 21 { - // buf[0] = (self | B as u8) as u8; - // println!("{:b}", buf[0]); - // buf[1] = (buf[0] >> 7) | B; - // println!("{:b}", buf[1]); - // buf[2] = buf[1] >> 14; - // println!("{:b}", buf[2]); - // } else if self < 1 << 28 { - // buf[0] = (self | B as u8) as u8; - // println!("{:b}", buf[0]); - // buf[1] = (buf[0] >> 7) | B; - // println!("{:b}", buf[1]); - // buf[2] = (buf[1] >> 14) | B; - // println!("{:b}", buf[2]); - // buf[3] = buf[2] >> 21; - // } else { - // buf[0] = (self | B as u8) as u8; - // println!("{:b}", buf[0]); - // buf[1] = (buf[0] >> 7) | B; - // println!("{:b}", buf[1]); - // buf[2] = (buf[1] >> 14) | B; - // println!("{:b}", buf[2]); - // buf[3] = (buf[2] >> 21) | B; - // println!("{:b}", buf[3]); - // buf[4] = buf[3] >> 28; - // } +/// 编解码特性 +/// LevelDB需要支持的基本类型都需要实现此特质, 如 u8, i8, u32 等 +pub trait Coding { + + fn write(self, ptr: DataPtr) -> DataPtr; + + fn read(ptr: DataPtr) -> T; + + fn read_once(ptr: DataPtr) -> (T, DataPtr) { + let value: T = Self::read(ptr); + unsafe { + (value, ptr.offset(size_of::() as isize)) + } } } \ No newline at end of file diff --git a/src/util/coding_test.rs b/src/util/coding_test.rs index 3c4184f..ed03565 100644 --- a/src/util/coding_test.rs +++ b/src/util/coding_test.rs @@ -1,20 +1,4 @@ mod test { use crate::util::coding::Coding; - #[test] - fn test_i32() { - let mut buf: [u8; 8] = [0, 0, 0, 0, 0, 0, 0, 0]; - let x = 127.varint32(&mut buf); - println!("{:?}", buf); - println!("{:?}", x); - println!("{:b}", buf[0]); - } - - #[test] - fn test_offset() { - let buf: [u8; 3] = [0, 1, 2]; - let mut offset: usize = 0; - offset += 1; - println!("{:?}", buf[offset]) - } } diff --git a/src/util/data_ptr.rs b/src/util/data_ptr.rs new file mode 100644 index 0000000..76c2245 --- /dev/null +++ b/src/util/data_ptr.rs @@ -0,0 +1,84 @@ +use std::mem; +use std::mem::size_of; + +#[derive(Copy, Clone)] +pub struct DataPtr { + ptr: *mut u8, +} + +impl From<*mut u8> for DataPtr { + #[inline] + fn from(ptr: *mut u8) -> Self { + Self { + ptr + } + } +} + +impl From<*const u8> for DataPtr { + #[inline] + fn from(ptr: *const u8) -> Self { + Self { + ptr: ptr as *mut u8 + } + } +} + +impl DataPtr { + /// 向 DataPtr 中写入一个值 + /// + /// # Unsafe + /// 调用方需要保证写入数据的大小不会超过 DataPtr 剩余可用的内存大小 + /// + /// # Arguments + /// + /// * `value`: 要被写入的值 + /// + /// returns: DataPtr 写入后的指针偏移量 + /// + /// # Examples + /// + /// ``` + /// use std::alloc::{alloc, Layout}; + /// let raw_ptr = unsafe { + /// alloc(Layout::from_size_align(8, 8).unwrap()) + /// }; + /// let ptr = DataPtr::from(raw_ptr); + /// unsafe { + /// // write multi values + /// ptr.write(18_u32).write(32_u32); + /// } + /// ``` + #[inline] + pub unsafe fn write(&self, value: T) -> DataPtr + where T: Sized { + unsafe { + (self.ptr as *mut _ as *mut T).write(value); + self.ptr.offset(size_of::() as isize).into() + } + } + + + /// 让 DataPtr 的指针偏移指定长度 + /// + /// # Unsafe + /// 调用方必须保证增加额外得偏移长度不会造成指针越界 + /// + /// # Arguments + /// + /// * `offset`: 偏移长度 + /// + /// returns: DataPtr + /// + /// # Examples + /// + /// ``` + /// + /// ``` + #[inline] + pub unsafe fn offset(&self, offset: isize) -> DataPtr { + self.ptr.offset(offset).into() + } + + +} \ No newline at end of file diff --git a/src/util/data_ptr_test.rs b/src/util/data_ptr_test.rs new file mode 100644 index 0000000..940b63d --- /dev/null +++ b/src/util/data_ptr_test.rs @@ -0,0 +1,14 @@ +use std::alloc::{alloc, Layout}; +use crate::util::data_ptr::DataPtr; + +#[test] +fn test_create() { + let raw_ptr = unsafe { + alloc(Layout::from_size_align(8, 8).unwrap()) + }; + let ptr = DataPtr::from(raw_ptr); + unsafe { + ptr.write(18_u32); + ptr.write(32_u32); + } +} \ No newline at end of file diff --git a/src/util/mod.rs b/src/util/mod.rs index fe7c884..2703933 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -2,4 +2,7 @@ pub mod slice; pub mod status; mod slice_test; pub mod coding; -mod coding_test; \ No newline at end of file +mod coding_test; +pub mod arena; +pub mod data_ptr; +mod data_ptr_test; \ No newline at end of file -- Gitee From 4ef960e302f563a129642d009d9a9b5a78069360 Mon Sep 17 00:00:00 2001 From: wangboo <5417808+wangboa@user.noreply.gitee.com> Date: Mon, 12 Dec 2022 20:05:05 +0800 Subject: [PATCH 13/16] =?UTF-8?q?=E5=A2=9E=E5=8A=A0arena=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/arena.rs | 94 ++++++++++++++++++++++++++++++++++----- src/util/arena_test.rs | 35 +++++++++++++++ src/util/coding.rs | 18 +------- src/util/data_ptr.rs | 84 ---------------------------------- src/util/data_ptr_test.rs | 14 ------ src/util/mod.rs | 5 ++- 6 files changed, 121 insertions(+), 129 deletions(-) create mode 100644 src/util/arena_test.rs delete mode 100644 src/util/data_ptr.rs delete mode 100644 src/util/data_ptr_test.rs diff --git a/src/util/arena.rs b/src/util/arena.rs index 7263060..d9b3f95 100644 --- a/src/util/arena.rs +++ b/src/util/arena.rs @@ -1,36 +1,106 @@ +use std::alloc::{alloc, dealloc, Layout}; use std::ptr::NonNull; -use crate::util::data_ptr::DataPtr; +use std::slice; // Arena block size const ARENA_BLOCK_SIZE: usize = 4096; -struct Arena { +pub struct Arena { + alloc_ptr: Option>, + alloc_bytes_remaining: usize, + blocks: Vec<(NonNull, Layout)>, + memory_usage: usize, +} +impl Default for Arena { + fn default() -> Self { + Self { + alloc_ptr: None, + alloc_bytes_remaining: 0, + blocks: vec![], + memory_usage: 0, + } + } } impl Arena { - pub fn allocate(_bytes: usize) -> NonNull { - todo!() + /// 申请一块内存 + /// + /// # Arguments + /// + /// * `bytes`: 申请内存大小(byte) + /// + /// returns: &mut [u8] + /// 内存的 byte 数组 + /// # Examples + /// + /// ``` + ///let arena = Arena::default(); + /// // 申请 12 字节大小的内存 + /// let buf = arena.allocate(12); + /// ``` + #[inline] + pub fn allocate(&mut self, bytes: usize) -> &mut [u8] { + self.allocate_align(bytes, 1) } - pub fn allocate_align(_bytes: usize) -> NonNull { - todo!() + pub fn allocate_align(&mut self, bytes: usize, align: usize) -> &mut [u8] { + if bytes <= self.alloc_bytes_remaining { + self.alloc_bytes_remaining -= bytes; + let result = unsafe { slice::from_raw_parts_mut(self.alloc_ptr.unwrap().as_ptr(), bytes) }; + unsafe { + let new_ptr = self.alloc_ptr.unwrap().as_ptr().offset(bytes as isize); + self.alloc_ptr = Some(NonNull::new_unchecked(new_ptr)); + }; + return result; + } + return self.allocate_fallback(bytes, align); } - fn allocate_fallback(_bytes: usize) -> DataPtr { - todo!() + pub fn memory_usage(&self) -> usize { + self.memory_usage } - fn allocate_new_block(_block_size: usize) -> DataPtr { - todo!() + fn allocate_fallback(&mut self, bytes: usize, align: usize) -> &mut [u8] { + if bytes > ARENA_BLOCK_SIZE / 4 { + unsafe { + let layout = Layout::from_size_align_unchecked(bytes, align); + return self.allocate_new_block(layout); + } + } + unsafe { + self.alloc_bytes_remaining = ARENA_BLOCK_SIZE - bytes; + let layout = Layout::from_size_align_unchecked(ARENA_BLOCK_SIZE, align); + let new_block = self.allocate_new_block(layout); + unsafe { + let ptr = new_block.as_ptr() as *mut u8; + let result = slice::from_raw_parts_mut(ptr, bytes); + self.alloc_ptr = Some(NonNull::new_unchecked(ptr.offset(bytes as isize))); + result + } + } } + + /// 分配一块新的内存 + fn allocate_new_block(&mut self, layout: Layout) -> &mut [u8] { + unsafe { + let data = alloc(layout); + self.memory_usage += layout.size(); + self.blocks.push((NonNull::new_unchecked(data), layout)); + slice::from_raw_parts_mut(data, layout.size()) + } + } } impl Drop for Arena { - + /// 释放内存 fn drop(&mut self) { - todo!() + for (block, layout) in self.blocks.iter() { + unsafe { + dealloc(block.as_ptr(), *layout) + } + } } } \ No newline at end of file diff --git a/src/util/arena_test.rs b/src/util/arena_test.rs new file mode 100644 index 0000000..dbc8cf1 --- /dev/null +++ b/src/util/arena_test.rs @@ -0,0 +1,35 @@ +use crate::util::Arena; + +#[test] +fn test_memory_usage() { + let mut arena = Arena::default(); + let _buf0 = arena.allocate(12); + let _buf1 = arena.allocate(16); + assert_eq!(4096, arena.memory_usage()); + let _buf2 = arena.allocate(3900); + assert_eq!(4096, arena.memory_usage()); + let _buf3 = arena.allocate(1200); + assert_eq!(4096 + 1200, arena.memory_usage()); +} + +#[test] +fn test_allocate() { + let mut arena = Arena::default(); + for i in 0..=12 { + let byte_size = 1 << i; + let buf = arena.allocate(byte_size); + assert_eq!(byte_size, buf.len()); + } + assert_eq!(8192, arena.memory_usage()); +} + +#[test] +fn test_allocate_align() { + let mut arena = Arena::default(); + for i in 0..=12 { + let byte_size = 1 << i; + let buf = arena.allocate_align(byte_size, 8); + assert_eq!(byte_size, buf.len()); + } + assert_eq!(4096 * 2, arena.memory_usage()); +} \ No newline at end of file diff --git a/src/util/coding.rs b/src/util/coding.rs index 99a5c67..1170950 100644 --- a/src/util/coding.rs +++ b/src/util/coding.rs @@ -1,19 +1,3 @@ -use std::mem::size_of; +pub struct Coding { -use crate::util::data_ptr::DataPtr; - -/// 编解码特性 -/// LevelDB需要支持的基本类型都需要实现此特质, 如 u8, i8, u32 等 -pub trait Coding { - - fn write(self, ptr: DataPtr) -> DataPtr; - - fn read(ptr: DataPtr) -> T; - - fn read_once(ptr: DataPtr) -> (T, DataPtr) { - let value: T = Self::read(ptr); - unsafe { - (value, ptr.offset(size_of::() as isize)) - } - } } \ No newline at end of file diff --git a/src/util/data_ptr.rs b/src/util/data_ptr.rs deleted file mode 100644 index 76c2245..0000000 --- a/src/util/data_ptr.rs +++ /dev/null @@ -1,84 +0,0 @@ -use std::mem; -use std::mem::size_of; - -#[derive(Copy, Clone)] -pub struct DataPtr { - ptr: *mut u8, -} - -impl From<*mut u8> for DataPtr { - #[inline] - fn from(ptr: *mut u8) -> Self { - Self { - ptr - } - } -} - -impl From<*const u8> for DataPtr { - #[inline] - fn from(ptr: *const u8) -> Self { - Self { - ptr: ptr as *mut u8 - } - } -} - -impl DataPtr { - /// 向 DataPtr 中写入一个值 - /// - /// # Unsafe - /// 调用方需要保证写入数据的大小不会超过 DataPtr 剩余可用的内存大小 - /// - /// # Arguments - /// - /// * `value`: 要被写入的值 - /// - /// returns: DataPtr 写入后的指针偏移量 - /// - /// # Examples - /// - /// ``` - /// use std::alloc::{alloc, Layout}; - /// let raw_ptr = unsafe { - /// alloc(Layout::from_size_align(8, 8).unwrap()) - /// }; - /// let ptr = DataPtr::from(raw_ptr); - /// unsafe { - /// // write multi values - /// ptr.write(18_u32).write(32_u32); - /// } - /// ``` - #[inline] - pub unsafe fn write(&self, value: T) -> DataPtr - where T: Sized { - unsafe { - (self.ptr as *mut _ as *mut T).write(value); - self.ptr.offset(size_of::() as isize).into() - } - } - - - /// 让 DataPtr 的指针偏移指定长度 - /// - /// # Unsafe - /// 调用方必须保证增加额外得偏移长度不会造成指针越界 - /// - /// # Arguments - /// - /// * `offset`: 偏移长度 - /// - /// returns: DataPtr - /// - /// # Examples - /// - /// ``` - /// - /// ``` - #[inline] - pub unsafe fn offset(&self, offset: isize) -> DataPtr { - self.ptr.offset(offset).into() - } - - -} \ No newline at end of file diff --git a/src/util/data_ptr_test.rs b/src/util/data_ptr_test.rs deleted file mode 100644 index 940b63d..0000000 --- a/src/util/data_ptr_test.rs +++ /dev/null @@ -1,14 +0,0 @@ -use std::alloc::{alloc, Layout}; -use crate::util::data_ptr::DataPtr; - -#[test] -fn test_create() { - let raw_ptr = unsafe { - alloc(Layout::from_size_align(8, 8).unwrap()) - }; - let ptr = DataPtr::from(raw_ptr); - unsafe { - ptr.write(18_u32); - ptr.write(32_u32); - } -} \ No newline at end of file diff --git a/src/util/mod.rs b/src/util/mod.rs index 2703933..567d645 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -4,5 +4,6 @@ mod slice_test; pub mod coding; mod coding_test; pub mod arena; -pub mod data_ptr; -mod data_ptr_test; \ No newline at end of file +mod arena_test; + +pub use arena::Arena; \ No newline at end of file -- Gitee From 4353d2aff66ca95330558d17fd49039ad6bd4a12 Mon Sep 17 00:00:00 2001 From: wangboo <5417808+wangboa@user.noreply.gitee.com> Date: Mon, 12 Dec 2022 21:48:25 +0800 Subject: [PATCH 14/16] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=B8=80=E4=B8=AA=20fr?= =?UTF-8?q?om=5Fbuf=20=E7=9A=84=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/slice.rs | 8 ++++++++ src/util/slice_test.rs | 3 +++ 2 files changed, 11 insertions(+) diff --git a/src/util/slice.rs b/src/util/slice.rs index 6f07e61..734f35f 100644 --- a/src/util/slice.rs +++ b/src/util/slice.rs @@ -22,6 +22,14 @@ impl Default for Slice { } impl Slice { + /// 从 &mut [u8] 转到 Slice + pub fn from_buf(buf: &mut [u8]) -> Self { + unsafe { + Self { + data: Vec::from_raw_parts(buf.as_mut_ptr(), buf.len(), buf.len()) + } + } + } /// 获取 slice 长度 #[inline] pub fn size(&self) -> usize { diff --git a/src/util/slice_test.rs b/src/util/slice_test.rs index 9eabf59..f306f6d 100644 --- a/src/util/slice_test.rs +++ b/src/util/slice_test.rs @@ -10,6 +10,9 @@ mod test { // from String let a1 = Slice::from(String::from("123")); assert_eq!(String::from("123"), String::from(a1)); + + let a2 = Slice::from_buf([30_u8, 31, 32].as_mut_slice()); + assert_eq!(String::from("012"), String::from(a2)); } #[test] -- Gitee From b02863bcf061bf7942583f7dc1b9cc38d9907d7c Mon Sep 17 00:00:00 2001 From: fengyang Date: Mon, 12 Dec 2022 23:25:14 +0800 Subject: [PATCH 15/16] =?UTF-8?q?status=20=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/mod.rs | 11 +- src/util/status.rs | 283 ++++++++++++++++++++++------------------ src/util/status_test.rs | 48 +++++++ 3 files changed, 213 insertions(+), 129 deletions(-) create mode 100644 src/util/status_test.rs diff --git a/src/util/mod.rs b/src/util/mod.rs index fcbc066..d2fb80b 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1,5 +1,7 @@ +use crate::util::status::LevelError; +use std::result; + pub mod slice; -pub mod status; mod slice_test; pub mod coding; mod coding_test; @@ -7,4 +9,9 @@ pub mod arena; mod arena_test; pub use arena::Arena; -mod status_test; \ No newline at end of file + +pub mod status; +mod status_test; + +/// 定义别名 +pub type Result = result::Result; diff --git a/src/util/status.rs b/src/util/status.rs index 968bb88..c576126 100644 --- a/src/util/status.rs +++ b/src/util/status.rs @@ -1,157 +1,186 @@ /// 使用 Status 这个类来得到你的函数的返回的状态 /// use std::borrow::{Borrow, Cow}; -use std::io::Write; +use std::fmt::Debug; use std::ptr; use std::ptr::{NonNull, null}; use crate::util::slice::Slice; -use crate::util::status::Code::kOk; - -#[derive(Debug)] -pub struct Status { - /// state_[0, 3] 字节代表消息的长度,这个长度是从 state_[5, ...] 开始的,前面的 5 个字节不算。 - /// state_[4] 字节代表消息的类型,就是上面介绍的 enum Code 的 6 种类型。 - /// state_[5, ...] 代表实际的消息体。 - - /// OK status has a null state_. Otherwise, state_ is a new[] array - /// of the following form: - /// state_[0..3] == length of message - /// state_[4] == code - /// state_[5..] == message - pub state_: String, +use crate::util::status::LevelError::{kCorruption, kInvalidArgument, kIOError, kNotFound, kNotSupported, kOk}; + +/// Status 的状态 +pub enum LevelError { + kOk, + kNotFound(Option), + kCorruption(Option), + kNotSupported(Option), + kInvalidArgument(Option), + kIOError(Option), + } -impl Default for Status { +impl Default for LevelError { fn default() -> Self { - unsafe { - Self { - state_: String::new() - } - } + kOk } } -impl Status { - /// 构造一个 Status - fn off(state: String) -> Status { - unsafe { - Status { - state_: state - } +impl LevelError { + pub fn get_code(&self) -> u32 { + match self { + kOk => {0}, + kNotFound(_) => {1}, + kCorruption(_) => {2}, + kNotSupported(_) => {3}, + kInvalidArgument(_) => {4}, + kIOError(_) => {5}, } } - /// 构造一个 Status - pub fn of(code: Code, msg: Slice, msg2:Slice) -> Status { - let len2: usize = msg2.len(); - let msgSize: usize = msg.len() + (2 + len2); + /// 得到 error 中的 slice 信息 + pub fn into_msg(self) -> Option { + match self { + kOk => {None}, + kNotFound(slice) => { + slice + }, + kCorruption(slice) => { + // println!("The slice to be {:?}", slice); + slice + }, + kNotSupported(slice) => { + // println!("The slice to be {:?}", slice); + slice + }, + kInvalidArgument(slice) => { + // println!("The slice to be {:?}", slice); + slice + }, + kIOError(slice) => { + // println!("The slice to be {:?}", slice); + slice + }, + } + } - let mut vecStatus: Vec = Vec::with_capacity(msgSize); + /// 判断 状态是否为默认值 + fn is_default(&self) -> bool { + self.ok() + } - let msgSizeV: u32 = msgSize.try_into().unwrap(); + /// Returns true iff the status indicates success. + pub fn ok(&self) -> bool { + match self { + kOk => true, + _ => false + } + } - // 0,1,2,3 - // unsafe { - // vecStatus.as_mut_ptr().cast::().offset(0) - // .write(msgSizeV); - // } - vecStatus.push(msgSizeV as u8); - vecStatus.push((msgSizeV >> 8) as u8); - vecStatus.push((msgSizeV >> 16) as u8); - vecStatus.push((msgSizeV >> 24) as u8); + /// Returns true iff the status indicates a NotFound error. + pub fn is_not_found(&self) -> bool { + match self { + kNotFound(_) => true, + _ => false + } + } - // 4 - vecStatus.push(code as u8); + /// Returns true iff the status indicates a Corruption error. + pub fn is_corruption(&self) -> bool { + match self { + kCorruption(_) => true, + _ => false + } + } - // data 1 - vecStatus.write(msg.as_ref()); + /// Returns true iff the status indicates an IOError. + pub fn is_io_error(&self) -> bool { + match self { + kIOError(_) => true, + _ => false + } + } - if len2 > 0 { - vecStatus.write(":".as_bytes()); - vecStatus.write(" ".as_bytes()); - vecStatus.write(msg2.as_ref()); + /// Returns true iff the status indicates a NotSupportedError. + pub fn is_not_supported_error(&self) -> bool { + match self { + kNotSupported(_) => true, + _ => false } + } - unsafe { - return Status::off(String::from_utf8_unchecked(vecStatus)); + /// Returns true iff the status indicates an InvalidArgument. + pub fn is_invalid_argument(&self) -> bool { + match self { + kInvalidArgument(_) => true, + _ => false } } -// fn code(&self) -> Code { -// if self.state_ == nullptr -// return Code::kOk; -// -// -// return () ? : self.state_[4]; -// } -// -// /// Returns true iff the status indicates success. -// pub fn ok(&self) -> bool { -// self.state_ == NonNull -// // let code: Cow = Slice::borrow_data(&Slice::from(String::from("123").into())); -// // true -// } -// -// /// Returns true iff the status indicates a NotFound error. -// pub fn is_not_found(&self) -> bool { -// true -// } -// -// /// Returns true iff the status indicates a Corruption error. -// pub fn is_corruption(&self) -> bool { -// true -// } -// -// /// Returns true iff the status indicates an IOError. -// pub fn is_io_error(&self) -> bool { -// true -// } -// -// /// Returns true iff the status indicates a NotSupportedError. -// pub fn is_not_supported_error(&self) -> bool { -// true -// } -// -// /// Returns true iff the status indicates an InvalidArgument. -// pub fn is_invalid_argument(&self) -> bool { -// true -// } -// -// /// Return a string representation of this status suitable for printing. -// /// Returns the string "OK" for success. -// pub fn to_string(&self) -> String { -// format!("{}", "") -// } -} + /// Return a string representation of this status suitable for printing. + /// Returns the string "OK" for success. + pub fn to_string(self) -> String { + if self.is_default() { + return String::from("OK") + } + + let _tmp:Vec = Vec::with_capacity(30); + let mut _type: &str = ""; + + match self { + kOk => { + _type = "OK"; + }, + kNotFound(_) => { + _type = "NotFound: "; + }, + kCorruption(_) => { + _type = "Corruption: "; + }, + kNotSupported(_) => { + _type = "Not implemented: "; + }, + kInvalidArgument(_) => { + _type = "Invalid argument: "; + }, + kIOError(_) => { + _type = "IO error: "; + } + } + + // todo -impl<'a> Status { - /// 返回 ok的 Status - pub fn ok(&self) -> Status { - Status::default() - } - - // /// 返回 ok的 Status - // pub fn not_found(msg: Slice) -> Status { - // Status::default() - // } - // - // /// 借取 Slice 中的数据, 调用方只拥有读权限 - // pub fn copy_state(&self) -> Cow<'a, String> { - // let size : u32; - // let str = unsafe { - // String::from_raw_parts(self.data.as_ptr(), self.len, self.len) - // }; - // Cow::Owned(str) - // } + String::from(_type) + } } -/// Status 的状态 -#[derive(Debug, PartialEq)] -pub enum Code { - kOk = 0, - kNotFound = 1, - kCorruption = 2, - kNotSupported = 3, - kInvalidArgument = 4, - kIOError = 5, +// 这一组函数用来组合指定的状态信息 +impl<'a> LevelError { + /// 返回 ok 的 Status + pub fn OK() -> LevelError { + kOk + } + + /// 返回 not_found 的 Status + pub fn not_found(msg: Slice, msg2: Slice) -> LevelError { + kNotFound(Some(msg)) + } + + /// 返回 Corruption 的 Status + pub fn corruption(msg: Slice, msg2: Slice) -> LevelError { + kCorruption(Some(msg)) + } + + /// 返回 NotSupported 的 Status + pub fn not_supportedfound(msg: Slice, msg2: Slice) -> LevelError { + LevelError::kNotSupported(Some(msg)) + } + + /// 返回 InvalidArgument 的 Status + pub fn invalid_argument(msg: Slice, msg2: Slice) -> LevelError { + LevelError::kInvalidArgument(Some(msg)) + } + + /// 返回 IOError 的 Status + pub fn io_error(msg: Slice, msg2: Slice) -> LevelError { + LevelError::kIOError(Some(msg)) + } } diff --git a/src/util/status_test.rs b/src/util/status_test.rs new file mode 100644 index 0000000..c15f276 --- /dev/null +++ b/src/util/status_test.rs @@ -0,0 +1,48 @@ + +mod test { + use crate::util::slice::Slice; + use crate::util::status::LevelError; + + #[test] + fn test_of() { + let msg1 = "abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc"; + let msg2 = "456456456456456456456456456456456456456456456456"; + + let err: LevelError = LevelError::io_error(String::from(msg1).into(), + String::from(msg2).into()); + let slice: Option = err.into_msg(); + assert_eq!("abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc", + String::from(slice.unwrap())); + + let err: LevelError = LevelError::OK(); + let slice: Option = err.into_msg(); + assert!(Option::None == slice); + } + + // #[test] + // fn test_toString() { + // // ok + // let status: LevelError = LevelError::OK(); + // assert_eq!("OK", status.to_string()); + // + // let msg1 = "abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc\ + // abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc\ + // abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc\ + // abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc\ + // abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc"; + // let msg2 = "456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456\ + // 456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456\ + // 456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456\ + // 456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456\ + // 456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456456"; + // + // let status: Status = Status::of(Code::kIOError, + // String::from(msg1).into(), + // String::from(msg2).into()); + // + // let expectString: String = String::from("".to_owned() + msg1 + ""); + // assert_eq!("IO error: 101".to_owned() + msg1 + ": " + msg2, + // status.to_string()); + // } + +} -- Gitee From 1dc1143bd89710ca0e59640de53bba86b74a531b Mon Sep 17 00:00:00 2001 From: wangboo <5417808+wangboa@user.noreply.gitee.com> Date: Mon, 12 Dec 2022 23:26:30 +0800 Subject: [PATCH 16/16] =?UTF-8?q?=E5=A2=9E=E5=8A=A0merge=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/arena.rs | 10 ++++------ src/util/slice.rs | 24 ++++++++++++++++++----- src/util/slice_test.rs | 43 ++++++++++++++++++++++++++++++++++++++---- 3 files changed, 62 insertions(+), 15 deletions(-) diff --git a/src/util/arena.rs b/src/util/arena.rs index d9b3f95..611053b 100644 --- a/src/util/arena.rs +++ b/src/util/arena.rs @@ -73,12 +73,10 @@ impl Arena { self.alloc_bytes_remaining = ARENA_BLOCK_SIZE - bytes; let layout = Layout::from_size_align_unchecked(ARENA_BLOCK_SIZE, align); let new_block = self.allocate_new_block(layout); - unsafe { - let ptr = new_block.as_ptr() as *mut u8; - let result = slice::from_raw_parts_mut(ptr, bytes); - self.alloc_ptr = Some(NonNull::new_unchecked(ptr.offset(bytes as isize))); - result - } + let ptr = new_block.as_ptr() as *mut u8; + let result = slice::from_raw_parts_mut(ptr, bytes); + self.alloc_ptr = Some(NonNull::new_unchecked(ptr.offset(bytes as isize))); + result } } diff --git a/src/util/slice.rs b/src/util/slice.rs index 734f35f..7616c13 100644 --- a/src/util/slice.rs +++ b/src/util/slice.rs @@ -23,11 +23,11 @@ impl Default for Slice { impl Slice { /// 从 &mut [u8] 转到 Slice - pub fn from_buf(buf: &mut [u8]) -> Self { - unsafe { - Self { - data: Vec::from_raw_parts(buf.as_mut_ptr(), buf.len(), buf.len()) - } + /// # Unsafe + /// 这里目前存在内存泄漏和double free问题, 先别用 + pub unsafe fn from_buf(buf: &mut [u8]) -> Self { + Self { + data: Vec::from_raw_parts(buf.as_mut_ptr(), buf.len(), buf.len()) } } /// 获取 slice 长度 @@ -67,6 +67,20 @@ impl Slice { other.size()) == 0 }; } + + pub fn merge(&mut self, mut other: Self, joiner: Option) { + if other.empty() { + return; + } + match joiner { + None => self.data.append(&mut other.data), + Some(mut j) => unsafe { + self.data.append(j.as_mut_vec()); + self.data.append(&mut other.data); + } + } + } + } impl<'a> Slice { diff --git a/src/util/slice_test.rs b/src/util/slice_test.rs index f306f6d..06591c9 100644 --- a/src/util/slice_test.rs +++ b/src/util/slice_test.rs @@ -1,5 +1,6 @@ mod test { use std::cmp::Ordering; + use std::mem::ManuallyDrop; use crate::util::slice::Slice; #[test] @@ -10,9 +11,11 @@ mod test { // from String let a1 = Slice::from(String::from("123")); assert_eq!(String::from("123"), String::from(a1)); - - let a2 = Slice::from_buf([30_u8, 31, 32].as_mut_slice()); - assert_eq!(String::from("012"), String::from(a2)); + // from buf + // let mut data = ManuallyDrop::new([48_u8, 49, 50]); + // let slice = data.as_mut_slice(); + // let a2 = Slice::from_buf(slice); + // assert_eq!(String::from("012"), String::from(a2)); } #[test] @@ -70,6 +73,38 @@ mod test { } #[test] + fn test_merge() { + let mut a0 = Slice::from("123"); + let a1 = Slice::default(); + a0.merge(a1, None); + assert_eq!(String::from("123"), String::from(a0)); + } + + #[test] + fn test_merge1() { + let mut a0 = Slice::from("123"); + let a1 = Slice::default(); + a0.merge(a1, Some(String::from("ok"))); + assert_eq!(String::from("123"), String::from(a0)); + } + + #[test] + fn test_merge2() { + let mut a0 = Slice::from("123"); + let mut a2 = Slice::from("456"); + a0.merge(a2, None); + assert_eq!(String::from("123456"), String::from(a0)); + } + + #[test] + fn test_merge3() { + let mut a0 = Slice::from("123"); + let a2 = Slice::from("456"); + a0.merge(a2, Some(String::from("ok"))); + assert_eq!(String::from("123ok456"), String::from(a0)); + } + + // #[test] fn test_memory_leak() { // 申请 100G 内存, 查看是否内存泄漏。如果内存泄漏,程序会OOM (0..100_000_000).for_each(|_| { @@ -87,7 +122,7 @@ mod test { 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ 301230123012301230123012301230123012301230123012301230123012301230123012301230123012\ 301230123012301230123012301230123"; - let _: Slice = str.into(); + let _: Slice = Slice::from(str); }) } } \ No newline at end of file -- Gitee