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 1/5] =?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 2/5] =?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 3/5] =?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 4/5] =?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 5/5] =?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