base files

This commit is contained in:
Lokathor
2020-01-06 19:29:40 -07:00
parent 27084dfc5e
commit 76058032f5
6 changed files with 182 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
/target
Cargo.lock
+12
View File
@@ -0,0 +1,12 @@
[package]
name = "tinyvec"
description = "Just, really the littlest Vec you could need. So smol."
version = "0.0.0-alpha"
authors = ["Lokathor <zefria@gmail.com>"]
edition = "2018"
license = "Zlib"
keywords = ["vec", "no_std", "smol"]
categories = ["data-structures", "no-std"]
[dependencies]
# not even std!
+11
View File
@@ -0,0 +1,11 @@
Copyright (c) 2019 Daniel "Lokathor" Gee.
This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
+8
View File
@@ -0,0 +1,8 @@
merge_imports = true
use_try_shorthand = true
tab_spaces = 2
max_width = 80
color = "Never"
use_small_heuristics = "Max"
format_code_in_doc_comments = true
wrap_comments = true
+116
View File
@@ -0,0 +1,116 @@
#![no_std]
#![forbid(unsafe_code)]
//! Just, really the littlest Vec you could need. So smol.
use core::ops::{Deref, DerefMut};
use core::mem::replace;
extern crate alloc;
use alloc::vec::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()
}
}
}
}
+33
View File
@@ -0,0 +1,33 @@
extern crate std;
use tinyvec::*;
#[test]
fn test_push_pop() {
let mut tv = TinyVec::new();
assert_eq!(tv.pop(), None);
tv.push(5_i32);
assert_eq!(tv.pop(), Some(5_i32));
assert_eq!(tv.len(), 0);
for i in 0 .. 10 {
tv.push(i);
}
assert_eq!(tv.len(), 10);
assert_eq!(tv.pop(), Some(9));
assert_eq!(tv.pop(), Some(8));
assert_eq!(tv.pop(), Some(7));
assert_eq!(tv.pop(), Some(6));
assert_eq!(tv.pop(), Some(5));
assert_eq!(tv.pop(), Some(4));
assert_eq!(tv.pop(), Some(3));
assert_eq!(tv.pop(), Some(2));
assert_eq!(tv.pop(), Some(1));
assert_eq!(tv.pop(), Some(0));
assert_eq!(tv.pop(), None);
assert_eq!(tv.pop(), None);
assert_eq!(tv.pop(), None);
}