/*
 * Copyright 2019 The Starlark in Rust Authors.
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

use dupe::Clone_;

use crate::iter::def_double_ended_iter;
use crate::iter::def_iter;
use crate::vec_map;
use crate::Hashed;

/// Iterator over the hashed entries of [`SmallMap`](crate::small_map::SmallMap).
#[derive(Clone_)]
pub struct IterHashed<'a, K, V> {
    pub(crate) iter: vec_map::IterHashed<'a, K, V>,
}

impl<'a, K, V> IterHashed<'a, K, V> {
    #[inline]
    fn map((k, v): (Hashed<&'a K>, &'a V)) -> <Self as Iterator>::Item {
        (k, v)
    }
}

impl<'a, K, V> Iterator for IterHashed<'a, K, V> {
    type Item = (Hashed<&'a K>, &'a V);

    def_iter!();
}

impl<'a, K, V> ExactSizeIterator for IterHashed<'a, K, V> {
    #[inline]
    fn len(&self) -> usize {
        self.iter.len()
    }
}

impl<'a, K, V> DoubleEndedIterator for IterHashed<'a, K, V> {
    def_double_ended_iter!();
}

/// Iterator over a small map entry references.
#[derive(Clone_)]
pub struct Iter<'a, K, V> {
    pub(crate) iter: vec_map::Iter<'a, K, V>,
}

impl<'a, K, V> Iter<'a, K, V> {
    #[inline]
    fn map((k, v): (&'a K, &'a V)) -> <Self as Iterator>::Item {
        (k, v)
    }
}

impl<'a, K, V> Iterator for Iter<'a, K, V> {
    type Item = (&'a K, &'a V);

    def_iter!();
}

impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {
    #[inline]
    fn len(&self) -> usize {
        self.iter.len()
    }
}

impl<'a, K, V> DoubleEndedIterator for Iter<'a, K, V> {
    def_double_ended_iter!();
}

/// Iterator over a small map mutable entry references.
pub struct IterMut<'a, K, V> {
    pub(crate) iter: vec_map::IterMut<'a, K, V>,
}

/// Iterator over a small map mutable entry references.
///
/// This iterator provides mutable references to keys, not just to values.
pub struct IterMutUnchecked<'a, K, V> {
    pub(crate) iter: vec_map::IterMutUnchecked<'a, K, V>,
}

impl<'a, K, V> IterMut<'a, K, V> {
    #[inline]
    fn map((k, v): (&'a K, &'a mut V)) -> <Self as Iterator>::Item {
        (k, v)
    }
}

impl<'a, K, V> IterMutUnchecked<'a, K, V> {
    #[inline]
    fn map((k, v): (&'a mut K, &'a mut V)) -> <Self as Iterator>::Item {
        (k, v)
    }
}

impl<'a, K, V> Iterator for IterMut<'a, K, V> {
    type Item = (&'a K, &'a mut V);

    def_iter!();
}

impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> {
    #[inline]
    fn len(&self) -> usize {
        self.iter.len()
    }
}

impl<'a, K, V> DoubleEndedIterator for IterMut<'a, K, V> {
    def_double_ended_iter!();
}

impl<'a, K, V> Iterator for IterMutUnchecked<'a, K, V> {
    type Item = (&'a mut K, &'a mut V);

    def_iter!();
}

impl<'a, K, V> ExactSizeIterator for IterMutUnchecked<'a, K, V> {
    #[inline]
    fn len(&self) -> usize {
        self.iter.len()
    }
}

impl<'a, K, V> DoubleEndedIterator for IterMutUnchecked<'a, K, V> {
    def_double_ended_iter!();
}

/// Iterator that moves hashed entries out of a [`SmallMap`](crate::small_map::SmallMap).
pub struct IntoIterHashed<K, V> {
    pub(crate) iter: vec_map::IntoIterHashed<K, V>,
}

impl<K, V> IntoIterHashed<K, V> {
    #[inline]
    fn map((k, v): (Hashed<K>, V)) -> <Self as Iterator>::Item {
        (k, v)
    }
}

impl<K, V> Iterator for IntoIterHashed<K, V> {
    type Item = (Hashed<K>, V);

    def_iter!();
}

impl<K, V> ExactSizeIterator for IntoIterHashed<K, V> {
    #[inline]
    fn len(&self) -> usize {
        self.iter.len()
    }
}

impl<K, V> DoubleEndedIterator for IntoIterHashed<K, V> {
    def_double_ended_iter!();
}

/// Iterator that moves entries out of a [`SmallMap`](crate::small_map::SmallMap).
pub struct IntoIter<K, V> {
    pub(crate) iter: vec_map::IntoIter<K, V>,
}

impl<K, V> IntoIter<K, V> {
    #[inline]
    fn map((k, v): (K, V)) -> <Self as Iterator>::Item {
        (k, v)
    }
}

impl<K, V> Iterator for IntoIter<K, V> {
    type Item = (K, V);

    def_iter!();
}

impl<K, V> ExactSizeIterator for IntoIter<K, V> {
    #[inline]
    fn len(&self) -> usize {
        self.iter.len()
    }
}

impl<K, V> DoubleEndedIterator for IntoIter<K, V> {
    def_double_ended_iter!();
}

/// Iterator over a [`SmallMap`](crate::small_map::SmallMap) keys.
#[derive(Clone_)]
pub struct Keys<'a, K, V> {
    pub(crate) iter: vec_map::Keys<'a, K, V>,
}

impl<'a, K, V> Keys<'a, K, V> {
    #[inline]
    fn map(k: &'a K) -> <Self as Iterator>::Item {
        k
    }
}

impl<'a, K, V> Iterator for Keys<'a, K, V> {
    type Item = &'a K;

    def_iter!();
}

impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> {
    #[inline]
    fn len(&self) -> usize {
        self.iter.len()
    }
}

impl<'a, K, V> DoubleEndedIterator for Keys<'a, K, V> {
    def_double_ended_iter!();
}

/// Iterator over a [`SmallMap`](crate::small_map::SmallMap) values.
#[derive(Clone_)]
pub struct Values<'a, K, V> {
    pub(crate) iter: vec_map::Values<'a, K, V>,
}

impl<'a, K, V> Values<'a, K, V> {
    #[inline]
    fn map(v: &'a V) -> <Self as Iterator>::Item {
        v
    }
}

impl<'a, K, V> Iterator for Values<'a, K, V> {
    type Item = &'a V;

    def_iter!();
}

impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> {
    #[inline]
    fn len(&self) -> usize {
        self.iter.len()
    }
}

impl<'a, K, V> DoubleEndedIterator for Values<'a, K, V> {
    def_double_ended_iter!();
}

/// Iterator that moves keys out of [`SmallMap`](crate::small_map::SmallMap).
pub struct IntoKeys<K, V> {
    pub(crate) iter: vec_map::IntoIter<K, V>,
}

impl<K, V> IntoKeys<K, V> {
    #[inline]
    fn map((k, _): (K, V)) -> <Self as Iterator>::Item {
        k
    }
}

impl<K, V> Iterator for IntoKeys<K, V> {
    type Item = K;

    def_iter!();
}

impl<K, V> ExactSizeIterator for IntoKeys<K, V> {
    #[inline]
    fn len(&self) -> usize {
        self.iter.len()
    }
}

impl<K, V> DoubleEndedIterator for IntoKeys<K, V> {
    def_double_ended_iter!();
}

/// Iterator that moves values out of [`SmallMap`](crate::small_map::SmallMap).
pub struct IntoValues<K, V> {
    pub(crate) iter: vec_map::IntoIter<K, V>,
}

impl<K, V> IntoValues<K, V> {
    #[inline]
    fn map((_, v): (K, V)) -> <Self as Iterator>::Item {
        v
    }
}

impl<K, V> Iterator for IntoValues<K, V> {
    type Item = V;

    def_iter!();
}

impl<K, V> ExactSizeIterator for IntoValues<K, V> {
    #[inline]
    fn len(&self) -> usize {
        self.iter.len()
    }
}

impl<K, V> DoubleEndedIterator for IntoValues<K, V> {
    def_double_ended_iter!();
}

/// Iterator over a [`SmallMap`](crate::small_map::SmallMap) mutable values.
pub struct ValuesMut<'a, K, V> {
    pub(crate) iter: vec_map::ValuesMut<'a, K, V>,
}

impl<'a, K, V> ValuesMut<'a, K, V> {
    #[inline]
    fn map(v: &'a mut V) -> <Self as Iterator>::Item {
        v
    }
}

impl<'a, K, V> Iterator for ValuesMut<'a, K, V> {
    type Item = &'a mut V;

    def_iter!();
}

impl<'a, K, V> ExactSizeIterator for ValuesMut<'a, K, V> {
    #[inline]
    fn len(&self) -> usize {
        self.iter.len()
    }
}

impl<'a, K, V> DoubleEndedIterator for ValuesMut<'a, K, V> {
    def_double_ended_iter!();
}

fn _assert_iterators_sync_send() {
    fn assert_sync_send<T: Sync + Send>(_: T) {}
    fn test_iter_hashed(iter: IterHashed<String, u32>) {
        assert_sync_send(iter);
    }
    fn test_iter(iter: Iter<String, u32>) {
        assert_sync_send(iter);
    }
    fn test_into_iter_hashed(iter: IntoIterHashed<String, u32>) {
        assert_sync_send(iter);
    }
    fn test_into_iter(iter: IntoIter<String, u32>) {
        assert_sync_send(iter);
    }
    fn test_keys(iter: Keys<String, u32>) {
        assert_sync_send(iter);
    }
    fn test_values(iter: Values<String, u32>) {
        assert_sync_send(iter);
    }
    fn test_into_keys(iter: IntoKeys<String, u32>) {
        assert_sync_send(iter);
    }
    fn test_into_values(iter: IntoValues<String, u32>) {
        assert_sync_send(iter);
    }
}


/*
 * Copyright 2019 The Starlark in Rust Authors.
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//! A Map with deterministic iteration order that specializes its storage based on the number of
//! entries to optimize memory. This is essentially `IndexMap` with two changes:
//! * no index is created for small maps
//! * short hashes are stored next to keys

use std::fmt;
use std::fmt::Debug;
use std::hash::Hash;
use std::hash::Hasher;
use std::marker::PhantomData;
use std::mem;

use allocative::Allocative;
use hashbrown::raw::RawTable;
use serde::Deserialize;
use serde::Serialize;

use crate::equivalent::Equivalent;
use crate::hashed::Hashed;
pub use crate::small_map::iter::IntoIter;
pub use crate::small_map::iter::IntoIterHashed;
pub use crate::small_map::iter::IntoKeys;
pub use crate::small_map::iter::IntoValues;
pub use crate::small_map::iter::Iter;
pub use crate::small_map::iter::IterHashed;
pub use crate::small_map::iter::IterMut;
pub use crate::small_map::iter::IterMutUnchecked;
pub use crate::small_map::iter::Keys;
pub use crate::small_map::iter::Values;
pub use crate::small_map::iter::ValuesMut;
use crate::vec_map::VecMap;
use crate::StarlarkHashValue;

mod iter;

/// Max size of a map when we do not create an index.
/// 32 is the value where `buck2 cquery some-target` is the fastest and consumes the least memory.
/// Note the test was performed for buck2-specific patterns.
/// On nightly we use SIMD to speed up the search, so use 16 on stable to be safe.
#[cfg(rust_nightly)]
const NO_INDEX_THRESHOLD: usize = 32;
#[cfg(not(rust_nightly))]
const NO_INDEX_THRESHOLD: usize = 16;

/// An memory-efficient key-value map with deterministic order.
///
/// Provides the standard container operations, modelled most closely on `indexmap::IndexMap`, plus:
///
/// * Variants which take an already hashed value, e.g. [`get_hashed`](SmallMap::get_hashed).
///
/// * Functions which work with the position, e.g. [`get_index_of`](SmallMap::get_index_of).
#[repr(C)]
#[derive(Clone, Allocative)]
pub struct SmallMap<K, V> {
    entries: VecMap<K, V>,
    /// Map a key to the index in `entries`.
    /// This field is initialized when the size of the map exceeds `NO_INDEX_THRESHOLD`.
    index: Option<Box<RawTable<usize>>>,
}

impl<K, V> Default for SmallMap<K, V> {
    #[inline]
    fn default() -> Self {
        Self::new()
    }
}

impl<K: Debug, V: Debug> Debug for SmallMap<K, V> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_map().entries(self.iter()).finish()
    }
}

impl<K, V> SmallMap<K, V> {
    /// Empty map.
    #[inline]
    pub const fn new() -> Self {
        Self {
            entries: VecMap::new(),
            index: None,
        }
    }

    /// Create an empty map with specified capacity.
    #[inline]
    pub fn with_capacity(n: usize) -> Self {
        if n <= NO_INDEX_THRESHOLD {
            SmallMap {
                entries: VecMap::with_capacity(n),
                index: None,
            }
        } else {
            SmallMap {
                entries: VecMap::with_capacity(n),
                index: Some(Box::new(RawTable::with_capacity(n))),
            }
        }
    }

    /// Verify that the map is internally consistent.
    #[cfg(test)]
    fn assert_invariants(&self)
    where
        K: Eq,
    {
        if let Some(index) = &self.index {
            assert_eq!(index.len(), self.entries.len());
            for (i, (k, _)) in self.entries.iter_hashed().enumerate() {
                let j = *index
                    .get(k.hash().promote(), |j| {
                        &self.entries.get_index(*j).unwrap().0 == k.key()
                    })
                    .unwrap();
                assert_eq!(i, j);
            }
        } else {
            assert!(self.entries.len() <= NO_INDEX_THRESHOLD);
        }
    }

    /// Drop the index if the map is too small, and the index is not really needed.
    ///
    /// We don't allocate index prematurely when we add entries the map,
    /// but we keep it allocated when we remove entries from the map.
    ///
    /// This function allows to reclaim memory after some entries are removed.
    pub fn maybe_drop_index(&mut self) {
        if self.entries.len() <= NO_INDEX_THRESHOLD {
            self.index = None;
        }
    }

    /// Key references iterator.
    #[inline]
    pub fn keys(&self) -> Keys<K, V> {
        Keys {
            iter: self.entries.keys(),
        }
    }

    /// Value references iterator.
    #[inline]
    pub fn values(&self) -> Values<K, V> {
        Values {
            iter: self.entries.values(),
        }
    }

    /// Key owned iterator.
    #[inline]
    pub fn into_keys(self) -> IntoKeys<K, V> {
        IntoKeys {
            iter: self.entries.into_iter(),
        }
    }

    /// Value owned iterator.
    #[inline]
    pub fn into_values(self) -> IntoValues<K, V> {
        IntoValues {
            iter: self.entries.into_iter(),
        }
    }

    /// Mutable value references iterator.
    #[inline]
    pub fn values_mut(&mut self) -> ValuesMut<K, V> {
        ValuesMut {
            iter: self.entries.values_mut(),
        }
    }

    /// Entry references iterator.
    #[inline]
    pub fn iter(&self) -> Iter<'_, K, V> {
        Iter {
            iter: self.entries.iter(),
        }
    }

    /// Entry references with hashes iterator.
    #[inline]
    pub fn iter_hashed(&self) -> IterHashed<K, V> {
        IterHashed {
            iter: self.entries.iter_hashed(),
        }
    }

    /// Entries with hashes iterator.
    #[inline]
    pub fn into_iter_hashed(self) -> IntoIterHashed<K, V> {
        IntoIterHashed {
            iter: self.entries.into_iter_hashed(),
        }
    }

    /// Mutable entry references iterator.
    #[inline]
    pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
        IterMut {
            iter: self.entries.iter_mut(),
        }
    }

    /// Mutable entry references iterator, with mutable key references.
    ///
    /// This operation is memory safe, but otherwise no guarantees
    /// if keys are mutated inconsistently (hash or equality changes).
    #[inline]
    pub fn iter_mut_unchecked(&mut self) -> IterMutUnchecked<'_, K, V> {
        IterMutUnchecked {
            iter: self.entries.iter_mut_unchecked(),
        }
    }

    /// Entries iterator.
    #[inline]
    fn into_iter(self) -> IntoIter<K, V> {
        IntoIter {
            iter: self.entries.into_iter(),
        }
    }

    /// Query the map by a prehashed key.
    #[inline]
    pub fn get_hashed<Q>(&self, key: Hashed<&Q>) -> Option<&V>
    where
        Q: Equivalent<K> + ?Sized,
    {
        self.get_index_of_hashed(key)
            .map(|index| unsafe { self.entries.get_unchecked(index).1 })
    }

    /// Same as `get_hashed`, byt takes key by value instead of by reference.
    /// Sometimes it generates slightly better code for small values.
    #[inline]
    pub fn get_hashed_by_value<Q>(&self, key: Hashed<Q>) -> Option<&V>
    where
        Q: Equivalent<K>,
    {
        self.get_index_of_hashed_by_value(key)
            .map(|index| unsafe { self.entries.get_unchecked(index).1 })
    }

    /// Query the map by a given key.
    #[inline]
    pub fn get<Q>(&self, key: &Q) -> Option<&V>
    where
        Q: Hash + Equivalent<K> + ?Sized,
    {
        self.get_hashed(Hashed::new(key))
    }

    /// Query the map by a given key, return an index of the entry
    /// along with the entry key and value.
    #[inline]
    pub fn get_full<Q>(&self, key: &Q) -> Option<(usize, &K, &V)>
    where
        Q: Hash + Equivalent<K> + ?Sized,
    {
        self.get_full_hashed(Hashed::new(key))
    }

    /// Query the map by a given key, return an index of the entry
    /// along with the entry key and value.
    #[inline]
    pub fn get_full_hashed<Q>(&self, key: Hashed<&Q>) -> Option<(usize, &K, &V)>
    where
        Q: Equivalent<K> + ?Sized,
    {
        self.get_index_of_hashed(key).map(|index| {
            let (key, value) = unsafe { self.entries.get_unchecked(index) };
            (index, *key.key(), value)
        })
    }

    #[inline]
    fn get_index_of_hashed_raw_with_index(
        &self,
        hash: StarlarkHashValue,
        mut eq: impl FnMut(&K) -> bool,
        index: &RawTable<usize>,
    ) -> Option<usize> {
        index
            .get(hash.promote(), |&index| unsafe {
                eq(self.entries.get_unchecked(index).0.key())
            })
            .copied()
    }

    #[inline]
    pub(crate) fn get_index_of_hashed_raw(
        &self,
        hash: StarlarkHashValue,
        eq: impl FnMut(&K) -> bool,
    ) -> Option<usize> {
        match &self.index {
            None => self.entries.get_index_of_hashed_raw(hash, eq),
            Some(index) => self.get_index_of_hashed_raw_with_index(hash, eq, index),
        }
    }

    /// Find the index of the given hashed key.
    #[inline]
    pub fn get_index_of_hashed<Q>(&self, key: Hashed<&Q>) -> Option<usize>
    where
        Q: Equivalent<K> + ?Sized,
    {
        self.get_index_of_hashed_raw(key.hash(), |k| key.key().equivalent(k))
    }

    /// Get the index of the entry given a hashed key.
    #[inline]
    pub fn get_index_of_hashed_by_value<Q>(&self, key: Hashed<Q>) -> Option<usize>
    where
        Q: Equivalent<K>,
    {
        self.get_index_of_hashed_raw(key.hash(), |k| key.key().equivalent(k))
    }

    /// Find an entry by an index.
    #[inline]
    pub fn get_index(&self, index: usize) -> Option<(&K, &V)> {
        self.entries.get_index(index)
    }

    /// The an entry index by a given key.
    #[inline]
    pub fn get_index_of<Q>(&self, key: &Q) -> Option<usize>
    where
        Q: Hash + Equivalent<K> + ?Sized,
    {
        self.get_index_of_hashed(Hashed::new(key))
    }

    /// Find a mutable value by a hashed key.
    #[inline]
    pub fn get_mut_hashed<Q>(&mut self, key: Hashed<&Q>) -> Option<&mut V>
    where
        Q: Equivalent<K> + ?Sized,
    {
        let i = self.get_index_of_hashed(key)?;
        debug_assert!(i < self.entries.len());
        Some(unsafe { self.entries.get_unchecked_mut(i).1 })
    }

    /// Find the entry by a given key.
    #[inline]
    pub fn get_mut<Q>(&mut self, key: &Q) -> Option<&mut V>
    where
        Q: Hash + Equivalent<K> + ?Sized,
    {
        self.get_mut_hashed(Hashed::new(key))
    }

    /// Find if an entry by a given prehashed key exists.
    #[inline]
    pub fn contains_key_hashed<Q>(&self, key: Hashed<&Q>) -> bool
    where
        Q: Equivalent<K> + ?Sized,
    {
        self.get_index_of_hashed(key).is_some()
    }

    /// Find if an entry by a given hashed key exists.
    #[inline]
    pub fn contains_key_hashed_by_value<Q>(&self, key: Hashed<Q>) -> bool
    where
        Q: Equivalent<K>,
    {
        self.get_index_of_hashed_by_value(key).is_some()
    }

    /// Find if an entry by a given key exists.
    #[inline]
    pub fn contains_key<Q>(&self, key: &Q) -> bool
    where
        Q: Hash + Equivalent<K> + ?Sized,
    {
        self.contains_key_hashed(Hashed::new(key))
    }

    /// Reserve capacity for at least `additional` more elements to be inserted.
    #[inline]
    pub fn reserve(&mut self, additional: usize)
    where
        K: Eq,
    {
        self.entries.reserve(additional);
        if let Some(index) = &mut self.index {
            index.reserve(additional, Self::hasher(&self.entries));
        } else if self.len() + additional > NO_INDEX_THRESHOLD {
            self.create_index(self.len() + additional);
        }
    }

    /// Current map capacity.
    #[inline]
    pub fn capacity(&self) -> usize {
        self.entries.capacity()
    }

    /// Returns a reference to the first key-value pair.
    pub fn first(&self) -> Option<(&K, &V)> {
        self.iter().next()
    }

    /// Returns a reference to the last key-value pair.
    pub fn last(&self) -> Option<(&K, &V)> {
        self.iter().next_back()
    }

    #[cold]
    fn create_index(&mut self, capacity: usize) {
        debug_assert!(self.index.is_none());
        debug_assert!(capacity >= self.entries.len());
        let mut index = RawTable::with_capacity(capacity);
        for (i, (k, _)) in self.entries.iter_hashed().enumerate() {
            // SAFETY: capacity >= self.entries.len()
            unsafe { index.insert_no_grow(k.hash().promote(), i) };
        }
        self.index = Some(Box::new(index));
    }

    /// Hasher for index resize.
    #[inline(always)]
    fn hasher(entries: &VecMap<K, V>) -> impl Fn(&usize) -> u64 + '_ {
        move |&index| {
            debug_assert!(index < entries.len());
            unsafe { entries.get_unchecked(index).0.hash().promote() }
        }
    }

    /// Insert an entry into the map without checking for a duplicate key.
    #[inline]
    pub fn insert_hashed_unique_unchecked(&mut self, key: Hashed<K>, val: V) -> (&K, &mut V) {
        let hash = key.hash();
        let entry_index = self.entries.len();
        self.entries.insert_hashed_unique_unchecked(key, val);
        if let Some(index) = &mut self.index {
            index.insert(hash.promote(), entry_index, Self::hasher(&self.entries));
        } else if self.entries.len() == NO_INDEX_THRESHOLD + 1 {
            self.create_index(self.entries.len());
        } else {
            debug_assert!(self.entries.len() < NO_INDEX_THRESHOLD + 1);
        }
        // SAFETY: We've just inserted an entry, so we know entries is not empty.
        unsafe {
            let (key, value) = self.entries.get_unchecked_mut(self.entries.len() - 1);
            (key.key(), value)
        }
    }

    /// Insert a key-value pair into the map.
    #[inline]
    pub fn insert_hashed(&mut self, key: Hashed<K>, val: V) -> Option<V>
    where
        K: Eq,
    {
        match self.get_index_of_hashed_raw(key.hash(), |k| key.key().equivalent(k)) {
            None => {
                self.insert_hashed_unique_unchecked(key, val);
                None
            }
            Some(i) => unsafe {
                debug_assert!(i < self.entries.len());
                Some(mem::replace(self.entries.get_unchecked_mut(i).1, val))
            },
        }
    }

    /// Insert a key-value pair into the map.
    #[inline]
    pub fn insert(&mut self, key: K, val: V) -> Option<V>
    where
        K: Hash + Eq,
    {
        self.insert_hashed(Hashed::new(key), val)
    }

    /// Insert a key-value pair into the map without checking for a duplicate key.
    #[inline]
    pub fn insert_unique_unchecked(&mut self, key: K, val: V) -> (&K, &mut V)
    where
        K: Hash,
    {
        self.insert_hashed_unique_unchecked(Hashed::new(key), val)
    }

    /// Remove the entry for the key.
    ///
    /// Time complexity of this operation is *O(N)* where *N* is the number of entries in the map.
    pub fn remove_hashed<Q>(&mut self, key: Hashed<&Q>) -> Option<V>
    where
        Q: ?Sized + Equivalent<K>,
    {
        self.remove_hashed_entry(key).map(|(_k, v)| v)
    }

    /// Remove the entry for the key.
    ///
    /// Time complexity of this operation is *O(N)* where *N* is the number of entries in the map.
    pub fn remove_hashed_entry<Q>(&mut self, key: Hashed<&Q>) -> Option<(K, V)>
    where
        Q: ?Sized + Equivalent<K>,
    {
        let hash = key.hash();
        if let Some(index) = &mut self.index {
            let entries = &self.entries;
            let i = index.remove_entry(hash.promote(), |&i| unsafe {
                key.key().equivalent(entries.get_unchecked(i).0.key())
            })?;
            unsafe {
                // No need to update the index when the last entry is removed.
                if i != self.entries.len() - 1 {
                    for bucket in index.iter() {
                        debug_assert!(*bucket.as_ref() != i);
                        if *bucket.as_mut() > i {
                            *bucket.as_mut() -= 1;
                        }
                    }
                }
            }
            let (key, value) = self.entries.remove(i);
            Some((key.into_key(), value))
        } else {
            self.entries.remove_hashed_entry(key)
        }
    }

    /// Remove the entry for the key.
    ///
    /// Time complexity of this operation is *O(N)* where *N* is the number of entries in the map.
    pub fn remove<Q>(&mut self, key: &Q) -> Option<V>
    where
        Q: ?Sized + Hash + Equivalent<K>,
    {
        self.remove_hashed(Hashed::new(key))
    }

    /// Remove the entry for the key.
    ///
    /// Time complexity of this operation is *O(N)* where *N* is the number of entries in the map.
    pub fn remove_entry<Q>(&mut self, key: &Q) -> Option<(K, V)>
    where
        Q: ?Sized + Hash + Equivalent<K>,
    {
        self.remove_hashed_entry(Hashed::new(key))
    }

    /// Get the entry (occupied or not) for the key.
    #[inline]
    pub fn entry_hashed(&mut self, key: Hashed<K>) -> Entry<'_, K, V>
    where
        K: Eq,
    {
        match self.get_index_of_hashed_raw(key.hash(), |k| key.key().equivalent(k)) {
            Some(i) => {
                let (key, value) = unsafe { self.entries.get_unchecked_mut(i) };
                Entry::Occupied(OccupiedEntry {
                    key: key.key(),
                    value,
                })
            }
            None => Entry::Vacant(VacantEntry { key, map: self }),
        }
    }

    /// Remove the last element.
    pub fn pop(&mut self) -> Option<(K, V)> {
        match self.entries.pop() {
            None => None,
            Some((key, value)) => {
                if let Some(index) = &mut self.index {
                    let removed =
                        index.remove_entry(key.hash().promote(), |&i| i == self.entries.len());
                    debug_assert!(removed.unwrap() == self.entries.len());
                }
                Some((key.into_key(), value))
            }
        }
    }

    /// Get the entry (occupied or not) for the key.
    #[inline]
    pub fn entry(&mut self, key: K) -> Entry<'_, K, V>
    where
        K: Eq + Hash,
    {
        self.entry_hashed(Hashed::new(key))
    }

    /// Is the map empty?
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.entries.is_empty()
    }

    /// Get the number of elements in the map.
    #[inline]
    pub fn len(&self) -> usize {
        self.entries.len()
    }

    /// Remove all elements from the map.
    ///
    /// Retain the capacity.
    #[inline]
    pub fn clear(&mut self) {
        self.entries.clear();
        if let Some(index) = &mut self.index {
            // Note we are keeping the `index` object initialized here.
            // So next insert will have to update the index.
            // Which is probably suboptimal (hard to say),
            // but `clear` is rare operation anyway.
            index.clear();
        }
    }

    /// Basic check the map invariants are hold.
    #[cfg(test)]
    fn state_check(&self) {
        if let Some(index) = &self.index {
            assert_eq!(self.entries.len(), index.len());
            let mut set_fields = vec![false; self.entries.len()];
            unsafe {
                for bucket in index.iter() {
                    let i = *bucket.as_ref();
                    let prev = mem::replace(&mut set_fields[i], true);
                    assert!(!prev);
                }
            }
        } else {
            assert!(self.entries.len() <= NO_INDEX_THRESHOLD);
        }
    }

    fn is_sorted_by_key(&self) -> bool
    where
        K: Ord,
    {
        self.entries.is_sorted_by_key()
    }

    /// Sort entries by key.
    pub fn sort_keys(&mut self)
    where
        K: Ord,
    {
        // Check if sorted first, otherwise we may need to rebuild the index
        // even if the map is already sorted.
        if self.is_sorted_by_key() {
            return;
        }

        // Rebuild index on drop to make this code panic-safe.
        struct RebuildIndexOnDrop<'a, K, V> {
            map: &'a mut SmallMap<K, V>,
        }

        impl<'a, K, V> Drop for RebuildIndexOnDrop<'a, K, V> {
            fn drop(&mut self) {
                if let Some(index) = &mut self.map.index {
                    index.clear();
                    for (i, (k, _)) in self.map.entries.iter_hashed().enumerate() {
                        // SAFETY: capacity >= self.entries.len()
                        unsafe { index.insert_no_grow(k.hash().promote(), i) };
                    }
                }
            }
        }

        let map = RebuildIndexOnDrop { map: self };
        map.map.entries.sort_keys();
    }

    /// Equal if the keys and values are equal in the iteration order.
    pub fn eq_ordered(&self, other: &Self) -> bool
    where
        K: PartialEq,
        V: PartialEq,
    {
        self.entries.eq_ordered(&other.entries)
    }

    /// Hash entries in the iteration order.
    ///
    /// Note, keys are not hashed, but previously computed hashes are hashed instead.
    pub fn hash_ordered<H: Hasher>(&self, state: &mut H)
    where
        K: Hash,
        V: Hash,
    {
        self.entries.hash_ordered(state)
    }
}

/// Reference to the actual entry in the map.
pub struct OccupiedEntry<'a, K, V> {
    /// Pointer to the key in the map.
    key: &'a K,
    /// Pointer to the value in the map.
    value: &'a mut V,
}

/// Reference to a vacant entry in the map.
///
/// This can be used to insert an entry into the map.
pub struct VacantEntry<'a, K, V> {
    key: Hashed<K>,
    map: &'a mut SmallMap<K, V>,
}

/// Occupied or vacant entry.
pub enum Entry<'a, K, V> {
    /// Occupied entry.
    Occupied(OccupiedEntry<'a, K, V>),
    /// No entry for given key.
    Vacant(VacantEntry<'a, K, V>),
}

impl<'a, K, V> OccupiedEntry<'a, K, V> {
    /// Key for this entry.
    #[inline]
    pub fn key(&self) -> &K {
        self.key
    }

    /// Value for this entry.
    #[inline]
    pub fn get(&self) -> &V {
        self.value
    }

    /// Mutable reference to the value in the entry.
    #[inline]
    pub fn get_mut(&mut self) -> &mut V {
        self.value
    }

    /// Get a reference to the value in the entry with map lifetime.
    #[inline]
    pub fn into_mut(self) -> &'a mut V {
        self.value
    }

    #[inline]
    pub(crate) fn into_mut_entry(self) -> (&'a K, &'a mut V) {
        (self.key, self.value)
    }
}

impl<'a, K, V> VacantEntry<'a, K, V>
where
    K: Eq,
{
    /// Key for this entry.
    #[inline]
    pub fn key(&self) -> &K {
        self.key.key()
    }

    /// Insert the value into the entry.
    #[inline]
    pub fn insert(self, value: V) -> &'a mut V {
        self.insert_entry(value).1
    }

    #[inline]
    pub(crate) fn insert_entry(self, value: V) -> (&'a K, &'a mut V) {
        self.map.insert_hashed_unique_unchecked(self.key, value)
    }
}

impl<'a, K, V> Entry<'a, K, V>
where
    K: Eq,
{
    /// Key for this entry.
    #[inline]
    pub fn key(&self) -> &K {
        match self {
            Entry::Occupied(e) => e.key(),
            Entry::Vacant(e) => e.key(),
        }
    }

    /// Insert if vacant.
    #[inline]
    pub fn or_insert(self, default: V) -> &'a mut V {
        self.or_insert_with(|| default)
    }

    /// Insert if vacant.
    #[inline]
    pub fn or_insert_with(self, default: impl FnOnce() -> V) -> &'a mut V {
        self.or_insert_entry_with(default).1
    }

    /// Insert if vacant.
    #[inline]
    pub fn or_default(self) -> &'a mut V
    where
        V: Default,
    {
        self.or_insert_with(V::default)
    }

    #[inline]
    pub(crate) fn or_insert_entry_with(self, default: impl FnOnce() -> V) -> (&'a K, &'a mut V) {
        match self {
            Entry::Occupied(e) => e.into_mut_entry(),
            Entry::Vacant(e) => e.insert_entry(default()),
        }
    }
}

impl<K, V> FromIterator<(K, V)> for SmallMap<K, V>
where
    K: Hash + Eq,
{
    fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
        let iter = iter.into_iter();
        let mut mp = Self::with_capacity(iter.size_hint().0);
        for (k, v) in iter {
            mp.insert(k, v);
        }
        mp
    }
}

impl<K, V> FromIterator<(Hashed<K>, V)> for SmallMap<K, V>
where
    K: Eq,
{
    fn from_iter<I: IntoIterator<Item = (Hashed<K>, V)>>(iter: I) -> Self {
        let iter = iter.into_iter();
        let mut mp = Self::with_capacity(iter.size_hint().0);
        for (k, v) in iter {
            mp.insert_hashed(k, v);
        }
        mp
    }
}

impl<K, V> IntoIterator for SmallMap<K, V> {
    type Item = (K, V);
    type IntoIter = IntoIter<K, V>;

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        self.into_iter()
    }
}

impl<'a, K, V> IntoIterator for &'a SmallMap<K, V> {
    type Item = (&'a K, &'a V);
    type IntoIter = Iter<'a, K, V>;

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<'a, K, V> IntoIterator for &'a mut SmallMap<K, V> {
    type Item = (&'a K, &'a mut V);
    type IntoIter = IterMut<'a, K, V>;

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        self.iter_mut()
    }
}

impl<K: Eq, V: PartialEq> PartialEq for SmallMap<K, V> {
    fn eq(&self, other: &Self) -> bool {
        self.len() == other.len()
            && self
                .iter_hashed()
                .all(|(k, v)| other.get_hashed(k) == Some(v))
    }
}

impl<K: Eq, V: Eq> Eq for SmallMap<K, V> {}

impl<K, V> Extend<(K, V)> for SmallMap<K, V>
where
    K: Hash + Eq,
{
    fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
        for (k, v) in iter {
            self.insert(k, v);
        }
    }
}

/// Create a [`SmallMap`](SmallMap) from a list of key-value pairs.
///
/// ## Example
///
/// ```
/// use starlark_map::smallmap;
///
/// let map = smallmap!{
///     "a" => 1,
///     "b" => 2,
/// };
/// assert_eq!(map.get("a"), Some(&1));
/// assert_eq!(map.get("b"), Some(&2));
/// assert_eq!(map.get("c"), None);
/// ```
#[macro_export]
macro_rules! smallmap {
    (@single $($x:tt)*) => (());
    (@count $($rest:expr),*) => (<[()]>::len(&[$(smallmap!(@single $rest)),*]));

    ($($key:expr => $value:expr,)+) => { smallmap!($($key => $value),+) };
    ($($key:expr => $value:expr),*) => {
        {
            let cap = smallmap!(@count $($key),*);
            #[allow(unused_mut)]
            let mut map = $crate::small_map::SmallMap::with_capacity(cap);
            $(
                map.insert($key, $value);
            )*
            map
        }
    };
}

impl<K: Serialize, V: Serialize> Serialize for SmallMap<K, V> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        serializer.collect_map(self.iter())
    }
}

impl<'de, K, V> Deserialize<'de> for SmallMap<K, V>
where
    K: Deserialize<'de> + Hash + Eq,
    V: Deserialize<'de>,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        struct MapVisitor<K, V> {
            marker: PhantomData<SmallMap<K, V>>,
        }

        impl<'de, K, V> serde::de::Visitor<'de> for MapVisitor<K, V>
        where
            K: Deserialize<'de> + Hash + Eq,
            V: Deserialize<'de>,
        {
            type Value = SmallMap<K, V>;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("a map")
            }

            #[inline]
            fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
            where
                A: serde::de::MapAccess<'de>,
            {
                let mut values = SmallMap::with_capacity(map.size_hint().unwrap_or(0));
                while let Some((key, value)) = map.next_entry()? {
                    values.insert(key, value);
                }
                Ok(values)
            }
        }

        let visitor = MapVisitor {
            marker: PhantomData,
        };
        deserializer.deserialize_map(visitor)
    }
}

#[cfg(test)]
mod tests {
    use std::cmp::Ordering;
    use std::panic::catch_unwind;
    use std::panic::AssertUnwindSafe;

    use super::*;

    #[test]
    fn empty_map() {
        let m = SmallMap::<i8, &str>::new();
        assert_eq!(m.is_empty(), true);
        assert_eq!(m.len(), 0);
        assert_eq!(m.iter().next(), None);
    }

    #[test]
    fn few_entries() {
        let entries1 = vec![(0, 'a'), (1, 'b')];
        let m1 = entries1.iter().copied().collect::<SmallMap<_, _>>();

        let entries2 = vec![(1, 'b'), (0, 'a')];
        let m2 = entries2.iter().copied().collect::<SmallMap<_, _>>();
        assert_eq!(m1.is_empty(), false);
        assert_eq!(m1.len(), 2);
        assert_eq!(m2.is_empty(), false);
        assert_eq!(m2.len(), 2);

        assert_eq!(m1.iter().eq(entries1.iter().map(|(k, v)| (k, v))), true);
        assert_eq!(m2.iter().eq(entries2.iter().map(|(k, v)| (k, v))), true);
        assert_eq!(m1.iter().eq(m2.iter()), false);
        assert_eq!(m1.eq(&m1), true);
        assert_eq!(m2.eq(&m2), true);
        assert_eq!(m1, m2);

        assert_eq!(m1.get(&0), Some(&'a'));
        assert_eq!(m1.get(&3), None);
        assert_eq!(m2.get(&1), Some(&'b'));
        assert_eq!(m2.get(&3), None);

        assert_eq!(m1.get_index(0), Some((&0, &'a')));
        assert_eq!(m1.get_index(1), Some((&1, &'b')));
        assert_eq!(m1.get_index(2), None);

        assert_ne!(m1, smallmap! { 0 => 'a', 1 => 'c' });

        let iter = m1.iter();
        let (values1, values2): (Vec<_>, Vec<_>) = (iter.clone().collect(), iter.collect());
        assert_eq!(values1, values2);
    }

    #[test]
    fn many_entries() {
        let numbers = 0..26;
        let letters = 'a'..='z';

        let entries1 = numbers.zip(letters);
        let m1 = entries1.clone().collect::<SmallMap<_, _>>();

        let numbers = (0..26).rev();
        let letters = ('a'..='z').rev();
        let entries2 = numbers.zip(letters);
        let m2 = entries2.clone().collect::<SmallMap<_, _>>();
        assert_eq!(m1.is_empty(), false);
        assert_eq!(m1.len(), 26);
        assert_eq!(m2.is_empty(), false);
        assert_eq!(m2.len(), 26);

        assert_eq!(m1.clone().into_iter().eq(entries1), true);
        assert_eq!(m2.clone().into_iter().eq(entries2), true);
        assert_eq!(m1.iter().eq(m2.iter()), false);
        assert_eq!(m1.eq(&m1), true);
        assert_eq!(m2.eq(&m2), true);
        assert_eq!(m1, m2);

        assert_eq!(m1.get(&1), Some(&'b'));
        assert_eq!(m1.get(&30), None);
        assert_eq!(m2.get(&0), Some(&'a'));
        assert_eq!(m2.get(&30), None);
        assert_eq!(m2.get_full(&0), Some((25, &0, &'a')));
        assert_eq!(m2.get_full(&25), Some((0, &25, &'z')));
        assert_eq!(m2.get_full(&29), None);

        let not_m1 = {
            let mut m = m1.clone();
            m.remove(&1);
            m
        };
        assert_ne!(m1, not_m1);

        let iter = m1.iter();
        let (values1, values2): (Vec<_>, Vec<_>) = (iter.clone().collect(), iter.collect());
        assert_eq!(values1, values2);
    }

    #[test]
    fn test_smallmap_macro() {
        let map = smallmap![1 => "a", 3 => "b"];
        let mut i = map.into_iter();
        assert_eq!(i.next(), Some((1, "a")));
        assert_eq!(i.next(), Some((3, "b")));
        assert_eq!(i.next(), None);
    }

    #[test]
    fn test_clone() {
        let map = smallmap![1 => "a", 3 => "b"];
        let iter = map.iter();
        let values1: Vec<_> = iter.clone().collect();
        let values2: Vec<_> = iter.collect();
        assert_eq!(vec![(&1, &"a"), (&3, &"b")], values1);
        assert_eq!(values1, values2);

        let iter = map.keys();
        let values1: Vec<_> = iter.clone().collect();
        let values2: Vec<_> = iter.collect();
        assert_eq!(vec![&1, &3], values1);
        assert_eq!(values1, values2);

        let iter = map.values();
        let values1: Vec<_> = iter.clone().collect();
        let values2: Vec<_> = iter.collect();
        assert_eq!(vec![&"a", &"b"], values1);
        assert_eq!(values1, values2);
    }

    #[test]
    fn test_duplicate_hashes() {
        // A type which always gives hash collisions
        #[derive(PartialEq, Eq, Debug)]
        struct K(i32);
        #[allow(clippy::derived_hash_with_manual_eq)]
        impl Hash for K {
            fn hash<H: Hasher>(&self, _state: &mut H) {}
        }

        let mut map = smallmap![K(1) => "test", K(3) => "more"];
        assert_eq!(map.get(&K(1)), Some(&"test"));
        assert_eq!(map.get(&K(2)), None);
        assert_eq!(map.get(&K(3)), Some(&"more"));

        assert_eq!(map.insert(K(2), "magic"), None);
        assert_eq!(map.get(&K(2)), Some(&"magic"));

        assert_eq!(map.remove(&K(1)), Some("test"));
        assert_eq!(map.get(&K(1)), None);
        assert_eq!(map.keys().collect::<Vec<_>>(), vec![&K(3), &K(2)]);
    }

    #[test]
    fn test_smallmap_debug() {
        let s = format!("{:?}", smallmap![1 => "test", 2 => "more"]);
        assert_eq!(s, "{1: \"test\", 2: \"more\"}")
    }

    #[test]
    fn entry() {
        let mut map = SmallMap::new();
        for i in 0..100 {
            match map.entry(i) {
                Entry::Vacant(e) => {
                    e.insert(i * 2);
                }
                Entry::Occupied(..) => panic!(),
            }
            match map.entry(i) {
                Entry::Occupied(..) => {}
                Entry::Vacant(..) => panic!(),
            }
        }
    }

    #[test]
    fn test_pop_small() {
        let mut map = SmallMap::new();
        for i in 0..=5 {
            map.insert(i, i * 10);
        }
        for i in (0..=5).rev() {
            assert_eq!((i, i * 10), map.pop().unwrap());
            map.state_check();
        }
        assert!(map.is_empty());
    }

    #[test]
    fn test_pop_large() {
        let mut map = SmallMap::new();
        for i in 0..=500 {
            map.insert(i, i * 10);
        }
        for i in (0..=500).rev() {
            assert_eq!((i, i * 10), map.pop().unwrap());
            if i % 100 == 0 {
                map.state_check();
            }
        }
        assert!(map.is_empty());
    }

    #[test]
    fn test_first() {
        let mut map = SmallMap::new();
        map.insert(1, 10);
        assert_eq!(map.first(), Some((&1, &10)));
        map.insert(2, 20);
        assert_eq!(map.first(), Some((&1, &10)));
        map.remove(&1);
        assert_eq!(map.first(), Some((&2, &20)));
    }

    #[test]
    fn test_last() {
        let mut map = SmallMap::new();
        map.insert(1, 10);
        assert_eq!(map.last(), Some((&1, &10)));
        map.insert(2, 20);
        assert_eq!(map.last(), Some((&2, &20)));
        map.insert(1, 100);
        assert_eq!(map.last(), Some((&2, &20)));
    }

    #[test]
    fn test_sort_keys_no_index() {
        let mut map = SmallMap::new();
        map.insert(2, 20);
        map.insert(1, 10);
        map.insert(3, 30);
        map.sort_keys();
        assert_eq!(
            vec![(&1, &10), (&2, &20), (&3, &30)],
            map.iter().collect::<Vec<_>>()
        );
        assert_eq!(&10, map.get(&1).unwrap());
        assert_eq!(&20, map.get(&2).unwrap());
        assert_eq!(&30, map.get(&3).unwrap());
    }

    #[test]
    fn test_sort_keys_with_index() {
        let mut map = SmallMap::new();
        for i in 1..=100 {
            map.insert(i, i * 10);
        }
        map.sort_keys();
        assert_eq!(
            (1..=100).map(|i| (i, i * 10)).collect::<Vec<_>>(),
            map.iter().map(|(k, v)| (*k, *v)).collect::<Vec<_>>()
        );
        for i in 1..=100 {
            assert_eq!(i * 10, *map.get(&i).unwrap());
        }
    }

    #[test]
    fn test_sort_keys_updates_index_on_panic() {
        #[derive(Hash, PartialEq, Eq, Debug)]
        struct Key(u32);

        impl PartialOrd for Key {
            fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
                Some(self.cmp(other))
            }
        }

        impl Ord for Key {
            fn cmp(&self, other: &Self) -> Ordering {
                if self.0 < 10 && other.0 < 10 {
                    panic!("panic in Ord::cmp")
                }
                self.0.cmp(&other.0)
            }
        }

        let mut map = SmallMap::new();
        for i in (1..=100).rev() {
            map.insert(Key(i), i * 10);
        }
        catch_unwind(AssertUnwindSafe(|| map.sort_keys())).unwrap_err();
        // If index is not updated on panic, the following assertion will fail.
        map.assert_invariants();
    }

    #[test]
    fn test_eq_ordered() {
        let m0 = SmallMap::from_iter([(1, 2), (3, 4)]);
        let m1 = SmallMap::from_iter([(1, 2), (3, 4)]);
        let m2 = SmallMap::from_iter([(3, 4), (1, 2)]);
        let m3 = SmallMap::from_iter([(3, 4)]);
        assert!(m0.eq_ordered(&m0));
        assert!(m0.eq_ordered(&m1));
        assert!(!m0.eq_ordered(&m2));
        assert!(!m0.eq_ordered(&m3));
    }

    #[test]
    fn test_remove() {
        // Large enough so the index is used.
        let mut m = (0..100).map(|i| (i, i * 10)).collect::<SmallMap<_, _>>();
        assert_eq!(Some((1, 10)), m.remove_entry(&1));
        assert_eq!(Some(&30), m.get(&3));
        m.assert_invariants();
    }

    #[test]
    fn test_remove_last() {
        // Large enough so the index is used.
        let mut m = (0..100).map(|i| (i, i * 10)).collect::<SmallMap<_, _>>();
        assert_eq!(Some((99, 990)), m.remove_entry(&99));
        assert_eq!(Some(&980), m.get(&98));
        m.assert_invariants();
    }

    #[test]
    fn test_json() {
        let mp = smallmap! {"a".to_owned() => 1, "b".to_owned() => 2};
        let expected = serde_json::json!({
            "a": 1,
            "b": 2,
        });
        assert_eq!(serde_json::to_value(&mp).unwrap(), expected);
        assert_eq!(
            serde_json::from_value::<SmallMap<String, i32>>(expected).unwrap(),
            mp
        );
    }
}


/*
 * Copyright 2019 The Starlark in Rust Authors.
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

use crate::iter::def_double_ended_iter;
use crate::iter::def_iter;
use crate::small_map;
use crate::Hashed;

/// Iterator over the hashed entries of [`SmallSet`](crate::small_set::SmallSet).
pub struct Iter<'a, T> {
    pub(crate) iter: small_map::Iter<'a, T, ()>,
}

/// Iterator over mutable entries of [`SmallSet`](crate::small_set::SmallSet).
pub struct IterMutUnchecked<'a, T> {
    pub(crate) iter: small_map::IterMutUnchecked<'a, T, ()>,
}

/// Iterator over the hashed entries of [`SmallSet`](crate::small_set::SmallSet).
pub struct IterHashed<'a, T> {
    pub(crate) iter: small_map::IterHashed<'a, T, ()>,
}

/// Iterator that moves entries out of a [`SmallSet`](crate::small_set::SmallSet).
pub struct IntoIter<T> {
    pub(crate) iter: small_map::IntoIter<T, ()>,
}

/// Iterator that moves hashed entries out of a [`SmallSet`](crate::small_set::SmallSet).
pub struct IntoIterHashed<T> {
    pub(crate) iter: small_map::IntoIterHashed<T, ()>,
}

impl<'a, T> Clone for Iter<'a, T> {
    fn clone(&self) -> Iter<'a, T> {
        Iter {
            iter: self.iter.clone(),
        }
    }
}

impl<'a, T> Iter<'a, T> {
    #[inline]
    fn map((k, ()): (&'a T, &'a ())) -> &'a T {
        k
    }
}

impl<'a, T> IterMutUnchecked<'a, T> {
    #[inline]
    fn map((k, ()): (&'a mut T, &'a mut ())) -> &'a mut T {
        k
    }
}

impl<'a, T> IterHashed<'a, T> {
    #[inline]
    fn map((k, ()): (Hashed<&'a T>, &'a ())) -> Hashed<&'a T> {
        k
    }
}

impl<T> IntoIter<T> {
    #[inline]
    fn map((k, ()): (T, ())) -> T {
        k
    }
}

impl<T> IntoIterHashed<T> {
    #[inline]
    fn map((k, ()): (Hashed<T>, ())) -> Hashed<T> {
        k
    }
}

impl<'a, T> Iterator for Iter<'a, T> {
    type Item = &'a T;

    def_iter!();
}

impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
    def_double_ended_iter!();
}

impl<'a, T> ExactSizeIterator for Iter<'a, T> {
    #[inline]
    fn len(&self) -> usize {
        self.iter.len()
    }
}

impl<'a, T> Iterator for IterMutUnchecked<'a, T> {
    type Item = &'a mut T;

    def_iter!();
}

impl<'a, T> DoubleEndedIterator for IterMutUnchecked<'a, T> {
    def_double_ended_iter!();
}

impl<'a, T> ExactSizeIterator for IterMutUnchecked<'a, T> {
    #[inline]
    fn len(&self) -> usize {
        self.iter.len()
    }
}

impl<'a, T> Iterator for IterHashed<'a, T> {
    type Item = Hashed<&'a T>;

    def_iter!();
}

impl<'a, T> DoubleEndedIterator for IterHashed<'a, T> {
    def_double_ended_iter!();
}

impl<'a, T> ExactSizeIterator for IterHashed<'a, T> {
    #[inline]
    fn len(&self) -> usize {
        self.iter.len()
    }
}

impl<T> Iterator for IntoIter<T> {
    type Item = T;

    def_iter!();
}

impl<T> DoubleEndedIterator for IntoIter<T> {
    def_double_ended_iter!();
}

impl<T> ExactSizeIterator for IntoIter<T> {
    #[inline]
    fn len(&self) -> usize {
        self.iter.len()
    }
}

impl<T> Iterator for IntoIterHashed<T> {
    type Item = Hashed<T>;

    def_iter!();
}

impl<T> DoubleEndedIterator for IntoIterHashed<T> {
    def_double_ended_iter!();
}

impl<T> ExactSizeIterator for IntoIterHashed<T> {
    #[inline]
    fn len(&self) -> usize {
        self.iter.len()
    }
}


/*
 * Copyright 2019 The Starlark in Rust Authors.
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//! Ordered set.

mod iter;

use std::fmt;
use std::fmt::Debug;
use std::hash::Hash;
use std::hash::Hasher;
use std::marker::PhantomData;

use allocative::Allocative;
use serde::Deserialize;
use serde::Serialize;

use crate::equivalent::Equivalent;
use crate::hashed::Hashed;
use crate::small_map::SmallMap;
pub use crate::small_set::iter::IntoIter;
pub use crate::small_set::iter::IntoIterHashed;
pub use crate::small_set::iter::Iter;
pub use crate::small_set::iter::IterHashed;
pub use crate::small_set::iter::IterMutUnchecked;

/// An memory-efficient set with deterministic order, based on [`SmallMap`].
#[derive(Clone, Allocative)]
pub struct SmallSet<T>(SmallMap<T, ()>);

impl<T> Default for SmallSet<T> {
    #[inline]
    fn default() -> Self {
        Self::new()
    }
}

impl<T: Debug> Debug for SmallSet<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_set().entries(self.iter()).finish()
    }
}

impl<T> Eq for SmallSet<T> where T: Eq {}

impl<T> PartialEq for SmallSet<T>
where
    T: Eq,
{
    fn eq(&self, other: &Self) -> bool {
        self.0.eq(&other.0)
    }
}

impl<T> FromIterator<T> for SmallSet<T>
where
    T: Hash + Eq,
{
    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
        let iter = iter.into_iter();
        let mut smallset = Self::with_capacity(iter.size_hint().0);
        for t in iter {
            smallset.insert(t);
        }
        smallset
    }
}

impl<T> SmallSet<T> {
    /// Creates an empty `SmallSet`.
    #[inline]
    pub const fn new() -> Self {
        SmallSet(SmallMap::new())
    }

    /// Empty small set with preallocated capacity.
    #[inline]
    pub fn with_capacity(n: usize) -> Self {
        Self(SmallMap::with_capacity(n))
    }

    /// Current capacity of the set.
    #[inline]
    pub fn capacity(&self) -> usize {
        self.0.capacity()
    }

    /// Iterate the element references.
    #[inline]
    pub fn iter(&self) -> Iter<T> {
        self.into_iter()
    }

    /// Iterate the hashed element references.
    #[inline]
    pub fn iter_hashed(&self) -> IterHashed<T> {
        IterHashed {
            iter: self.0.iter_hashed(),
        }
    }

    /// Iterate the mutable element references.
    ///
    /// This operation is memory safe, but otherwise no guarantees
    /// if keys are mutated inconsistently (hash or equality changes).
    #[inline]
    pub fn iter_mut_unchecked(&mut self) -> IterMutUnchecked<T> {
        IterMutUnchecked {
            iter: self.0.iter_mut_unchecked(),
        }
    }

    /// Into hashed entries.
    #[inline]
    pub fn into_iter_hashed(self) -> IntoIterHashed<T> {
        IntoIterHashed {
            iter: self.0.into_iter_hashed(),
        }
    }

    /// Insert the element into the set.
    ///
    /// Return `true` iff the element was inserted.
    #[inline]
    pub fn insert(&mut self, key: T) -> bool
    where
        T: Hash + Eq,
    {
        self.0.insert(key, ()).is_none()
    }

    /// Insert the element into the set without checking for a duplicate entry.
    #[inline]
    pub fn insert_unique_unchecked(&mut self, key: T)
    where
        T: Hash + Eq,
    {
        self.0.insert_unique_unchecked(key, ());
    }

    /// Insert the element into the set.
    ///
    /// Return `true` iff the element was inserted.
    #[inline]
    pub fn insert_hashed(&mut self, key: Hashed<T>) -> bool
    where
        T: Eq,
    {
        self.0.insert_hashed(key, ()).is_none()
    }

    /// Insert an entry into the set without checking for a duplicate key.
    #[inline]
    pub fn insert_hashed_unique_unchecked(&mut self, key: Hashed<T>) {
        self.0.insert_hashed_unique_unchecked(key, ());
    }

    /// Return a reference to the value stored in the set, if it is present,
    /// else `None`.
    ///
    /// Computes in **O(1)** time (average).
    #[inline]
    pub fn get<Q>(&self, value: &Q) -> Option<&T>
    where
        Q: Hash + Equivalent<T> + ?Sized,
        T: Eq,
    {
        self.0.get_full(value).map(|(_, t, _)| t)
    }

    /// Query the set by a prehashed value.
    #[inline]
    pub fn get_hashed<Q>(&self, value: Hashed<&Q>) -> Option<&T>
    where
        Q: Equivalent<T> + ?Sized,
        T: Eq,
    {
        self.0.get_full_hashed(value).map(|(_, t, _)| t)
    }

    /// Find an entry by an index.
    #[inline]
    pub fn get_index(&self, index: usize) -> Option<&T> {
        self.0.get_index(index).map(|(k, _)| k)
    }

    /// Return item index, if it exists in the set
    #[inline]
    pub fn get_index_of<Q>(&self, value: &Q) -> Option<usize>
    where
        Q: Hash + Equivalent<T> + ?Sized,
        T: Eq,
    {
        self.0.get_index_of(value)
    }

    /// Find the index of the given hashed value.
    #[inline]
    pub fn get_index_of_hashed<Q>(&self, value: Hashed<&Q>) -> Option<usize>
    where
        Q: Equivalent<T> + ?Sized,
        T: Eq,
    {
        self.0.get_index_of_hashed(value)
    }

    /// Find the index of the given hashed value.
    ///
    /// This operations is similar to [`get_index_of_hashed`](Self::get_index_of_hashed),
    /// but it takes the key by value, instead of by reference
    /// which sometimes generates better code.
    #[inline]
    pub fn get_index_of_hashed_by_value<Q>(&self, value: Hashed<Q>) -> Option<usize>
    where
        Q: Equivalent<T>,
        T: Eq,
    {
        self.0.get_index_of_hashed_by_value(value)
    }

    /// Remove the element from the set if it is present.
    ///
    /// Time complexity of this operation is *O(N)* where *N* is the number of entries in the set.
    #[inline]
    pub fn remove<Q>(&mut self, key: &Q) -> bool
    where
        Q: ?Sized + Hash + Equivalent<T>,
        T: Eq,
    {
        self.0.remove(key).is_some()
    }

    /// Insert entry if it doesn't exist.
    ///
    /// Return the resulting entry in the map.
    #[inline]
    pub fn get_or_insert(&mut self, value: T) -> &T
    where
        T: Hash + Eq,
    {
        let value = Hashed::new(value);
        match self
            .0
            .get_index_of_hashed_raw(value.hash(), |v| value.key().equivalent(v))
        {
            Some(index) => self.0.get_index(index).unwrap().0,
            None => self.0.insert_hashed_unique_unchecked(value, ()).0,
        }
    }

    /// Insert entry if it doesn't exist.
    ///
    /// Return the resulting entry in the map.
    #[inline]
    pub fn get_or_insert_owned<Q>(&mut self, value: &Q) -> &T
    where
        Q: Hash + Equivalent<T> + ToOwned<Owned = T> + ?Sized,
        T: Eq,
    {
        let value = Hashed::new(value);
        match self.0.get_index_of_hashed(value) {
            Some(index) => self.0.get_index(index).unwrap().0,
            None => self.0.insert_hashed_unique_unchecked(value.owned(), ()).0,
        }
    }

    /// Remove the element from the set if it is present,
    ///
    /// and return the removed element.
    #[inline]
    pub fn take<Q>(&mut self, key: &Q) -> Option<T>
    where
        Q: ?Sized + Hash + Equivalent<T>,
        T: Eq,
    {
        self.0.remove_entry(key).map(|(k, _)| k)
    }

    /// Remove the last element from the set.
    #[inline]
    pub fn pop(&mut self) -> Option<T>
    where
        T: Eq,
    {
        self.0.pop().map(|(k, ())| k)
    }

    /// Is the set empty?
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.0.is_empty()
    }

    /// Number of elements in the set.
    #[inline]
    pub fn len(&self) -> usize {
        self.0.len()
    }

    /// Check if the set contains an element.
    #[inline]
    pub fn contains<Q>(&self, key: &Q) -> bool
    where
        Q: Hash + Equivalent<T> + ?Sized,
        T: Eq,
    {
        self.0.contains_key(key)
    }

    /// Check if the set contains an element.
    #[inline]
    pub fn contains_hashed<Q>(&self, key: Hashed<&Q>) -> bool
    where
        Q: Equivalent<T> + ?Sized,
        T: Eq,
    {
        self.0.contains_key_hashed(key)
    }

    /// Remove all elements from the set.
    ///
    /// Retain the capacity.
    #[inline]
    pub fn clear(&mut self) {
        self.0.clear()
    }

    /// Returns a reference to the first item.
    #[inline]
    pub fn first(&self) -> Option<&T> {
        self.0.first().map(|(k, ())| k)
    }

    /// Returns a reference to the last item.
    #[inline]
    pub fn last(&self) -> Option<&T> {
        self.0.last().map(|(k, ())| k)
    }

    /// Iterator over elements of this set which are not in the other set.
    pub fn difference<'a>(&'a self, other: &'a Self) -> Difference<'a, T>
    where
        T: Eq + Hash,
    {
        Difference {
            iter: self.iter(),
            other,
        }
    }

    /// Iterator over union of two sets.
    ///
    /// Iteration order is: elements of this set followed by elements in the other set
    /// not present in this set.
    pub fn union<'a>(&'a self, other: &'a Self) -> Union<'a, T>
    where
        T: Eq + Hash,
    {
        Union {
            iter: self.iter().chain(other.difference(self)),
        }
    }

    /// Sort entries.
    pub fn sort(&mut self)
    where
        T: Ord,
    {
        self.0.sort_keys();
    }

    /// Equal if entries are equal in iteration order.
    pub fn eq_ordered(&self, other: &Self) -> bool
    where
        T: PartialEq,
    {
        self.0.eq_ordered(&other.0)
    }

    /// Hash entries in iteration order.
    ///
    /// Note, entries are not hashed, but previously computed hashes are hashed instead.
    pub fn hash_ordered<H: Hasher>(&self, state: &mut H)
    where
        T: Hash,
    {
        self.0.hash_ordered(state)
    }
}

impl<'a, T> IntoIterator for &'a SmallSet<T> {
    type Item = &'a T;
    type IntoIter = Iter<'a, T>;

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        Iter {
            iter: self.0.iter(),
        }
    }
}

impl<T> IntoIterator for SmallSet<T> {
    type Item = T;
    type IntoIter = IntoIter<T>;

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        IntoIter {
            iter: self.0.into_iter(),
        }
    }
}

impl<T> Extend<T> for SmallSet<T>
where
    T: Eq + Hash,
{
    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
        self.0.extend(iter.into_iter().map(|v| (v, ())));
    }
}

/// Iterator over the difference of two sets.
pub struct Difference<'a, T: 'a> {
    iter: Iter<'a, T>,
    other: &'a SmallSet<T>,
}

impl<'a, T: 'a> Iterator for Difference<'a, T>
where
    T: Hash + Eq,
{
    type Item = &'a T;

    #[allow(clippy::while_let_on_iterator)]
    fn next(&mut self) -> Option<Self::Item> {
        while let Some(item) = self.iter.next() {
            if !self.other.contains(item) {
                return Some(item);
            }
        }
        None
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (
            self.iter.len().saturating_sub(self.other.len()),
            Some(self.iter.len()),
        )
    }
}

/// Iterator over a union of two sets.
pub struct Union<'a, T: 'a> {
    iter: std::iter::Chain<Iter<'a, T>, Difference<'a, T>>,
}

impl<'a, T: 'a> Iterator for Union<'a, T>
where
    T: Hash + Eq,
{
    type Item = &'a T;

    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next()
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

/// Create a [`SmallSet`](SmallSet) from a list of values.
///
/// ## Example
///
/// ```
/// use starlark_map::smallset;
///
/// let set = smallset!{"a", "b"};
/// assert_eq!(set.contains("a"), true);
/// assert_eq!(set.len(), 2);
/// assert_eq!(set.contains("c"), false);
/// ```
#[macro_export]
macro_rules! smallset {
    (@single $($x:tt)*) => (());
    (@count $($rest:expr),*) => (<[()]>::len(&[$(smallset!(@single $rest)),*]));

    ($($key:expr,)+) => { smallset!($($key),+) };
    ($($key:expr),*) => {
        {
            let cap = smallset!(@count $($key),*);
            let mut set = $crate::small_set::SmallSet::with_capacity(cap);
            $(
                set.insert($key);
            )*
            set
        }
    };
}

impl<T: Serialize> Serialize for SmallSet<T> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        serializer.collect_seq(self.iter())
    }
}

impl<'de, T> Deserialize<'de> for SmallSet<T>
where
    T: Deserialize<'de> + Hash + Eq,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        struct SeqVisitor<T> {
            marker: PhantomData<SmallSet<T>>,
        }

        impl<'de, T> serde::de::Visitor<'de> for SeqVisitor<T>
        where
            T: serde::de::Deserialize<'de> + Hash + Eq,
        {
            type Value = SmallSet<T>;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("a sequence")
            }

            #[inline]
            fn visit_seq<A>(self, mut set: A) -> Result<Self::Value, A::Error>
            where
                A: serde::de::SeqAccess<'de>,
            {
                let mut values = SmallSet::with_capacity(set.size_hint().unwrap_or(0));
                while let Some(value) = set.next_element()? {
                    values.insert(value);
                }
                Ok(values)
            }
        }

        let visitor = SeqVisitor {
            marker: PhantomData,
        };
        deserializer.deserialize_seq(visitor)
    }
}

#[allow(clippy::from_iter_instead_of_collect)]
#[cfg(test)]
mod tests {
    use std::collections::HashSet;
    use std::rc::Rc;

    use dupe::Dupe;
    use dupe::IterDupedExt;

    use super::*;

    #[test]
    fn empty_set() {
        let m = SmallSet::<i8>::new();
        assert_eq!(m.is_empty(), true);
        assert_eq!(m.len(), 0);
        assert_eq!(m.iter().next(), None);
    }

    #[test]
    fn few_entries() {
        let entries1 = vec![(0), (1)];
        let m1 = entries1.iter().duped().collect::<SmallSet<_>>();

        let entries2 = vec![(1), (0)];
        let m2 = entries2.iter().duped().collect::<SmallSet<_>>();
        assert_eq!(m1.is_empty(), false);
        assert_eq!(m1.len(), 2);
        assert_eq!(m2.is_empty(), false);
        assert_eq!(m2.len(), 2);

        assert_eq!(m1.iter().eq(entries1.iter()), true);
        assert_eq!(m2.iter().eq(entries2.iter()), true);
        assert_eq!(m1.iter().eq(m2.iter()), false);
        assert_eq!(m1.eq(&m1), true);
        assert_eq!(m2.eq(&m2), true);
        assert_eq!(m1, m2);

        assert_ne!(m1, smallset![1])
    }

    #[test]
    fn many_entries() {
        let letters = 'a'..='z';

        let entries1 = letters;
        let m1 = entries1.clone().collect::<SmallSet<_>>();

        assert_eq!(m1.get(&'b'), Some(&'b'));
        assert_eq!(m1.get_index_of(&'b'), Some(1));

        assert_eq!(m1.get(&'!'), None);
        assert_eq!(m1.get_index_of(&'!'), None);

        let letters = ('a'..='z').rev();
        let entries2 = letters;
        let m2 = entries2.clone().collect::<SmallSet<_>>();
        assert_eq!(m1.is_empty(), false);
        assert_eq!(m1.len(), 26);
        assert_eq!(m2.is_empty(), false);
        assert_eq!(m2.len(), 26);

        assert_eq!(m1.clone().into_iter().eq(entries1), true);
        assert_eq!(m2.clone().into_iter().eq(entries2), true);
        assert_eq!(m1.iter().eq(m2.iter()), false);
        assert_eq!(m1.eq(&m1), true);
        assert_eq!(m2.eq(&m2), true);
        assert_eq!(m1, m2);

        let not_m1 = {
            let mut s = m1.clone();
            s.remove(&'a');
            s
        };
        assert_ne!(m1, not_m1);
    }

    #[test]
    fn small_set_macros() {
        let s = smallset![1, 4, 2];
        let mut i = s.into_iter();
        assert_eq!(i.next(), Some(1));
        assert_eq!(i.next(), Some(4));
        assert_eq!(i.next(), Some(2));
        assert_eq!(i.next(), None);
    }

    #[test]
    fn small_set_inserts() {
        let mut s = SmallSet::new();
        assert_eq!(s.insert(2), true);
        assert_eq!(s.insert(5), true);

        assert_eq!(s.insert(5), false);
    }

    #[test]
    fn get_or_insert() {
        let mut set = SmallSet::new();
        let x = set.get_or_insert(Rc::new(1)).dupe();
        let x1 = set.get_or_insert(Rc::new(1));
        assert!(Rc::ptr_eq(&x, x1));
    }

    #[test]
    fn get_or_insert_owned() {
        let mut set = SmallSet::new();
        let x = set.get_or_insert_owned(&Rc::new(1)).dupe();
        let x1 = set.get_or_insert_owned(&Rc::new(1));
        assert!(Rc::ptr_eq(&x, x1));
    }

    #[test]
    fn test_first() {
        let mut s = SmallSet::new();
        s.insert(1);
        assert_eq!(s.first(), Some(&1));
        s.insert(2);
        assert_eq!(s.first(), Some(&1));
        s.remove(&1);
        assert_eq!(s.first(), Some(&2));
    }

    #[test]
    fn test_last() {
        let mut s = SmallSet::new();
        s.insert(1);
        assert_eq!(s.last(), Some(&1));
        s.insert(2);
        assert_eq!(s.last(), Some(&2));
    }

    #[test]
    fn test_remove() {
        let mut h: HashSet<u32> = HashSet::from_iter([17]);
        let mut s: SmallSet<u32> = SmallSet::from_iter([17]);
        assert!(h.remove(&17));
        assert!(s.remove(&17));
        assert!(!h.remove(&17));
        assert!(!s.remove(&17));
    }

    #[test]
    fn test_difference() {
        let a = SmallSet::from_iter([1, 2, 3]);
        let b = SmallSet::from_iter([2, 4, 1]);
        let d = Vec::from_iter(a.difference(&b).copied());
        assert_eq!(vec![3], d);
    }

    #[test]
    fn test_union() {
        let a = SmallSet::from_iter([1, 2, 3]);
        let b = SmallSet::from_iter([2, 4, 1]);
        let d = Vec::from_iter(a.union(&b).copied());
        assert_eq!(vec![1, 2, 3, 4], d);
    }

    #[test]
    fn test_sort() {
        let mut a = SmallSet::from_iter([1, 3, 2]);
        a.sort();
        assert_eq!(vec![1, 2, 3], Vec::from_iter(a));
    }

    #[test]
    fn test_difference_size_hint() {
        let a = SmallSet::from_iter([1, 2, 3]);
        let b = SmallSet::from_iter([2]);
        let mut iter = a.difference(&b);
        assert_eq!((2, Some(3)), iter.size_hint());
        assert_eq!(Some(&1), iter.next());
        assert_eq!((1, Some(2)), iter.size_hint());
        assert_eq!(Some(&3), iter.next());
        assert_eq!((0, Some(0)), iter.size_hint());
        assert_eq!(None, iter.next());
    }

    #[test]
    fn test_json() {
        let mp = smallset! {"a".to_owned() , "b".to_owned() };
        let expected = serde_json::json!(["a", "b"]);
        assert_eq!(serde_json::to_value(&mp).unwrap(), expected);
        assert_eq!(
            serde_json::from_value::<SmallSet<String>>(expected).unwrap(),
            mp
        );
    }
}


/*
 * Copyright 2019 The Starlark in Rust Authors.
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//! Generic insertion sort (sort arbitrary collections, not just slices).

use std::ptr;

/// Find the insertion point for an element.
///
/// The array is sorted up to `next_unsorted`,
/// and the element to insert is at `next_unsorted`.
fn find_insertion_point<T: ?Sized>(
    array: &mut T,
    next_unsorted: usize,
    mut less: impl FnMut(&mut T, usize, usize) -> bool,
) -> usize {
    let mut i = next_unsorted;
    while i > 0 && less(array, next_unsorted, i - 1) {
        i -= 1;
    }
    i
}

/// `swap_shift` operation for generic `insertion_sort` implemented for slices.
///
/// Index `a` is strictly less than index `b`, and `b` is less than slice length.
/// Perform two operations simultaneously:
/// * Move the element at `b` to `a`
/// * Shift all elements in the range `a..b` one position to the right
pub(crate) fn slice_swap_shift<T>(slice: &mut [T], a: usize, b: usize) {
    // Assert parameters are valid because this function performs unsafe operations.
    assert!(a < b);
    assert!(b < slice.len());

    unsafe {
        let tmp = ptr::read(slice.as_mut_ptr().add(b));
        ptr::copy(slice.as_ptr().add(a), slice.as_mut_ptr().add(a + 1), b - a);
        ptr::write(slice.as_mut_ptr().add(a), tmp);
    }
}

/// Insertion sort for generic collections (not just slices).
pub(crate) fn insertion_sort<A: ?Sized>(
    array: &mut A,
    len: usize,
    mut less: impl FnMut(&mut A, usize, usize) -> bool,
    // Function takes two indices, `a` and `b`. `a` is strictly less than `b`.
    // Function moves the element at `b` to the position at `a`,
    // and simultaneously shifts all elements in the range `a..b` one position to the right.
    mut swap_shift: impl FnMut(&mut A, usize, usize),
) {
    for i in 1..len {
        // At this point, the array is sorted up to `i`.
        let insertion_point = find_insertion_point(array, i, &mut less);
        debug_assert!(insertion_point <= i);
        if insertion_point != i {
            // Move the element at `i` to the insertion point.
            swap_shift(array, insertion_point, i);
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::sorting::insertion::find_insertion_point;
    use crate::sorting::insertion::insertion_sort;
    use crate::sorting::insertion::slice_swap_shift;

    #[test]
    fn test_find_insertion_point() {
        fn find_insertion_point_ints(slice: &mut [u32]) -> usize {
            find_insertion_point(slice, slice.len() - 1, |slice, i, j| slice[i] < slice[j])
        }

        assert_eq!(0, find_insertion_point_ints(&mut [2, 4, 6, 0]));
        assert_eq!(0, find_insertion_point_ints(&mut [2, 4, 6, 1]));
        assert_eq!(1, find_insertion_point_ints(&mut [2, 4, 6, 2]));
        assert_eq!(1, find_insertion_point_ints(&mut [2, 4, 6, 3]));
        assert_eq!(2, find_insertion_point_ints(&mut [2, 4, 6, 4]));
        assert_eq!(2, find_insertion_point_ints(&mut [2, 4, 6, 5]));
        assert_eq!(3, find_insertion_point_ints(&mut [2, 4, 6, 6]));
    }

    #[test]
    fn test_insertion_sort() {
        fn insertion_sort_ints(slice: &mut [u32]) {
            insertion_sort(
                slice,
                slice.len(),
                |slice, i, j| {
                    // Compare / 100 to test stability.
                    slice[i] / 100 < slice[j] / 100
                },
                slice_swap_shift,
            );
        }

        let mut slice = [200, 400, 600];
        insertion_sort_ints(&mut slice);
        assert_eq!([200, 400, 600], slice);

        let mut slice = [600, 200, 400];
        insertion_sort_ints(&mut slice);
        assert_eq!([200, 400, 600], slice);

        // Now test sorting is stable.
        let mut slice = [202, 402, 602, 201, 401, 601];
        insertion_sort_ints(&mut slice);
        assert_eq!([202, 201, 402, 401, 602, 601], slice);
    }
}


/*
 * Copyright 2019 The Starlark in Rust Authors.
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pub(crate) mod insertion;


/*
 * Copyright 2019 The Starlark in Rust Authors.
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

use std::marker::PhantomData;
use std::ptr;
use std::ptr::NonNull;
use std::slice;

use dupe::Clone_;

use crate::vec2::Vec2;

/// Iterator over [`Vec2`] elements.
#[derive(Clone_)]
pub struct Iter<'a, A, B> {
    pub(crate) aaa: slice::Iter<'a, A>,
    pub(crate) bbb: NonNull<B>,
    pub(crate) _marker: PhantomData<slice::Iter<'a, B>>,
}

unsafe impl<A: Sync, B: Sync> Sync for Iter<'_, A, B> {}
unsafe impl<A: Sync, B: Sync> Send for Iter<'_, A, B> {}

impl<'s, A, B> Iterator for Iter<'s, A, B> {
    type Item = (&'s A, &'s B);

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        let a = self.aaa.next()?;
        let b = unsafe { &*self.bbb.as_ptr() };
        self.bbb = unsafe { NonNull::new_unchecked(self.bbb.as_ptr().add(1)) };
        Some((a, b))
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.aaa.size_hint()
    }
}

impl<'s, A, B> ExactSizeIterator for Iter<'s, A, B> {
    #[inline]
    fn len(&self) -> usize {
        self.aaa.len()
    }
}

impl<'s, A, B> DoubleEndedIterator for Iter<'s, A, B> {
    #[inline]
    fn next_back(&mut self) -> Option<Self::Item> {
        let a = self.aaa.next_back()?;
        let b = unsafe { &*self.bbb.as_ptr().add(self.aaa.len()) };
        Some((a, b))
    }
}

/// Iterator which consumes the [`Vec2`].
pub struct IntoIter<A, B> {
    /// Pointer to the next `A`. Updated as we iterate.
    pub(crate) aaa_begin: NonNull<A>,
    /// Pointer to the next `B`. Updated as we iterate.
    pub(crate) bbb_begin: NonNull<B>,
    /// Pointer to the end of the `bbb`. Updated as we iterate.
    pub(crate) bbb_end: NonNull<B>,
    /// The layout of `Vec2` is `[padding, aaa, bbb]`.
    /// This field is a pointer to `bbb`. Used for `Drop`.
    pub(crate) bbb_ptr: NonNull<B>,
    /// `Vec2` capacity. Used for `Drop`.
    pub(crate) cap: usize,
}

unsafe impl<A: Send, B: Send> Send for IntoIter<A, B> {}
unsafe impl<A: Sync, B: Sync> Sync for IntoIter<A, B> {}

impl<A, B> Iterator for IntoIter<A, B> {
    type Item = (A, B);

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        if self.bbb_begin == self.bbb_end {
            None
        } else {
            unsafe {
                let a = ptr::read(self.aaa_begin.as_ref());
                let b = ptr::read(self.bbb_begin.as_ref());
                self.aaa_begin = NonNull::new_unchecked(self.aaa_begin.as_ptr().add(1));
                self.bbb_begin = NonNull::new_unchecked(self.bbb_begin.as_ptr().add(1));
                Some((a, b))
            }
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let rem = self.len();
        (rem, Some(rem))
    }
}

impl<A, B> Drop for IntoIter<A, B> {
    fn drop(&mut self) {
        unsafe {
            let rem = self.len();
            ptr::drop_in_place(slice::from_raw_parts_mut(self.aaa_begin.as_ptr(), rem));
            ptr::drop_in_place(slice::from_raw_parts_mut(self.bbb_begin.as_ptr(), rem));
            Vec2::<A, B>::dealloc_impl(self.bbb_ptr, self.cap);
        }
    }
}

impl<A, B> ExactSizeIterator for IntoIter<A, B> {
    #[inline]
    fn len(&self) -> usize {
        unsafe { self.bbb_end.as_ptr().offset_from(self.bbb_begin.as_ptr()) as usize }
    }
}

impl<A, B> DoubleEndedIterator for IntoIter<A, B> {
    fn next_back(&mut self) -> Option<Self::Item> {
        if self.bbb_begin == self.bbb_end {
            None
        } else {
            unsafe {
                self.bbb_end = NonNull::new_unchecked(self.bbb_end.as_ptr().sub(1));
                let new_len = self.len();

                debug_assert!(ptr::eq(
                    self.bbb_begin.as_ptr().add(new_len),
                    self.bbb_end.as_ptr()
                ));

                let a = ptr::read(self.aaa_begin.as_ptr().add(new_len));
                let b = ptr::read(self.bbb_end.as_ptr());

                Some((a, b))
            }
        }
    }
}


/*
 * Copyright 2019 The Starlark in Rust Authors.
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//! A `Vec<(A, B)>` like object which stores `A` and `B` separately.

use std::alloc;
use std::alloc::Layout;
use std::alloc::LayoutError;
use std::cmp;
use std::cmp::Ordering;
use std::fmt::Debug;
use std::hash::Hash;
use std::hash::Hasher;
use std::marker::PhantomData;
use std::mem;
use std::mem::MaybeUninit;
use std::ptr;
use std::ptr::NonNull;
use std::slice;

use allocative::Allocative;
use allocative::Visitor;

use crate::sorting::insertion::insertion_sort;
use crate::sorting::insertion::slice_swap_shift;
pub use crate::vec2::iter::IntoIter;
pub use crate::vec2::iter::Iter;

mod iter;

#[derive(Eq, PartialEq, Debug)]
struct Vec2Layout<A, B> {
    layout: Layout,
    offset_of_bbb: usize,
    _marker: PhantomData<*mut (A, B)>,
}

impl<A, B> Vec2Layout<A, B> {
    fn new(cap: usize) -> Vec2Layout<A, B> {
        Self::new_checked(cap).unwrap_or_else(|err| {
            panic!(
                "Vec2Layout failed with {:?} when allocating capacity of {}",
                err, cap
            )
        })
    }

    fn new_checked(cap: usize) -> Result<Vec2Layout<A, B>, LayoutError> {
        debug_assert!(cap != 0);
        let a = Layout::array::<A>(cap)?;
        let b = Layout::array::<B>(cap)?;
        let (layout, offset_of_bbb) = a.extend(b)?;

        debug_assert!(offset_of_bbb <= layout.size());
        debug_assert!(layout.align() >= a.align());
        debug_assert!(layout.align() >= b.align());
        debug_assert!(offset_of_bbb % a.align() == 0);

        Ok(Vec2Layout {
            layout,
            offset_of_bbb,
            _marker: PhantomData,
        })
    }

    unsafe fn alloc(&self) -> NonNull<B> {
        let ptr: *mut u8 = alloc::alloc(self.layout);
        let bbb_ptr: *mut B = ptr.add(self.offset_of_bbb).cast();
        NonNull::new_unchecked(bbb_ptr)
    }

    unsafe fn dealloc(&self, bbb_ptr: NonNull<B>) {
        let ptr: *mut u8 = bbb_ptr.as_ptr().cast::<u8>().sub(self.offset_of_bbb);
        alloc::dealloc(ptr, self.layout)
    }
}

/// Array of pairs `(A, B)`, where `A` and `B` are stored separately.
/// This reduces memory consumption when `A` and `B` have different alignments.
pub struct Vec2<A, B> {
    // Layout is `[padding, A, A, ..., A, B, B, ..., B]`
    bbb_ptr: NonNull<B>,
    len: usize,
    cap: usize,
    _marker: PhantomData<(A, B)>,
}

unsafe impl<A: Send, B: Send> Send for Vec2<A, B> {}
unsafe impl<A: Sync, B: Sync> Sync for Vec2<A, B> {}

impl<A, B> Default for Vec2<A, B> {
    #[inline]
    fn default() -> Vec2<A, B> {
        Vec2::new()
    }
}

impl<A: Debug, B: Debug> Debug for Vec2<A, B> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_list().entries(self.iter()).finish()
    }
}

impl<A: Clone, B: Clone> Clone for Vec2<A, B> {
    fn clone(&self) -> Vec2<A, B> {
        let mut r = Vec2::with_capacity(self.len());
        for (a, b) in self.iter() {
            r.push(a.clone(), b.clone());
        }
        r
    }
}

impl<A, B> Vec2<A, B> {
    /// Empty vec.
    #[inline]
    pub const fn new() -> Vec2<A, B> {
        Vec2 {
            // Provide a dangling pointer aligned to both A and B, so that aaa_ptr()
            // returns a properly aligned pointer
            bbb_ptr: NonNull::<(A, B)>::dangling().cast(),
            len: 0,
            cap: 0,
            _marker: PhantomData,
        }
    }

    /// New instance with given capacity.
    #[inline]
    pub fn with_capacity(cap: usize) -> Vec2<A, B> {
        if cap == 0 {
            Vec2::new()
        } else {
            let bbb_ptr = unsafe { Vec2Layout::<A, B>::new(cap).alloc() };
            Vec2 {
                bbb_ptr,
                len: 0,
                cap,
                _marker: PhantomData,
            }
        }
    }

    /// Number of elements.
    #[inline]
    pub fn len(&self) -> usize {
        self.len
    }

    /// Capacity.
    #[inline]
    pub fn capacity(&self) -> usize {
        self.cap
    }

    /// Is empty.
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.len == 0
    }

    #[inline]
    fn aaa_ptr(&self) -> NonNull<A> {
        unsafe { NonNull::new_unchecked(self.bbb_ptr.cast::<A>().as_ptr().sub(self.cap)) }
    }

    #[inline]
    fn bbb_ptr(&self) -> NonNull<B> {
        self.bbb_ptr
    }

    #[inline]
    pub(crate) fn aaa(&self) -> &[A] {
        unsafe { slice::from_raw_parts(self.aaa_ptr().as_ptr(), self.len) }
    }

    #[inline]
    pub(crate) fn aaa_mut(&mut self) -> &mut [A] {
        unsafe { slice::from_raw_parts_mut(self.aaa_ptr().as_ptr(), self.len) }
    }

    #[inline]
    fn aaa_uninit(&mut self) -> &mut [MaybeUninit<A>] {
        unsafe { slice::from_raw_parts_mut(self.aaa_ptr().as_ptr() as *mut _, self.cap) }
    }

    #[inline]
    pub(crate) fn bbb(&self) -> &[B] {
        unsafe { slice::from_raw_parts(self.bbb_ptr().as_ptr(), self.len) }
    }

    #[inline]
    fn bbb_mut(&mut self) -> &mut [B] {
        unsafe { slice::from_raw_parts_mut(self.bbb_ptr().as_ptr(), self.len) }
    }

    #[inline]
    fn bbb_uninit(&mut self) -> &mut [MaybeUninit<B>] {
        unsafe { slice::from_raw_parts_mut(self.bbb_ptr().as_ptr() as *mut _, self.cap) }
    }

    // This is what `Vec` does.
    const MIN_NON_ZERO_CAP: usize = if mem::size_of::<(A, B)>() == 1 {
        8
    } else if mem::size_of::<(A, B)>() <= 1024 {
        4
    } else {
        1
    };

    #[cold]
    fn reserve_slow(&mut self, additional: usize) {
        debug_assert!(self.cap - self.len < additional);

        let required_cap = self.len.checked_add(additional).expect("capacity overflow");
        let new_cap = cmp::max(required_cap, Self::MIN_NON_ZERO_CAP);
        let new_cap = cmp::max(new_cap, self.cap * 2);
        let new = Self::with_capacity(new_cap);
        unsafe {
            ptr::copy_nonoverlapping(self.aaa_ptr().as_ptr(), new.aaa_ptr().as_ptr(), self.len);
            ptr::copy_nonoverlapping(self.bbb_ptr().as_ptr(), new.bbb_ptr().as_ptr(), self.len);
            self.dealloc();
            self.bbb_ptr = new.bbb_ptr;
            mem::forget(new);
            self.cap = new_cap;
        }
    }

    /// Reserve capacity for `additional` elements.
    #[inline]
    pub fn reserve(&mut self, additional: usize) {
        if self.cap - self.len < additional {
            self.reserve_slow(additional);
        }
    }

    #[inline]
    unsafe fn dealloc_impl(data: NonNull<B>, cap: usize) {
        if cap != 0 {
            Vec2Layout::<A, B>::new(cap).dealloc(data);
        }
    }

    /// Deallocate, but do not call destructors.
    #[inline]
    unsafe fn dealloc(&mut self) {
        Self::dealloc_impl(self.bbb_ptr, self.cap);
    }

    unsafe fn drop_in_place(&mut self) {
        ptr::drop_in_place::<[A]>(self.aaa_mut());
        ptr::drop_in_place::<[B]>(self.bbb_mut());
    }

    /// Push an element.
    #[inline]
    pub fn push(&mut self, a: A, b: B) {
        self.reserve(1);
        let len = self.len;
        unsafe {
            self.aaa_uninit().get_unchecked_mut(len).write(a);
            self.bbb_uninit().get_unchecked_mut(len).write(b);
        }
        self.len += 1;
    }

    /// Get an element reference by index.
    #[inline]
    pub fn get(&self, index: usize) -> Option<(&A, &B)> {
        if index < self.len {
            unsafe {
                let a = self.aaa().get_unchecked(index);
                let b = self.bbb().get_unchecked(index);
                Some((a, b))
            }
        } else {
            None
        }
    }

    /// Get an element reference by index skipping bounds check.
    #[inline]
    pub unsafe fn get_unchecked(&self, index: usize) -> (&A, &B) {
        debug_assert!(index < self.len);
        (
            self.aaa().get_unchecked(index),
            self.bbb().get_unchecked(index),
        )
    }

    /// Get an element mutable reference by index.
    #[inline]
    pub unsafe fn get_unchecked_mut(&mut self, index: usize) -> (&mut A, &mut B) {
        debug_assert!(index < self.len);
        let k_ptr = self.aaa_ptr().as_ptr();
        let v_ptr = self.bbb_ptr().as_ptr();
        (&mut *k_ptr.add(index), &mut *v_ptr.add(index))
    }

    #[inline]
    unsafe fn read(&self, index: usize) -> (A, B) {
        debug_assert!(index < self.len);
        let (a, b) = self.get_unchecked(index);
        (ptr::read(a), ptr::read(b))
    }

    /// Remove an element by index.
    ///
    /// This is an `O(n)` operation.
    pub fn remove(&mut self, index: usize) -> (A, B) {
        assert!(index < self.len);
        unsafe {
            let (a, b) = self.read(index);
            ptr::copy(
                self.aaa_ptr().as_ptr().add(index + 1),
                self.aaa_ptr().as_ptr().add(index),
                self.len - index - 1,
            );
            ptr::copy(
                self.bbb_ptr().as_ptr().add(index + 1),
                self.bbb_ptr().as_ptr().add(index),
                self.len - index - 1,
            );
            self.len -= 1;
            (a, b)
        }
    }

    /// Remove all elements.
    #[inline]
    pub fn clear(&mut self) {
        unsafe {
            self.drop_in_place();
            self.len = 0;
        }
    }

    /// Remove the last element.
    #[inline]
    pub fn pop(&mut self) -> Option<(A, B)> {
        let new_len = self.len.checked_sub(1)?;
        let (a, b) = unsafe { self.read(new_len) };
        self.len = new_len;
        Some((a, b))
    }

    /// Get the first element reference.
    #[inline]
    pub fn first(&self) -> Option<(&A, &B)> {
        self.get(0)
    }

    /// Get the last element reference.
    #[inline]
    pub fn last(&self) -> Option<(&A, &B)> {
        self.get(self.len.checked_sub(1)?)
    }

    /// If capacity exceeds length, shrink capacity to length.
    pub fn shrink_to_fit(&mut self) {
        if self.len() < self.capacity() {
            let mut new_vec = Vec2::with_capacity(self.len());
            for (a, b) in mem::take(self).into_iter() {
                new_vec.push(a, b);
            }
            *self = new_vec;
        } else {
            debug_assert!(self.len() == self.capacity());
        }
    }

    /// Iterate over the elements.
    #[inline]
    pub fn iter(&self) -> Iter<'_, A, B> {
        Iter {
            aaa: self.aaa().iter(),
            bbb: self.bbb_ptr(),
            _marker: PhantomData,
        }
    }

    pub(crate) fn sort_insertion_by<F>(&mut self, mut compare: F)
    where
        F: FnMut((&A, &B), (&A, &B)) -> Ordering,
    {
        insertion_sort(
            self,
            self.len,
            |vec2, i, j| unsafe {
                compare(vec2.get_unchecked(i), vec2.get_unchecked(j)) == Ordering::Less
            },
            |vec2, a, b| {
                slice_swap_shift(vec2.aaa_mut(), a, b);
                slice_swap_shift(vec2.bbb_mut(), a, b);
            },
        );
    }

    /// Sort the elements using given comparator.
    pub fn sort_by<F>(&mut self, mut compare: F)
    where
        F: FnMut((&A, &B), (&A, &B)) -> Ordering,
    {
        // Constant from rust stdlib.
        const MAX_INSERTION: usize = 20;
        if self.len() <= MAX_INSERTION {
            self.sort_insertion_by(compare);
            return;
        }

        // TODO: sort without allocation.
        // TODO: drain.
        let mut entries: Vec<(A, B)> = mem::take(self).into_iter().collect();
        entries.sort_by(|(xa, xb), (ya, yb)| compare((xa, xb), (ya, yb)));
        for (a, b) in entries {
            self.push(a, b);
        }
    }
}

impl<A, B> Drop for Vec2<A, B> {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            if self.cap != 0 {
                self.drop_in_place();
                self.dealloc();
            }
        }
    }
}

impl<'s, A, B> IntoIterator for &'s Vec2<A, B> {
    type Item = (&'s A, &'s B);
    type IntoIter = Iter<'s, A, B>;

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<A, B> IntoIterator for Vec2<A, B> {
    type Item = (A, B);
    type IntoIter = IntoIter<A, B>;

    #[inline]
    fn into_iter(self) -> IntoIter<A, B> {
        let iter = IntoIter {
            aaa_begin: self.aaa_ptr(),
            bbb_begin: self.bbb_ptr(),
            bbb_end: unsafe { NonNull::new_unchecked(self.bbb_ptr().as_ptr().add(self.len)) },
            bbb_ptr: self.bbb_ptr,
            cap: self.cap,
        };
        mem::forget(self);
        iter
    }
}

impl<A: PartialEq, B: PartialEq> PartialEq for Vec2<A, B> {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.len == other.len && self.iter().eq(other.iter())
    }
}

impl<A: Eq, B: Eq> Eq for Vec2<A, B> {}

impl<A: Hash, B: Hash> Hash for Vec2<A, B> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.len.hash(state);
        for (a, b) in self.iter() {
            a.hash(state);
            b.hash(state);
        }
    }
}

impl<A: Allocative, B: Allocative> Allocative for Vec2<A, B> {
    fn visit<'a, 'b: 'a>(&self, visitor: &'a mut Visitor<'b>) {
        let mut visitor = visitor.enter_self_sized::<Self>();
        if self.cap != 0 {
            let mut visitor =
                visitor.enter_unique(allocative::Key::new("ptr"), mem::size_of::<*const ()>());
            {
                let mut visitor = visitor.enter(
                    allocative::Key::new("data"),
                    Vec2Layout::<A, B>::new(self.cap).layout.size(),
                );
                for (a, b) in self {
                    a.visit(&mut visitor);
                    b.visit(&mut visitor);
                }
                visitor.exit();
            }
            visitor.exit();
        }
        visitor.exit();
    }
}

#[cfg(test)]
mod tests {
    use std::alloc::Layout;
    use std::marker::PhantomData;

    use crate::vec2::Vec2;
    use crate::vec2::Vec2Layout;

    #[test]
    fn test_layout_for() {
        assert_eq!(
            Vec2Layout {
                offset_of_bbb: 4,
                layout: Layout::from_size_align(8, 4).unwrap(),
                _marker: PhantomData,
            },
            Vec2Layout::<[u8; 3], u32>::new(1)
        );
    }

    #[test]
    fn test_alloc_dealloc() {
        unsafe {
            let layout = Vec2Layout::<[u8; 3], u32>::new(100);
            let data = layout.alloc();
            layout.dealloc(data);
        }
    }

    #[test]
    fn test_push() {
        let mut v = Vec2::new();
        v.push(1, 2);
        assert_eq!(1, v.len());
        assert_eq!(Some((&1, &2)), v.get(0));
    }

    #[test]
    fn test_push_many() {
        let mut v = Vec2::new();
        for i in 0..100 {
            v.push(i.to_string(), i * 2);
        }
        assert_eq!(100, v.len());
        for i in 0..100 {
            assert_eq!(Some((&i.to_string(), &(i * 2))), v.get(i));
        }
    }

    #[test]
    fn test_into_iter() {
        let mut v = Vec2::new();
        for i in 0..100 {
            v.push(i.to_string(), i * 2);
        }
        for (i, (a, b)) in v.into_iter().enumerate() {
            assert_eq!(i.to_string(), a);
            assert_eq!(i * 2, b);
        }
    }

    #[test]
    fn test_sort_insertion_by() {
        let mut v = Vec2::new();
        v.push(1, 2);
        v.push(3, 4);
        v.push(2, 3);
        v.push(3, 2);
        v.sort_insertion_by(|(xa, xb), (ya, yb)| (xa, xb).cmp(&(ya, yb)));
        assert_eq!(Some((&1, &2)), v.get(0));
        assert_eq!(Some((&2, &3)), v.get(1));
        assert_eq!(Some((&3, &2)), v.get(2));
        assert_eq!(Some((&3, &4)), v.get(3));
    }

    #[test]
    fn test_shrink_to_fit() {
        let mut v = Vec2::with_capacity(10);
        v.push("a".to_owned(), "b".to_owned());
        v.push("c".to_owned(), "d".to_owned());
        v.shrink_to_fit();
        for _ in 0..2 {
            assert_eq!(2, v.len());
            assert_eq!(2, v.capacity());
            assert_eq!(
                vec![("a", "b"), ("c", "d")],
                v.iter()
                    .map(|(a, b)| (a.as_str(), b.as_str()))
                    .collect::<Vec<_>>()
            );
        }
    }

    #[test]
    fn test_first() {
        let mut v: Vec2<u32, u32> = Vec2::new();
        assert_eq!(None, v.first());
        v.push(1, 2);
        assert_eq!(Some((&1, &2)), v.first());
        v.push(3, 4);
        assert_eq!(Some((&1, &2)), v.first());
    }

    #[test]
    fn test_last() {
        let mut v: Vec2<u32, u32> = Vec2::new();
        assert_eq!(None, v.last());
        v.push(1, 2);
        assert_eq!(Some((&1, &2)), v.last());
        v.push(3, 4);
        assert_eq!(Some((&3, &4)), v.last());
    }

    #[repr(align(16))]
    struct Align16;

    #[repr(align(8))]
    struct Align8;

    #[test]
    fn test_alignment() {
        let v: Vec2<Align16, Align8> = Vec2::new();
        assert_eq!(
            v.aaa_ptr()
                .as_ptr()
                .align_offset(std::mem::align_of::<Align16>()),
            0
        );
        assert_eq!(
            v.bbb_ptr()
                .as_ptr()
                .align_offset(std::mem::align_of::<Align8>()),
            0
        );
    }
}


/*
 * Copyright 2019 The Starlark in Rust Authors.
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#[cfg(rust_nightly)]
pub(crate) use std::intrinsics::likely;
#[cfg(not(rust_nightly))]
#[inline(always)]
pub(crate) fn likely(x: bool) -> bool {
    x
}