Add basic `IArray` impl
parent
e3d749ac20
commit
3739aa54fd
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Created on Sun Jul 04 2021
|
||||
*
|
||||
* This file is a part of Skytable
|
||||
* Skytable (formerly known as TerrabaseDB or Skybase) is a free and open-source
|
||||
* NoSQL database written by Sayan Nandan ("the Author") with the
|
||||
* vision to provide flexibility in data modelling without compromising
|
||||
* on performance, queryability or scalability.
|
||||
*
|
||||
* Copyright (c) 2021, Sayan Nandan <ohsayan@outlook.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#![allow(dead_code)] // TODO(@ohsayan): Remove this once we're done
|
||||
|
||||
use std::mem;
|
||||
use std::mem::ManuallyDrop;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::ptr;
|
||||
|
||||
pub trait MemoryBlock {
|
||||
type LayoutItem;
|
||||
fn size() -> usize;
|
||||
}
|
||||
|
||||
impl<T, const N: usize> MemoryBlock for [T; N] {
|
||||
type LayoutItem = T;
|
||||
fn size() -> usize {
|
||||
N
|
||||
}
|
||||
}
|
||||
|
||||
pub union InlineArray<A: MemoryBlock> {
|
||||
inline_store: ManuallyDrop<MaybeUninit<A>>,
|
||||
heap_ptr_len: (*mut A::LayoutItem, usize),
|
||||
}
|
||||
|
||||
impl<A: MemoryBlock> InlineArray<A> {
|
||||
unsafe fn inline_ptr(&self) -> *const A::LayoutItem {
|
||||
self.inline_store.as_ptr() as *const _
|
||||
}
|
||||
unsafe fn inline_ptr_mut(&mut self) -> *mut A::LayoutItem {
|
||||
self.inline_store.as_mut_ptr() as *mut _
|
||||
}
|
||||
fn from_inline(inline_store: MaybeUninit<A>) -> Self {
|
||||
Self {
|
||||
inline_store: ManuallyDrop::new(inline_store),
|
||||
}
|
||||
}
|
||||
fn from_heap_ptr(start_ptr: *mut A::LayoutItem, len: usize) -> Self {
|
||||
Self {
|
||||
heap_ptr_len: (start_ptr, len),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IArray<A: MemoryBlock> {
|
||||
cap: usize,
|
||||
store: InlineArray<A>,
|
||||
}
|
||||
|
||||
impl<A: MemoryBlock> IArray<A> {
|
||||
pub fn new() -> IArray<A> {
|
||||
Self {
|
||||
cap: 0,
|
||||
store: InlineArray::from_inline(MaybeUninit::uninit()),
|
||||
}
|
||||
}
|
||||
pub fn from_vec(mut vec: Vec<A::LayoutItem>) -> Self {
|
||||
if vec.capacity() <= Self::inline_capacity() {
|
||||
let mut store = InlineArray::<A>::from_inline(MaybeUninit::uninit());
|
||||
let len = vec.len();
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping(vec.as_ptr(), store.inline_ptr_mut(), len);
|
||||
}
|
||||
// done with the copy
|
||||
Self { cap: len, store }
|
||||
} else {
|
||||
let (start_ptr, cap, len) = (vec.as_mut_ptr(), vec.capacity(), vec.len());
|
||||
// leak the vec
|
||||
mem::forget(vec);
|
||||
IArray {
|
||||
cap,
|
||||
store: InlineArray::from_heap_ptr(start_ptr, len),
|
||||
}
|
||||
}
|
||||
}
|
||||
fn inline_capacity() -> usize {
|
||||
if mem::size_of::<A::LayoutItem>() > 0 {
|
||||
// not a ZST, so cap of array
|
||||
A::size()
|
||||
} else {
|
||||
usize::MAX
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue