more stuff

This commit is contained in:
Lokathor
2020-01-09 02:04:44 -07:00
parent e50dfd5a5a
commit 31049d32df
3 changed files with 94 additions and 137 deletions
+8 -3
View File
@@ -5,18 +5,23 @@ version = "0.0.1-alpha.0"
authors = ["Lokathor <zefria@gmail.com>"]
edition = "2018"
license = "Zlib"
keywords = ["vec", "no_std", "smol"]
keywords = ["vec", "no_std", "no-std", "smol"]
categories = ["data-structures", "no-std"]
[dependencies]
# not even std!
[features]
default = ["extern_crate_alloc"]
default = ["extern_crate_alloc", "nightly_slice_partition_dedup"]
# Provide additional types and impls related to the `alloc` trait.
# Provide additional types and impls related to the `alloc` crate.
extern_crate_alloc = []
# allow use of nightly feature `slice_partition_dedup`,
# will become useless once that is stabilized:
# https://github.com/rust-lang/rust/issues/54279
nightly_slice_partition_dedup = []
[badges]
appveyor = { repository = "Lokathor/tinyvec" }
travis-ci = { repository = "Lokathor/tinyvec" }
+80 -21
View File
@@ -24,19 +24,19 @@ impl<A: Arrayish> DerefMut for ArrayishVec<A> {
}
}
impl<A: Arrayish> Index<usize> for ArrayishVec<A> {
type Output = A::Item;
impl<A: Arrayish, I: SliceIndex<[A::Item]>> Index<I> for ArrayishVec<A> {
type Output = <I as SliceIndex<[A::Item]>>::Output;
#[inline(always)]
#[must_use]
fn index(&self, index: usize) -> &Self::Output {
fn index(&self, index: I) -> &Self::Output {
&self.deref()[index]
}
}
impl<A: Arrayish> IndexMut<usize> for ArrayishVec<A> {
impl<A: Arrayish, I: SliceIndex<[A::Item]>> IndexMut<I> for ArrayishVec<A> {
#[inline(always)]
#[must_use]
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
fn index_mut(&mut self, index: I) -> &mut Self::Output {
&mut self.deref_mut()[index]
}
}
@@ -49,7 +49,8 @@ impl<A: Arrayish> ArrayishVec<A> {
panic!("ArrayishVec: overflow!");
}
let target_slice = &mut self.data.slice_mut()[self.len..final_len];
for (target_mut, app_mut) in target_slice.iter_mut().zip(other.deref_mut()) {
for (target_mut, app_mut) in target_slice.iter_mut().zip(other.deref_mut())
{
replace(target_mut, replace(app_mut, A::Item::default()));
}
self.len = final_len;
@@ -91,9 +92,38 @@ impl<A: Arrayish> ArrayishVec<A> {
self.truncate(0)
}
// TODO(Vec): dedup
// TODO(Vec): dedup_by
// TODO(Vec): dedup_by_key
#[cfg(feature = "nightly_slice_partition_dedup")]
#[inline(always)]
pub fn dedup(&mut self)
where
A::Item: PartialEq,
{
self.dedup_by(|a, b| a == b)
}
#[cfg(feature = "nightly_slice_partition_dedup")]
#[inline(always)]
pub fn dedup_by<F>(&mut self, same_bucket: F)
where
F: FnMut(&mut A::Item, &mut A::Item) -> bool,
{
let len = {
let (dedup, _) = self.as_mut_slice().partition_dedup_by(same_bucket);
dedup.len()
};
self.truncate(len);
}
#[cfg(feature = "nightly_slice_partition_dedup")]
#[inline(always)]
pub fn dedup_by_key<F, K>(&mut self, mut key: F)
where
F: FnMut(&mut A::Item) -> K,
K: PartialEq,
{
self.dedup_by(|a, b| key(a) == key(b))
}
// TODO(Vec): drain
// TODO(Vec): drain_filter #nightly
@@ -256,8 +286,13 @@ impl<A: Arrayish> BorrowMut<[A::Item]> for ArrayishVec<A> {
}
}
// TODO(Vec): Extend<&'a T>
// TODO(Vec): Extend<T>
impl<A: Arrayish> Extend<A::Item> for ArrayishVec<A> {
fn extend<T: IntoIterator<Item = A::Item>>(&mut self, iter: T) {
for t in iter {
self.push(t)
}
}
}
impl<A: Arrayish> From<A> for ArrayishVec<A> {
#[inline(always)]
@@ -281,9 +316,6 @@ impl<A: Arrayish + Default> FromIterator<A::Item> for ArrayishVec<A> {
}
}
// TODO(Vec): Index<I: SliceIndex>
// TODO(Vec): IndexMut<I: SliceIndex>
pub struct ArrayishVecIterator<A: Arrayish> {
base: usize,
len: usize,
@@ -343,19 +375,40 @@ impl<A: Arrayish> PartialEq for ArrayishVec<A>
where
A::Item: PartialEq,
{
#[inline(always)]
#[inline]
#[must_use]
fn eq(&self, other: &Self) -> bool {
self.deref() == other.deref()
self.deref().eq(other.deref())
}
}
impl<A: Arrayish> Eq for ArrayishVec<A> where A::Item: Eq {}
impl<A: Arrayish> PartialOrd for ArrayishVec<A>
where
A::Item: PartialOrd,
{
#[inline]
#[must_use]
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
self.deref().partial_cmp(other.deref())
}
}
impl<A: Arrayish> Ord for ArrayishVec<A>
where
A::Item: Ord,
{
#[inline]
#[must_use]
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.deref().cmp(other.deref())
}
}
impl<A: Arrayish> PartialEq<&A> for ArrayishVec<A>
where
A::Item: PartialEq,
{
#[inline(always)]
#[inline]
#[must_use]
fn eq(&self, other: &&A) -> bool {
self.deref() == other.slice()
@@ -366,25 +419,31 @@ impl<A: Arrayish> PartialEq<&[A::Item]> for ArrayishVec<A>
where
A::Item: PartialEq,
{
#[inline(always)]
#[inline]
#[must_use]
fn eq(&self, other: &&[A::Item]) -> bool {
self.deref() == *other
}
}
/*
I think, in retrospect, this is useless?
The `&mut [A::Item]` should coerce to `&[A::Item]` and use the above impl.
I'll leave it here for now though since we already had it written out..
impl<A: Arrayish> PartialEq<&mut [A::Item]> for ArrayishVec<A>
where
A::Item: PartialEq,
{
#[inline(always)]
#[inline]
#[must_use]
fn eq(&self, other: &&mut [A::Item]) -> bool {
self.deref() == *other
}
}
// TODO: PartialOrd, Ord, Hash
*/
// //
// Formatting impls
+6 -113
View File
@@ -1,5 +1,9 @@
#![no_std]
#![forbid(unsafe_code)]
#![cfg_attr(
feature = "nightly_slice_partition_dedup",
feature(slice_partition_dedup)
)]
//! Just, really the littlest Vec you could need. So smol.
@@ -12,9 +16,10 @@ use core::{
Binary, Debug, Display, Formatter, LowerExp, LowerHex, Octal, Pointer,
UpperExp, UpperHex,
},
iter::{FromIterator, IntoIterator, Iterator},
iter::{Extend, FromIterator, IntoIterator, Iterator},
mem::{needs_drop, replace},
ops::{Deref, DerefMut, Index, IndexMut},
slice::SliceIndex,
};
#[cfg(feature = "extern_crate_alloc")]
@@ -25,115 +30,3 @@ pub use arrayish::*;
mod arrayish_vec;
pub use arrayish_vec::*;
/*
// Note(Lokathor): We just want to hide the enum details away. Rust doesn't let
// you be an enum with private variants, so instead we make this be a private
// inner field of the public `TinyVec<T>` type.
#[derive(Debug, Clone)]
enum Payload<T: Default> {
Inline { len: usize, data: [T; 8] },
Heap(Vec<T>),
}
/// A `TinyVec<T>` is like a `Vec<T>`, but it will store up to 8 elements
/// "inline" on the stack before transitioning into being a normal `Vec<T>`.
#[derive(Debug, Clone)]
#[repr(transparent)]
pub struct TinyVec<T: Default>(Payload<T>);
// TODO: impl a better Debug
impl<T: Default> Default for TinyVec<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: Default> Deref for TinyVec<T> {
type Target = [T];
fn deref(&self) -> &[T] {
match &self.0 {
Payload::Inline { len, data } => &data[..*len],
Payload::Heap(vec) => &vec,
}
}
}
impl<T: Default> DerefMut for TinyVec<T> {
fn deref_mut(&mut self) -> &mut [T] {
match &mut self.0 {
Payload::Inline { len, data } => &mut data[..*len],
Payload::Heap(ref mut vec) => &mut vec[..],
}
}
}
impl<T: Default> TinyVec<T> {
pub fn new() -> Self {
Self(Payload::Inline {
len: 0,
data: [
T::default(),
T::default(),
T::default(),
T::default(),
T::default(),
T::default(),
T::default(),
T::default(),
],
})
}
pub fn push(&mut self, val: T) {
match &mut self.0 {
Payload::Inline { len: 8, data } => {
let mut v = Vec::with_capacity(8 + 10);
for data_mut in data.iter_mut() {
v.push(replace(data_mut, T::default()));
}
v.push(val);
replace(&mut self.0, Payload::Heap(v));
}
Payload::Inline { len, data } => {
debug_assert!(*len < 8, "push: illegal len: {}", len);
data[*len] = val;
*len += 1;
}
Payload::Heap(ref mut vec) => vec.push(val),
}
}
pub fn pop(&mut self) -> Option<T> {
match &mut self.0 {
Payload::Inline { len: 0, .. } => None,
Payload::Inline { len, data } => {
debug_assert!(*len > 0, "pop: illegal len: {}", len);
let out = replace(&mut data[*len - 1], T::default());
*len -= 1;
Some(out)
}
Payload::Heap(ref mut vec) => vec.pop(),
}
}
pub fn truncate(&mut self, new_len: usize) {
match &mut self.0 {
Payload::Inline { len, data } => {
if needs_drop::<T>() {
while *len > new_len {
replace(&mut data[*len - 1], T::default());
*len -= 1;
}
} else {
*len = (*len).min(new_len);
}
}
Payload::Heap(ref mut vec) => vec.truncate(new_len),
}
}
}
*/