mirror of
https://github.com/openharmony/third_party_rust_tinyvec.git
synced 2026-07-01 20:44:03 -04:00
base files
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
/target
|
||||
Cargo.lock
|
||||
+12
@@ -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!
|
||||
@@ -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.
|
||||
@@ -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
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user