|
|
@ -24,12 +24,17 @@
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
use super::def::{AsKey, AsValue};
|
|
|
|
use super::def::{AsKey, AsKeyRef, AsValue};
|
|
|
|
use std::{
|
|
|
|
use std::{
|
|
|
|
alloc::{alloc as std_alloc, dealloc as std_dealloc, Layout},
|
|
|
|
alloc::{alloc as std_alloc, dealloc as std_dealloc, Layout},
|
|
|
|
borrow::Borrow,
|
|
|
|
borrow::Borrow,
|
|
|
|
collections::{hash_map::RandomState, HashMap as StdMap},
|
|
|
|
collections::{
|
|
|
|
|
|
|
|
hash_map::{Iter, Keys as StdMapIterKey, RandomState, Values as StdMapIterVal},
|
|
|
|
|
|
|
|
HashMap as StdMap,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
fmt::{self, Debug},
|
|
|
|
hash::{BuildHasher, Hash, Hasher},
|
|
|
|
hash::{BuildHasher, Hash, Hasher},
|
|
|
|
|
|
|
|
iter::FusedIterator,
|
|
|
|
mem,
|
|
|
|
mem,
|
|
|
|
ptr::{self, NonNull},
|
|
|
|
ptr::{self, NonNull},
|
|
|
|
};
|
|
|
|
};
|
|
|
@ -47,7 +52,6 @@ pub type IndexSTSeq<K, V, S = RandomState> = IndexSTSeqDll<K, V, S>;
|
|
|
|
-- Sayan (@ohsayan) // Jan. 16 '23
|
|
|
|
-- Sayan (@ohsayan) // Jan. 16 '23
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
|
|
|
#[repr(transparent)]
|
|
|
|
#[repr(transparent)]
|
|
|
|
/// # WARNING: Segfault/UAF alert
|
|
|
|
/// # WARNING: Segfault/UAF alert
|
|
|
|
///
|
|
|
|
///
|
|
|
@ -55,7 +59,14 @@ pub type IndexSTSeq<K, V, S = RandomState> = IndexSTSeqDll<K, V, S>;
|
|
|
|
/// you're unsure about it's validity. For example, if you simply `==` this or attempt to use it an a hashmap,
|
|
|
|
/// you're unsure about it's validity. For example, if you simply `==` this or attempt to use it an a hashmap,
|
|
|
|
/// you can segfault. IFF, the ptr is valid will it not segfault
|
|
|
|
/// you can segfault. IFF, the ptr is valid will it not segfault
|
|
|
|
struct IndexSTSeqDllKeyptr<K> {
|
|
|
|
struct IndexSTSeqDllKeyptr<K> {
|
|
|
|
p: *mut K,
|
|
|
|
p: *const K,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl<K> IndexSTSeqDllKeyptr<K> {
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
|
|
|
|
fn new(r: &K) -> Self {
|
|
|
|
|
|
|
|
Self { p: r as *const _ }
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl<K: Hash> Hash for IndexSTSeqDllKeyptr<K> {
|
|
|
|
impl<K: Hash> Hash for IndexSTSeqDllKeyptr<K> {
|
|
|
@ -90,7 +101,7 @@ impl<K: PartialEq> PartialEq for IndexSTSeqDllKeyptr<K> {
|
|
|
|
impl<K: Eq> Eq for IndexSTSeqDllKeyptr<K> {}
|
|
|
|
impl<K: Eq> Eq for IndexSTSeqDllKeyptr<K> {}
|
|
|
|
|
|
|
|
|
|
|
|
// stupid type for trait impl conflict riddance
|
|
|
|
// stupid type for trait impl conflict riddance
|
|
|
|
#[derive(Debug, Hash, PartialEq)]
|
|
|
|
#[derive(Debug, Hash, PartialEq, Eq)]
|
|
|
|
#[repr(transparent)]
|
|
|
|
#[repr(transparent)]
|
|
|
|
struct IndexSTSeqDllQref<Q: ?Sized>(Q);
|
|
|
|
struct IndexSTSeqDllQref<Q: ?Sized>(Q);
|
|
|
|
|
|
|
|
|
|
|
@ -140,7 +151,7 @@ impl<K, V> IndexSTSeqDllNode<K, V> {
|
|
|
|
unsafe {
|
|
|
|
unsafe {
|
|
|
|
// UNSAFE(@ohsayan): aight shut up, it's a malloc
|
|
|
|
// UNSAFE(@ohsayan): aight shut up, it's a malloc
|
|
|
|
let ptr = std_alloc(Self::LAYOUT) as *mut Self;
|
|
|
|
let ptr = std_alloc(Self::LAYOUT) as *mut Self;
|
|
|
|
assert!(ptr.is_null(), "damn the allocator failed");
|
|
|
|
assert!(!ptr.is_null(), "damn the allocator failed");
|
|
|
|
ptr
|
|
|
|
ptr
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -169,7 +180,7 @@ impl<K, V> IndexSTSeqDllNode<K, V> {
|
|
|
|
Self::_alloc::<true, true>(Self::new(k, v, p, n))
|
|
|
|
Self::_alloc::<true, true>(Self::new(k, v, p, n))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#[inline(always)]
|
|
|
|
#[inline(always)]
|
|
|
|
unsafe fn dealloc(slf: *mut Self) {
|
|
|
|
unsafe fn _drop(slf: *mut Self) {
|
|
|
|
let _ = Box::from_raw(slf);
|
|
|
|
let _ = Box::from_raw(slf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#[inline(always)]
|
|
|
|
#[inline(always)]
|
|
|
@ -189,6 +200,13 @@ impl<K, V> IndexSTSeqDllNode<K, V> {
|
|
|
|
(*from).n = to;
|
|
|
|
(*from).n = to;
|
|
|
|
(*(*to).n).p = to;
|
|
|
|
(*(*to).n).p = to;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
|
|
|
|
fn alloc_box(node: IndexSTSeqDllNode<K, V>) -> NonNull<IndexSTSeqDllNode<K, V>> {
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
|
|
|
|
// UNSAFE(@ohsayan): Safe because of box alloc
|
|
|
|
|
|
|
|
NonNull::new_unchecked(Box::into_raw(Box::new(node)))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
type IndexSTSeqDllNodePtr<K, V> = NonNull<IndexSTSeqDllNode<K, V>>;
|
|
|
|
type IndexSTSeqDllNodePtr<K, V> = NonNull<IndexSTSeqDllNode<K, V>>;
|
|
|
@ -238,37 +256,63 @@ impl<K, V> IndexSTSeqDll<K, V, RandomState> {
|
|
|
|
impl<K, V, S> IndexSTSeqDll<K, V, S> {
|
|
|
|
impl<K, V, S> IndexSTSeqDll<K, V, S> {
|
|
|
|
#[inline(always)]
|
|
|
|
#[inline(always)]
|
|
|
|
fn ensure_sentinel(&mut self) {
|
|
|
|
fn ensure_sentinel(&mut self) {
|
|
|
|
|
|
|
|
if self.h.is_null() {
|
|
|
|
let ptr = IndexSTSeqDllNode::_alloc_with_garbage();
|
|
|
|
let ptr = IndexSTSeqDllNode::_alloc_with_garbage();
|
|
|
|
unsafe {
|
|
|
|
unsafe {
|
|
|
|
|
|
|
|
// UNSAFE(@ohsayan): Fresh alloc
|
|
|
|
self.h = ptr;
|
|
|
|
self.h = ptr;
|
|
|
|
(*ptr).p = ptr;
|
|
|
|
(*ptr).p = ptr;
|
|
|
|
(*ptr).n = ptr;
|
|
|
|
(*ptr).n = ptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
#[inline(always)]
|
|
|
|
#[inline(always)]
|
|
|
|
/// ## Safety
|
|
|
|
/// ## Safety
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// Head must not be null
|
|
|
|
/// Head must not be null
|
|
|
|
unsafe fn drop_nodes_full(&mut self) {
|
|
|
|
unsafe fn drop_nodes_full(&mut self) {
|
|
|
|
let mut c = self.h;
|
|
|
|
// don't drop sentinenl
|
|
|
|
while !c.is_null() {
|
|
|
|
let mut c = (*self.h).n;
|
|
|
|
|
|
|
|
while c != self.h {
|
|
|
|
let nx = (*c).n;
|
|
|
|
let nx = (*c).n;
|
|
|
|
IndexSTSeqDllNode::dealloc(c);
|
|
|
|
IndexSTSeqDllNode::_drop(c);
|
|
|
|
c = nx;
|
|
|
|
c = nx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#[inline(always)]
|
|
|
|
#[inline(always)]
|
|
|
|
fn vacuum_free(&mut self) {
|
|
|
|
fn vacuum_free(&mut self) {
|
|
|
|
unsafe {
|
|
|
|
unsafe {
|
|
|
|
|
|
|
|
// UNSAFE(@ohsayan): All nullck
|
|
|
|
let mut c = self.f;
|
|
|
|
let mut c = self.f;
|
|
|
|
while !c.is_null() {
|
|
|
|
while !c.is_null() {
|
|
|
|
let nx = (*c).n;
|
|
|
|
let nx = (*c).n;
|
|
|
|
IndexSTSeqDllNode::dealloc_headless(nx);
|
|
|
|
IndexSTSeqDllNode::dealloc_headless(c);
|
|
|
|
c = nx;
|
|
|
|
c = nx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
self.f = ptr::null_mut();
|
|
|
|
self.f = ptr::null_mut();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
|
|
|
|
fn recycle_or_alloc(&mut self, node: IndexSTSeqDllNode<K, V>) -> IndexSTSeqDllNodePtr<K, V> {
|
|
|
|
|
|
|
|
if self.f.is_null() {
|
|
|
|
|
|
|
|
IndexSTSeqDllNode::alloc_box(node)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
|
|
|
|
// UNSAFE(@ohsayan): Safe because we already did a nullptr check
|
|
|
|
|
|
|
|
let f = self.f;
|
|
|
|
|
|
|
|
self.f = (*self.f).n;
|
|
|
|
|
|
|
|
ptr::write(f, node);
|
|
|
|
|
|
|
|
IndexSTSeqDllNodePtr::new_unchecked(f)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
|
|
|
|
/// NOTE: `&mut Self` for aliasing
|
|
|
|
|
|
|
|
/// ## Safety
|
|
|
|
|
|
|
|
/// Ensure head is non null
|
|
|
|
|
|
|
|
unsafe fn link(&mut self, node: IndexSTSeqDllNodePtr<K, V>) {
|
|
|
|
|
|
|
|
IndexSTSeqDllNode::link(self.h, node.as_ptr())
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl<K: AsKey, V: AsValue, S: BuildHasher> IndexSTSeqDll<K, V, S> {
|
|
|
|
impl<K: AsKey, V: AsValue, S: BuildHasher> IndexSTSeqDll<K, V, S> {
|
|
|
@ -279,3 +323,310 @@ impl<K: AsKey, V: AsValue, S: BuildHasher> IndexSTSeqDll<K, V, S> {
|
|
|
|
self.vacuum_free();
|
|
|
|
self.vacuum_free();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl<K: AsKey, V: AsValue, S: BuildHasher> IndexSTSeqDll<K, V, S> {
|
|
|
|
|
|
|
|
const GET_REFRESH: bool = true;
|
|
|
|
|
|
|
|
const GET_BYPASS: bool = false;
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
|
|
|
|
fn _insert(&mut self, k: K, v: V) -> bool {
|
|
|
|
|
|
|
|
if self.m.contains_key(&IndexSTSeqDllKeyptr::new(&k)) {
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
self.__insert(k, v)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
fn _get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
|
|
|
|
|
|
|
|
where
|
|
|
|
|
|
|
|
K: Borrow<Q>,
|
|
|
|
|
|
|
|
Q: AsKeyRef,
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
self.m
|
|
|
|
|
|
|
|
.get(unsafe {
|
|
|
|
|
|
|
|
// UNSAFE(@ohsayan): Ref with correct bounds
|
|
|
|
|
|
|
|
IndexSTSeqDllQref::from_ref(k)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.map(|e| unsafe {
|
|
|
|
|
|
|
|
// UNSAFE(@ohsayan): ref is non-null and ensures aliasing reqs
|
|
|
|
|
|
|
|
&(e.as_ref()).read_value().v
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
|
|
|
|
fn _update<Q: ?Sized>(&mut self, k: &Q, v: V) -> Option<V>
|
|
|
|
|
|
|
|
where
|
|
|
|
|
|
|
|
K: Borrow<Q>,
|
|
|
|
|
|
|
|
Q: AsKeyRef,
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
match self.m.get(unsafe {
|
|
|
|
|
|
|
|
// UNSAFE(@ohsayan): Just got a ref with the right bounds
|
|
|
|
|
|
|
|
IndexSTSeqDllQref::from_ref(k)
|
|
|
|
|
|
|
|
}) {
|
|
|
|
|
|
|
|
Some(e) => unsafe {
|
|
|
|
|
|
|
|
// UNSAFE(@ohsayan): Impl guarantees that entry presence == nullck head
|
|
|
|
|
|
|
|
self.__update(*e, v)
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
None => return None,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
|
|
|
|
fn _upsert(&mut self, k: K, v: V) -> Option<V> {
|
|
|
|
|
|
|
|
match self.m.get(&IndexSTSeqDllKeyptr::new(&k)) {
|
|
|
|
|
|
|
|
Some(e) => unsafe {
|
|
|
|
|
|
|
|
// UNSAFE(@ohsayan): Impl guarantees that entry presence == nullck head
|
|
|
|
|
|
|
|
self.__update(*e, v)
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
None => {
|
|
|
|
|
|
|
|
let _ = self.__insert(k, v);
|
|
|
|
|
|
|
|
None
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
|
|
|
|
fn _remove<Q>(&mut self, k: &Q) -> Option<V>
|
|
|
|
|
|
|
|
where
|
|
|
|
|
|
|
|
K: Borrow<Q>,
|
|
|
|
|
|
|
|
Q: AsKeyRef + ?Sized,
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
self.m
|
|
|
|
|
|
|
|
.remove(unsafe {
|
|
|
|
|
|
|
|
// UNSAFE(@ohsayan): good trait bounds and type
|
|
|
|
|
|
|
|
IndexSTSeqDllQref::from_ref(k)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.map(|n| unsafe {
|
|
|
|
|
|
|
|
let n = n.as_ptr();
|
|
|
|
|
|
|
|
// UNSAFE(@ohsayan): Correct init and aligned to K
|
|
|
|
|
|
|
|
drop(ptr::read(&(*n).k));
|
|
|
|
|
|
|
|
// UNSAFE(@ohsayan): Correct init and aligned to V
|
|
|
|
|
|
|
|
let v = ptr::read(&(*n).v);
|
|
|
|
|
|
|
|
// UNSAFE(@ohsayan): non-null guaranteed by as_ptr
|
|
|
|
|
|
|
|
IndexSTSeqDllNode::unlink(n);
|
|
|
|
|
|
|
|
(*n).n = self.f;
|
|
|
|
|
|
|
|
self.f = n;
|
|
|
|
|
|
|
|
v
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
|
|
|
|
fn __insert(&mut self, k: K, v: V) -> bool {
|
|
|
|
|
|
|
|
self.ensure_sentinel();
|
|
|
|
|
|
|
|
let node = self.recycle_or_alloc(IndexSTSeqDllNode::new_null(k, v));
|
|
|
|
|
|
|
|
let kptr = unsafe {
|
|
|
|
|
|
|
|
// UNSAFE(@ohsayan): All g, we allocated it rn
|
|
|
|
|
|
|
|
IndexSTSeqDllKeyptr::new(&node.as_ref().k)
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
let _ = self.m.insert(kptr, node);
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
|
|
|
|
// UNSAFE(@ohsayan): sentinel check done
|
|
|
|
|
|
|
|
self.link(node);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
true
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
|
|
|
|
/// ## Safety
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// Has sentinel
|
|
|
|
|
|
|
|
unsafe fn __update(&mut self, e: NonNull<IndexSTSeqDllNode<K, V>>, v: V) -> Option<V> {
|
|
|
|
|
|
|
|
let old = unsafe {
|
|
|
|
|
|
|
|
// UNSAFE(@ohsayan): Same type layout, alignments and non-null
|
|
|
|
|
|
|
|
ptr::replace(&mut (*e.as_ptr()).v, v)
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
self._refresh(e);
|
|
|
|
|
|
|
|
Some(old)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
|
|
|
|
/// ## Safety
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// Has sentinel
|
|
|
|
|
|
|
|
unsafe fn _refresh(&mut self, e: NonNull<IndexSTSeqDllNode<K, V>>) {
|
|
|
|
|
|
|
|
// UNSAFE(@ohsayan): Since it's in the collection, it is a valid ptr
|
|
|
|
|
|
|
|
IndexSTSeqDllNode::unlink(e.as_ptr());
|
|
|
|
|
|
|
|
// UNSAFE(@ohsayan): As we found a node, our impl guarantees that the head is not-null
|
|
|
|
|
|
|
|
self.link(e);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
|
|
|
|
fn _clear(&mut self) {
|
|
|
|
|
|
|
|
self.m.clear();
|
|
|
|
|
|
|
|
if !self.h.is_null() {
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
|
|
|
|
// UNSAFE(@ohsayan): nullck
|
|
|
|
|
|
|
|
self.drop_nodes_full();
|
|
|
|
|
|
|
|
// UNSAFE(@ohsayan): Drop won't kill sentinel; link back to self
|
|
|
|
|
|
|
|
(*self.h).p = self.h;
|
|
|
|
|
|
|
|
(*self.h).n = self.h;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
|
|
|
|
fn _iter_unord_kv<'a>(&'a self) -> IndexSTSeqDllIterUnordKV<'a, K, V> {
|
|
|
|
|
|
|
|
IndexSTSeqDllIterUnordKV::new(&self.m)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
|
|
|
|
fn _iter_unord_k<'a>(&'a self) -> IndexSTSeqDllIterUnordK<'a, K, V> {
|
|
|
|
|
|
|
|
IndexSTSeqDllIterUnordK::new(&self.m)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
|
|
|
|
fn _iter_unord_v<'a>(&'a self) -> IndexSTSeqDllIterUnordV<'a, K, V> {
|
|
|
|
|
|
|
|
IndexSTSeqDllIterUnordV::new(&self.m)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl<K, V, S> Drop for IndexSTSeqDll<K, V, S> {
|
|
|
|
|
|
|
|
fn drop(&mut self) {
|
|
|
|
|
|
|
|
if !self.h.is_null() {
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
|
|
|
|
// UNSAFE(@ohsayan): nullck
|
|
|
|
|
|
|
|
self.drop_nodes_full();
|
|
|
|
|
|
|
|
// UNSAFE(@ohsayan): nullck: drop doesn't clear sentinel
|
|
|
|
|
|
|
|
IndexSTSeqDllNode::dealloc_headless(self.h);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
self.vacuum_free();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
unsafe impl<K: Send, V: Send, S: Send> Send for IndexSTSeqDll<K, V, S> {}
|
|
|
|
|
|
|
|
unsafe impl<K: Sync, V: Sync, S: Sync> Sync for IndexSTSeqDll<K, V, S> {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
macro_rules! unsafe_marker_impl {
|
|
|
|
|
|
|
|
($ty:ty) => {
|
|
|
|
|
|
|
|
unsafe impl<'a, K: Send, V: Send> Send for $ty {}
|
|
|
|
|
|
|
|
unsafe impl<'a, K: Sync, V: Sync> Sync for $ty {}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub struct IndexSTSeqDllIterUnordKV<'a, K: 'a, V: 'a> {
|
|
|
|
|
|
|
|
i: Iter<'a, IndexSTSeqDllKeyptr<K>, IndexSTSeqDllNodePtr<K, V>>,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// UNSAFE(@ohsayan): aliasing guarantees correctness
|
|
|
|
|
|
|
|
unsafe_marker_impl!(IndexSTSeqDllIterUnordKV<'a, K, V>);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl<'a, K: 'a, V: 'a> IndexSTSeqDllIterUnordKV<'a, K, V> {
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
|
|
|
|
fn new<S>(m: &'a StdMap<IndexSTSeqDllKeyptr<K>, NonNull<IndexSTSeqDllNode<K, V>>, S>) -> Self {
|
|
|
|
|
|
|
|
Self { i: m.iter() }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl<K, V> Clone for IndexSTSeqDllIterUnordKV<'_, K, V> {
|
|
|
|
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
|
|
|
|
Self { i: self.i.clone() }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl<'a, K, V> Iterator for IndexSTSeqDllIterUnordKV<'a, K, V> {
|
|
|
|
|
|
|
|
type Item = (&'a K, &'a V);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
|
|
|
|
|
self.i.next().map(|(_, n)| {
|
|
|
|
|
|
|
|
let n = n.as_ptr();
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
|
|
|
|
// UNSAFE(@ohsayan): nullck
|
|
|
|
|
|
|
|
(&(*n).k, &(*n).v)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl<'a, K, V> ExactSizeIterator for IndexSTSeqDllIterUnordKV<'a, K, V> {
|
|
|
|
|
|
|
|
fn len(&self) -> usize {
|
|
|
|
|
|
|
|
self.i.len()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl<'a, K, V> FusedIterator for IndexSTSeqDllIterUnordKV<'a, K, V> {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl<K: Debug, V: Debug> Debug for IndexSTSeqDllIterUnordKV<'_, K, V> {
|
|
|
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
|
|
|
|
f.debug_list().entries(self.clone()).finish()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub struct IndexSTSeqDllIterUnordK<'a, K: 'a, V: 'a> {
|
|
|
|
|
|
|
|
k: StdMapIterKey<'a, IndexSTSeqDllKeyptr<K>, IndexSTSeqDllNodePtr<K, V>>,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// UNSAFE(@ohsayan): aliasing guarantees correctness
|
|
|
|
|
|
|
|
unsafe_marker_impl!(IndexSTSeqDllIterUnordK<'a, K, V>);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl<'a, K: 'a, V: 'a> IndexSTSeqDllIterUnordK<'a, K, V> {
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
|
|
|
|
fn new<S>(m: &'a StdMap<IndexSTSeqDllKeyptr<K>, NonNull<IndexSTSeqDllNode<K, V>>, S>) -> Self {
|
|
|
|
|
|
|
|
Self { k: m.keys() }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl<K, V> Clone for IndexSTSeqDllIterUnordK<'_, K, V> {
|
|
|
|
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
|
|
|
|
Self { k: self.k.clone() }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl<'a, K, V> Iterator for IndexSTSeqDllIterUnordK<'a, K, V> {
|
|
|
|
|
|
|
|
type Item = &'a K;
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
|
|
|
|
|
self.k.next().map(|k| {
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
|
|
|
|
// UNSAFE(@ohsayan): nullck
|
|
|
|
|
|
|
|
&*(*k).p
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl<'a, K, V> ExactSizeIterator for IndexSTSeqDllIterUnordK<'a, K, V> {
|
|
|
|
|
|
|
|
fn len(&self) -> usize {
|
|
|
|
|
|
|
|
self.k.len()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl<'a, K, V> FusedIterator for IndexSTSeqDllIterUnordK<'a, K, V> {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl<'a, K: Debug, V> Debug for IndexSTSeqDllIterUnordK<'_, K, V> {
|
|
|
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
|
|
|
|
f.debug_list().entries(self.clone()).finish()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub struct IndexSTSeqDllIterUnordV<'a, K: 'a, V: 'a> {
|
|
|
|
|
|
|
|
v: StdMapIterVal<'a, IndexSTSeqDllKeyptr<K>, IndexSTSeqDllNodePtr<K, V>>,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// UNSAFE(@ohsayan): aliasing guarantees correctness
|
|
|
|
|
|
|
|
unsafe_marker_impl!(IndexSTSeqDllIterUnordV<'a, K, V>);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl<'a, K: 'a, V: 'a> IndexSTSeqDllIterUnordV<'a, K, V> {
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
|
|
|
|
fn new<S>(m: &'a StdMap<IndexSTSeqDllKeyptr<K>, NonNull<IndexSTSeqDllNode<K, V>>, S>) -> Self {
|
|
|
|
|
|
|
|
Self { v: m.values() }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl<K, V> Clone for IndexSTSeqDllIterUnordV<'_, K, V> {
|
|
|
|
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
|
|
|
|
Self { v: self.v.clone() }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl<'a, K, V> Iterator for IndexSTSeqDllIterUnordV<'a, K, V> {
|
|
|
|
|
|
|
|
type Item = &'a V;
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
|
|
|
|
|
self.v.next().map(|k| {
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
|
|
|
|
// UNSAFE(@ohsayan): nullck
|
|
|
|
|
|
|
|
&(*k.as_ptr()).v
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl<'a, K, V> ExactSizeIterator for IndexSTSeqDllIterUnordV<'a, K, V> {
|
|
|
|
|
|
|
|
fn len(&self) -> usize {
|
|
|
|
|
|
|
|
self.v.len()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl<'a, K, V> FusedIterator for IndexSTSeqDllIterUnordV<'a, K, V> {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl<'a, K, V: Debug> Debug for IndexSTSeqDllIterUnordV<'_, K, V> {
|
|
|
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
|
|
|
|
f.debug_list().entries(self.clone()).finish()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|