use core::mem::ManuallyDrop;
use facet_core::{Facet, MapDef};
use crate::{HeapValue, ReflectError, ReflectErrorKind};
use super::Poke;
pub struct PokeMap<'mem, 'facet> {
value: Poke<'mem, 'facet>,
def: MapDef,
}
impl<'mem, 'facet> core::fmt::Debug for PokeMap<'mem, 'facet> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("PokeMap").finish_non_exhaustive()
}
}
impl<'mem, 'facet> PokeMap<'mem, 'facet> {
#[inline]
pub const unsafe fn new(value: Poke<'mem, 'facet>, def: MapDef) -> Self {
Self { value, def }
}
fn err(&self, kind: ReflectErrorKind) -> ReflectError {
self.value.err(kind)
}
#[inline]
pub fn len(&self) -> usize {
unsafe { (self.def.vtable.len)(self.value.data()) }
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub fn contains_key(&self, key: &impl Facet<'facet>) -> Result<bool, ReflectError> {
self.contains_key_peek(crate::Peek::new(key))
}
#[inline]
pub fn contains_key_peek(&self, key: crate::Peek<'_, 'facet>) -> Result<bool, ReflectError> {
if self.def.k() == key.shape() {
return Ok(unsafe { (self.def.vtable.contains_key)(self.value.data(), key.data()) });
}
Err(self.err(ReflectErrorKind::WrongShape {
expected: self.def.k(),
actual: key.shape(),
}))
}
#[inline]
pub fn get(
&self,
key: &impl Facet<'facet>,
) -> Result<Option<crate::Peek<'_, 'facet>>, ReflectError> {
self.get_peek(crate::Peek::new(key))
}
#[inline]
pub fn get_peek(
&self,
key: crate::Peek<'_, 'facet>,
) -> Result<Option<crate::Peek<'_, 'facet>>, ReflectError> {
if self.def.k() != key.shape() {
return Err(self.err(ReflectErrorKind::WrongShape {
expected: self.def.k(),
actual: key.shape(),
}));
}
let value_ptr = unsafe { (self.def.vtable.get_value_ptr)(self.value.data(), key.data()) };
if value_ptr.is_null() {
return Ok(None);
}
let value_ptr = facet_core::PtrConst::new_sized(value_ptr);
Ok(Some(unsafe {
crate::Peek::unchecked_new(value_ptr, self.def.v())
}))
}
pub fn insert<K, V>(&mut self, key: K, value: V) -> Result<(), ReflectError>
where
K: Facet<'facet>,
V: Facet<'facet>,
{
if self.def.k() != K::SHAPE {
return Err(self.err(ReflectErrorKind::WrongShape {
expected: self.def.k(),
actual: K::SHAPE,
}));
}
if self.def.v() != V::SHAPE {
return Err(self.err(ReflectErrorKind::WrongShape {
expected: self.def.v(),
actual: V::SHAPE,
}));
}
let mut key = ManuallyDrop::new(key);
let mut value = ManuallyDrop::new(value);
unsafe {
let key_ptr = facet_core::PtrMut::new(&mut key as *mut ManuallyDrop<K> as *mut u8);
let value_ptr = facet_core::PtrMut::new(&mut value as *mut ManuallyDrop<V> as *mut u8);
(self.def.vtable.insert)(self.value.data_mut(), key_ptr, value_ptr);
}
Ok(())
}
pub fn insert_from_heap<const KB: bool, const VB: bool>(
&mut self,
key: HeapValue<'facet, KB>,
value: HeapValue<'facet, VB>,
) -> Result<(), ReflectError> {
if self.def.k() != key.shape() {
return Err(self.err(ReflectErrorKind::WrongShape {
expected: self.def.k(),
actual: key.shape(),
}));
}
if self.def.v() != value.shape() {
return Err(self.err(ReflectErrorKind::WrongShape {
expected: self.def.v(),
actual: value.shape(),
}));
}
let mut key = key;
let mut value = value;
let key_guard = key.guard.take().expect("key HeapValue guard already taken");
let value_guard = value
.guard
.take()
.expect("value HeapValue guard already taken");
unsafe {
let key_ptr = facet_core::PtrMut::new(key_guard.ptr.as_ptr());
let value_ptr = facet_core::PtrMut::new(value_guard.ptr.as_ptr());
(self.def.vtable.insert)(self.value.data_mut(), key_ptr, value_ptr);
}
drop(key_guard);
drop(value_guard);
Ok(())
}
#[inline]
pub fn iter(&self) -> crate::PeekMapIter<'_, 'facet> {
self.as_peek_map().iter()
}
#[inline]
pub const fn def(&self) -> MapDef {
self.def
}
#[inline]
pub fn into_inner(self) -> Poke<'mem, 'facet> {
self.value
}
#[inline]
pub fn as_peek_map(&self) -> crate::PeekMap<'_, 'facet> {
unsafe { crate::PeekMap::new(self.value.as_peek(), self.def) }
}
}
#[cfg(test)]
mod tests {
use alloc::collections::BTreeMap;
use super::*;
#[test]
fn poke_map_len_and_insert() {
let mut m: BTreeMap<String, i32> = BTreeMap::new();
let poke = Poke::new(&mut m);
let mut map = poke.into_map().unwrap();
assert_eq!(map.len(), 0);
map.insert(String::from("one"), 1i32).unwrap();
map.insert(String::from("two"), 2i32).unwrap();
assert_eq!(map.len(), 2);
assert_eq!(m.get("one"), Some(&1));
assert_eq!(m.get("two"), Some(&2));
}
#[test]
fn poke_map_contains_and_get() {
let mut m: BTreeMap<String, i32> = BTreeMap::new();
m.insert(String::from("a"), 10);
let poke = Poke::new(&mut m);
let map = poke.into_map().unwrap();
let key = String::from("a");
assert!(map.contains_key(&key).unwrap());
let v = map.get(&key).unwrap().unwrap();
assert_eq!(*v.get::<i32>().unwrap(), 10);
}
#[test]
fn poke_map_insert_from_heap() {
let mut m: BTreeMap<String, i32> = BTreeMap::new();
let poke = Poke::new(&mut m);
let mut map = poke.into_map().unwrap();
let key = crate::Partial::alloc::<String>()
.unwrap()
.set(String::from("k"))
.unwrap()
.build()
.unwrap();
let value = crate::Partial::alloc::<i32>()
.unwrap()
.set(42i32)
.unwrap()
.build()
.unwrap();
map.insert_from_heap(key, value).unwrap();
assert_eq!(m.get("k"), Some(&42));
}
}