Skip to content
Closed
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
29 changes: 23 additions & 6 deletions benches/bench.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#![allow(deprecated)]

use criterion::{criterion_group, criterion_main, Bencher, Criterion};
use smallvec::{smallvec, SmallVec};
use std::hint::black_box;
use std::time::Duration;
use {
criterion::{criterion_group, criterion_main, Bencher, Criterion},
smallvec::{smallvec, SmallVec},
std::{hint::black_box, time::Duration},
};

const VEC_SIZE: usize = 16;
const SPILLED_SIZE: usize = 100;
Expand All @@ -26,27 +27,35 @@ impl<T: Copy> Vector<T> for Vec<T> {
fn new() -> Self {
Self::with_capacity(VEC_SIZE)
}

fn push(&mut self, val: T) {
self.push(val)
}

fn pop(&mut self) -> Option<T> {
self.pop()
}

fn remove(&mut self, p: usize) -> T {
self.remove(p)
}

fn insert(&mut self, n: usize, val: T) {
self.insert(n, val)
}

fn from_elem(val: T, n: usize) -> Self {
vec![val; n]
}

fn from_elems(val: &[T]) -> Self {
val.to_owned()
}

fn extend_from_slice(&mut self, other: &[T]) {
Vec::extend_from_slice(self, other)
}

fn retain_mut<F>(&mut self, f: F)
where
F: FnMut(&mut T) -> bool,
Expand All @@ -59,27 +68,35 @@ impl<T: Copy> Vector<T> for SmallVec<T, VEC_SIZE> {
fn new() -> Self {
Self::new()
}

fn push(&mut self, val: T) {
self.push(val)
}

fn pop(&mut self) -> Option<T> {
self.pop()
}

fn remove(&mut self, p: usize) -> T {
self.remove(p)
}

fn insert(&mut self, n: usize, val: T) {
self.insert(n, val)
}

fn from_elem(val: T, n: usize) -> Self {
smallvec![val; n]
}

fn from_elems(val: &[T]) -> Self {
SmallVec::from(val)
}

fn extend_from_slice(&mut self, other: &[T]) {
SmallVec::extend_from_slice(self, other)
}

fn retain_mut<F>(&mut self, f: F)
where
F: FnMut(&mut T) -> bool,
Expand All @@ -100,8 +117,8 @@ macro_rules! make_benches {
}
}

/* ---------- Bench generation (same list, just using the new macro)
* ---------- */
// ---------- Bench generation (same list, just using the new macro)
// ----------
make_benches! {
SmallVec<u64, VEC_SIZE> {
bench_push => gen_push(SPILLED_SIZE as _),
Expand Down
65 changes: 65 additions & 0 deletions src/bytes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
use {
super::SmallVec,
bytes::{buf::UninitSlice, BufMut},
};

unsafe impl<const N: usize> BufMut for SmallVec<u8, N> {
fn remaining_mut(&self) -> usize {
// A vector can never have more than isize::MAX bytes
isize::MAX as usize - self.len()
}

unsafe fn advance_mut(&mut self, cnt: usize) {
let len = self.len();
let remaining = self.capacity() - len;

if remaining < cnt {
panic!("advance out of bounds: the len is {remaining} but advancing by {cnt}");
}

// Addition will not overflow since the sum is at most the capacity.
self.set_len(len + cnt);
}

fn chunk_mut(&mut self) -> &mut UninitSlice {
if self.capacity() == self.len() {
self.reserve(64); // Grow the smallvec
}

let cap = self.capacity();
let len = self.len();

let ptr = self.as_mut_ptr();
// SAFETY: Since `ptr` is valid for `cap` bytes, `ptr.add(len)` must be
// valid for `cap - len` bytes. The subtraction will not underflow since
// `len <= cap`.
unsafe { UninitSlice::from_raw_parts_mut(ptr.add(len), cap - len) }
}

// Specialize these methods so they can skip checking `remaining_mut`
// and `advance_mut`.
fn put<T: bytes::Buf>(&mut self, mut src: T)
where
Self: Sized,
{
// In case the src isn't contiguous, reserve upfront.
self.reserve(src.remaining());

while src.has_remaining() {
let s = src.chunk();
let l = s.len();
self.extend_from_slice(s);
src.advance(l);
}
}

fn put_slice(&mut self, src: &[u8]) {
self.extend_from_slice(src);
}

fn put_bytes(&mut self, val: u8, cnt: usize) {
// If the addition overflows, then the `resize` will fail.
let new_len = self.len().saturating_add(cnt);
self.resize(new_len, val);
}
}
52 changes: 52 additions & 0 deletions src/comparisons.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use super::SmallVec;

impl<T: PartialEq<U>, U, const N: usize, const M: usize> PartialEq<SmallVec<U, M>>
for SmallVec<T, N>
{
fn eq(&self, other: &SmallVec<U, M>) -> bool {
self.as_slice().eq(other.as_slice())
}
}
impl<T, const N: usize> Eq for SmallVec<T, N> where T: Eq {}

impl<T: PartialEq<U>, U, const N: usize, const M: usize> PartialEq<[U; M]> for SmallVec<T, N> {
fn eq(&self, other: &[U; M]) -> bool {
self[..] == other[..]
}
}

impl<T: PartialEq<U>, U, const N: usize, const M: usize> PartialEq<&[U; M]> for SmallVec<T, N> {
fn eq(&self, other: &&[U; M]) -> bool {
self[..] == other[..]
}
}

impl<T: PartialEq<U>, U, const N: usize> PartialEq<[U]> for SmallVec<T, N> {
fn eq(&self, other: &[U]) -> bool {
self[..] == other[..]
}
}

impl<T: PartialEq<U>, U, const N: usize> PartialEq<&[U]> for SmallVec<T, N> {
fn eq(&self, other: &&[U]) -> bool {
self[..] == other[..]
}
}

impl<T: PartialEq<U>, U, const N: usize> PartialEq<&mut [U]> for SmallVec<T, N> {
fn eq(&self, other: &&mut [U]) -> bool {
self[..] == other[..]
}
}

impl<T: PartialOrd, const N: usize> PartialOrd for SmallVec<T, N> {
fn partial_cmp(&self, other: &SmallVec<T, N>) -> Option<core::cmp::Ordering> {
self.as_slice().partial_cmp(other.as_slice())
}
}

impl<T: Ord, const N: usize> Ord for SmallVec<T, N> {
fn cmp(&self, other: &SmallVec<T, N>) -> core::cmp::Ordering {
self.as_slice().cmp(other.as_slice())
}
}
Loading
Loading