#[cfg(feature = "validation")]
pub mod validation;
use crate::{Archive, ArchivePointee, Archived, RelPtr};
use core::{
borrow::Borrow,
cmp::Ordering,
fmt,
hash::{Hash, Hasher},
iter::FusedIterator,
marker::PhantomData,
ops::Index,
ptr::NonNull,
};
use ptr_meta::Pointee;
#[cfg_attr(feature = "strict", repr(C))]
struct InnerNodeEntry<K> {
ptr: RelPtr<NodeHeader>,
key: K,
}
#[cfg_attr(feature = "strict", repr(C))]
struct LeafNodeEntry<K, V> {
key: K,
value: V,
}
impl<'a, UK: Archive, UV: Archive> Archive for LeafNodeEntry<&'a UK, &'a UV> {
type Archived = LeafNodeEntry<UK::Archived, UV::Archived>;
type Resolver = (UK::Resolver, UV::Resolver);
#[inline]
unsafe fn resolve(&self, pos: usize, resolver: Self::Resolver, out: *mut Self::Archived) {
let (fp, fo) = out_field!(out.key);
self.key.resolve(pos + fp, resolver.0, fo);
let (fp, fo) = out_field!(out.value);
self.value.resolve(pos + fp, resolver.1, fo);
}
}
#[cfg_attr(feature = "strict", repr(C))]
struct NodeHeader {
meta: Archived<u16>,
size: Archived<usize>,
ptr: RelPtr<NodeHeader>,
}
impl NodeHeader {
#[inline]
fn is_inner(&self) -> bool {
split_meta(from_archived!(self.meta)).0
}
#[inline]
fn is_leaf(&self) -> bool {
!split_meta(from_archived!(self.meta)).0
}
#[inline]
fn len(&self) -> usize {
split_meta(from_archived!(self.meta)).1
}
}
#[inline]
#[cfg(feature = "alloc")]
fn combine_meta(is_inner: bool, len: usize) -> u16 {
if is_inner {
0x80_00 | len as u16
} else {
len as u16
}
}
#[inline]
fn split_meta(meta: u16) -> (bool, usize) {
(meta & 0x80_00 == 0x80_00, (meta & 0x7F_FF) as usize)
}
#[cfg_attr(feature = "strict", repr(C))]
struct Node<T: ?Sized> {
header: NodeHeader,
tail: T,
}
impl<T> Pointee for Node<[T]> {
type Metadata = usize;
}
impl<T> ArchivePointee for Node<[T]> {
type ArchivedMetadata = Archived<usize>;
#[inline]
fn pointer_metadata(archived: &Self::ArchivedMetadata) -> <Self as Pointee>::Metadata {
from_archived!(*archived) as usize
}
}
type InnerNode<K> = Node<[InnerNodeEntry<K>]>;
type LeafNode<K, V> = Node<[LeafNodeEntry<K, V>]>;
struct NodeHeaderData {
meta: u16,
size: usize,
pos: Option<usize>,
}
impl Archive for NodeHeaderData {
type Archived = NodeHeader;
type Resolver = ();
#[inline]
unsafe fn resolve(&self, pos: usize, _: Self::Resolver, out: *mut Self::Archived) {
let (fp, fo) = out_field!(out.meta);
self.meta.resolve(pos + fp, (), fo);
let (fp, fo) = out_field!(out.size);
self.size.resolve(pos + fp, (), fo);
let (fp, fo) = out_field!(out.ptr);
RelPtr::emplace(pos + fp, self.pos.unwrap_or(pos + fp), fo);
}
}
struct InnerNodeEntryData<'a, UK> {
key: &'a UK,
}
impl<'a, UK: Archive> Archive for InnerNodeEntryData<'a, UK> {
type Archived = InnerNodeEntry<UK::Archived>;
type Resolver = (usize, UK::Resolver);
#[inline]
unsafe fn resolve(&self, pos: usize, resolver: Self::Resolver, out: *mut Self::Archived) {
let (fp, fo) = out_field!(out.ptr);
RelPtr::emplace(pos + fp, resolver.0, fo);
let (fp, fo) = out_field!(out.key);
self.key.resolve(pos + fp, resolver.1, fo);
}
}
enum ClassifiedNode<'a, K, V> {
Inner(&'a InnerNode<K>),
Leaf(&'a LeafNode<K, V>),
}
impl NodeHeader {
#[inline]
fn classify<K, V>(&self) -> ClassifiedNode<'_, K, V> {
if self.is_inner() {
ClassifiedNode::Inner(self.classify_inner())
} else {
ClassifiedNode::Leaf(self.classify_leaf())
}
}
#[inline]
fn classify_inner_ptr<K>(&self) -> *const InnerNode<K> {
ptr_meta::from_raw_parts(self as *const Self as *const (), self.len() as usize)
}
#[inline]
fn classify_inner<K>(&self) -> &'_ InnerNode<K> {
debug_assert!(self.is_inner());
unsafe { &*self.classify_inner_ptr() }
}
#[inline]
fn classify_leaf_ptr<K, V>(&self) -> *const LeafNode<K, V> {
ptr_meta::from_raw_parts(self as *const Self as *const (), self.len() as usize)
}
#[inline]
fn classify_leaf<K, V>(&self) -> &'_ LeafNode<K, V> {
debug_assert!(self.is_leaf());
unsafe { &*self.classify_leaf_ptr() }
}
}
#[cfg_attr(feature = "strict", repr(C))]
pub struct ArchivedBTreeMap<K, V> {
len: Archived<usize>,
root: RelPtr<NodeHeader>,
_phantom: PhantomData<(K, V)>,
}
pub struct BTreeMapResolver {
root_pos: usize,
}
pub const MIN_ENTRIES_PER_LEAF_NODE: usize = 1;
pub const MIN_ENTRIES_PER_INNER_NODE: usize = 2;
impl<K, V> ArchivedBTreeMap<K, V> {
#[inline]
fn root(&self) -> Option<ClassifiedNode<K, V>> {
if self.is_empty() {
None
} else {
let root = unsafe { &*self.root.as_ptr() };
Some(root.classify())
}
}
#[inline]
fn first(&self) -> NonNull<NodeHeader> {
if let Some(mut node) = self.root() {
while let ClassifiedNode::Inner(inner) = node {
let next = unsafe { &*inner.header.ptr.as_ptr() };
node = next.classify();
}
match node {
ClassifiedNode::Leaf(leaf) => unsafe {
let node = (leaf as *const LeafNode<K, V> as *mut LeafNode<K, V>).cast();
NonNull::new_unchecked(node)
},
ClassifiedNode::Inner(_) => unsafe { core::hint::unreachable_unchecked() },
}
} else {
NonNull::dangling()
}
}
#[inline]
pub fn contains_key<Q: Ord + ?Sized>(&self, key: &Q) -> bool
where
K: Borrow<Q> + Ord,
{
self.get_key_value(key).is_some()
}
#[inline]
pub fn get<Q: Ord + ?Sized>(&self, key: &Q) -> Option<&V>
where
K: Borrow<Q> + Ord,
{
self.get_key_value(key).map(|(_, v)| v)
}
pub fn get_key_value<Q: Ord + ?Sized>(&self, k: &Q) -> Option<(&K, &V)>
where
K: Borrow<Q> + Ord,
{
if let Some(mut current) = self.root() {
loop {
match current {
ClassifiedNode::Inner(node) => {
let next = match node
.tail
.binary_search_by(|probe| probe.key.borrow().cmp(k))
{
Ok(i) => unsafe { &*node.tail[i].ptr.as_ptr() },
Err(i) => {
if i == 0 {
unsafe { &*node.header.ptr.as_ptr() }
} else {
unsafe { &*node.tail[i - 1].ptr.as_ptr() }
}
}
};
current = next.classify();
}
ClassifiedNode::Leaf(node) => {
if let Ok(i) = node
.tail
.binary_search_by(|probe| probe.key.borrow().cmp(k))
{
let entry = &node.tail[i];
break Some((&entry.key, &entry.value));
} else {
break None;
}
}
}
}
} else {
None
}
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub fn iter(&self) -> Iter<'_, K, V> {
Iter {
inner: RawIter::new(self.first(), 0, self.len()),
}
}
#[inline]
pub fn keys(&self) -> Keys<'_, K, V> {
Keys {
inner: RawIter::new(self.first(), 0, self.len()),
}
}
#[inline]
pub fn len(&self) -> usize {
from_archived!(self.len) as usize
}
#[inline]
pub fn values(&self) -> Values<'_, K, V> {
Values {
inner: RawIter::new(self.first(), 0, self.len()),
}
}
#[inline]
pub unsafe fn resolve_from_len(
len: usize,
pos: usize,
resolver: BTreeMapResolver,
out: *mut Self,
) {
let (fp, fo) = out_field!(out.len);
len.resolve(pos + fp, (), fo);
let (fp, fo) = out_field!(out.root);
RelPtr::emplace(pos + fp, resolver.root_pos, fo);
}
}
#[cfg(feature = "alloc")]
const _: () = {
use crate::{ser::Serializer, Serialize};
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
use core::mem;
impl<K, V> ArchivedBTreeMap<K, V> {
pub unsafe fn serialize_from_reverse_iter<'a, UK, UV, S, I>(
mut iter: I,
serializer: &mut S,
) -> Result<BTreeMapResolver, S::Error>
where
UK: 'a + Serialize<S, Archived = K>,
UV: 'a + Serialize<S, Archived = V>,
S: Serializer + ?Sized,
I: ExactSizeIterator<Item = (&'a UK, &'a UV)>,
{
if iter.len() == 0 {
Ok(BTreeMapResolver { root_pos: 0 })
} else {
const MAX_NODE_SIZE: usize = 4096;
let mut next_level = Vec::new();
let mut resolvers = Vec::new();
while let Some((key, value)) = iter.next() {
let block_start_pos = serializer.pos();
resolvers.push((
key,
value,
key.serialize(serializer)?,
value.serialize(serializer)?,
));
loop {
let estimated_block_size = serializer.pos() - block_start_pos
+ mem::size_of::<NodeHeader>()
+ resolvers.len() * mem::size_of::<LeafNodeEntry<K, V>>();
if estimated_block_size >= MAX_NODE_SIZE
&& resolvers.len() >= MIN_ENTRIES_PER_LEAF_NODE
{
break;
}
if let Some((key, value)) = iter.next() {
resolvers.push((
key,
value,
key.serialize(serializer)?,
value.serialize(serializer)?,
));
} else {
break;
}
}
serializer.align(usize::max(
mem::align_of::<NodeHeader>(),
mem::align_of::<LeafNodeEntry<K, V>>(),
))?;
let raw_node = NodeHeaderData {
meta: combine_meta(false, resolvers.len()),
size: serializer.pos() - block_start_pos,
pos: next_level.last().map(|&(_, pos)| pos),
};
next_level.push((
resolvers.last().unwrap().0,
serializer.resolve_aligned(&raw_node, ())?,
));
serializer.align_for::<LeafNodeEntry<K, V>>()?;
for (key, value, key_resolver, value_resolver) in resolvers.drain(..).rev() {
serializer.resolve_aligned(
&LeafNodeEntry { key, value },
(key_resolver, value_resolver),
)?;
}
}
let mut current_level = Vec::new();
let mut resolvers = Vec::new();
while next_level.len() > 1 {
mem::swap(&mut current_level, &mut next_level);
let mut iter = current_level.drain(..);
while iter.len() > 1 {
let block_start_pos = serializer.pos();
while iter.len() > 1 {
let (key, pos) = iter.next().unwrap();
resolvers.push((key, pos, key.serialize(serializer)?));
let estimated_block_size = serializer.pos() - block_start_pos
+ mem::size_of::<NodeHeader>()
+ resolvers.len() * mem::size_of::<InnerNodeEntry<K>>();
if estimated_block_size >= MAX_NODE_SIZE
&& resolvers.len() >= MIN_ENTRIES_PER_INNER_NODE
{
break;
}
}
if iter.len() == 2 {
let (key, pos) = iter.next().unwrap();
resolvers.push((key, pos, key.serialize(serializer)?));
}
let (first_key, first_pos) = iter.next().unwrap();
serializer.align(usize::max(
mem::align_of::<NodeHeaderData>(),
mem::align_of::<InnerNodeEntry<K>>(),
))?;
let node_header = NodeHeaderData {
meta: combine_meta(true, resolvers.len()),
size: serializer.pos() - block_start_pos,
pos: Some(first_pos),
};
next_level.push((first_key, serializer.resolve_aligned(&node_header, ())?));
serializer.align_for::<InnerNodeEntry<K>>()?;
for (key, pos, resolver) in resolvers.drain(..).rev() {
let inner_node_data = InnerNodeEntryData::<UK> { key };
serializer.resolve_aligned(&inner_node_data, (pos, resolver))?;
}
}
debug_assert!(iter.len() == 0);
}
Ok(BTreeMapResolver {
root_pos: next_level[0].1,
})
}
}
}
};
impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for ArchivedBTreeMap<K, V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_map().entries(self.iter()).finish()
}
}
impl<K, Q, V> Index<&'_ Q> for ArchivedBTreeMap<K, V>
where
K: Borrow<Q> + Ord,
Q: Ord + ?Sized,
{
type Output = V;
fn index(&self, key: &Q) -> &V {
self.get(key).unwrap()
}
}
impl<'a, K, V> IntoIterator for &'a ArchivedBTreeMap<K, V> {
type Item = (&'a K, &'a V);
type IntoIter = Iter<'a, K, V>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<K: Eq, V: Eq> Eq for ArchivedBTreeMap<K, V> {}
impl<K: Hash, V: Hash> Hash for ArchivedBTreeMap<K, V> {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
for pair in self.iter() {
pair.hash(state);
}
}
}
impl<K: Ord, V: Ord> Ord for ArchivedBTreeMap<K, V> {
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
self.iter().cmp(other.iter())
}
}
impl<K: PartialEq, V: PartialEq> PartialEq for ArchivedBTreeMap<K, V> {
#[inline]
fn eq(&self, other: &Self) -> bool {
if self.len() != other.len() {
false
} else {
self.iter().zip(other.iter()).all(|(a, b)| a.eq(&b))
}
}
}
impl<K: PartialOrd, V: PartialOrd> PartialOrd for ArchivedBTreeMap<K, V> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.iter().partial_cmp(other.iter())
}
}
struct RawIter<'a, K, V> {
leaf: NonNull<NodeHeader>,
index: usize,
remaining: usize,
_phantom: PhantomData<(&'a K, &'a V)>,
}
impl<'a, K, V> RawIter<'a, K, V> {
fn new(leaf: NonNull<NodeHeader>, index: usize, remaining: usize) -> Self {
Self {
leaf,
index,
remaining,
_phantom: PhantomData,
}
}
}
impl<'a, K, V> Iterator for RawIter<'a, K, V> {
type Item = (&'a K, &'a V);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.remaining == 0 {
None
} else {
unsafe {
let leaf = self.leaf.as_ref().classify_leaf::<K, V>();
if self.index == leaf.tail.len() {
self.index = 0;
self.leaf = NonNull::new_unchecked(leaf.header.ptr.as_ptr() as *mut _);
}
let result = &self.leaf.as_ref().classify_leaf().tail[self.index];
self.index += 1;
self.remaining -= 1;
Some((&result.key, &result.value))
}
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.remaining, Some(self.remaining))
}
}
impl<'a, K, V> ExactSizeIterator for RawIter<'a, K, V> {}
impl<'a, K, V> FusedIterator for RawIter<'a, K, V> {}
pub struct Iter<'a, K, V> {
inner: RawIter<'a, K, V>,
}
impl<'a, K, V> Iterator for Iter<'a, K, V> {
type Item = (&'a K, &'a V);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {}
impl<'a, K, V> FusedIterator for Iter<'a, K, V> {}
pub struct Keys<'a, K, V> {
inner: RawIter<'a, K, V>,
}
impl<'a, K, V> Iterator for Keys<'a, K, V> {
type Item = &'a K;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(|(k, _)| k)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> {}
impl<'a, K, V> FusedIterator for Keys<'a, K, V> {}
pub struct Values<'a, K, V> {
inner: RawIter<'a, K, V>,
}
impl<'a, K, V> Iterator for Values<'a, K, V> {
type Item = &'a V;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(|(_, v)| v)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> {}
impl<'a, K, V> FusedIterator for Values<'a, K, V> {}