use super::{Nothing, PushedVal};
trait IntoPo {
type Po;
fn into_po(self) -> Option<Self::Po>;
}
impl<T> IntoPo for Option<T> {
type Po = T;
#[inline]
fn into_po(self) -> Option<T> {
self
}
}
impl IntoPo for bool {
type Po = PushedVal;
#[inline]
fn into_po(self) -> Option<PushedVal> {
if self { None } else { Some(PushedVal) }
}
}
impl IntoPo for () {
type Po = Nothing;
#[inline]
fn into_po(self) -> Option<Self::Po> {
None
}
}
#[cfg(feature = "alloc")]
macro_rules! do_impl {
(CanPush for $impl_for:ty, $t:ty, $po:ty; $($gen:tt)*) => {
impl<$($gen)*> $crate::base::CanPush<$t> for $impl_for {
type PushedOut = $po;
}
};
(Push for $impl_for:ty, $method:path, $t:ty, $po:ty; $($gen:tt)*) => {
do_impl!(CanPush for $impl_for, $t, $po; $($gen)*);
impl<$($gen)*> $crate::base::Push<$t> for $impl_for {
fn push(&mut self, val: $t) -> Option<Self::PushedOut> {
$crate::impls::IntoPo::into_po($method(self, val))
}
}
};
(keyval Push for $impl_for:ty, $method:path, $t:ty, $po:ty; $($gen:tt)*) => {
do_impl!(CanPush for $impl_for, $t, $po; $($gen)*);
impl<$($gen)*> $crate::base::Push<$t> for $impl_for {
fn push(&mut self, (key, val): $t) -> Option<Self::PushedOut> {
$crate::impls::IntoPo::into_po($method(self, key, val))
}
}
};
(PushSorted for $impl_for:ty, $method:path, $t:ty, $po:ty; $($gen:tt)*) => {
do_impl!(CanPush for $impl_for, $t, $po; $($gen)*);
impl<$($gen)*> $crate::sorted::PushSorted<$t> for $impl_for {
fn push_sorted(&mut self, val: $t) -> Option<Self::PushedOut> {
$crate::impls::IntoPo::into_po($method(self, val))
}
}
};
(keyval PushSorted for $impl_for:ty, $method:path, $t:ty, $po:ty; $($gen:tt)*) => {
do_impl!(CanPush for $impl_for, $t, $po; $($gen)*);
impl<$($gen)*> $crate::sorted::PushSorted<$t> for $impl_for {
fn push_sorted(&mut self, (key, val): $t) -> Option<Self::PushedOut> {
$crate::impls::IntoPo::into_po($method(self, key, val))
}
}
};
(PushBack for $impl_for:ty, $method:path, $t:ty, $po:ty; $($gen:tt)*) => {
do_impl!(Push for $impl_for, $method, $t, $po; $($gen)*);
impl<$($gen)*> $crate::ordered::PushBack<$t> for $impl_for { }
};
(keyval PushBack for $impl_for:ty, $method:path, $t:ty, $po:ty; $($gen:tt)*) => {
do_impl!(keyval Push for $impl_for, $method, $t, $po; $($gen)*);
impl<$($gen)*> $crate::ordered::PushBack<$t> for $impl_for { }
};
(PushFront for $impl_for:ty, $method:path, $t:ty, $po:ty; $($gen:tt)*) => {
impl<$($gen)*> $crate::ordered::PushFront<$t> for $impl_for {
fn push_front(&mut self, val: $t) -> Option<Self::PushedOut> {
$crate::impls::IntoPo::into_po($method(self, val))
}
}
};
(Insert for $impl_for:ty, $method:path, $t:ty, $po:ty; $($gen:tt)*) => {
impl<$($gen)*> $crate::ordered::Insert<$t> for $impl_for {
fn insert(&mut self, index: usize, val: $t) -> Option<Self::PushedOut> {
$crate::impls::IntoPo::into_po($method(self, index, val))
}
}
};
(Append for $impl_for:ty, $method:path; $($gen:tt)*) => {
impl<$($gen)*> $crate::append::Append for $impl_for {
fn append(&mut self, val: &mut Self) {
$method(self, val)
}
}
};
(AppendBack for $impl_for:ty, $method:path; $($gen:tt)*) => {
do_impl!(Append for $impl_for, $method; $($gen)*);
impl<$($gen)*> $crate::append::AppendBack for $impl_for {}
impl<$($gen)*> $crate::append::AppendFront for $impl_for {}
};
}
#[cfg_attr(feature = "cargo-clippy", allow(linkedlist))]
cfg_if! {
if #[cfg(feature = "alloc")] {
cfg_if! {
if #[cfg(feature = "std")] {
use std::collections;
} else {
use alloc::{self as collections, String, Vec};
}
}
use self::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
do_impl!(Append for BTreeSet<T>, BTreeSet::append; T: Ord);
do_impl!(PushSorted for BTreeSet<T>, BTreeSet::insert, T, super::PushedVal; T: Ord);
do_impl!(Append for BinaryHeap<T>, BinaryHeap::append; T: Ord);
do_impl!(PushSorted for BinaryHeap<T>, BinaryHeap::push, T, super::Nothing; T: Ord);
do_impl!(Append for BTreeMap<K, V>, BTreeMap::append; K: Ord, V);
do_impl!(keyval PushSorted for BTreeMap<K, V>, BTreeMap::insert, (K, V), V; K: Ord, V);
do_impl!(AppendBack for LinkedList<T>, LinkedList::append; T);
do_impl!(PushBack for LinkedList<T>, LinkedList::push_back, T, super::Nothing; T);
do_impl!(PushFront for LinkedList<T>, LinkedList::push_front, T, super::Nothing; T);
do_impl!(AppendBack for String, string_append; );
do_impl!(PushBack for String, String::push, char, super::Nothing; );
do_impl!(PushBack for String, String::push_str, &'a str, super::Nothing; 'a);
do_impl!(Insert for String, String::insert, char, super::Nothing; );
do_impl!(Insert for String, String::insert_str, &'a str, super::Nothing; 'a);
fn string_append(lhs: &mut String, rhs: &mut String) {
lhs.push_str(rhs);
rhs.clear();
}
do_impl!(AppendBack for Vec<T>, Vec::append; T);
do_impl!(PushBack for Vec<T>, Vec::push, T, super::Nothing; T);
do_impl!(PushBack for Vec<u8>, push_utf8_char, char, super::Nothing; );
do_impl!(PushBack for Vec<u16>, push_utf16_char, char, super::Nothing; );
do_impl!(PushBack for Vec<u32>, push_utf32_char, char, super::Nothing; );
do_impl!(PushBack for Vec<T>,
Vec::extend_from_slice, &'a [T], super::Nothing; 'a, T: 'a + Clone);
do_impl!(Insert for Vec<T>, Vec::insert, T, super::Nothing; T);
do_impl!(Insert for Vec<u32>, insert_utf32_char, char, super::Nothing; );
fn push_utf8_char(lhs: &mut Vec<u8>, rhs: char) {
let mut buf = [0; 4];
Vec::extend_from_slice(lhs, rhs.encode_utf8(&mut buf).as_bytes())
}
fn push_utf16_char(lhs: &mut Vec<u16>, rhs: char) {
let mut buf = [0; 2];
Vec::extend_from_slice(lhs, rhs.encode_utf16(&mut buf))
}
fn push_utf32_char(lhs: &mut Vec<u32>, rhs: char) {
Vec::push(lhs, rhs as u32)
}
fn insert_utf32_char(lhs: &mut Vec<u32>, index: usize, rhs: char) {
Vec::insert(lhs, index, rhs as u32)
}
cfg_if! {
if #[cfg(feature = "nightly")] {
do_impl!(Insert for Vec<u8>, insert_utf8_char, char, super::Nothing; );
do_impl!(Insert for Vec<u16>, insert_utf16_char, char, super::Nothing; );
do_impl!(Insert for Vec<T>,
insert_slice, &'a [T], super::Nothing; 'a, T: 'a + Clone);
fn insert_utf8_char(lhs: &mut Vec<u8>, index: usize, rhs: char) {
let mut buf = [0; 4];
Vec::splice(lhs, index..index, rhs.encode_utf8(&mut buf).bytes());
}
fn insert_utf16_char(lhs: &mut Vec<u16>, index: usize, rhs: char) {
let mut buf = [0; 2];
Vec::splice(lhs, index..index, rhs.encode_utf16(&mut buf).iter().cloned());
}
fn insert_slice<T: Clone>(lhs: &mut Vec<T>, index: usize, rhs: &[T]) {
Vec::splice(lhs, index..index, rhs.iter().cloned());
}
}
}
do_impl!(AppendBack for VecDeque<T>, VecDeque::append; T);
do_impl!(PushBack for VecDeque<T>, VecDeque::push_back, T, super::Nothing; T);
do_impl!(PushFront for VecDeque<T>, VecDeque::push_front, T, super::Nothing; T);
do_impl!(Insert for VecDeque<T>, VecDeque::insert, T, super::Nothing; T);
}
}
cfg_if! {
if #[cfg(feature = "std")] {
use std::collections::{HashMap, HashSet};
use std::ffi::{OsStr, OsString};
use std::hash::Hash;
do_impl!(AppendBack for OsString, os_string_append; );
do_impl!(PushBack for OsString, OsString::push, &'a OsStr, super::Nothing; 'a);
do_impl!(PushBack for OsString, OsString::push, &'a str, super::Nothing; 'a);
fn os_string_append(lhs: &mut OsString, rhs: &mut OsString) {
lhs.push(&rhs);
rhs.clear();
}
do_impl!(keyval Push for HashMap<K, V>, HashMap::insert, (K, V), V; K: Hash + Eq, V);
do_impl!(Push for HashSet<T>, HashSet::insert, T, super::PushedVal; T: Hash + Eq);
}
}