From f00c900832fef03d60488287ed995eeacaea4d96 Mon Sep 17 00:00:00 2001 From: wangboo <5417808+wangboa@user.noreply.gitee.com> Date: Fri, 17 Mar 2023 17:16:19 +0800 Subject: [PATCH 1/2] =?UTF-8?q?skiplist=E5=A2=9E=E5=8A=A0=E8=BF=AD?= =?UTF-8?q?=E4=BB=A3=E5=99=A8=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/db/skip_list.rs | 56 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/db/skip_list.rs b/src/db/skip_list.rs index 449712f..367dd1d 100644 --- a/src/db/skip_list.rs +++ b/src/db/skip_list.rs @@ -7,6 +7,7 @@ use std::sync::{Arc, RwLock}; use rand::prelude::*; use crate::debug; use crate::traits::comparator_trait::Comparator; +use crate::traits::DataIterator; use crate::util::arena::ArenaRef; use crate::util::{Arena, Result}; @@ -42,6 +43,13 @@ pub struct SkipList { arena: ArenaRef, } +struct DataIter { + head: RawNode, + tail: RawNode, + current: RawNode, + cmp: Cmp, +} + pub struct Iter<'a, Cmp: Comparator> { list: &'a SkipList, node: RawNode, @@ -401,4 +409,52 @@ impl<'a, Cmp: Comparator> Iterator for Iter<'a, Cmp> { (&*self.node).key.as_ref() } } +} + +impl DataIterator for DataIter { + + #[inline] + fn valid(&self) -> bool { + unsafe { + (&*self.current).is_head_or_tail() + } + } + + #[inline] + fn seek_to_first(&mut self) { + self.current = self.head + } + + #[inline] + fn seek_to_last(&mut self) { + self.current = self.tail + } + + fn seek(&mut self, key: &Slice) { + todo!() + } + + fn next(&mut self) { + unsafe { + if (&*self.current).is_tail() { + return; + } + self.current = (&*self.current).get_node(0); + } + } + + fn pre(&mut self) { + todo!() + } + + fn key(&self) -> &Slice { + let mem_key = unsafe { + (&*self.current).key.as_ref().unwrap() + }; + mem_key + } + + fn value(&self) -> &Slice { + todo!() + } } \ No newline at end of file -- Gitee From 99dd80d8bb06c2f907388eca8a66a69638d3dbf0 Mon Sep 17 00:00:00 2001 From: wangboo <5417808+wangboa@user.noreply.gitee.com> Date: Wed, 22 Mar 2023 09:49:44 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20UnsafeSlice?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/db/db_format.rs | 13 +++- src/db/mem_table.rs | 15 +++-- src/db/mod.rs | 2 +- src/db/skip_list.rs | 80 ++++++++++++------------- src/db/skip_list_test.rs | 11 ++-- src/db/version_set.rs | 8 +-- src/traits/comparator_trait.rs | 5 +- src/traits/iterator.rs | 5 +- src/util/comparator.rs | 44 ++++++++++---- src/util/mod.rs | 1 + src/util/options.rs | 3 +- src/util/slice.rs | 7 +++ src/util/unsafe_slice.rs | 105 +++++++++++++++++++++++++++++++++ 13 files changed, 222 insertions(+), 77 deletions(-) create mode 100644 src/util/unsafe_slice.rs diff --git a/src/db/db_format.rs b/src/db/db_format.rs index 49e7194..b36a3c1 100644 --- a/src/db/db_format.rs +++ b/src/db/db_format.rs @@ -1,5 +1,6 @@ use std::cmp::Ordering; use std::io::Write; +use std::sync::Arc; use crate::db::db_format::ValueType::{KTypeDeletion, KTypeValue}; use crate::db::file_meta_data::FileMetaData; use crate::traits::coding_trait::CodingTrait; @@ -28,7 +29,7 @@ pub struct InternalKey { /// InternalKeyComparator pub struct InternalKeyComparator { - user_comparator_: dyn Comparator + user_comparator_: Arc } /// 查找键 @@ -201,8 +202,14 @@ impl InternalKey { } } +impl Default for InternalKeyComparator { + fn default() -> Self { + todo!() + } +} + impl InternalKeyComparator { - pub fn create(c: Box) -> Box { + pub fn create(_cmp: Box) -> Box { todo!() } @@ -223,7 +230,7 @@ impl Comparator for InternalKeyComparator { // todo!() // } - fn compare(&self, _a: &Slice, _b: &Slice) -> Option { + fn compare(&self, _a: &[u8], _b: &[u8]) -> Option { todo!() } diff --git a/src/db/mem_table.rs b/src/db/mem_table.rs index aff4c60..d2746f4 100644 --- a/src/db/mem_table.rs +++ b/src/db/mem_table.rs @@ -9,6 +9,7 @@ use crate::util::arena::ArenaRef; use crate::util::slice::Slice; use crate::util::{Arena, Result}; use crate::util::coding::Coding; +use crate::util::unsafe_slice::UnsafeSlice; /// 内存表 pub struct MemTable { @@ -65,9 +66,11 @@ impl MemTable { } /// 像内存表中写入或删除一个元素 - pub fn add(&mut self, seq_no: usize, v_type: ValueType, key: &Slice, value: Slice) -> Result<()> { - let key_size = key.size(); - let value_size = value.size(); + pub fn add>(&mut self, seq_no: usize, v_type: ValueType, key: &R, value: &R) -> Result<()> { + let key_buf = key.as_ref(); + let value_buf = value.as_ref(); + let key_size = key_buf.len(); + let value_size = value_buf.len(); let internal_key_size = key_size + 8; let encoded_len = Coding::varint_length(key_size) + internal_key_size @@ -79,13 +82,13 @@ impl MemTable { // write key size offset = Coding::encode_varint32(internal_key_size as u32, buf, offset); // write key slice - offset += (&mut buf[offset..]).write(key.as_ref())?; + offset += (&mut buf[offset..]).write(key_buf)?; // write seq_no and type offset = Coding::encode_fixed64((seq_no << 8 | v_type.get_value()) as u64, buf, offset); // write value slice - (&mut buf[offset..]).write(value.as_ref())?; + (&mut buf[offset..]).write(value_buf)?; let slice = Slice::from_buf(buf); - self.list.insert(slice) + self.list.insert(UnsafeSlice::new_with_arena(buf, self.arena.clone())?) } /// 通过 key 查找结果 diff --git a/src/db/mod.rs b/src/db/mod.rs index b82f563..24a37d4 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -23,4 +23,4 @@ mod version_edit_test; /// 默认调表 pub type DefaultSkipList = SkipList; /// 默认内存表 -pub type DefaultMemTable = MemTable; \ No newline at end of file +pub type DefaultMemTable = MemTable; diff --git a/src/db/skip_list.rs b/src/db/skip_list.rs index 367dd1d..a043adc 100644 --- a/src/db/skip_list.rs +++ b/src/db/skip_list.rs @@ -12,16 +12,16 @@ use crate::traits::DataIterator; use crate::util::arena::ArenaRef; use crate::util::{Arena, Result}; use crate::util::slice::Slice; +use crate::util::unsafe_slice::UnsafeSlice; use crate::util::status::{LevelError, Status}; type RawNode = *mut Node; const MAX_LEVEL: usize = 8; -// todo struct Node { /// 存储的值, 如果为空,则是头指针或者尾指针 - key: Option, + key: Option, /// 数组元素首地址,代表一个数组,指向每层的下一个节点。 next_elems: *mut RawNode, /// 当前节点高度 @@ -43,16 +43,11 @@ pub struct SkipList { arena: ArenaRef, } -struct DataIter { +pub struct Iter { head: RawNode, tail: RawNode, current: RawNode, - cmp: Cmp, -} - -pub struct Iter<'a, Cmp: Comparator> { - list: &'a SkipList, - node: RawNode, + cmp: Arc, } impl SkipList { @@ -67,7 +62,7 @@ impl SkipList { } } - pub fn insert(&mut self, key: Slice) -> Result<()> { + pub fn insert(&mut self, key: UnsafeSlice) -> Result<()> { // TODO 这里是否可以优化 if self.contains(&key) { return Ok(()); @@ -82,9 +77,9 @@ impl SkipList { } #[inline] - fn insert_ele0(&mut self, key: Slice) -> Result<()> { + fn insert_ele0(&mut self, key: UnsafeSlice) -> Result<()> { let level = rand_level(); - debug!("insert {}, level: {}", &key, level); + debug!("insert {}, level: {}", String::from_utf8_lossy(key.as_ref()), level); let node = Node::create(key, level, self.arena.clone()); // head bind node // TODO, use macro to expand for-loop @@ -101,7 +96,7 @@ impl SkipList { return Ok(()); } - unsafe fn insert_elen(&mut self, key: Slice) -> Result<()> { + unsafe fn insert_elen(&mut self, key: UnsafeSlice) -> Result<()> { let mut current = self.head; let node_height = rand_level(); let node_top_level = node_height - 1; @@ -119,13 +114,13 @@ impl SkipList { (&mut *current).set_node(l, node_ptr); node.set_node(l, self.tail); debug!("bind: {} before: {}, after: , at level: {}", - node.key.as_ref().unwrap(), - (&*current).key.as_ref().unwrap(), + node.key.unwrap(), + (&*current).key.unwrap(), l); } break 'inner_loop; } else { - match self.cmp.compare(node.key.as_ref().unwrap(), ele.key.as_ref().unwrap()) { + match self.cmp.compare(node.key.unwrap().as_ref(), ele.key.unwrap().as_ref()) { Some(Ordering::Less) => { // node higher than current level at ele if node_top_level >= l { @@ -133,14 +128,14 @@ impl SkipList { node.set_node(l, ele_ptr); if (&*current).is_head() { debug!("bind: {} before: , after: {}, at level: {}", - node.key.as_ref().unwrap(), - ele.key.as_ref().unwrap(), + node.key.unwrap(), + ele.key.unwrap(), l); } else { debug!("bind: {} before: {}, after: {}, at level: {}", - node.key.as_ref().unwrap(), - (&*current).key.as_ref().unwrap(), - ele.key.as_ref().unwrap(), + node.key.unwrap(), + (&*current).key.unwrap(), + ele.key.unwrap(), l); } } @@ -172,8 +167,9 @@ impl SkipList { Ok(()) } - pub fn contains(&self, key: &Slice) -> bool { - debug!("================== begin contains, key: {} ==================", key); + pub fn contains>(&self, key: &R) -> bool { + let key_buf = key.as_ref(); + debug!("================== begin contains, key: {} ==================", String::from_utf8_lossy(key_buf)); if self.num == 0 { return false; } @@ -194,9 +190,9 @@ impl SkipList { } } { - debug!("node: {} at level: {}", ele.key.as_ref().unwrap(), level) + debug!("node: {} at level: {}", ele.key.unwrap(), level) } - match self.cmp.compare(key, ele.key.as_ref().unwrap()) { + match self.cmp.compare(key_buf, ele.key.unwrap().as_ref()) { None => return false, Some(Ordering::Equal) => return true, Some(Ordering::Less) => { @@ -261,7 +257,7 @@ impl ToString for SkipList { // calculate each item width let mut widths = Vec::with_capacity(tree.len()); self.iter().for_each(|s| { - widths.push(s.size()); + widths.push(s.len()); }); // print value list if self.num > 0 { @@ -270,7 +266,7 @@ impl ToString for SkipList { tree.push_str("[head]"); while !node.is_head_or_tail() { tree.push_str(" -> "); - tree.push_str(node.key.as_ref().unwrap().as_str()); + tree.push_str(node.key.unwrap().as_str()); let level_str = format!("({})", node.level); tree.push_str(level_str.as_str()); node = &*node.get_node(0); @@ -285,7 +281,7 @@ impl ToString for SkipList { impl Node { #[inline] - fn create(src: Slice, level: usize, arena: ArenaRef) -> RawNode { + fn create(src: UnsafeSlice, level: usize, arena: ArenaRef) -> RawNode { let node = box Self { key: Some(src), next_elems: allocate_next_elems(arena), @@ -386,32 +382,34 @@ fn min_max(a: usize, b: usize) -> (usize, usize) { } // 'b lifetime is bigger than 'a -impl<'a, Cmp: Comparator> Iter<'a, Cmp> { - fn create(list: &'a SkipList) -> Self { +impl Iter { + fn create(list: &SkipList) -> Self { Self { - list, - node: list.head, + head: list.head, + tail: list.tail, + current: list.head, + cmp: list.cmp.clone(), } } } -impl<'a, Cmp: Comparator> Iterator for Iter<'a, Cmp> { - type Item = &'a Slice; +impl Iterator for Iter { + type Item = UnsafeSlice; #[inline] fn next(&mut self) -> Option { unsafe { - if (&*self.node).is_tail() { + if (&*self.current).is_tail() { return None; } else { - self.node = (&*self.node).get_node(0); + self.current = (&*self.current).get_node(0); } - (&*self.node).key.as_ref() + (&*self.current).key } } } -impl DataIterator for DataIter { +impl DataIterator for Iter { #[inline] fn valid(&self) -> bool { @@ -447,14 +445,14 @@ impl DataIterator for DataIter { todo!() } - fn key(&self) -> &Slice { + fn key(&self) -> UnsafeSlice { let mem_key = unsafe { - (&*self.current).key.as_ref().unwrap() + (&*self.current).key.unwrap() }; mem_key } - fn value(&self) -> &Slice { + fn value(&self) -> UnsafeSlice { todo!() } } \ No newline at end of file diff --git a/src/db/skip_list_test.rs b/src/db/skip_list_test.rs index 7ac6f6f..11ef4bd 100644 --- a/src/db/skip_list_test.rs +++ b/src/db/skip_list_test.rs @@ -8,15 +8,16 @@ mod test { use crate::util::comparator::BytewiseComparatorImpl; use crate::util::Result; use crate::util::slice::Slice; + use crate::util::unsafe_slice::TryIntoUnsafeSlice; #[test] fn test_add() -> Result<()> { let cmp = Arc::new(BytewiseComparatorImpl::default()); let arena = Arc::new(Mutex::new(Arena::default())); - let mut list = DefaultSkipList::create(cmp, arena); + let mut list = DefaultSkipList::create(cmp, arena.clone()); let len = 10; for i in 0..len { - list.insert(format!("key_{}", i).into()).expect("insert ok"); + list.insert(format!("key_{}", i).try_into_unsafe_slice(arena.clone())?).expect("insert ok"); } assert_eq!(10, list.len(), "expect 10, but actually is: {}", list.len()); debug!("{}", list.to_string()); @@ -35,7 +36,7 @@ mod test { fn test_rnd_add() -> Result<()> { let cmp = Arc::new(BytewiseComparatorImpl::default()); let arena = Arc::new(Mutex::new(Arena::default())); - let mut list = DefaultSkipList::create(cmp, arena); + let mut list = DefaultSkipList::create(cmp, arena.clone()); let len = 10; let mut rnd = rand::thread_rng(); let mut set = HashSet::new(); @@ -43,12 +44,12 @@ mod test { let j = rnd.gen_range(0..len); let key = format!("key_{}", j); set.insert(key.clone()); - list.insert(key.into())?; + list.insert(key.try_into_unsafe_slice(arena.clone())?)?; debug!("skiplist: {}", list.to_string()); } assert_eq!(set.len(), list.len(), "list length must eq: {}", list.len()); set.iter().for_each(|key| { - let c = list.contains(&key.clone().into()); + let c = list.contains(&key); assert!(c, "must contains key: {}", key) }); diff --git a/src/db/version_set.rs b/src/db/version_set.rs index 15dabb0..831183d 100644 --- a/src/db/version_set.rs +++ b/src/db/version_set.rs @@ -42,7 +42,7 @@ pub struct VersionSet { dbname_: Slice, options_: Options, table_cache_: TableCache, - icmp_: Box, + icmp_: InternalKeyComparator, next_file_number_: u64, manifest_file_number_: u64, last_sequence_: u64, @@ -101,7 +101,7 @@ struct GetStats { // ,cc line 163 struct LevelFileNumIterator { - icmp_: Rc, + icmp_: InternalKeyComparator, flist_: Vec, index_: u32, @@ -329,7 +329,7 @@ impl VersionSet { /// ``` /// /// ``` - fn find_file(icmp: &InternalKeyComparator, files:&Vec, key:&Slice) -> u32 { + fn find_file(icmp: InternalKeyComparator, files:&Vec, key:&Slice) -> u32 { todo!() } @@ -359,7 +359,7 @@ impl VersionSet { /// ``` /// /// ``` - fn some_file_overlaps_range(icmp: &InternalKeyComparator, disjoint_sorted_files:bool, + fn some_file_overlaps_range(icmp: InternalKeyComparator, disjoint_sorted_files:bool, files:&Vec, smallest_user_key:&Slice,largest_user_key:&Slice) -> bool { todo!() } diff --git a/src/traits/comparator_trait.rs b/src/traits/comparator_trait.rs index a7a74c1..477eb58 100644 --- a/src/traits/comparator_trait.rs +++ b/src/traits/comparator_trait.rs @@ -17,16 +17,17 @@ pub trait Comparator { /// /// ``` /// use std::cmp::Ordering; + /// use crate::util::slice::Slice; /// /// let comp = BytewiseComparatorImpl::default(); - /// optionVal = comp.compare(&Slice::from("a"), &Slice::from("ab")); + /// optionVal = comp.compare("a", "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; + fn compare(&self, a: &[u8], b: &[u8]) -> Option; /// 返回comparator的名字 fn get_name(&self) -> String; diff --git a/src/traits/iterator.rs b/src/traits/iterator.rs index 7717574..164fcc5 100644 --- a/src/traits/iterator.rs +++ b/src/traits/iterator.rs @@ -1,4 +1,5 @@ use crate::util::slice::Slice; +use crate::util::unsafe_slice::UnsafeSlice; pub trait DataIterator { /// 检查当前位置是否有效 @@ -92,7 +93,7 @@ pub trait DataIterator { /// ``` /// /// ``` - fn key(&self) -> &Slice; + fn key(&self) -> UnsafeSlice; /// 获取value值 /// /// # Arguments @@ -105,6 +106,6 @@ pub trait DataIterator { /// ``` /// /// ``` - fn value(&self) -> &Slice; + fn value(&self) -> UnsafeSlice; } diff --git a/src/util/comparator.rs b/src/util/comparator.rs index e7fb05d..661a930 100644 --- a/src/util/comparator.rs +++ b/src/util/comparator.rs @@ -1,8 +1,9 @@ - use std::cmp::{min, Ordering}; -use crate::traits::comparator_trait::{Comparator}; + +use crate::traits::comparator_trait::Comparator; use crate::util::slice::Slice; +#[derive(Copy, Clone)] pub struct BytewiseComparatorImpl {} /// @@ -11,14 +12,33 @@ pub struct BytewiseComparatorImpl {} /// 也就是说 i>helloworld,因为先比较i和h,i>h,比较直接结束 impl Default for BytewiseComparatorImpl { fn default() -> Self { - Self{} + Self {} } } +#[allow(improper_ctypes)] +extern { + fn memcmp(s1: *const i8, s2: *const i8, n: usize) -> i32; +} + impl Comparator for BytewiseComparatorImpl { - fn compare(&self, a: &Slice, b: &Slice) -> Option { - a.partial_cmp(b) + fn compare(&self, a: &[u8], b: &[u8]) -> Option { + let min = a.len().min(b.len()); + let cmp = unsafe { + memcmp( + a.as_ptr() as *const i8, + b.as_ptr() as *const i8, + min, + ) + }; + if cmp == 0 { + a.len().partial_cmp(&b.len()) + } else if cmp > 0 { + Some(Ordering::Greater) + } else { + Some(Ordering::Less) + } } fn get_name(&self) -> String { @@ -30,7 +50,7 @@ impl Comparator for BytewiseComparatorImpl { let min_length: usize = min(start.len(), limit.len()); let mut diff_index: usize = 0; - let mut start_char_vec: Vec = start.as_bytes().to_vec(); + let mut start_char_vec: Vec = start.as_bytes().to_vec(); let limit_char_vec: &Vec = &limit.to_vec(); // or use // let start_char_vec: Vec = start.chars().collect::>(); @@ -47,7 +67,7 @@ impl Comparator for BytewiseComparatorImpl { // 如果一个字符串是另个一字符串的前缀,无需做截短操作,否则进入 else。 if diff_index >= min_length { // 说明 start是limit的前缀,或者反之,此时不作修改,直接返回 - } else{ + } else { // 尝试执行字符start[diff_index]++, 设置start长度为diff_index+1,并返回 // ++条件:字符 < oxff 并且字符+1 < limit上该index的字符 let diff_byte: u8 = start_char_vec[diff_index]; @@ -61,8 +81,8 @@ impl Comparator for BytewiseComparatorImpl { } } - let shortest_separator: &[u8] = &start_char_vec[0..diff_index+1]; - let shortest_separator_val: String= Slice::from_buf(shortest_separator).into(); + let shortest_separator: &[u8] = &start_char_vec[0..diff_index + 1]; + let shortest_separator_val: String = Slice::from_buf(shortest_separator).into(); shortest_separator_val } @@ -71,15 +91,15 @@ impl Comparator for BytewiseComparatorImpl { // 如果找不到说明 key的字符都是 u8::MAX,直接返回 let key_len = key.len(); - let mut key_char_vec: Vec = key.as_bytes().to_vec(); + let mut key_char_vec: Vec = key.as_bytes().to_vec(); for i in 0..key_len { let byte_val: u8 = key_char_vec[i]; if byte_val != u8::MAX { key_char_vec[i] = byte_val + 1; - let short_successor: &[u8] = &key_char_vec[0..i+1]; + let short_successor: &[u8] = &key_char_vec[0..i + 1]; - let short_successor_val: String= Slice::from_buf(short_successor).into(); + let short_successor_val: String = Slice::from_buf(short_successor).into(); return short_successor_val; } } diff --git a/src/util/mod.rs b/src/util/mod.rs index 5a8fc32..ade5ddc 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -40,6 +40,7 @@ pub mod options; pub mod debug; pub mod linked_list; mod linked_list_test; +pub mod unsafe_slice; /// 定义别名 pub type Result = result::Result; diff --git a/src/util/options.rs b/src/util/options.rs index a63c9f6..9028980 100644 --- a/src/util/options.rs +++ b/src/util/options.rs @@ -1,4 +1,5 @@ use crate::db::db::Snapshot; +use crate::db::db_format::InternalKeyComparator; use crate::traits::comparator_trait::Comparator; use crate::util::comparator::BytewiseComparatorImpl; @@ -132,7 +133,7 @@ pub struct WriteOptions { impl Default for Options { fn default() -> Self { Self { - cmp: Box::new(BytewiseComparatorImpl::default()), + cmp: Box::new(InternalKeyComparator::default()), create_if_missing: false, error_if_exists: false, paranoid_checks: false, diff --git a/src/util/slice.rs b/src/util/slice.rs index f172c83..dde1318 100644 --- a/src/util/slice.rs +++ b/src/util/slice.rs @@ -154,6 +154,13 @@ impl > From for Slice { } } +impl AsRef<[u8]> for Slice { + #[inline] + fn as_ref(&self) -> &[u8] { + self.data.as_slice() + } +} + impl PartialEq for Slice { /// 判断两个 Slice 是否相同 #[inline] diff --git a/src/util/unsafe_slice.rs b/src/util/unsafe_slice.rs new file mode 100644 index 0000000..5705b41 --- /dev/null +++ b/src/util/unsafe_slice.rs @@ -0,0 +1,105 @@ +use std::alloc::{alloc, Layout}; +use std::fmt::{Display, Formatter}; +use std::io::Write; +use std::mem::ManuallyDrop; + +use crate::util::arena::ArenaRef; +use crate::util::Result; +use crate::util::slice::Slice; + +/// 提供一种将其它结构体转为 UnsafeSlice 的特质 +pub trait TryIntoUnsafeSlice { + /// 尝试将结构体通过 arena 内存分配器,构造出一个新的 UnsafeSlice + fn try_into_unsafe_slice(&self, arena: ArenaRef) -> Result; +} + +/// 内存不安全的 Slice, 内存由 Arena 分配和管理。 +/// 实现了 Copy 语义,有更高效的读 api +#[derive(Copy, Clone)] +pub struct UnsafeSlice { + ptr: *mut u8, + len: usize, +} + +impl UnsafeSlice { + + /// 利用 arena 生成 UnsafeSlice + pub fn new_with_arena>(data: B, arena: ArenaRef) -> Result { + let mut lock = arena.lock()?; + let src = data.as_ref(); + let mut buf = lock.allocate(src.len()); + buf.write(src)?; + Ok(Self { + ptr: buf.as_mut_ptr(), + len: buf.len(), + }) + } + + #[inline] + pub fn len(&self) -> usize { + self.len + } + + #[inline] + pub fn as_str(&self) -> &str { + unsafe { + core::str::from_utf8_unchecked(self.as_ref()) + } + } +} + +impl UnsafeSlice { + + /// 返回子串。这个方法是高效的,在内部只复制了裸指针偏的移量。 + pub unsafe fn sub_slice(&self, start: usize, len: usize) -> Self { + assert!(start + len < self.len, "sub_slice out of range"); + Self { + ptr: self.ptr.offset(start as isize), + len, + } + } + + /// 生成 Slice 串,由于 Slice 是内存安全的,所以实现上会有内存拷贝。 + /// 高性能场景优先考虑 UnsafeSlice + pub fn to_slice(&self) -> Slice { + unsafe { + let raw_ptr = alloc(Layout::from_size_align_unchecked(self.len, 8)); + Slice::from_raw_parts(raw_ptr, self.len) + } + } +} + +impl AsRef<[u8]> for UnsafeSlice { + + #[inline] + fn as_ref(&self) -> &[u8] { + unsafe { + core::slice::from_raw_parts(self.ptr, self.len) + } + } +} + +impl Display for UnsafeSlice { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + unsafe { + let string = ManuallyDrop::new( + String::from_raw_parts(self.ptr, self.len, self.len) + ); + f.write_str(string.as_str()) + } + } +} + +impl TryIntoUnsafeSlice for &str { + #[inline] + fn try_into_unsafe_slice(&self, arena: ArenaRef) -> Result { + UnsafeSlice::new_with_arena(self.as_bytes(), arena) + } +} + +impl TryIntoUnsafeSlice for String { + #[inline] + fn try_into_unsafe_slice(&self, arena: ArenaRef) -> Result { + UnsafeSlice::new_with_arena(self.as_bytes(), arena) + } +} \ No newline at end of file -- Gitee