#![forbid(unsafe_code)]
use alloc::vec::Vec;
use core::iter::Peekable;
use super::BBTreeMap;
use crate::allocator::{Allocator, Global};
use crate::inline_key::InlineKeyStrategy;
use crate::tree::build::TreeBuilder;
use crate::tree::root::Tree;
impl<K: Ord, V> BBTreeMap<K, V> {
fn from_sorted_keeping_last(entries: impl Iterator<Item = (K, V)>) -> Self {
let entries = LastOfEqualKeys {
entries: entries.peekable(),
};
Self::from_ascending_entries(entries, Global)
}
}
impl<K, V, S: InlineKeyStrategy<K>, A: Allocator + Clone> BBTreeMap<K, V, S, A> {
#[inline(never)]
fn extend_batches(&mut self, entries: impl Iterator<Item = (K, V)>)
where
K: Ord,
{
let mut entries = entries.fuse();
loop {
let batch: [_; 16] = core::array::from_fn(|_| entries.next());
if batch[15].is_none() {
for (key, value) in batch.into_iter().flatten() {
self.tree.insert(key, value, &self.alloc, &mut self.length);
}
return;
}
self.insert_many(batch.map(|entry| entry.expect("a full batch")));
}
}
pub(crate) fn from_ascending_entries(entries: impl Iterator<Item = (K, V)>, alloc: A) -> Self {
let mut builder = TreeBuilder::new(&alloc);
builder.extend(entries);
let (tree, length) = builder.finish();
Self {
tree,
length,
alloc,
}
}
}
struct LastOfEqualKeys<I: Iterator> {
entries: Peekable<I>,
}
impl<K: PartialEq, V, I: Iterator<Item = (K, V)>> Iterator for LastOfEqualKeys<I> {
type Item = (K, V);
fn next(&mut self) -> Option<(K, V)> {
loop {
let entry = self.entries.next()?;
if self.entries.peek().is_none_or(|next| next.0 != entry.0) {
return Some(entry);
}
}
}
}
impl<K: Ord, V> FromIterator<(K, V)> for BBTreeMap<K, V> {
fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
let mut entries: Vec<(K, V)> = iter.into_iter().collect();
entries.sort_by(|a, b| a.0.cmp(&b.0));
Self::from_sorted_keeping_last(entries.into_iter())
}
}
impl<K: Ord, V, const N: usize> From<[(K, V); N]> for BBTreeMap<K, V> {
fn from(mut entries: [(K, V); N]) -> Self {
entries.sort_by(|a, b| a.0.cmp(&b.0));
Self::from_sorted_keeping_last(entries.into_iter())
}
}
impl<K: Ord, V, S: InlineKeyStrategy<K>, A: Allocator + Clone> Extend<(K, V)>
for BBTreeMap<K, V, S, A>
{
fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
let mut entries = iter.into_iter();
if core::mem::size_of::<[Option<(K, V)>; 16]>() > 4096
|| entries.size_hint().1.is_some_and(|remaining| {
!Tree::<K, V, S>::batches(self.length.saturating_add(remaining))
})
{
for (key, value) in entries {
self.tree.insert(key, value, &self.alloc, &mut self.length);
}
return;
}
while !Tree::<K, V, S>::batches(self.length) {
let Some((key, value)) = entries.next() else {
return;
};
self.tree.insert(key, value, &self.alloc, &mut self.length);
}
self.extend_batches(entries);
}
}
impl<'a, K: Ord + Copy, V: Copy, S: InlineKeyStrategy<K>, A: Allocator + Clone>
Extend<(&'a K, &'a V)> for BBTreeMap<K, V, S, A>
{
fn extend<T: IntoIterator<Item = (&'a K, &'a V)>>(&mut self, iter: T) {
self.extend(iter.into_iter().map(|(&key, &value)| (key, value)));
}
}