use std::cmp::Ordering;
use std::mem::ManuallyDrop;
use std::{mem, ptr, slice};
use compare::Compare;
use crate::{read_int, read_int_ptr, write_int, write_int_ptr, LenType};
#[derive(Clone)]
pub(crate) struct MaxHeapCompare {
pub(crate) heap: *mut FieldHeap<MaxHeapCompare>,
}
impl Compare<FieldMeta> for MaxHeapCompare {
fn compare(&self, l: &FieldMeta, r: &FieldMeta) -> Ordering {
unsafe {
let field_heap = &(*self.heap);
let p = field_heap.data.as_ptr().offset(field_heap.bst_capt + FieldHeap::<MaxHeapCompare>::BST_OFFSET);
let l_len = read_int_ptr::<SizeField>(p.offset(l.offset)) as usize;
let l_v = slice::from_raw_parts(p.offset(l_len as isize + l.offset), l_len);
let r_len = read_int_ptr::<SizeField>(p.offset(r.offset)) as usize;
let r_v = slice::from_raw_parts(p.offset(r_len as isize + r.offset), r_len);
l_v.cmp(r_v)
}
}
}
#[derive(Clone)]
pub(crate) struct MinHeapCompare {
pub(crate) heap: *mut FieldHeap<MinHeapCompare>,
}
impl Compare<FieldMeta> for MinHeapCompare {
fn compare(&self, l: &FieldMeta, r: &FieldMeta) -> Ordering {
unsafe {
let field_heap = &(*self.heap);
let p = field_heap.data.as_ptr().offset(field_heap.bst_capt + FieldHeap::<MaxHeapCompare>::BST_OFFSET);
let l_len = read_int_ptr::<SizeField>(p.offset(l.offset)) as usize;
let l_v = slice::from_raw_parts(p.offset(l_len as isize + l.offset), l_len);
let r_len = read_int_ptr::<SizeField>(p.offset(r.offset)) as usize;
let r_v = slice::from_raw_parts(p.offset(r_len as isize + r.offset), r_len);
r_v.cmp(l_v)
}
}
}
pub(crate) struct FieldHeap<T: Compare<FieldMeta> + Clone> {
pub data: Vec<u8>,
bst_capt: isize,
comparer: Option<T>,
}
pub(crate) type SizeField = i32;
pub(crate) struct FieldMeta {
pub offset: isize,
}
impl<T: Compare<FieldMeta> + Clone> FieldHeap<T> {
pub const SIZE: usize = mem::size_of::<SizeField>();
pub const BST_OFFSET: isize = 2 * (mem::size_of::<LenType>() as isize);
pub const BST_EXPAND: isize = 64 * (mem::size_of::<FieldMeta>() as isize);
pub fn new(data: Vec<u8>) -> Self {
let mut data = data;
let mut bst_capt = Self::BST_EXPAND;
if data.is_empty() {
data.resize(Self::BST_OFFSET as usize + bst_capt as usize, 0);
unsafe { write_int_ptr(data.as_mut_ptr().offset(mem::size_of::<LenType>() as isize), bst_capt as LenType) }
} else {
unsafe {
bst_capt = read_int_ptr::<LenType>(data.as_ptr().offset(mem::size_of::<LenType>() as isize)) as isize;
}
};
FieldHeap { data, bst_capt, comparer: None }
}
pub fn init(&mut self, comparer: T) {
self.comparer = Some(comparer);
}
fn make_heap(&mut self) -> binary_heap_plus::BinaryHeap<FieldMeta, T> {
let head_array = unsafe {
Vec::from_raw_parts(
self.data.as_mut_ptr().offset(Self::BST_OFFSET as isize) as *mut FieldMeta,
self.len(),
self.bst_capt as usize / mem::size_of::<FieldMeta>(),
)
};
let t = unsafe { binary_heap_plus::BinaryHeap::from_vec_cmp_raw(head_array, self.comparer.as_ref().expect("").clone(), false) };
return t;
}
fn drop_heap(&mut self, heap: binary_heap_plus::BinaryHeap<FieldMeta, T>) {
let data = heap.into_vec();
let _ = ManuallyDrop::new(data);
}
fn field_offset(&self) -> isize {
Self::BST_OFFSET + self.bst_capt
}
pub fn peek(&mut self) -> Option<Vec<u8>> {
let heap = self.make_heap();
let v = heap.peek();
let pop_v = if let Some(v) = v {
let start = v.offset + Self::BST_OFFSET + self.bst_capt;
let field_size = unsafe { read_int_ptr::<SizeField>(self.data.as_ptr().offset(start)) };
let end = start + Self::SIZE as isize + field_size as isize;
let re = self.data[start as usize + Self::SIZE as usize..end as usize].to_vec();
Some(re)
} else {
None
};
self.drop_heap(heap);
pop_v
}
pub fn pop(&mut self) -> Option<Vec<u8>> {
let mut heap = self.make_heap();
let v = heap.pop();
self.drop_heap(heap);
if let Some(v) = v {
let len_field = self.len() - 1;
self.set_len(len_field);
let start = v.offset + Self::BST_OFFSET + self.bst_capt;
let field_size = unsafe { read_int_ptr::<SizeField>(self.data.as_ptr().offset(start)) };
let end = start + Self::SIZE as isize + field_size as isize;
let re = self.data[start as usize + Self::SIZE as usize..end as usize].to_vec();
if self.bst_capt as usize - len_field * mem::size_of::<FieldMeta>() > Self::BST_EXPAND as usize {
self.reduce();
}
Some(re)
} else {
None
}
}
pub fn push(&mut self, field: &[u8]) {
let len = self.len();
if len * mem::size_of::<FieldMeta>() >= self.bst_capt as usize {
self.expand();
}
let add = Self::SIZE + field.len();
self.data.reserve(add);
let len_data = self.data.len();
unsafe {
let p = self.data.as_mut_ptr().offset(len_data as isize);
write_int_ptr(p, field.len() as SizeField);
ptr::copy_nonoverlapping(field.as_ptr(), p.offset(Self::SIZE as isize), field.len());
self.data.set_len(self.data.len() + add)
}
let mut heap = self.make_heap();
heap.push(FieldMeta { offset: len_data as isize - Self::BST_OFFSET - self.bst_capt });
self.drop_heap(heap);
let len = self.len() + 1;
write_int_ptr(self.data.as_mut_ptr(), len as LenType);
}
pub fn len(&self) -> usize {
let l = read_int::<LenType>(&self.data);
return l as usize;
}
pub fn set_len(&mut self, l: usize) {
write_int::<LenType>(&mut self.data, l as LenType);
}
pub(crate) fn new_field_it(&self) -> FieldIt<'_, T> {
FieldIt::new(self)
}
fn expand(&mut self) {
let expand_size = Self::BST_EXPAND as isize;
self.data.reserve(expand_size as usize);
unsafe {
self.data.set_len(self.data.len() + expand_size as usize);
}
let old_capt = self.bst_capt;
unsafe {
let p_data = self.data.as_mut_ptr().offset(Self::BST_OFFSET + old_capt);
ptr::copy(p_data, p_data.offset(expand_size as isize), self.data.len() - expand_size as usize - Self::BST_OFFSET as usize - old_capt as usize);
write_int_ptr(self.data.as_mut_ptr().offset(mem::size_of::<LenType>() as isize), old_capt as LenType + expand_size as LenType);
};
self.bst_capt = old_capt + expand_size;
}
fn reduce(&mut self) {
let reduce_size = Self::BST_EXPAND;
let mut temp_fields = Vec::<u8>::with_capacity(self.data.len() - self.bst_capt as usize - Self::BST_OFFSET as usize);
let mut head_array = unsafe {
Vec::from_raw_parts(
self.data.as_mut_ptr().offset(Self::BST_OFFSET) as *mut FieldMeta,
self.len(),
self.bst_capt as usize / mem::size_of::<FieldMeta>(),
)
};
let mut offset = 0;
let p_data = unsafe { self.data.as_ptr().offset(Self::BST_OFFSET + self.bst_capt) };
for field_meta in &mut head_array {
let start = field_meta.offset;
let field_size = unsafe { read_int_ptr::<SizeField>(p_data.offset(start)) };
unsafe {
ptr::copy_nonoverlapping(p_data.offset(start), temp_fields.as_mut_ptr().offset(offset), field_size as usize + Self::SIZE);
}
field_meta.offset = offset;
offset += field_size as isize + Self::SIZE as isize;
unsafe {
temp_fields.set_len(offset as usize);
}
}
let _ = ManuallyDrop::new(head_array);
self.bst_capt -= reduce_size;
unsafe {
temp_fields.set_len(offset as usize);
write_int_ptr(self.data.as_mut_ptr().offset(mem::size_of::<LenType>() as isize), self.bst_capt as LenType);
ptr::copy_nonoverlapping(temp_fields.as_ptr(), self.data.as_mut_ptr().offset(Self::BST_OFFSET + self.bst_capt), temp_fields.len());
self.data.set_len(Self::BST_OFFSET as usize + self.bst_capt as usize + temp_fields.len());
}
}
}
pub(crate) struct FieldIt<'a, T: Compare<FieldMeta> + Clone> {
data: &'a FieldHeap<T>,
len: isize,
index: isize,
offset: isize,
}
impl<'a, T: Compare<FieldMeta> + Clone> FieldIt<'a, T> {
pub fn new(d: &'a FieldHeap<T>) -> Self {
FieldIt { data: d, len: 0, index: -1, offset: 0 }
}
}
pub(crate) struct FieldItValue<'a> {
pub field: &'a [u8],
}
impl<'a, T: Compare<FieldMeta> + Clone> Iterator for FieldIt<'a, T> {
type Item = FieldItValue<'a>;
fn next(&mut self) -> Option<Self::Item> {
if self.index >= self.len {
return None;
}
if self.index < 0 {
self.len = self.data.len() as isize;
if self.len < 1 {
return None;
}
self.offset = mem::size_of::<LenType>() as isize;
}
self.index += 1;
let field_size = read_int_ptr::<SizeField>(unsafe { self.data.data.as_ptr().offset(self.offset) });
let it = FieldItValue {
field: unsafe { slice::from_raw_parts(self.data.data.as_ptr().offset(self.offset + FieldHeap::<T>::SIZE as isize), field_size as usize) },
};
return Some(it);
}
}
#[cfg(test)]
mod test {
use std::mem;
use crate::write_int;
#[test]
fn test_binary_heap() {
{
{
let mut t = binary_heap_plus::BinaryHeap::new();
t.push(1);
t.push(2);
t.push(3);
assert_eq!(3, t.pop().expect(""));
assert_eq!(2, t.pop().expect(""));
assert_eq!(1, t.pop().expect(""));
}
{
const MAX: i32 = 6;
let mut t = binary_heap_plus::BinaryHeap::<[u8; mem::size_of::<i32>()]>::new();
for i in 1..MAX {
let mut field: [u8; mem::size_of::<i32>()] = [0; mem::size_of::<i32>()];
write_int(field.as_mut(), i);
t.push(field);
}
for i in (1..MAX).rev() {
let mut field: [u8; mem::size_of::<i32>()] = [0; mem::size_of::<i32>()];
write_int(field.as_mut(), i);
let data = t.pop().expect("");
assert_eq!(field, data);
}
}
{
const MAX: i32 = 6;
let mut t = binary_heap_plus::BinaryHeap::new();
for i in 1..MAX {
let mut field: [u8; mem::size_of::<i32>()] = [0; mem::size_of::<i32>()];
write_int(field.as_mut(), i);
t.push(field.to_vec());
}
for i in (1..MAX).rev() {
let mut field: [u8; mem::size_of::<i32>()] = [0; mem::size_of::<i32>()];
write_int(field.as_mut(), i);
let data = t.pop().expect("");
assert_eq!(field.to_vec(), data);
}
}
}
{
{
let mut t = binary_heap_plus::BinaryHeap::new_min();
t.push(1);
t.push(2);
t.push(3);
assert_eq!(1, t.pop().expect(""));
assert_eq!(2, t.pop().expect(""));
assert_eq!(3, t.pop().expect(""));
}
{
const MAX: i32 = 6;
let mut t = binary_heap_plus::BinaryHeap::new_min();
for i in 1..MAX {
let mut field: [u8; mem::size_of::<i32>()] = [0; mem::size_of::<i32>()];
write_int(field.as_mut(), i);
t.push(field.to_vec());
}
for i in 1..MAX {
let mut field: [u8; mem::size_of::<i32>()] = [0; mem::size_of::<i32>()];
write_int(field.as_mut(), i);
let data = t.pop().expect("");
assert_eq!(field.to_vec(), data);
}
}
}
}
}