diff --git a/Cargo.toml b/Cargo.toml index efad701..5dea02c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,24 +1,27 @@ [package] -name = "gapbuf" -version = "0.1.4" -authors = ["FrozenLib"] +name = "gap-buf" +version = "0.6.1" +authors = ["FrozenLib", "AhoyISki"] license = "MIT OR Apache-2.0" readme = "README.md" -repository = "https://github.com/frozenlib/gapbuf-rs" -documentation = "https://docs.rs/gapbuf/" +repository = "https://github.com/AhoyISki/gap-buf-rs" +documentation = "https://docs.rs/gap-buf/" keywords = ["gap", "gapbuffer"] categories = ["data-structures"] description = "Generic gap buffer." -edition = "2021" - -[features] -docs-rs = [] +edition = "2024" [dependencies] +bincode = { version = "2.0.1", optional = true } +unty = { version = "0.0.5", optional = true } [dev-dependencies] test-strategy = "0.2.0" proptest = "1.0.0" +[features] +docs-rs = [] +bincode = ["dep:bincode", "dep:unty"] + [package.metadata.docs.rs] features = ["docs-rs"] diff --git a/README.md b/README.md index 77f5ab2..48b72c3 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -# gapbuf-rs +# gap-buf-rs -[![Crates.io](https://img.shields.io/crates/v/gapbuf.svg)](https://crates.io/crates/gapbuf) -[![Docs.rs](https://docs.rs/gapbuf/badge.svg)](https://docs.rs/gapbuf) -[![Actions Status](https://github.com/frozenlib/gapbuf-rs/workflows/CI/badge.svg)](https://github.com/frozenlib/gapbuf-rs/actions) +[![Crates.io](https://img.shields.io/crates/v/gap-buf.svg)](https://crates.io/crates/gap-buf) +[![Docs.rs](https://docs.rs/gapbuf/badge.svg)](https://docs.rs/gap-buf) +[![Actions Status](https://github.com/AhoyISki/gap-buf-rs/workflows/CI/badge.svg)](https://github.com/AhoyISki/gap-buf-rs/actions) Generic gap buffer implementation in Rust. @@ -12,7 +12,7 @@ This type has methods similar to `Vec`. ## Examples ```rust -use gapbuf::gap_buffer; +use gap_buf::gap_buffer; let mut b = gap_buffer![1, 2, 3]; b.insert(1, 10); diff --git a/benchmarks/Cargo.toml b/benchmarks/Cargo.toml index 194ba99..c484bb4 100644 --- a/benchmarks/Cargo.toml +++ b/benchmarks/Cargo.toml @@ -7,4 +7,4 @@ publish = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -gapbuf = { path = "../" } +gap_buf = { path = "../" } diff --git a/benchmarks/benches/benches.rs b/benchmarks/benches/benches.rs index f254047..649ffbb 100644 --- a/benchmarks/benches/benches.rs +++ b/benchmarks/benches/benches.rs @@ -3,7 +3,7 @@ extern crate test; use self::test::Bencher; -use gapbuf::GapBuffer; +use gap_buf::GapBuffer; use std::collections::VecDeque; #[bench] diff --git a/examples/simple.rs b/examples/simple.rs index 2031195..da5aa9c 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -1,4 +1,4 @@ -use gapbuf::gap_buffer; +use gap_buf::gap_buffer; fn main() { let mut b = gap_buffer![1, 2, 3]; diff --git a/src/gap_buffer.rs b/src/gap_buffer.rs index 5744bbe..4f61d57 100644 --- a/src/gap_buffer.rs +++ b/src/gap_buffer.rs @@ -1,12 +1,12 @@ -use std::alloc::{alloc, dealloc, handle_alloc_error, realloc, Layout}; -use std::cmp::{max, Ordering}; +use std::alloc::{Layout, alloc, dealloc, handle_alloc_error, realloc}; +use std::cmp::{Ordering, max}; use std::fmt::{Debug, Error, Formatter}; use std::hash::{Hash, Hasher}; use std::iter::{Chain, Fuse, FusedIterator}; use std::marker::PhantomData; use std::mem::{self, align_of, needs_drop, size_of}; use std::ops::{Deref, DerefMut, Drop, FnMut, Index, IndexMut, RangeBounds}; -use std::ptr::{self, copy, drop_in_place, write, NonNull}; +use std::ptr::{self, NonNull, copy, drop_in_place, write}; use std::slice; /// Creates a [`GapBuffer`] containing the arguments. @@ -17,7 +17,7 @@ use std::slice; /// - Create a [`GapBuffer`] containing a given list of elements: /// /// ``` -/// use gapbuf::gap_buffer; +/// use gap_buf::gap_buffer; /// let b = gap_buffer![1, 2, 3]; /// assert_eq!(b.len(), 3); /// assert_eq!(b[0], 1); @@ -28,14 +28,12 @@ use std::slice; /// - Create a [`GapBuffer`] from a given element and size: /// /// ``` -/// use gapbuf::gap_buffer; +/// use gap_buf::gap_buffer; /// let b = gap_buffer!["abc"; 2]; /// assert_eq!(b.len(), 2); /// assert_eq!(b[0], "abc"); /// assert_eq!(b[1], "abc"); /// ``` -/// -/// [`GapBuffer`]: ../gapbuf/struct.GapBuffer.html #[macro_export] macro_rules! gap_buffer { ($elem:expr; $n:expr) => ( @@ -61,6 +59,7 @@ macro_rules! gap_buffer { /// /// `GapBuffer` has methods similar to [`Vec`](std::vec::Vec). #[derive(Hash)] +#[cfg_attr(feature = "bincode", derive(bincode::Decode, bincode::Encode))] pub struct GapBuffer(RawGapBuffer); impl GapBuffer { @@ -70,7 +69,7 @@ impl GapBuffer { /// /// # Examples /// ``` - /// # use gapbuf::GapBuffer; + /// # use gap_buf::GapBuffer; /// let mut buf = GapBuffer::::new(); /// /// assert_eq!(buf.is_empty(), true); @@ -79,13 +78,13 @@ impl GapBuffer { /// ``` /// /// ``` - /// use gapbuf::GapBuffer; + /// use gap_buf::GapBuffer; /// /// let mut buf = GapBuffer::new(); /// buf.push_back(5); /// ``` #[inline] - pub fn new() -> Self { + pub const fn new() -> Self { GapBuffer(RawGapBuffer::new()) } @@ -93,7 +92,7 @@ impl GapBuffer { /// /// # Examples /// ``` - /// use gapbuf::GapBuffer; + /// use gap_buf::GapBuffer; /// /// let buf: GapBuffer = GapBuffer::with_capacity(5); /// assert_eq!(buf.is_empty(), true); @@ -110,14 +109,14 @@ impl GapBuffer { /// /// # Examples /// ``` - /// use gapbuf::GapBuffer; + /// use gap_buf::GapBuffer; /// /// let buf: GapBuffer = GapBuffer::with_capacity(10); /// assert_eq!(buf.capacity(), 10); /// ``` #[inline] - pub fn capacity(&self) -> usize { - self.cap + pub const fn capacity(&self) -> usize { + self.0.0.cap } /// Reserves capacity for at least additional more elements to be inserted in the given `GapBuffer`. @@ -130,7 +129,7 @@ impl GapBuffer { /// /// # Examples /// ``` - /// use gapbuf::GapBuffer; + /// use gap_buf::GapBuffer; /// /// let mut buf = GapBuffer::new(); /// buf.push_back(1); @@ -154,7 +153,7 @@ impl GapBuffer { /// /// # Examples /// ``` - /// use gapbuf::GapBuffer; + /// use gap_buf::GapBuffer; /// /// let mut buf = GapBuffer::new(); /// buf.push_back(1); @@ -191,7 +190,7 @@ impl GapBuffer { /// /// # Examples /// ``` - /// use gapbuf::GapBuffer; + /// use gap_buf::GapBuffer; /// /// let mut buf = GapBuffer::new(); /// buf.push_back(1); @@ -216,6 +215,7 @@ impl GapBuffer { /// # Computational amount /// `O(n)` , `n = |self.gap() - gap|` #[inline] + #[track_caller] pub fn set_gap(&mut self, gap: usize) { assert!(gap <= self.len()); if gap != self.gap() { @@ -223,24 +223,11 @@ impl GapBuffer { self.gap = gap; } } - fn move_values(&mut self, gap: usize) { - let gap_old = self.gap; - let gap_len = self.gap_len(); - let (src, dest, count) = if gap < gap_old { - (gap, gap + gap_len, gap_old - gap) - } else { - (gap_old + gap_len, gap_old, gap - gap_old) - }; - let p = self.as_mut_ptr(); - unsafe { - copy(p.add(src), p.add(dest), count); - } - } /// Return gap offset of the `GapBuffer`. #[inline] - pub fn gap(&self) -> usize { - self.gap + pub const fn gap(&self) -> usize { + self.0.0.gap } #[inline] @@ -259,6 +246,7 @@ impl GapBuffer { /// # Computational amount /// `O(n)` , `n = |index - self.gap()|` #[inline] + #[track_caller] pub fn insert(&mut self, index: usize, element: T) { assert!(index <= self.len()); if self.gap() != index || self.len == self.capacity() { @@ -282,6 +270,7 @@ impl GapBuffer { /// Panics if `index > len`. /// /// Panics if the number of elements in the gap buffer overflows a usize. + #[track_caller] pub fn insert_many(&mut self, mut index: usize, iter: impl IntoIterator) { assert!(index <= self.len()); let mut iter = iter.into_iter(); @@ -350,7 +339,7 @@ impl GapBuffer { /// /// # Examples /// ``` - /// use gapbuf::gap_buffer; + /// use gap_buf::gap_buffer; /// /// let mut buf = gap_buffer![1, 2, 3, 4, 5]; /// buf.set_gap(5); @@ -358,6 +347,7 @@ impl GapBuffer { /// assert_eq!(value, 1); /// assert_eq!(buf, [5, 2, 3, 4]); /// ``` + #[track_caller] pub fn swap_remove(&mut self, index: usize) -> T { assert!(index < self.len()); @@ -390,13 +380,14 @@ impl GapBuffer { /// /// # Examples /// ``` - /// use gapbuf::gap_buffer; + /// use gap_buf::gap_buffer; /// /// let mut buf = gap_buffer![1, 2, 3, 4, 5]; /// let value = buf.remove(0); /// assert_eq!(value, 1); /// assert_eq!(buf, [2, 3, 4, 5]); /// ``` + #[track_caller] pub fn remove(&mut self, index: usize) -> T { assert!(index <= self.len()); let offset; @@ -431,7 +422,7 @@ impl GapBuffer { /// # Examples /// /// ``` - /// use gapbuf::gap_buffer; + /// use gap_buf::gap_buffer; /// /// let mut buf = gap_buffer![1, 2, 3, 4]; /// buf.truncate(2); @@ -458,7 +449,7 @@ impl GapBuffer { /// # Examples /// /// ``` - /// use gapbuf::gap_buffer; + /// use gap_buf::gap_buffer; /// /// let mut buf = gap_buffer![1, 2, 3, 4]; /// buf.retain(|&x| x%2 == 0); @@ -504,7 +495,7 @@ impl GapBuffer { /// # Examples /// /// ``` - /// use gapbuf::gap_buffer; + /// use gap_buf::gap_buffer; /// /// let mut buf = gap_buffer![1, 2, 3, 4]; /// @@ -515,6 +506,7 @@ impl GapBuffer { /// buf.drain(..); /// assert_eq!(buf.is_empty(), true); /// ``` + #[track_caller] pub fn drain(&mut self, range: impl RangeBounds) -> Drain<'_, T> { let (idx, len) = self.to_idx_len(range); Drain { @@ -524,6 +516,46 @@ impl GapBuffer { } } + /// Creates an extracting iterator that removes elements from the specified range in the GapBuffer based on a predicate + /// + /// Note that this iterator will only remove elements that are consumed. If dropped, it will retain the remaining elements. + /// + /// # Panics + /// + /// Panics if the `range` is out of bounds. + /// + /// # Examples + /// + /// ``` + /// use gap_buf::gap_buffer; + /// + /// let mut buf = gap_buffer![1, 2, 3, 4]; + /// + /// let d : Vec<_> = buf.extract_if(.., |num| *num % 2 == 1).collect(); + /// assert_eq!(buf, [2, 4]); + /// assert_eq!(d, [1, 3]); + /// + /// buf.extract_if(.., |_| true); + /// assert_eq!(buf.is_empty(), false); + /// ``` + #[track_caller] + pub fn extract_if( + &mut self, + range: impl RangeBounds, + filter: F, + ) -> ExtractIf<'_, T, F> + where + F: FnMut(&mut T) -> bool, + { + let (idx, end) = self.to_idx_len(range); + ExtractIf { + buf: self, + idx, + end, + pred: filter, + } + } + /// Creates a splicing iterator /// that replaces the specified range in the GapBuffer with the given replace_with iterator and /// yields the removed items. @@ -537,7 +569,7 @@ impl GapBuffer { /// # Examples /// /// ``` - /// use gapbuf::gap_buffer; + /// use gap_buf::gap_buffer; /// /// let mut b = gap_buffer![1, 2, 3, 4]; /// let r : Vec<_> = b.splice(1..3, vec![7, 8, 9]).collect(); @@ -545,6 +577,7 @@ impl GapBuffer { /// assert_eq!(b, [1, 7, 8, 9, 4]); /// assert_eq!(r, [2, 3]); /// ``` + #[track_caller] pub fn splice>( &mut self, range: impl RangeBounds, @@ -563,13 +596,13 @@ impl GapBuffer { /// A splicing iterator for [`GapBuffer`]. /// /// This struct is created by [`GapBuffer::splice`]. -pub struct Splice<'a, T: 'a, I: Iterator> { - buf: &'a mut GapBuffer, +pub struct Splice<'gb, T: 'gb, I: Iterator> { + buf: &'gb mut GapBuffer, idx: usize, end: usize, iter: Fuse, } -impl<'a, T: 'a, I: Iterator> Iterator for Splice<'a, T, I> { +impl<'gb, T: 'gb, I: Iterator> Iterator for Splice<'gb, T, I> { type Item = T; fn next(&mut self) -> Option { @@ -592,15 +625,15 @@ impl<'a, T: 'a, I: Iterator> Iterator for Splice<'a, T, I> { (size, Some(size)) } } -impl<'a, T: 'a, I: Iterator> Drop for Splice<'a, T, I> { +impl<'gb, T: 'gb, I: Iterator> Drop for Splice<'gb, T, I> { fn drop(&mut self) { while self.next().is_some() {} self.buf.insert_many(self.idx, &mut self.iter); } } -impl<'a, T: 'a, I: Iterator> ExactSizeIterator for Splice<'a, T, I> {} -impl<'a, T: 'a, I: Iterator> FusedIterator for Splice<'a, T, I> {} -impl<'a, T: 'a, I: DoubleEndedIterator> DoubleEndedIterator for Splice<'a, T, I> { +impl<'gb, T: 'gb, I: Iterator> ExactSizeIterator for Splice<'gb, T, I> {} +impl<'gb, T: 'gb, I: Iterator> FusedIterator for Splice<'gb, T, I> {} +impl<'gb, T: 'gb, I: DoubleEndedIterator> DoubleEndedIterator for Splice<'gb, T, I> { fn next_back(&mut self) -> Option { if self.idx < self.end { let i = self.end - 1; @@ -660,6 +693,13 @@ impl DerefMut for GapBuffer { } } +impl From> for GapBuffer { + /// An `O(1)` conversion from a [`Vec`]. + fn from(value: Vec) -> Self { + Self(RawGapBuffer::from_vec(value)) + } +} + impl FromIterator for GapBuffer { fn from_iter>(s: S) -> GapBuffer { let mut buf = GapBuffer::new(); @@ -673,26 +713,33 @@ impl Clone for GapBuffer { self.iter().cloned().collect() } } + impl Extend for GapBuffer { fn extend>(&mut self, iter: I) { let len = self.len; self.insert_many(len, iter); } } -impl<'a, T: 'a + Copy> Extend<&'a T> for GapBuffer { - fn extend>(&mut self, iter: I) { + +impl<'gb, T: 'gb + Copy> Extend<&'gb T> for GapBuffer { + fn extend>(&mut self, iter: I) { self.extend(iter.into_iter().cloned()); } } #[derive(Hash)] +#[cfg_attr(feature = "bincode", derive(bincode::Decode, bincode::Encode))] struct RawGapBuffer(Slice); impl RawGapBuffer { - fn new() -> Self { + const fn new() -> Self { RawGapBuffer(Slice::empty()) } + const fn from_vec(vec: Vec) -> Self { + Self(Slice::from_vec(vec)) + } + fn realloc(&mut self, new_cap: usize) { let old_cap = self.0.cap; if old_cap == new_cap { @@ -718,6 +765,7 @@ impl RawGapBuffer { } self.0.cap = new_cap; } + fn get_layout(cap: usize) -> Layout { let new_size = size_of::() .checked_mul(cap) @@ -739,22 +787,22 @@ impl Drop for RawGapBuffer { /// /// This struct is created by [`Slice::range`]. #[derive(Hash)] -pub struct Range<'a, T: 'a> { +pub struct Range<'gb, T: 'gb> { s: Slice, - _phantom: PhantomData<&'a [T]>, + _phantom: PhantomData<&'gb [T]>, } /// Mutable sub-range of [`GapBuffer`]. /// /// This struct is created by [`Slice::range_mut`]. #[derive(Hash)] -pub struct RangeMut<'a, T: 'a> { +pub struct RangeMut<'gb, T: 'gb> { s: Slice, - _phantom: PhantomData<&'a mut [T]>, + _phantom: PhantomData<&'gb mut [T]>, } -impl<'a, T: 'a> Range<'a, T> { +impl<'gb, T: 'gb> Range<'gb, T> { #[inline] - unsafe fn new(s: Slice) -> Self { + const unsafe fn new(s: Slice) -> Self { Range { s, _phantom: PhantomData, @@ -763,7 +811,7 @@ impl<'a, T: 'a> Range<'a, T> { /// Construct a new, empty `Range`. #[inline] - pub fn empty() -> Self { + pub const fn empty() -> Self { unsafe { Range::new(Slice::empty()) } } @@ -771,14 +819,14 @@ impl<'a, T: 'a> Range<'a, T> { /// /// Unlike [`Slice::get`], return value not borrow `self`. #[inline] - pub fn get(&self, index: usize) -> Option<&'a T> { + pub fn get(&self, index: usize) -> Option<&'gb T> { unsafe { self.s.get_with_lifetime(index) } } /// Return a immutable sub-range of this Slice. /// /// Unlike [`Slice::range`], return value not borrow `self`. - pub fn range(&self, range: impl RangeBounds) -> Range<'a, T> { + pub fn range(&self, range: impl RangeBounds) -> Range<'gb, T> { unsafe { self.range_with_lifetime(range) } } @@ -786,13 +834,13 @@ impl<'a, T: 'a> Range<'a, T> { /// First slice is before gap. Second slice is after gap. /// /// Unlike [`Slice::as_slices`], return value not borrow `self`. - pub fn as_slices(&self) -> (&'a [T], &'a [T]) { + pub fn as_slices(&self) -> (&'gb [T], &'gb [T]) { unsafe { self.as_slices_with_lifetime() } } } -impl<'a, T: 'a> RangeMut<'a, T> { +impl<'gb, T: 'gb> RangeMut<'gb, T> { #[inline] - unsafe fn new(s: Slice) -> Self { + const unsafe fn new(s: Slice) -> Self { RangeMut { s, _phantom: PhantomData, @@ -801,7 +849,7 @@ impl<'a, T: 'a> RangeMut<'a, T> { /// Construct a new, empty `RangeMut`. #[inline] - pub fn empty() -> Self { + pub const fn empty() -> Self { unsafe { RangeMut::new(Slice::empty()) } } } @@ -829,6 +877,7 @@ impl DerefMut for RangeMut<'_, T> { &mut self.s } } + impl Clone for Range<'_, T> { fn clone(&self) -> Self { unsafe { @@ -856,7 +905,7 @@ pub struct Slice { } impl Slice { /// Construct a new, empty `Slice`. - pub fn empty() -> Self { + pub const fn empty() -> Self { Slice { ptr: NonNull::dangling(), cap: 0, @@ -865,15 +914,32 @@ impl Slice { } } + /// Constructs a `Slice` from a [`Vec`] at `O(1)`. + const fn from_vec(mut vec: Vec) -> Self { + let slice = Slice { + ptr: match NonNull::new(vec.as_mut_ptr()) { + Some(non_null) => non_null, + None => NonNull::dangling(), + }, + cap: vec.capacity(), + gap: vec.len(), + len: vec.len(), + }; + + let _dont_drop = std::mem::ManuallyDrop::new(vec); + + slice + } + /// Returns the number of elements in the GapBuffer. #[inline] - pub fn len(&self) -> usize { + pub const fn len(&self) -> usize { self.len } /// Returns true if the GapBuffer contains no elements. #[inline] - pub fn is_empty(&self) -> bool { + pub const fn is_empty(&self) -> bool { self.len() == 0 } @@ -883,8 +949,9 @@ impl Slice { unsafe { self.get_with_lifetime(index) } } #[inline] - unsafe fn get_with_lifetime<'a>(&self, index: usize) -> Option<&'a T> { - self.get_offset(index).map(|o| &*self.as_ptr().add(o)) + unsafe fn get_with_lifetime<'gb>(&self, index: usize) -> Option<&'gb T> { + self.get_offset(index) + .map(|o| unsafe { &*self.as_ptr().add(o) }) } /// Returns a mutable reference to an element at index or None if out of bounds. @@ -894,6 +961,21 @@ impl Slice { .map(|o| unsafe { &mut *self.as_mut_ptr().add(o) }) } + #[inline] + fn move_values(&mut self, gap: usize) { + let gap_old = self.gap; + let gap_len = self.gap_len(); + let (src, dest, count) = if gap < gap_old { + (gap, gap + gap_len, gap_old - gap) + } else { + (gap_old + gap_len, gap_old, gap - gap_old) + }; + let p = self.as_mut_ptr(); + unsafe { + copy(p.add(src), p.add(dest), count); + } + } + /// Swaps two elements in the GapBuffer. /// /// # Arguments @@ -904,7 +986,8 @@ impl Slice { /// # Panics /// Panics if `a >= self.len()` or `b >= self.len()`. #[inline] - pub fn swap(&mut self, a: usize, b: usize) { + #[track_caller] + pub const fn swap(&mut self, a: usize, b: usize) { let oa = self.get_offset(a).expect("a is out of bounds."); let ob = self.get_offset(b).expect("b is out of bounds."); let p = self.as_mut_ptr(); @@ -918,7 +1001,7 @@ impl Slice { /// /// # Examples /// ``` - /// use gapbuf::gap_buffer; + /// use gap_buf::gap_buffer; /// /// let buf = gap_buffer![1, 2, 3, 4, 5]; /// @@ -928,11 +1011,14 @@ impl Slice { /// let r2 = r1.range(1..3); /// assert_eq!(r2, [3, 4]); /// ``` + #[track_caller] pub fn range(&self, range: impl RangeBounds) -> Range<'_, T> { unsafe { self.range_with_lifetime(range) } } - unsafe fn range_with_lifetime<'a>(&self, range: impl RangeBounds) -> Range<'a, T> { - Range::new(self.range_slice(range)) + + #[track_caller] + unsafe fn range_with_lifetime<'gb>(&self, range: impl RangeBounds) -> Range<'gb, T> { + unsafe { Range::new(self.range_slice(range)) } } /// Return a mutable sub-range of this Slice. @@ -942,7 +1028,7 @@ impl Slice { /// /// # Examples /// ``` - /// use gapbuf::gap_buffer; + /// use gap_buf::gap_buffer; /// /// let mut buf = gap_buffer![1, 2, 3, 4, 5]; /// { @@ -952,9 +1038,12 @@ impl Slice { /// } /// assert_eq!(buf, [1, 0, 3, 4, 5]); /// ``` + #[track_caller] pub fn range_mut(&mut self, range: impl RangeBounds) -> RangeMut<'_, T> { unsafe { RangeMut::new(self.range_slice(range)) } } + + #[track_caller] unsafe fn range_slice(&self, range: impl RangeBounds) -> Slice { let (idx, len) = self.to_idx_len(range); if len == 0 { @@ -975,12 +1064,14 @@ impl Slice { let end = if !gap_is_after { self.gap_len() } else { 0 } + idx + len; Slice { - ptr: NonNull::new(self.ptr.as_ptr().add(begin)).unwrap(), + ptr: NonNull::new(unsafe { self.ptr.as_ptr().add(begin) }).unwrap(), cap: end - begin, gap, len, } } + + #[track_caller] fn to_idx_len(&self, range: impl RangeBounds) -> (usize, usize) { use std::ops::Bound::*; const MAX: usize = usize::MAX; @@ -1006,7 +1097,7 @@ impl Slice { } if end < idx { - panic!("slice index starts at {idx} but ends at {len}"); + panic!("slice index starts at {idx} but ends at {end}"); } (idx, end - idx) } @@ -1016,7 +1107,7 @@ impl Slice { /// /// # Examples /// ``` - /// use gapbuf::gap_buffer; + /// use gap_buf::gap_buffer; /// /// let mut buf = gap_buffer![1, 2, 3, 4, 5]; /// buf.set_gap(2); @@ -1027,14 +1118,13 @@ impl Slice { pub fn as_slices(&self) -> (&[T], &[T]) { unsafe { self.as_slices_with_lifetime() } } - unsafe fn as_slices_with_lifetime<'a>(&self) -> (&'a [T], &'a [T]) { + const unsafe fn as_slices_with_lifetime<'gb>(&self) -> (&'gb [T], &'gb [T]) { let p0 = self.as_ptr(); let c1 = self.len - self.gap; - let p1 = p0.add(self.cap - c1); - ( - slice::from_raw_parts(p0, self.gap), - slice::from_raw_parts(p1, c1), - ) + let p1 = unsafe { p0.add(self.cap - c1) }; + (unsafe { slice::from_raw_parts(p0, self.gap) }, unsafe { + slice::from_raw_parts(p1, c1) + }) } /// Returns a pair of slices. @@ -1042,7 +1132,7 @@ impl Slice { /// /// # Examples /// ``` - /// use gapbuf::gap_buffer; + /// use gap_buf::gap_buffer; /// /// let mut buf = gap_buffer![1, 2, 3, 4, 5]; /// buf.set_gap(2); @@ -1053,7 +1143,7 @@ impl Slice { /// } /// assert_eq!(buf, [10, 2, 11, 4, 5]); /// ``` - pub fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) { + pub const fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) { unsafe { let p0 = self.as_mut_ptr(); let c1 = self.len - self.gap; @@ -1078,7 +1168,7 @@ impl Slice { } #[inline] - fn get_offset(&self, index: usize) -> Option { + const fn get_offset(&self, index: usize) -> Option { if index < self.gap { Some(index) } else if index < self.len { @@ -1089,23 +1179,94 @@ impl Slice { } #[inline] - fn gap_len(&self) -> usize { + const fn gap_len(&self) -> usize { self.cap - self.len } #[inline] - fn as_ptr(&self) -> *const T { + const fn as_ptr(&self) -> *const T { self.ptr.as_ptr() } #[inline] - fn as_mut_ptr(&mut self) -> *mut T { + const fn as_mut_ptr(&mut self) -> *mut T { self.ptr.as_ptr() } } + +impl Clone for Slice { + fn clone(&self) -> Self { + let vec = self.iter().cloned().collect(); + Self::from_vec(vec) + } +} + unsafe impl Sync for Slice {} unsafe impl Send for Slice {} +#[cfg(feature = "bincode")] +impl, Context> bincode::Decode for Slice { + fn decode>( + decoder: &mut D, + ) -> Result { + let vec: Vec = bincode::Decode::decode(decoder)?; + Ok(Self::from_vec(vec)) + } +} + +#[cfg(feature = "bincode")] +impl<'de, T, Context> bincode::BorrowDecode<'de, Context> for Slice +where + T: bincode::BorrowDecode<'de, Context>, +{ + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + let vec: Vec = bincode::BorrowDecode::borrow_decode(decoder)?; + Ok(Self::from_vec(vec)) + } +} + +#[cfg(feature = "bincode")] +impl bincode::Encode for Slice { + fn encode( + &self, + encoder: &mut E, + ) -> Result<(), bincode::error::EncodeError> { + use bincode::enc::write::Writer; + let (s0, s1) = self.as_slices(); + + bincode::Encode::encode(&(self.len as u64), encoder)?; + + if unty::type_equal::() { + // Safety: T = u8 + let s0: &[u8] = unsafe { core::mem::transmute(s0) }; + encoder.writer().write(s0)?; + let s1: &[u8] = unsafe { core::mem::transmute(s1) }; + encoder.writer().write(s1)?; + } else { + for item in self { + item.encode(encoder)?; + } + } + + Ok(()) + } +} + +impl From> for Vec { + fn from(mut value: Slice) -> Self { + if value.gap != value.len { + value.move_values(value.len); + } + let vec = unsafe { Self::from_raw_parts(value.ptr.as_ptr(), value.len, value.cap) }; + + let _dont_drop = std::mem::ManuallyDrop::new(value); + + vec + } +} + //////////////////////////////////////////////////////////////////////////////// // Default //////////////////////////////////////////////////////////////////////////////// @@ -1361,10 +1522,10 @@ impl Ord for Slice { //////////////////////////////////////////////////////////////////////////////// /// Immutable GapBuffer iterator. -pub type Iter<'a, T> = Chain, slice::Iter<'a, T>>; +pub type Iter<'gb, T> = Chain, slice::Iter<'gb, T>>; /// Mutable GapBuffer iterator. -pub type IterMut<'a, T> = Chain, slice::IterMut<'a, T>>; +pub type IterMut<'gb, T> = Chain, slice::IterMut<'gb, T>>; /// An iterator that moves out of a [`GapBuffer`]. pub struct IntoIter { @@ -1397,54 +1558,56 @@ impl IntoIterator for GapBuffer { } } -impl<'a, T> IntoIterator for &'a GapBuffer { - type Item = &'a T; - type IntoIter = Iter<'a, T>; - fn into_iter(self) -> Iter<'a, T> { +impl<'gb, T> IntoIterator for &'gb GapBuffer { + type Item = &'gb T; + type IntoIter = Iter<'gb, T>; + fn into_iter(self) -> Iter<'gb, T> { self.iter() } } -impl<'a, T> IntoIterator for &'a Range<'_, T> { - type Item = &'a T; - type IntoIter = Iter<'a, T>; - fn into_iter(self) -> Iter<'a, T> { +impl<'gb, T> IntoIterator for &'gb Range<'_, T> { + type Item = &'gb T; + type IntoIter = Iter<'gb, T>; + fn into_iter(self) -> Iter<'gb, T> { self.iter() } } -impl<'a, T> IntoIterator for &'a RangeMut<'_, T> { - type Item = &'a T; - type IntoIter = Iter<'a, T>; - fn into_iter(self) -> Iter<'a, T> { +impl<'gb, T> IntoIterator for &'gb RangeMut<'_, T> { + type Item = &'gb T; + type IntoIter = Iter<'gb, T>; + fn into_iter(self) -> Iter<'gb, T> { self.iter() } } -impl<'a, T> IntoIterator for &'a Slice { - type Item = &'a T; - type IntoIter = Iter<'a, T>; - fn into_iter(self) -> Iter<'a, T> { +impl<'gb, T> IntoIterator for &'gb Slice { + type Item = &'gb T; + type IntoIter = Iter<'gb, T>; + fn into_iter(self) -> Iter<'gb, T> { self.iter() } } -impl<'a, T> IntoIterator for &'a mut GapBuffer { - type Item = &'a mut T; - type IntoIter = IterMut<'a, T>; - fn into_iter(self) -> IterMut<'a, T> { +impl<'gb, T> IntoIterator for &'gb mut GapBuffer { + type Item = &'gb mut T; + type IntoIter = IterMut<'gb, T>; + fn into_iter(self) -> IterMut<'gb, T> { self.iter_mut() } } -impl<'a, T> IntoIterator for &'a mut RangeMut<'a, T> { - type Item = &'a mut T; - type IntoIter = IterMut<'a, T>; - fn into_iter(self) -> IterMut<'a, T> { + +impl<'gb, T> IntoIterator for &'gb mut RangeMut<'gb, T> { + type Item = &'gb mut T; + type IntoIter = IterMut<'gb, T>; + fn into_iter(self) -> IterMut<'gb, T> { self.iter_mut() } } -impl<'a, T> IntoIterator for &'a mut Slice { - type Item = &'a mut T; - type IntoIter = IterMut<'a, T>; - fn into_iter(self) -> IterMut<'a, T> { + +impl<'gb, T> IntoIterator for &'gb mut Slice { + type Item = &'gb mut T; + type IntoIter = IterMut<'gb, T>; + fn into_iter(self) -> IterMut<'gb, T> { self.iter_mut() } } @@ -1452,11 +1615,12 @@ impl<'a, T> IntoIterator for &'a mut Slice { /// A draining iterator for [`GapBuffer`]. /// /// This struct is created by [`GapBuffer::drain`]. -pub struct Drain<'a, T: 'a> { - buf: &'a mut GapBuffer, +pub struct Drain<'gb, T: 'gb> { + buf: &'gb mut GapBuffer, idx: usize, len: usize, } + impl Iterator for Drain<'_, T> { type Item = T; fn next(&mut self) -> Option { @@ -1471,6 +1635,7 @@ impl Iterator for Drain<'_, T> { (self.len, Some(self.len)) } } + impl Drop for Drain<'_, T> { fn drop(&mut self) { let len = self.len; @@ -1480,3 +1645,36 @@ impl Drop for Drain<'_, T> { impl ExactSizeIterator for Drain<'_, T> {} impl FusedIterator for Drain<'_, T> {} + +/// An iterator that conditionally extracts from a [`GapBuffer`]. +/// +/// this struct is created by [`GapBuffer::extract_if`]. +#[must_use] +pub struct ExtractIf<'gb, T: 'gb, F> { + buf: &'gb mut GapBuffer, + idx: usize, + end: usize, + pred: F, +} + +impl Iterator for ExtractIf<'_, T, F> +where + F: FnMut(&mut T) -> bool, +{ + type Item = T; + + fn next(&mut self) -> Option { + while self.idx < self.end { + if (self.pred)(self.buf.get_mut(self.idx).unwrap()) { + self.end -= 1; + return Some(self.buf.remove(self.idx)); + } else { + self.idx += 1; + } + } + + None + } +} + +impl FusedIterator for ExtractIf<'_, T, F> where F: FnMut(&mut T) -> bool {} diff --git a/src/lib.rs b/src/lib.rs index 6343d90..3b3dcee 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,10 +1,10 @@ -//! `gapbuf` provides the type [`GapBuffer`]. +//! `gap_buf` provides the type [`GapBuffer`]. //! `GapBuffer` has methods similar to [`Vec`](std::vec::Vec). //! //! # Examples //! //! ``` -//! use gapbuf::gap_buffer; +//! use gap_buf::gap_buffer; //! //! let mut b = gap_buffer![1, 2, 3]; //! @@ -15,7 +15,7 @@ //! assert_eq!(b, [1, 10, 3]); //! ``` //! -#![doc(html_root_url = "https://docs.rs/gapbuf/0.1.2")] +#![doc(html_root_url = "https://docs.rs/gap_buf/0.1.2")] #[macro_use] mod finally; diff --git a/tests/tests.rs b/tests/tests.rs index 5f7aa1d..b66e4c0 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -1,4 +1,4 @@ -use gapbuf::{gap_buffer, GapBuffer}; +use gap_buf::{gap_buffer, GapBuffer}; use std::cell::RefCell; use std::collections::HashSet; use std::panic; @@ -700,7 +700,7 @@ fn eq_slice2() { } #[test] -fn eq_gapbuf1() { +fn eq_gap_buf1() { let mut buf = GapBuffer::new(); buf.push_back(1); @@ -708,7 +708,7 @@ fn eq_gapbuf1() { } #[test] -fn eq_gapbuf2() { +fn eq_gap_buf2() { let mut buf = GapBuffer::new(); buf.push_back(2); buf.push_back(8); @@ -838,23 +838,23 @@ fn covariant() { let s = String::from("bbb"); // `&GapBuffer<&static str>` can convert `&GapBuffer<&a>` - fn c_gapbuf<'a>(_buf: &GapBuffer<&'a str>, _s: &'a str) {} - c_gapbuf(&b, &s); + fn c_gap_buf<'a>(_buf: &GapBuffer<&'a str>, _s: &'a str) {} + c_gap_buf(&b, &s); // `Range<'b, &'static str>` can convert `Range<'b, &'a str>` - fn c_range<'a>(_buf: gapbuf::Range<&'a str>, _s: &'a str) {} + fn c_range<'a>(_buf: gap_buf::Range<&'a str>, _s: &'a str) {} c_range(b.range(0..1), &s); // `Range<'b, &'static str>` can not convert `Range<'b, &'a str>` - // fn c_range_mut<'a, 'b>(_buf: gapbuf::RangeMut<'b, &'a str>, _s: &'a str) {} + // fn c_range_mut<'a, 'b>(_buf: gap_buf::RangeMut<'b, &'a str>, _s: &'a str) {} // c_range_mut(b.range_mut(0..1), &s); // `&Slice<&static str>` can convert `&Slice<&a>` - fn c_slice<'a>(_buf: &gapbuf::Slice<&'a str>, _s: &'a str) {} + fn c_slice<'a>(_buf: &gap_buf::Slice<&'a str>, _s: &'a str) {} c_slice(&b, &s); // `&mut Slice<&static str>` can not convert `&mut Slice<&a>` - // fn c_mut_slice<'a>(_buf: &mut gapbuf::Slice<&'a str>, _s: &'a str) {} + // fn c_mut_slice<'a>(_buf: &mut gap_buf::Slice<&'a str>, _s: &'a str) {} // c_mut_slice(&mut b, &s); } diff --git a/tests/tests_proptest.rs b/tests/tests_proptest.rs index e2dba51..0b21670 100644 --- a/tests/tests_proptest.rs +++ b/tests/tests_proptest.rs @@ -1,4 +1,4 @@ -use gapbuf::GapBuffer; +use gap_buf::GapBuffer; use proptest::{collection::vec, prelude::*}; use test_strategy::{proptest, Arbitrary};