Skip to content
This repository was archived by the owner on Sep 11, 2023. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
strategy:
matrix:
toolchain:
- 1.61
- "1.65"
- stable
- beta
- nightly
Expand Down
7 changes: 1 addition & 6 deletions enum-map-derive/src/derive_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ impl EnumGenerator {
quote! {
#[automatically_derived]
impl ::enum_map::Enum for #name {
const LENGTH: ::enum_map::usize = #length;
type Array<__EnumMapInternalV> = [__EnumMapInternalV; #length];

#[inline]
fn from_usize(value: ::enum_map::usize) -> Self {
Expand All @@ -53,11 +53,6 @@ impl EnumGenerator {
}
}
}

#[automatically_derived]
impl<V> ::enum_map::EnumArray<V> for #name {
type Array = [V; #length];
}
}
}

Expand Down
7 changes: 1 addition & 6 deletions enum-map-derive/src/derive_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ impl StructGenerator {
quote! {
#[automatically_derived]
impl ::enum_map::Enum for #name {
const LENGTH: ::enum_map::usize = #length;
type Array<__EnumMapInternalV> = [__EnumMapInternalV; #length];

#[inline]
fn from_usize(value: ::enum_map::usize) -> Self {
Expand All @@ -114,11 +114,6 @@ impl StructGenerator {
#into_usize
}
}

#[automatically_derived]
impl<V> ::enum_map::EnumArray<V> for #name {
type Array = [V; #length];
}
}
}
}
2 changes: 1 addition & 1 deletion enum-map-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,6 @@ pub fn derive_enum_map(input: proc_macro::TokenStream) -> proc_macro::TokenStrea

fn type_length(ty: &Type) -> TokenStream {
quote! {
<#ty as ::enum_map::Enum>::LENGTH
::enum_map::enum_len::<#ty>()
}
}
2 changes: 1 addition & 1 deletion enum-map/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "enum-map"
version = "2.6.2"
authors = ["Konrad Borowski <[email protected]>"]
edition = "2021"
rust-version = "1.61"
rust-version = "1.65"
repository = "https://github.com/xfix/enum-map"
license = "MIT OR Apache-2.0"
description = "A map with C-like enum keys represented internally as an array"
Expand Down
12 changes: 7 additions & 5 deletions enum-map/src/arbitrary.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
use crate::{enum_map, EnumArray, EnumMap};
use crate::internal::Array;
use crate::{enum_map, Enum, EnumMap};
use arbitrary::{Arbitrary, Result, Unstructured};

/// Requires crate feature `"arbitrary"`
impl<'a, K: EnumArray<V>, V: Arbitrary<'a>> Arbitrary<'a> for EnumMap<K, V> {
impl<'a, K: Enum, 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 {
let len = K::Array::<V>::LENGTH;
if len == 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)),
lo.saturating_mul(len),
hi.and_then(|hi| hi.checked_mul(len)),
)
}
}
Expand Down
32 changes: 16 additions & 16 deletions enum-map/src/enum_map_impls.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
use crate::{enum_map, EnumArray, EnumMap};
use crate::{enum_map, Enum, 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> {
impl<K: Enum + 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> {
impl<K: Enum, 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;
Expand All @@ -20,7 +20,7 @@ impl<K: EnumArray<V>, V> Extend<(K, V)> for EnumMap<K, V> {

impl<'a, K, V> Extend<(&'a K, &'a V)> for EnumMap<K, V>
where
K: EnumArray<V> + Copy,
K: Enum + Copy,
V: Copy,
{
fn extend<I: IntoIterator<Item = (&'a K, &'a V)>>(&mut self, iter: I) {
Expand All @@ -31,7 +31,7 @@ where
impl<K, V> FromIterator<(K, V)> for EnumMap<K, V>
where
Self: Default,
K: EnumArray<V>,
K: Enum,
{
fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
let mut map = EnumMap::default();
Expand All @@ -40,7 +40,7 @@ where
}
}

impl<K: EnumArray<V>, V> Index<K> for EnumMap<K, V> {
impl<K: Enum, V> Index<K> for EnumMap<K, V> {
type Output = V;

#[inline]
Expand All @@ -49,7 +49,7 @@ impl<K: EnumArray<V>, V> Index<K> for EnumMap<K, V> {
}
}

impl<K: EnumArray<V>, V> IndexMut<K> for EnumMap<K, V> {
impl<K: Enum, 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()]
Expand All @@ -58,9 +58,9 @@ impl<K: EnumArray<V>, V> IndexMut<K> for EnumMap<K, V> {

// 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>
impl<K: Enum, V> Clone for EnumMap<K, V>
where
K::Array: Clone,
K::Array<V>: Clone,
{
#[inline]
fn clone(&self) -> Self {
Expand All @@ -70,38 +70,38 @@ where
}
}

impl<K: EnumArray<V>, V> Copy for EnumMap<K, V> where K::Array: Copy {}
impl<K: Enum, V> Copy for EnumMap<K, V> where K::Array<V>: Copy {}

impl<K: EnumArray<V>, V: PartialEq> PartialEq for EnumMap<K, V> {
impl<K: Enum, 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: Enum, V: Eq> Eq for EnumMap<K, V> {}

impl<K: EnumArray<V>, V: Hash> Hash for EnumMap<K, V> {
impl<K: Enum, 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> {
impl<K: Enum, 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> {
impl<K: Enum, 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> {
impl<K: Enum, V: Ord> Ord for EnumMap<K, V> {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.as_slice().cmp(other.as_slice())
}
Expand Down
54 changes: 15 additions & 39 deletions enum-map/src/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,39 +9,35 @@ use core::convert::Infallible;
/// 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;
/// Representation of an enum.
///
/// For an enum with four elements it looks like this.
///
/// ```
/// type Array<V> = [V; 4];
/// ```
type Array<V>: Array;

/// 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> {
pub unsafe trait Array {
// 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] {
unsafe impl<V, const N: usize> Array for [V; N] {
const LENGTH: usize = N;
}

Expand All @@ -52,7 +48,7 @@ pub fn out_of_bounds() -> ! {
}

impl Enum for bool {
const LENGTH: usize = 2;
type Array<V> = [V; 2];

#[inline]
fn from_usize(value: usize) -> Self {
Expand All @@ -68,12 +64,8 @@ impl Enum for bool {
}
}

impl<T> EnumArray<T> for bool {
type Array = [T; Self::LENGTH];
}

impl Enum for () {
const LENGTH: usize = 1;
type Array<V> = [V; 1];

#[inline]
fn from_usize(value: usize) -> Self {
Expand All @@ -88,12 +80,8 @@ impl Enum for () {
}
}

impl<T> EnumArray<T> for () {
type Array = [T; Self::LENGTH];
}

impl Enum for u8 {
const LENGTH: usize = 256;
type Array<V> = [V; 256];

#[inline]
fn from_usize(value: usize) -> Self {
Expand All @@ -105,12 +93,8 @@ impl Enum for u8 {
}
}

impl<T> EnumArray<T> for u8 {
type Array = [T; Self::LENGTH];
}

impl Enum for Infallible {
const LENGTH: usize = 0;
type Array<V> = [V; 0];

#[inline]
fn from_usize(_: usize) -> Self {
Expand All @@ -122,12 +106,8 @@ impl Enum for Infallible {
}
}

impl<T> EnumArray<T> for Infallible {
type Array = [T; Self::LENGTH];
}

impl Enum for Ordering {
const LENGTH: usize = 3;
type Array<V> = [V; 3];

#[inline]
fn from_usize(value: usize) -> Self {
Expand All @@ -147,7 +127,3 @@ impl Enum for Ordering {
}
}
}

impl<T> EnumArray<T> for Ordering {
type Array = [T; Self::LENGTH];
}
Loading