summaryrefslogtreecommitdiffstats
path: root/third_party/rust/enum-map/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /third_party/rust/enum-map/src
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/enum-map/src')
-rw-r--r--third_party/rust/enum-map/src/arbitrary.rs28
-rw-r--r--third_party/rust/enum-map/src/enum_map_impls.rs115
-rw-r--r--third_party/rust/enum-map/src/internal.rs159
-rw-r--r--third_party/rust/enum-map/src/iter.rs415
-rw-r--r--third_party/rust/enum-map/src/lib.rs509
-rw-r--r--third_party/rust/enum-map/src/serde.rs98
6 files changed, 1324 insertions, 0 deletions
diff --git a/third_party/rust/enum-map/src/arbitrary.rs b/third_party/rust/enum-map/src/arbitrary.rs
new file mode 100644
index 0000000000..e8c988d292
--- /dev/null
+++ b/third_party/rust/enum-map/src/arbitrary.rs
@@ -0,0 +1,28 @@
+// SPDX-FileCopyrightText: 2021 Bruno Corrêa Zimmermann <brunoczim@gmail.com>
+// SPDX-FileCopyrightText: 2021 Kamila Borowska <kamila@borowska.pw>
+//
+// SPDX-License-Identifier: MIT OR Apache-2.0
+
+use crate::{enum_map, EnumArray, EnumMap};
+use arbitrary::{Arbitrary, Result, Unstructured};
+
+/// Requires crate feature `"arbitrary"`
+impl<'a, K: EnumArray<V>, V: Arbitrary<'a>> Arbitrary<'a> for EnumMap<K, V> {
+ fn arbitrary(u: &mut Unstructured<'a>) -> Result<EnumMap<K, V>> {
+ Ok(enum_map! {
+ _ => Arbitrary::arbitrary(u)?,
+ })
+ }
+
+ fn size_hint(depth: usize) -> (usize, Option<usize>) {
+ if K::LENGTH == 0 {
+ (0, Some(0))
+ } else {
+ let (lo, hi) = V::size_hint(depth);
+ (
+ lo.saturating_mul(K::LENGTH),
+ hi.and_then(|hi| hi.checked_mul(K::LENGTH)),
+ )
+ }
+ }
+}
diff --git a/third_party/rust/enum-map/src/enum_map_impls.rs b/third_party/rust/enum-map/src/enum_map_impls.rs
new file mode 100644
index 0000000000..545ff33ddc
--- /dev/null
+++ b/third_party/rust/enum-map/src/enum_map_impls.rs
@@ -0,0 +1,115 @@
+// SPDX-FileCopyrightText: 2017 - 2021 Kamila Borowska <kamila@borowska.pw>
+// SPDX-FileCopyrightText: 2021 Bruno Corrêa Zimmermann <brunoczim@gmail.com>
+// SPDX-FileCopyrightText: 2021 micycle
+// SPDX-FileCopyrightText: 2023 Nicolas Carranza <nicarran@yandex.com>
+//
+// SPDX-License-Identifier: MIT OR Apache-2.0
+
+use crate::{enum_map, EnumArray, EnumMap};
+use core::fmt::{self, Debug, Formatter};
+use core::hash::{Hash, Hasher};
+use core::iter::{Extend, FromIterator};
+use core::ops::{Index, IndexMut};
+
+impl<K: EnumArray<V> + Debug, V: Debug> Debug for EnumMap<K, V> {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ f.debug_map().entries(self).finish()
+ }
+}
+
+impl<K: EnumArray<V>, V> Extend<(K, V)> for EnumMap<K, V> {
+ fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I) {
+ for (key, value) in iter {
+ self[key] = value;
+ }
+ }
+}
+
+impl<'a, K, V> Extend<(&'a K, &'a V)> for EnumMap<K, V>
+where
+ K: EnumArray<V> + Copy,
+ V: Copy,
+{
+ fn extend<I: IntoIterator<Item = (&'a K, &'a V)>>(&mut self, iter: I) {
+ self.extend(iter.into_iter().map(|(&key, &value)| (key, value)));
+ }
+}
+
+impl<K, V> FromIterator<(K, V)> for EnumMap<K, V>
+where
+ Self: Default,
+ K: EnumArray<V>,
+{
+ fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
+ let mut map = EnumMap::default();
+ map.extend(iter);
+ map
+ }
+}
+
+impl<K: EnumArray<V>, V> Index<K> for EnumMap<K, V> {
+ type Output = V;
+
+ #[inline]
+ fn index(&self, key: K) -> &V {
+ &self.as_slice()[key.into_usize()]
+ }
+}
+
+impl<K: EnumArray<V>, V> IndexMut<K> for EnumMap<K, V> {
+ #[inline]
+ fn index_mut(&mut self, key: K) -> &mut V {
+ &mut self.as_mut_slice()[key.into_usize()]
+ }
+}
+
+// Implementations provided by derive attribute are too specific, and put requirements on K.
+// This is caused by rust-lang/rust#26925.
+impl<K: EnumArray<V>, V> Clone for EnumMap<K, V>
+where
+ K::Array: Clone,
+{
+ #[inline]
+ fn clone(&self) -> Self {
+ EnumMap {
+ array: self.array.clone(),
+ }
+ }
+}
+
+impl<K: EnumArray<V>, V> Copy for EnumMap<K, V> where K::Array: Copy {}
+
+impl<K: EnumArray<V>, V: PartialEq> PartialEq for EnumMap<K, V> {
+ #[inline]
+ fn eq(&self, other: &Self) -> bool {
+ self.as_slice() == other.as_slice()
+ }
+}
+
+impl<K: EnumArray<V>, V: Eq> Eq for EnumMap<K, V> {}
+
+impl<K: EnumArray<V>, V: Hash> Hash for EnumMap<K, V> {
+ #[inline]
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.as_slice().hash(state);
+ }
+}
+
+impl<K: EnumArray<V>, V: Default> Default for EnumMap<K, V> {
+ #[inline]
+ fn default() -> Self {
+ enum_map! { _ => V::default() }
+ }
+}
+
+impl<K: EnumArray<V>, V: PartialOrd> PartialOrd for EnumMap<K, V> {
+ fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
+ self.as_slice().partial_cmp(other.as_slice())
+ }
+}
+
+impl<K: EnumArray<V>, V: Ord> Ord for EnumMap<K, V> {
+ fn cmp(&self, other: &Self) -> core::cmp::Ordering {
+ self.as_slice().cmp(other.as_slice())
+ }
+}
diff --git a/third_party/rust/enum-map/src/internal.rs b/third_party/rust/enum-map/src/internal.rs
new file mode 100644
index 0000000000..2a6235d09d
--- /dev/null
+++ b/third_party/rust/enum-map/src/internal.rs
@@ -0,0 +1,159 @@
+// SPDX-FileCopyrightText: 2017 - 2023 Kamila Borowska <kamila@borowska.pw>
+// SPDX-FileCopyrightText: 2021 Bruno Corrêa Zimmermann <brunoczim@gmail.com>
+// SPDX-FileCopyrightText: 2022 philipp <descpl@yahoo.de>
+//
+// SPDX-License-Identifier: MIT OR Apache-2.0
+
+use core::cmp::Ordering;
+use core::convert::Infallible;
+
+/// Enum mapping type.
+///
+/// This trait is implemented by `#[derive(Enum)]`.
+///
+/// This trait is also implemented by `bool` and `u8`. While `u8` is
+/// strictly speaking not an actual enum, there are good reasons to consider
+/// it like one, as array of `u8` keys is a relatively common pattern.
+pub trait Enum: Sized {
+ /// Length of the enum.
+ const LENGTH: usize;
+
+ /// Takes an usize, and returns an element matching `into_usize` function.
+ fn from_usize(value: usize) -> Self;
+ /// Returns an unique identifier for a value within range of `0..Array::LENGTH`.
+ fn into_usize(self) -> usize;
+}
+
+/// Trait associating enum with an array.
+///
+/// This exists due to limitations of Rust compiler that prevent arrays from using
+/// associated constants in structures. The array length must match `LENGTH` of an
+/// `Enum`.
+pub trait EnumArray<V>: Enum {
+ /// Representation of an enum map for type `V`.
+ type Array: Array<V>;
+}
+
+/// Array for enum-map storage.
+///
+/// This trait is inteded for primitive array types (with fixed length).
+///
+/// # Safety
+///
+/// The array length needs to match actual storage.
+pub unsafe trait Array<V> {
+ // This is necessary duplication because the length in Enum trait can be
+ // provided by user and may not be trustworthy for unsafe code.
+ const LENGTH: usize;
+}
+
+unsafe impl<V, const N: usize> Array<V> for [V; N] {
+ const LENGTH: usize = N;
+}
+
+#[doc(hidden)]
+#[inline]
+pub fn out_of_bounds() -> ! {
+ panic!("index out of range for Enum::from_usize");
+}
+
+impl Enum for bool {
+ const LENGTH: usize = 2;
+
+ #[inline]
+ fn from_usize(value: usize) -> Self {
+ match value {
+ 0 => false,
+ 1 => true,
+ _ => out_of_bounds(),
+ }
+ }
+ #[inline]
+ fn into_usize(self) -> usize {
+ usize::from(self)
+ }
+}
+
+impl<T> EnumArray<T> for bool {
+ type Array = [T; Self::LENGTH];
+}
+
+impl Enum for () {
+ const LENGTH: usize = 1;
+
+ #[inline]
+ fn from_usize(value: usize) -> Self {
+ match value {
+ 0 => (),
+ _ => out_of_bounds(),
+ }
+ }
+ #[inline]
+ fn into_usize(self) -> usize {
+ 0
+ }
+}
+
+impl<T> EnumArray<T> for () {
+ type Array = [T; Self::LENGTH];
+}
+
+impl Enum for u8 {
+ const LENGTH: usize = 256;
+
+ #[inline]
+ fn from_usize(value: usize) -> Self {
+ value.try_into().unwrap_or_else(|_| out_of_bounds())
+ }
+ #[inline]
+ fn into_usize(self) -> usize {
+ usize::from(self)
+ }
+}
+
+impl<T> EnumArray<T> for u8 {
+ type Array = [T; Self::LENGTH];
+}
+
+impl Enum for Infallible {
+ const LENGTH: usize = 0;
+
+ #[inline]
+ fn from_usize(_: usize) -> Self {
+ out_of_bounds();
+ }
+ #[inline]
+ fn into_usize(self) -> usize {
+ match self {}
+ }
+}
+
+impl<T> EnumArray<T> for Infallible {
+ type Array = [T; Self::LENGTH];
+}
+
+impl Enum for Ordering {
+ const LENGTH: usize = 3;
+
+ #[inline]
+ fn from_usize(value: usize) -> Self {
+ match value {
+ 0 => Ordering::Less,
+ 1 => Ordering::Equal,
+ 2 => Ordering::Greater,
+ _ => out_of_bounds(),
+ }
+ }
+ #[inline]
+ fn into_usize(self) -> usize {
+ match self {
+ Ordering::Less => 0,
+ Ordering::Equal => 1,
+ Ordering::Greater => 2,
+ }
+ }
+}
+
+impl<T> EnumArray<T> for Ordering {
+ type Array = [T; Self::LENGTH];
+}
diff --git a/third_party/rust/enum-map/src/iter.rs b/third_party/rust/enum-map/src/iter.rs
new file mode 100644
index 0000000000..393d8d1027
--- /dev/null
+++ b/third_party/rust/enum-map/src/iter.rs
@@ -0,0 +1,415 @@
+#![allow(clippy::module_name_repetitions)]
+
+// SPDX-FileCopyrightText: 2017 - 2022 Kamila Borowska <kamila@borowska.pw>
+// SPDX-FileCopyrightText: 2020 Amanieu d'Antras <amanieu@gmail.com>
+// SPDX-FileCopyrightText: 2021 Bruno Corrêa Zimmermann <brunoczim@gmail.com>
+//
+// SPDX-License-Identifier: MIT OR Apache-2.0
+
+use crate::{EnumArray, EnumMap};
+use core::iter::{Enumerate, FusedIterator};
+use core::marker::PhantomData;
+use core::mem::ManuallyDrop;
+use core::ops::Range;
+use core::ptr;
+use core::slice;
+
+/// Immutable enum map iterator
+///
+/// This struct is created by `iter` method or `into_iter` on a reference
+/// to `EnumMap`.
+///
+/// # Examples
+///
+/// ```
+/// use enum_map::{enum_map, Enum};
+///
+/// #[derive(Enum)]
+/// enum Example {
+/// A,
+/// B,
+/// C,
+/// }
+///
+/// let mut map = enum_map! { Example::A => 3, _ => 0 };
+/// assert_eq!(map[Example::A], 3);
+/// for (key, &value) in &map {
+/// assert_eq!(value, match key {
+/// Example::A => 3,
+/// _ => 0,
+/// });
+/// }
+/// ```
+#[derive(Debug)]
+pub struct Iter<'a, K, V: 'a> {
+ _phantom: PhantomData<fn() -> K>,
+ iterator: Enumerate<slice::Iter<'a, V>>,
+}
+
+impl<'a, K: EnumArray<V>, V> Clone for Iter<'a, K, V> {
+ fn clone(&self) -> Self {
+ Iter {
+ _phantom: PhantomData,
+ iterator: self.iterator.clone(),
+ }
+ }
+}
+
+impl<'a, K: EnumArray<V>, V> Iterator for Iter<'a, K, V> {
+ type Item = (K, &'a V);
+ #[inline]
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iterator
+ .next()
+ .map(|(index, item)| (K::from_usize(index), item))
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.iterator.size_hint()
+ }
+
+ fn fold<B, F>(self, init: B, f: F) -> B
+ where
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.iterator
+ .map(|(index, item)| (K::from_usize(index), item))
+ .fold(init, f)
+ }
+}
+
+impl<'a, K: EnumArray<V>, V> DoubleEndedIterator for Iter<'a, K, V> {
+ #[inline]
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.iterator
+ .next_back()
+ .map(|(index, item)| (K::from_usize(index), item))
+ }
+}
+
+impl<'a, K: EnumArray<V>, V> ExactSizeIterator for Iter<'a, K, V> {}
+
+impl<'a, K: EnumArray<V>, V> FusedIterator for Iter<'a, K, V> {}
+
+impl<'a, K: EnumArray<V>, V> IntoIterator for &'a EnumMap<K, V> {
+ type Item = (K, &'a V);
+ type IntoIter = Iter<'a, K, V>;
+ #[inline]
+ fn into_iter(self) -> Self::IntoIter {
+ Iter {
+ _phantom: PhantomData,
+ iterator: self.as_slice().iter().enumerate(),
+ }
+ }
+}
+
+/// Mutable map iterator
+///
+/// This struct is created by `iter_mut` method or `into_iter` on a mutable
+/// reference to `EnumMap`.
+///
+/// # Examples
+///
+/// ```
+/// use enum_map::{enum_map, Enum};
+///
+/// #[derive(Debug, Enum)]
+/// enum Example {
+/// A,
+/// B,
+/// C,
+/// }
+///
+/// let mut map = enum_map! { Example::A => 3, _ => 0 };
+/// for (_, value) in &mut map {
+/// *value += 1;
+/// }
+/// assert_eq!(map, enum_map! { Example::A => 4, _ => 1 });
+/// ```
+#[derive(Debug)]
+pub struct IterMut<'a, K, V: 'a> {
+ _phantom: PhantomData<fn() -> K>,
+ iterator: Enumerate<slice::IterMut<'a, V>>,
+}
+
+impl<'a, K: EnumArray<V>, V> Iterator for IterMut<'a, K, V> {
+ type Item = (K, &'a mut V);
+ #[inline]
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iterator
+ .next()
+ .map(|(index, item)| (K::from_usize(index), item))
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.iterator.size_hint()
+ }
+
+ fn fold<B, F>(self, init: B, f: F) -> B
+ where
+ F: FnMut(B, Self::Item) -> B,
+ {
+ self.iterator
+ .map(|(index, item)| (K::from_usize(index), item))
+ .fold(init, f)
+ }
+}
+
+impl<'a, K: EnumArray<V>, V> DoubleEndedIterator for IterMut<'a, K, V> {
+ #[inline]
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.iterator
+ .next_back()
+ .map(|(index, item)| (K::from_usize(index), item))
+ }
+}
+
+impl<'a, K: EnumArray<V>, V> ExactSizeIterator for IterMut<'a, K, V> {}
+
+impl<'a, K: EnumArray<V>, V> FusedIterator for IterMut<'a, K, V> {}
+
+impl<'a, K: EnumArray<V>, V> IntoIterator for &'a mut EnumMap<K, V> {
+ type Item = (K, &'a mut V);
+ type IntoIter = IterMut<'a, K, V>;
+ #[inline]
+ fn into_iter(self) -> Self::IntoIter {
+ IterMut {
+ _phantom: PhantomData,
+ iterator: self.as_mut_slice().iter_mut().enumerate(),
+ }
+ }
+}
+
+/// A map iterator that moves out of map.
+///
+/// This struct is created by `into_iter` on `EnumMap`.
+///
+/// # Examples
+///
+/// ```
+/// use enum_map::{enum_map, Enum};
+///
+/// #[derive(Debug, Enum)]
+/// enum Example {
+/// A,
+/// B,
+/// }
+///
+/// let map = enum_map! { Example::A | Example::B => String::from("123") };
+/// for (_, value) in map {
+/// assert_eq!(value + "4", "1234");
+/// }
+/// ```
+pub struct IntoIter<K: EnumArray<V>, V> {
+ map: ManuallyDrop<EnumMap<K, V>>,
+ alive: Range<usize>,
+}
+
+impl<K: EnumArray<V>, V> Iterator for IntoIter<K, V> {
+ type Item = (K, V);
+ fn next(&mut self) -> Option<(K, V)> {
+ let position = self.alive.next()?;
+ Some((K::from_usize(position), unsafe {
+ ptr::read(&self.map.as_slice()[position])
+ }))
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.alive.size_hint()
+ }
+}
+
+impl<K: EnumArray<V>, V> DoubleEndedIterator for IntoIter<K, V> {
+ fn next_back(&mut self) -> Option<(K, V)> {
+ let position = self.alive.next_back()?;
+ Some((K::from_usize(position), unsafe {
+ ptr::read(&self.map.as_slice()[position])
+ }))
+ }
+}
+
+impl<K: EnumArray<V>, V> ExactSizeIterator for IntoIter<K, V> {}
+
+impl<K: EnumArray<V>, V> FusedIterator for IntoIter<K, V> {}
+
+impl<K: EnumArray<V>, V> Drop for IntoIter<K, V> {
+ #[inline]
+ fn drop(&mut self) {
+ unsafe {
+ ptr::drop_in_place(&mut self.map.as_mut_slice()[self.alive.clone()]);
+ }
+ }
+}
+
+impl<K: EnumArray<V>, V> IntoIterator for EnumMap<K, V> {
+ type Item = (K, V);
+ type IntoIter = IntoIter<K, V>;
+ #[inline]
+ fn into_iter(self) -> Self::IntoIter {
+ let len = self.len();
+ IntoIter {
+ map: ManuallyDrop::new(self),
+ alive: 0..len,
+ }
+ }
+}
+
+impl<K: EnumArray<V>, V> EnumMap<K, V> {
+ /// An iterator visiting all values. The iterator type is `&V`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use enum_map::enum_map;
+ ///
+ /// let map = enum_map! { false => 3, true => 4 };
+ /// let mut values = map.values();
+ /// assert_eq!(values.next(), Some(&3));
+ /// assert_eq!(values.next(), Some(&4));
+ /// assert_eq!(values.next(), None);
+ /// ```
+ #[inline]
+ pub fn values(&self) -> Values<V> {
+ Values(self.as_slice().iter())
+ }
+
+ /// An iterator visiting all values mutably. The iterator type is `&mut V`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use enum_map::enum_map;
+ ///
+ /// let mut map = enum_map! { _ => 2 };
+ /// for value in map.values_mut() {
+ /// *value += 2;
+ /// }
+ /// assert_eq!(map[false], 4);
+ /// assert_eq!(map[true], 4);
+ /// ```
+ #[inline]
+ pub fn values_mut(&mut self) -> ValuesMut<V> {
+ ValuesMut(self.as_mut_slice().iter_mut())
+ }
+
+ /// Creates a consuming iterator visiting all the values. The map
+ /// cannot be used after calling this. The iterator element type
+ /// is `V`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use enum_map::enum_map;
+ ///
+ /// let mut map = enum_map! { false => "hello", true => "goodbye" };
+ /// assert_eq!(map.into_values().collect::<Vec<_>>(), ["hello", "goodbye"]);
+ /// ```
+ #[inline]
+ pub fn into_values(self) -> IntoValues<K, V> {
+ IntoValues {
+ inner: self.into_iter(),
+ }
+ }
+}
+
+/// An iterator over the values of `EnumMap`.
+///
+/// This `struct` is created by the `values` method of `EnumMap`.
+/// See its documentation for more.
+pub struct Values<'a, V: 'a>(slice::Iter<'a, V>);
+
+impl<'a, V> Clone for Values<'a, V> {
+ fn clone(&self) -> Self {
+ Values(self.0.clone())
+ }
+}
+
+impl<'a, V: 'a> Iterator for Values<'a, V> {
+ type Item = &'a V;
+ #[inline]
+ fn next(&mut self) -> Option<&'a V> {
+ self.0.next()
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.0.size_hint()
+ }
+}
+
+impl<'a, V: 'a> DoubleEndedIterator for Values<'a, V> {
+ #[inline]
+ fn next_back(&mut self) -> Option<&'a V> {
+ self.0.next_back()
+ }
+}
+
+impl<'a, V: 'a> ExactSizeIterator for Values<'a, V> {}
+
+impl<'a, V: 'a> FusedIterator for Values<'a, V> {}
+
+/// A mutable iterator over the values of `EnumMap`.
+///
+/// This `struct` is created by the `values_mut` method of `EnumMap`.
+/// See its documentation for more.
+pub struct ValuesMut<'a, V: 'a>(slice::IterMut<'a, V>);
+
+impl<'a, V: 'a> Iterator for ValuesMut<'a, V> {
+ type Item = &'a mut V;
+ #[inline]
+ fn next(&mut self) -> Option<&'a mut V> {
+ self.0.next()
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.0.size_hint()
+ }
+}
+
+impl<'a, V: 'a> DoubleEndedIterator for ValuesMut<'a, V> {
+ #[inline]
+ fn next_back(&mut self) -> Option<&'a mut V> {
+ self.0.next_back()
+ }
+}
+
+impl<'a, V: 'a> ExactSizeIterator for ValuesMut<'a, V> {}
+
+impl<'a, V: 'a> FusedIterator for ValuesMut<'a, V> {}
+
+/// An owning iterator over the values of an `EnumMap`.
+///
+/// This `struct` is created by the `into_values` method of `EnumMap`.
+/// See its documentation for more.
+pub struct IntoValues<K: EnumArray<V>, V> {
+ inner: IntoIter<K, V>,
+}
+
+impl<K, V> Iterator for IntoValues<K, V>
+where
+ K: EnumArray<V>,
+{
+ type Item = V;
+
+ fn next(&mut self) -> Option<V> {
+ Some(self.inner.next()?.1)
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.inner.size_hint()
+ }
+}
+
+impl<K: EnumArray<V>, V> DoubleEndedIterator for IntoValues<K, V> {
+ fn next_back(&mut self) -> Option<V> {
+ Some(self.inner.next_back()?.1)
+ }
+}
+
+impl<K, V> ExactSizeIterator for IntoValues<K, V> where K: EnumArray<V> {}
+
+impl<K, V> FusedIterator for IntoValues<K, V> where K: EnumArray<V> {}
diff --git a/third_party/rust/enum-map/src/lib.rs b/third_party/rust/enum-map/src/lib.rs
new file mode 100644
index 0000000000..cb933a3a5c
--- /dev/null
+++ b/third_party/rust/enum-map/src/lib.rs
@@ -0,0 +1,509 @@
+// SPDX-FileCopyrightText: 2017 - 2023 Kamila Borowska <kamila@borowska.pw>
+// SPDX-FileCopyrightText: 2019 Riey <creeper844@gmail.com>
+// SPDX-FileCopyrightText: 2021 Alex Sayers <alex@asayers.com>
+// SPDX-FileCopyrightText: 2021 Bruno Corrêa Zimmermann <brunoczim@gmail.com>
+// SPDX-FileCopyrightText: 2022 Cass Fridkin <cass@cloudflare.com>
+// SPDX-FileCopyrightText: 2022 Mateusz Kowalczyk <fuuzetsu@fuuzetsu.co.uk>
+//
+// SPDX-License-Identifier: MIT OR Apache-2.0
+
+//! An enum mapping type.
+//!
+//! It is implemented using an array type, so using it is as fast as using Rust
+//! arrays.
+//!
+//! # Examples
+//!
+//! ```
+//! use enum_map::{enum_map, Enum, EnumMap};
+//!
+//! #[derive(Debug, Enum)]
+//! enum Example {
+//! A(bool),
+//! B,
+//! C,
+//! }
+//!
+//! let mut map = enum_map! {
+//! Example::A(false) => 0,
+//! Example::A(true) => 1,
+//! Example::B => 2,
+//! Example::C => 3,
+//! };
+//! map[Example::C] = 4;
+//!
+//! assert_eq!(map[Example::A(true)], 1);
+//!
+//! for (key, &value) in &map {
+//! println!("{:?} has {} as value.", key, value);
+//! }
+//! ```
+
+#![no_std]
+#![deny(missing_docs)]
+#![warn(clippy::pedantic)]
+
+#[cfg(feature = "arbitrary")]
+mod arbitrary;
+mod enum_map_impls;
+mod internal;
+mod iter;
+#[cfg(feature = "serde")]
+mod serde;
+
+#[doc(hidden)]
+pub use core::mem::{self, ManuallyDrop, MaybeUninit};
+#[doc(hidden)]
+pub use core::primitive::usize;
+use core::slice;
+#[doc(hidden)]
+// unreachable needs to be exported for compatibility with older versions of enum-map-derive
+pub use core::{panic, ptr, unreachable};
+pub use enum_map_derive::Enum;
+#[doc(hidden)]
+pub use internal::out_of_bounds;
+use internal::Array;
+pub use internal::{Enum, EnumArray};
+pub use iter::{IntoIter, IntoValues, Iter, IterMut, Values, ValuesMut};
+
+// SAFETY: initialized needs to represent number of initialized elements
+#[doc(hidden)]
+pub struct Guard<'a, K, V>
+where
+ K: EnumArray<V>,
+{
+ array_mut: &'a mut MaybeUninit<K::Array>,
+ initialized: usize,
+}
+
+impl<K, V> Drop for Guard<'_, K, V>
+where
+ K: EnumArray<V>,
+{
+ fn drop(&mut self) {
+ // This is safe as arr[..len] is initialized due to
+ // Guard's type invariant.
+ unsafe {
+ ptr::slice_from_raw_parts_mut(self.as_mut_ptr(), self.initialized).drop_in_place();
+ }
+ }
+}
+
+impl<'a, K, V> Guard<'a, K, V>
+where
+ K: EnumArray<V>,
+{
+ #[doc(hidden)]
+ pub fn as_mut_ptr(&mut self) -> *mut V {
+ self.array_mut.as_mut_ptr().cast::<V>()
+ }
+
+ #[doc(hidden)]
+ #[must_use]
+ pub fn new(array_mut: &'a mut MaybeUninit<K::Array>) -> Self {
+ Self {
+ array_mut,
+ initialized: 0,
+ }
+ }
+
+ #[doc(hidden)]
+ #[must_use]
+ #[allow(clippy::unused_self)]
+ pub fn storage_length(&self) -> usize {
+ // SAFETY: We need to use LENGTH from K::Array, as K::LENGTH is
+ // untrustworthy.
+ K::Array::LENGTH
+ }
+
+ #[doc(hidden)]
+ #[must_use]
+ pub fn get_key(&self) -> K {
+ K::from_usize(self.initialized)
+ }
+
+ #[doc(hidden)]
+ // Unsafe as it can write out of bounds.
+ pub unsafe fn push(&mut self, value: V) {
+ self.as_mut_ptr().add(self.initialized).write(value);
+ self.initialized += 1;
+ }
+}
+
+#[doc(hidden)]
+pub struct TypeEqualizer<'a, K, V>
+where
+ K: EnumArray<V>,
+{
+ pub enum_map: [EnumMap<K, V>; 0],
+ pub guard: Guard<'a, K, V>,
+}
+
+/// Enum map constructor.
+///
+/// This macro allows to create a new enum map in a type safe way. It takes
+/// a list of `,` separated pairs separated by `=>`. Left side is `|`
+/// separated list of enum keys, or `_` to match all unmatched enum keys,
+/// while right side is a value.
+///
+/// The iteration order when using this macro is not guaranteed to be
+/// consistent. Future releases of this crate may change it, and this is not
+/// considered to be a breaking change.
+///
+/// # Examples
+///
+/// ```
+/// use enum_map::{enum_map, Enum};
+///
+/// #[derive(Enum)]
+/// enum Example {
+/// A,
+/// B,
+/// C,
+/// D,
+/// }
+///
+/// let enum_map = enum_map! {
+/// Example::A | Example::B => 1,
+/// Example::C => 2,
+/// _ => 3,
+/// };
+/// assert_eq!(enum_map[Example::A], 1);
+/// assert_eq!(enum_map[Example::B], 1);
+/// assert_eq!(enum_map[Example::C], 2);
+/// assert_eq!(enum_map[Example::D], 3);
+/// ```
+#[macro_export]
+macro_rules! enum_map {
+ {$($t:tt)*} => {{
+ let mut uninit = $crate::MaybeUninit::uninit();
+ let mut eq = $crate::TypeEqualizer {
+ enum_map: [],
+ guard: $crate::Guard::new(&mut uninit),
+ };
+ if false {
+ // Safe because this code is unreachable
+ unsafe { (&mut eq.enum_map).as_mut_ptr().read() }
+ } else {
+ for _ in 0..(&eq.guard).storage_length() {
+ struct __PleaseDoNotUseBreakWithoutLabel;
+ let _please_do_not_use_continue_without_label;
+ let value;
+ #[allow(unreachable_code)]
+ loop {
+ _please_do_not_use_continue_without_label = ();
+ value = match (&eq.guard).get_key() { $($t)* };
+ break __PleaseDoNotUseBreakWithoutLabel;
+ };
+
+ unsafe { (&mut eq.guard).push(value); }
+ }
+ $crate::mem::forget(eq);
+ // Safe because the array was fully initialized.
+ $crate::EnumMap::from_array(unsafe { uninit.assume_init() })
+ }
+ }};
+}
+
+/// An enum mapping.
+///
+/// This internally uses an array which stores a value for each possible
+/// enum value. To work, it requires implementation of internal (private,
+/// although public due to macro limitations) trait which allows extracting
+/// information about an enum, which can be automatically generated using
+/// `#[derive(Enum)]` macro.
+///
+/// Additionally, `bool` and `u8` automatically derives from `Enum`. While
+/// `u8` is not technically an enum, it's convenient to consider it like one.
+/// In particular, [reverse-complement in benchmark game] could be using `u8`
+/// as an enum.
+///
+/// # Examples
+///
+/// ```
+/// use enum_map::{enum_map, Enum, EnumMap};
+///
+/// #[derive(Enum)]
+/// enum Example {
+/// A,
+/// B,
+/// C,
+/// }
+///
+/// let mut map = EnumMap::default();
+/// // new initializes map with default values
+/// assert_eq!(map[Example::A], 0);
+/// map[Example::A] = 3;
+/// assert_eq!(map[Example::A], 3);
+/// ```
+///
+/// [reverse-complement in benchmark game]:
+/// http://benchmarksgame.alioth.debian.org/u64q/program.php?test=revcomp&lang=rust&id=2
+pub struct EnumMap<K: EnumArray<V>, V> {
+ array: K::Array,
+}
+
+impl<K: EnumArray<V>, V: Default> EnumMap<K, V> {
+ /// Clear enum map with default values.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use enum_map::{Enum, EnumMap};
+ ///
+ /// #[derive(Enum)]
+ /// enum Example {
+ /// A,
+ /// B,
+ /// }
+ ///
+ /// let mut enum_map = EnumMap::<_, String>::default();
+ /// enum_map[Example::B] = "foo".into();
+ /// enum_map.clear();
+ /// assert_eq!(enum_map[Example::A], "");
+ /// assert_eq!(enum_map[Example::B], "");
+ /// ```
+ #[inline]
+ pub fn clear(&mut self) {
+ for v in self.as_mut_slice() {
+ *v = V::default();
+ }
+ }
+}
+
+#[allow(clippy::len_without_is_empty)]
+impl<K: EnumArray<V>, V> EnumMap<K, V> {
+ /// Creates an enum map from array.
+ #[inline]
+ pub const fn from_array(array: K::Array) -> EnumMap<K, V> {
+ EnumMap { array }
+ }
+
+ /// Create an enum map, where each value is the returned value from `cb`
+ /// using provided enum key.
+ ///
+ /// ```
+ /// # use enum_map_derive::*;
+ /// use enum_map::{enum_map, Enum, EnumMap};
+ ///
+ /// #[derive(Enum, PartialEq, Debug)]
+ /// enum Example {
+ /// A,
+ /// B,
+ /// }
+ ///
+ /// let map = EnumMap::from_fn(|k| k == Example::A);
+ /// assert_eq!(map, enum_map! { Example::A => true, Example::B => false })
+ /// ```
+ pub fn from_fn<F>(mut cb: F) -> Self
+ where
+ F: FnMut(K) -> V,
+ {
+ enum_map! { k => cb(k) }
+ }
+
+ /// Returns an iterator over enum map.
+ ///
+ /// The iteration order is deterministic, and when using [macro@Enum] derive
+ /// it will be the order in which enum variants are declared.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use enum_map::{enum_map, Enum};
+ ///
+ /// #[derive(Enum, PartialEq)]
+ /// enum E {
+ /// A,
+ /// B,
+ /// C,
+ /// }
+ ///
+ /// let map = enum_map! { E::A => 1, E::B => 2, E::C => 3};
+ /// assert!(map.iter().eq([(E::A, &1), (E::B, &2), (E::C, &3)]));
+ /// ```
+ #[inline]
+ pub fn iter(&self) -> Iter<K, V> {
+ self.into_iter()
+ }
+
+ /// Returns a mutable iterator over enum map.
+ #[inline]
+ pub fn iter_mut(&mut self) -> IterMut<K, V> {
+ self.into_iter()
+ }
+
+ /// Returns number of elements in enum map.
+ #[inline]
+ #[allow(clippy::unused_self)]
+ pub const fn len(&self) -> usize {
+ K::Array::LENGTH
+ }
+
+ /// Swaps two indexes.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use enum_map::enum_map;
+ ///
+ /// let mut map = enum_map! { false => 0, true => 1 };
+ /// map.swap(false, true);
+ /// assert_eq!(map[false], 1);
+ /// assert_eq!(map[true], 0);
+ /// ```
+ #[inline]
+ pub fn swap(&mut self, a: K, b: K) {
+ self.as_mut_slice().swap(a.into_usize(), b.into_usize());
+ }
+
+ /// Consumes an enum map and returns the underlying array.
+ ///
+ /// The order of elements is deterministic, and when using [macro@Enum]
+ /// derive it will be the order in which enum variants are declared.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use enum_map::{enum_map, Enum};
+ ///
+ /// #[derive(Enum, PartialEq)]
+ /// enum E {
+ /// A,
+ /// B,
+ /// C,
+ /// }
+ ///
+ /// let map = enum_map! { E::A => 1, E::B => 2, E::C => 3};
+ /// assert_eq!(map.into_array(), [1, 2, 3]);
+ /// ```
+ pub fn into_array(self) -> K::Array {
+ self.array
+ }
+
+ /// Returns a reference to the underlying array.
+ ///
+ /// The order of elements is deterministic, and when using [macro@Enum]
+ /// derive it will be the order in which enum variants are declared.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use enum_map::{enum_map, Enum};
+ ///
+ /// #[derive(Enum, PartialEq)]
+ /// enum E {
+ /// A,
+ /// B,
+ /// C,
+ /// }
+ ///
+ /// let map = enum_map! { E::A => 1, E::B => 2, E::C => 3};
+ /// assert_eq!(map.as_array(), &[1, 2, 3]);
+ /// ```
+ pub const fn as_array(&self) -> &K::Array {
+ &self.array
+ }
+
+ /// Returns a mutable reference to the underlying array.
+ ///
+ /// The order of elements is deterministic, and when using [macro@Enum]
+ /// derive it will be the order in which enum variants are declared.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use enum_map::{enum_map, Enum};
+ ///
+ /// #[derive(Enum, PartialEq)]
+ /// enum E {
+ /// A,
+ /// B,
+ /// C,
+ /// }
+ ///
+ /// let mut map = enum_map! { E::A => 1, E::B => 2, E::C => 3};
+ /// map.as_mut_array()[1] = 42;
+ /// assert_eq!(map.as_array(), &[1, 42, 3]);
+ /// ```
+ pub fn as_mut_array(&mut self) -> &mut K::Array {
+ &mut self.array
+ }
+
+ /// Converts an enum map to a slice representing values.
+ ///
+ /// The order of elements is deterministic, and when using [macro@Enum]
+ /// derive it will be the order in which enum variants are declared.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use enum_map::{enum_map, Enum};
+ ///
+ /// #[derive(Enum, PartialEq)]
+ /// enum E {
+ /// A,
+ /// B,
+ /// C,
+ /// }
+ ///
+ /// let map = enum_map! { E::A => 1, E::B => 2, E::C => 3};
+ /// assert_eq!(map.as_slice(), &[1, 2, 3]);
+ /// ```
+ #[inline]
+ pub fn as_slice(&self) -> &[V] {
+ unsafe { slice::from_raw_parts(ptr::addr_of!(self.array).cast(), K::Array::LENGTH) }
+ }
+
+ /// Converts a mutable enum map to a mutable slice representing values.
+ #[inline]
+ pub fn as_mut_slice(&mut self) -> &mut [V] {
+ unsafe { slice::from_raw_parts_mut(ptr::addr_of_mut!(self.array).cast(), K::Array::LENGTH) }
+ }
+
+ /// Returns an enum map with function `f` applied to each element in order.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use enum_map::enum_map;
+ ///
+ /// let a = enum_map! { false => 0, true => 1 };
+ /// let b = a.map(|_, x| f64::from(x) + 0.5);
+ /// assert_eq!(b, enum_map! { false => 0.5, true => 1.5 });
+ /// ```
+ pub fn map<F, T>(self, mut f: F) -> EnumMap<K, T>
+ where
+ F: FnMut(K, V) -> T,
+ K: EnumArray<T>,
+ {
+ struct DropOnPanic<K, V>
+ where
+ K: EnumArray<V>,
+ {
+ position: usize,
+ map: ManuallyDrop<EnumMap<K, V>>,
+ }
+ impl<K, V> Drop for DropOnPanic<K, V>
+ where
+ K: EnumArray<V>,
+ {
+ fn drop(&mut self) {
+ unsafe {
+ ptr::drop_in_place(&mut self.map.as_mut_slice()[self.position..]);
+ }
+ }
+ }
+ let mut drop_protect = DropOnPanic {
+ position: 0,
+ map: ManuallyDrop::new(self),
+ };
+ enum_map! {
+ k => {
+ let value = unsafe { ptr::read(&drop_protect.map.as_slice()[drop_protect.position]) };
+ drop_protect.position += 1;
+ f(k, value)
+ }
+ }
+ }
+}
diff --git a/third_party/rust/enum-map/src/serde.rs b/third_party/rust/enum-map/src/serde.rs
new file mode 100644
index 0000000000..9ac434d5d0
--- /dev/null
+++ b/third_party/rust/enum-map/src/serde.rs
@@ -0,0 +1,98 @@
+// SPDX-FileCopyrightText: 2017 - 2023 Kamila Borowska <kamila@borowska.pw>
+// SPDX-FileCopyrightText: 2021 Bruno Corrêa Zimmermann <brunoczim@gmail.com>
+//
+// SPDX-License-Identifier: MIT OR Apache-2.0
+
+use crate::{enum_map, EnumArray, EnumMap};
+use core::fmt;
+use core::marker::PhantomData;
+use serde::de::{self, Deserialize, Deserializer, Error, MapAccess, SeqAccess};
+use serde::ser::{Serialize, SerializeTuple, Serializer};
+
+/// Requires crate feature `"serde"`
+impl<K: EnumArray<V> + Serialize, V: Serialize> Serialize for EnumMap<K, V> {
+ fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
+ if serializer.is_human_readable() {
+ serializer.collect_map(self)
+ } else {
+ let mut tup = serializer.serialize_tuple(self.len())?;
+ for value in self.values() {
+ tup.serialize_element(value)?;
+ }
+ tup.end()
+ }
+ }
+}
+
+/// Requires crate feature `"serde"`
+impl<'de, K, V> Deserialize<'de> for EnumMap<K, V>
+where
+ K: EnumArray<V> + EnumArray<Option<V>> + Deserialize<'de>,
+ V: Deserialize<'de>,
+{
+ fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
+ if deserializer.is_human_readable() {
+ deserializer.deserialize_map(HumanReadableVisitor(PhantomData))
+ } else {
+ deserializer.deserialize_tuple(K::LENGTH, CompactVisitor(PhantomData))
+ }
+ }
+}
+
+struct HumanReadableVisitor<K, V>(PhantomData<(K, V)>);
+
+impl<'de, K, V> de::Visitor<'de> for HumanReadableVisitor<K, V>
+where
+ K: EnumArray<V> + EnumArray<Option<V>> + Deserialize<'de>,
+ V: Deserialize<'de>,
+{
+ type Value = EnumMap<K, V>;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ write!(formatter, "a map")
+ }
+
+ fn visit_map<M: MapAccess<'de>>(self, mut access: M) -> Result<Self::Value, M::Error> {
+ let mut entries = EnumMap::default();
+ while let Some((key, value)) = access.next_entry()? {
+ entries[key] = Some(value);
+ }
+ for value in entries.values() {
+ value
+ .as_ref()
+ .ok_or_else(|| M::Error::custom("key not specified"))?;
+ }
+ Ok(enum_map! { key => entries[key].take().unwrap() })
+ }
+}
+
+struct CompactVisitor<K, V>(PhantomData<(K, V)>);
+
+impl<'de, K, V> de::Visitor<'de> for CompactVisitor<K, V>
+where
+ K: EnumArray<V> + EnumArray<Option<V>> + Deserialize<'de>,
+ V: Deserialize<'de>,
+{
+ type Value = EnumMap<K, V>;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ write!(formatter, "a sequence")
+ }
+
+ fn visit_seq<M: SeqAccess<'de>>(self, mut access: M) -> Result<Self::Value, M::Error> {
+ let mut entries = EnumMap::default();
+ let len = entries.len();
+ {
+ let mut iter = entries.values_mut();
+ while let Some(place) = iter.next() {
+ *place = Some(access.next_element()?.ok_or_else(|| {
+ M::Error::invalid_length(
+ len - iter.len() - 1,
+ &"a sequence with as many elements as there are variants",
+ )
+ })?);
+ }
+ }
+ Ok(enum_map! { key => entries[key].take().unwrap() })
+ }
+}