use super::Keyed;
use std::{cmp::Ordering, mem::MaybeUninit};
pub struct Item<K, V> {
key: MaybeUninit<K>,
value: MaybeUninit<V>,
}
impl<K: Clone, V: Clone> Clone for Item<K, V> {
fn clone(&self) -> Self {
unsafe {
Self::new(
self.key.assume_init_ref().clone(),
self.value.assume_init_ref().clone(),
)
}
}
}
impl<K, V> AsRef<Item<K, V>> for Item<K, V> {
fn as_ref(&self) -> &Self {
self
}
}
impl<K, V> Item<K, V> {
pub fn new(key: K, value: V) -> Item<K, V> {
Item {
key: MaybeUninit::new(key),
value: MaybeUninit::new(value),
}
}
#[inline]
pub fn key(&self) -> &K {
unsafe { self.key.assume_init_ref() }
}
#[inline]
pub fn key_mut(&mut self) -> &mut K {
unsafe { self.key.assume_init_mut() }
}
#[inline]
pub fn value(&self) -> &V {
unsafe { self.value.assume_init_ref() }
}
#[inline]
pub fn value_mut(&mut self) -> &mut V {
unsafe { self.value.assume_init_mut() }
}
#[inline]
pub fn set(&mut self, key: K, value: V) -> (K, V) {
let mut old_key = MaybeUninit::new(key);
let mut old_value = MaybeUninit::new(value);
std::mem::swap(&mut old_key, &mut self.key);
std::mem::swap(&mut old_value, &mut self.value);
unsafe { (old_key.assume_init(), old_value.assume_init()) }
}
#[inline]
pub fn set_key(&mut self, key: K) -> K {
let mut old_key = MaybeUninit::new(key);
std::mem::swap(&mut old_key, &mut self.key);
unsafe { old_key.assume_init() }
}
#[inline]
pub fn set_value(&mut self, value: V) -> V {
let mut old_value = MaybeUninit::new(value);
std::mem::swap(&mut old_value, &mut self.value);
unsafe { old_value.assume_init() }
}
#[inline]
pub fn maybe_uninit_value_mut(&mut self) -> &mut MaybeUninit<V> {
&mut self.value
}
#[inline]
pub fn into_key(self) -> K {
let (key, value) = self.into_inner();
unsafe {
std::mem::drop(value.assume_init());
key.assume_init()
}
}
#[inline]
pub fn into_value(self) -> V {
let (key, value) = self.into_inner();
unsafe {
std::mem::drop(key.assume_init());
value.assume_init()
}
}
#[inline]
pub fn as_pair(&self) -> (&K, &V) {
unsafe { (self.key.assume_init_ref(), self.value.assume_init_ref()) }
}
#[inline]
pub fn as_pair_mut(&mut self) -> (&mut K, &mut V) {
unsafe { (self.key.assume_init_mut(), self.value.assume_init_mut()) }
}
#[inline]
pub fn into_pair(self) -> (K, V) {
let (key, value) = self.into_inner();
unsafe { (key.assume_init(), value.assume_init()) }
}
#[inline]
pub unsafe fn forget_value(self) {
let (key, _) = self.into_inner();
std::mem::drop(key.assume_init())
}
#[inline]
pub fn into_inner(mut self) -> (MaybeUninit<K>, MaybeUninit<V>) {
let mut key = MaybeUninit::uninit();
let mut value = MaybeUninit::uninit();
std::mem::swap(&mut key, &mut self.key);
std::mem::swap(&mut value, &mut self.value);
std::mem::forget(self);
(key, value)
}
}
impl<K, V> Drop for Item<K, V> {
fn drop(&mut self) {
unsafe {
std::ptr::drop_in_place(self.key.assume_init_mut());
std::ptr::drop_in_place(self.value.assume_init_mut());
}
}
}
impl<K, V> Keyed for Item<K, V> {
type Key = K;
#[inline]
fn key(&self) -> &K {
self.key()
}
}
impl<K: PartialEq, V> PartialEq for Item<K, V> {
fn eq(&self, other: &Item<K, V>) -> bool {
self.key().eq(other.key())
}
}
impl<K: Ord + PartialEq, V> PartialOrd for Item<K, V> {
fn partial_cmp(&self, other: &Item<K, V>) -> Option<Ordering> {
Some(self.key().cmp(other.key()))
}
}