Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ jobs:
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.toolchain }}
components: rustfmt

- name: Style check
if: matrix.toolchain == 'nightly'
run: cargo fmt --all --check

- name: Cargo build
run: cargo build --verbose
Expand Down
30 changes: 4 additions & 26 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ serde_core = { version = "1.0.221", optional = true, default-features = false }
malloc_size_of = { version = "0.1.1", optional = true, default-features = false }

[dev-dependencies]
serde_json = "1.0"
serde_test = "1.0"

[package.metadata.docs.rs]
all-features = true
Expand Down
78 changes: 50 additions & 28 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,13 +195,13 @@ impl<T, const N: usize> RawSmallVec<T, N> {
// SAFETY: it is safe because we aren't reading the value, just getting a
// reference to it. reading it would be UB potentially, but for that downstream
// unsafe is required
(unsafe {&raw const self.inline}) as *mut T
(unsafe { &raw const self.inline }) as *mut T
}

#[inline]
const fn as_mut_ptr_inline(&mut self) -> *mut T {
// SAFETY: same as above
(unsafe {&raw mut self.inline}) as *mut T
(unsafe { &raw mut self.inline }) as *mut T
}

/// # Safety
Expand Down Expand Up @@ -292,7 +292,7 @@ impl<T> Clone for TaggedLen<T> {
fn clone(&self) -> Self {
Self(self.0, PhantomData)
}

#[inline]
fn clone_from(&mut self, source: &Self) {
self.0 = source.0;
Expand Down Expand Up @@ -493,7 +493,10 @@ impl<T, const N: usize> Drain<'_, T, N> {
let range_start = vec.len();
let range_end = self.tail_start;
let range_slice = unsafe {
core::slice::from_raw_parts_mut(vec.as_mut_ptr().add(range_start), range_end - range_start)
core::slice::from_raw_parts_mut(
vec.as_mut_ptr().add(range_start),
range_end - range_start,
)
};

for place in range_slice {
Expand Down Expand Up @@ -689,7 +692,11 @@ impl<I: Iterator, const N: usize> Drop for Splice<'_, I, N> {
}

// Collect any remaining elements.
let mut collected = self.replace_with.by_ref().collect::<SmallVec<I::Item, N>>().into_iter();
let mut collected = self
.replace_with
.by_ref()
.collect::<SmallVec<I::Item, N>>()
.into_iter();
// Now we have an exact count.
if collected.len() > 0 {
self.drain.move_tail(collected.len());
Expand Down Expand Up @@ -725,7 +732,6 @@ unsafe impl<T, const N: usize> Send for IntoIter<T, N> where T: Send {}
unsafe impl<T, const N: usize> Sync for IntoIter<T, N> where T: Sync {}

impl<T, const N: usize> IntoIter<T, N> {

#[inline]
const fn as_ptr(&self) -> *const T {
let on_heap = self.end.on_heap();
Expand Down Expand Up @@ -754,10 +760,7 @@ impl<T, const N: usize> IntoIter<T, N> {
// So the pointer arithmetic is valid, and so is the construction of the slice
unsafe {
let ptr = self.as_ptr();
core::slice::from_raw_parts(
ptr.add(self.begin),
self.end.value() - self.begin,
)
core::slice::from_raw_parts(ptr.add(self.begin), self.end.value() - self.begin)
}
}

Expand All @@ -766,10 +769,7 @@ impl<T, const N: usize> IntoIter<T, N> {
// SAFETY: see above
unsafe {
let ptr = self.as_mut_ptr();
core::slice::from_raw_parts_mut(
ptr.add(self.begin),
self.end.value() - self.begin,
)
core::slice::from_raw_parts_mut(ptr.add(self.begin), self.end.value() - self.begin)
}
}
}
Expand Down Expand Up @@ -842,7 +842,9 @@ impl<T, const N: usize> SmallVec<T, N> {

#[inline]
pub const fn from_buf<const S: usize>(elements: [T; S]) -> Self {
const { assert!(S <= N); }
const {
assert!(S <= N);
}

// Although we create a new buffer, since S and N are known at compile time,
// even with `-C opt-level=1`, it gets optimized as best as it could be. (Checked with <godbolt.org>)
Expand Down Expand Up @@ -1198,7 +1200,10 @@ impl<T, const N: usize> SmallVec<T, N> {
R: core::ops::RangeBounds<usize>,
I: IntoIterator<Item = T>,
{
Splice { drain: self.drain(range), replace_with: replace_with.into_iter() }
Splice {
drain: self.drain(range),
replace_with: replace_with.into_iter(),
}
}

#[inline]
Expand Down Expand Up @@ -1233,7 +1238,11 @@ impl<T, const N: usize> SmallVec<T, N> {
#[inline]
pub fn pop_if(&mut self, predicate: impl FnOnce(&mut T) -> bool) -> Option<T> {
let last = self.last_mut()?;
if predicate(last) { self.pop() } else { None }
if predicate(last) {
self.pop()
} else {
None
}
}

#[inline]
Expand Down Expand Up @@ -1398,7 +1407,10 @@ impl<T, const N: usize> SmallVec<T, N> {
self.set_inline();
alloc::alloc::dealloc(
ptr.cast().as_ptr(),
Layout::from_size_align_unchecked(capacity * size_of::<T>(), align_of::<T>()),
Layout::from_size_align_unchecked(
capacity * size_of::<T>(),
align_of::<T>(),
),
);
}
} else if target < self.capacity() {
Expand Down Expand Up @@ -1429,7 +1441,10 @@ impl<T, const N: usize> SmallVec<T, N> {
#[inline]
pub fn swap_remove(&mut self, index: usize) -> T {
let len = self.len();
assert!(index < len, "swap_remove index (is {index}) should be < len (is {len})");
assert!(
index < len,
"swap_remove index (is {index}) should be < len (is {len})"
);
// This can't overflow since `len > index >= 0`
let new_len = len - 1;
unsafe {
Expand Down Expand Up @@ -1461,7 +1476,10 @@ impl<T, const N: usize> SmallVec<T, N> {
#[inline]
pub fn remove(&mut self, index: usize) -> T {
let len = self.len();
assert!(index < len, "removal index (is {index}) should be < len (is {len})");
assert!(
index < len,
"removal index (is {index}) should be < len (is {len})"
);
let new_len = len - 1;
unsafe {
// SAFETY: new_len < len
Expand All @@ -1478,7 +1496,10 @@ impl<T, const N: usize> SmallVec<T, N> {
#[inline]
pub fn insert(&mut self, index: usize, value: T) {
let len = self.len();
assert!(index <= len, "insertion index (is {index}) should be <= len (is {len})");
assert!(
index <= len,
"insertion index (is {index}) should be <= len (is {len})"
);
self.reserve(1);
let ptr = self.as_mut_ptr();
unsafe {
Expand Down Expand Up @@ -1674,7 +1695,9 @@ impl<T, const N: usize> SmallVec<T, N> {

pub fn leak<'a>(self) -> &'a mut [T] {
if !self.spilled() {
panic!("SmallVec::leak() called on inline (stack) SmallVec, which cannot be safely leaked");
panic!(
"SmallVec::leak() called on inline (stack) SmallVec, which cannot be safely leaked"
);
}
let mut me = ManuallyDrop::new(self);
unsafe { core::slice::from_raw_parts_mut(me.as_mut_ptr(), me.len()) }
Expand Down Expand Up @@ -1807,12 +1830,11 @@ impl<T: Clone, const N: usize> SmallVec<T, N> {
#[inline]
pub fn extend_from_slice_copy(&mut self, other: &[T])
where
T: Copy
T: Copy,
{

let len = other.len();
let src = other.as_ptr();

let l = self.len();
self.reserve(len);

Expand All @@ -1828,7 +1850,7 @@ impl<T: Clone, const N: usize> SmallVec<T, N> {
pub fn extend_from_within_copy<R>(&mut self, src: R)
where
R: core::ops::RangeBounds<usize>,
T: Copy
T: Copy,
{
let src = slice_range(src, ..self.len());
let core::ops::Range { start, end } = src;
Expand All @@ -1847,7 +1869,7 @@ impl<T: Clone, const N: usize> SmallVec<T, N> {

pub fn insert_from_slice_copy(&mut self, index: usize, other: &[T])
where
T: Copy
T: Copy,
{
let l = self.len();
let len = other.len();
Expand All @@ -1871,7 +1893,7 @@ impl<T: Clone, const N: usize> SmallVec<T, N> {
/// for types with the [`Copy`] trait.
pub fn from_slice_copy(slice: &[T]) -> Self
where
T: Copy
T: Copy,
{
let src = slice.as_ptr();
let len = slice.len();
Expand Down
44 changes: 20 additions & 24 deletions src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,7 @@ fn test_from() {

let vec = vec![];
let small_vec: SmallVec<u8, 3> = SmallVec::from(vec);
assert_eq!(&*small_vec, &[0u8; 0]);
assert_eq!(&*small_vec, &[0u8; 0]);
drop(small_vec);

let vec = vec![1, 2, 3, 4, 5];
Expand Down Expand Up @@ -587,10 +587,7 @@ fn test_from() {
#[test]
fn test_from_slice() {
assert_eq!(&SmallVec::<u32, 2>::from(&[1][..])[..], [1]);
assert_eq!(
&SmallVec::<u32, 2>::from(&[1, 2, 3][..])[..],
[1, 2, 3]
);
assert_eq!(&SmallVec::<u32, 2>::from(&[1, 2, 3][..])[..], [1, 2, 3]);
}

#[test]
Expand Down Expand Up @@ -801,27 +798,26 @@ fn test_write() {
#[cfg(feature = "serde")]
#[test]
fn test_serde() {
use serde_core::{Serialize, Deserialize};
use serde_json::{Serializer, Deserializer};
let mut bytes = Vec::<u8>::new();
let mut serializer = Serializer::new(&mut bytes);
use serde_test::{assert_tokens, Token};
let mut small_vec: SmallVec<i32, 2> = SmallVec::new();
assert_tokens(&small_vec, &[Token::Seq { len: Some(0) }, Token::SeqEnd]);
small_vec.push(1);
let _ = small_vec.serialize(&mut serializer);
let mut deserializer = Deserializer::from_slice(bytes.as_slice());
let decoded: SmallVec<i32, 2> = SmallVec::deserialize(&mut deserializer).unwrap();
assert_eq!(small_vec, decoded);
// Spill the vec
small_vec.push(2);
small_vec.push(3);
small_vec.push(4);
// Check again after spilling.
let mut bytes = Vec::<u8>::new();
let mut serializer = Serializer::new(&mut bytes);
let _ = small_vec.serialize(&mut serializer);
let mut deserializer = Deserializer::from_slice(bytes.as_slice());
let decoded: SmallVec<i32, 2> = SmallVec::deserialize(&mut deserializer).unwrap();
assert_eq!(small_vec, decoded);
assert_tokens(
&small_vec,
&[Token::Seq { len: Some(1) }, Token::I32(1), Token::SeqEnd],
);
small_vec.extend([2, 3, 4]);
assert_tokens(
&small_vec,
&[
Token::Seq { len: Some(4) },
Token::I32(1),
Token::I32(2),
Token::I32(3),
Token::I32(4),
Token::SeqEnd,
],
);
}

#[test]
Expand Down
Loading