Git Product home page Git Product logo

enum-map's Introduction

enum-map's People

Contributors

amanieu avatar asayers avatar brunoczim avatar dependabot[bot] avatar enaut avatar fuuzetsu avatar hcpl avatar kamilaborowska avatar michel-slm avatar nicarran avatar phimuemue avatar riey avatar vmedea avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

enum-map's Issues

enum_map! is unusable as a const initializer, and the array field being private makes manual initialization impossible too

enum_map! is probably not fixable in stable Rust without the unstable const fn support, unless there's some clever approach I'm not seeing.

However, making the field public would allow to manually do it.

There's also the possibility of writing an enum_with_map! macro that would create both an enum and an enum map const (by just writing both the variants and the array items in the same order as provided by the user), which is easy and might be good enough in practice.

Possible implementation of such a macro (after changing EnumMap to be a tuple struct with a public array field):

#[macro_export]
macro_rules! enum_with_map {
	{$(#[$m:meta])* enum $e:ident, const $n:ident : EnumMap<_, $d:ty> = {$($k:ident => $v:expr),*};} => {
        $(#[$m])* #[derive(EnumMap)] enum $e {
            $($k),*
        }

        const $n: EnumMap<$e, $d> = EnumMap([
            $($v),*
        ]);
    };
}

Stabilize enum-map

For 1.0.0, an Internal interface which will likely be renamed to Enum will need to be stabilized. The plan is once const generics become stable (see rust-lang/rust#44580) - although worth noting that this doesn't need full const generics, just being able to use associated consts within a struct, an Internal trait would be rewritten as such.

trait Enum {
    const DISCRIMINANTS: usize;
    fn discriminant(self) -> usize;
    fn from_discriminant(discriminant: usize) -> Self;
}

Expose the `array` field (or add `as_array(&self) -> &K::Array`)

It's currently possible to:

  • Create EnumMap from K::Array with from_array
  • Destructure EnumMap to K::Array with into_array
  • Get a slice reference with as_slice and as_mut_slice

But it's currently not possible to get a reference to K::Array directly, mutable or not. This is useful if the contents aren't Clone-able but we still want to iterate over the values directly (without concerning ourselves with the keys).

At this point, it seems that just exposing the array field of EnumMap as public should be fair game: we already have setter/getter and hiding it just makes it inconvenient.

Clippy fails for single variant enum with Derive

error: any number modulo 1 will be 0
  --> some_filename.rs:13:10
   |
13 | #[derive(enum_map::Enum, Debug, Copy, Clone)]
#[derive(enum_map::Enum)]
pub enum Side {
    Bottom,
}

I'm not entirely sure what to do about it, just putting it here anyway.

`from_usize` gives a generic, misleading panic message on out-of-bounds

Currently, the implementation of from_usize for derive(Enum) will panic if given an out-of-bounds integer. That seems fine.

However, the panic message is currently:

panicked at 'internal error: entered unreachable code'

To me, that suggests an internal logic error in the derived impl, which doesn't appear to be the case. This case is trivially reachable if the caller provides a bogus integer. unreachable is an unusual way of handling this; for instance, slice index out of bounds does not print unreachable but rather that a slice index was out of bounds.

As a user I think it'd be a better experience if the message were something like index out of range for Enum::from_usize.

Strange code generated in enum_map_derive?

If we have an enum like this:

pub enum Scens {
    Zero,
    One,
    Two,
    Three,
    Four,
    Five,
}

doing #[derive(Enum)] produces code that looks like this:

pub fn from_usize(v: usize) -> Scens {
    use Scens::*;
    if v < 1 {
        Zero
    } else if v < 2 {
        One
    } else if v < 3 {
        Two
    } else if v < 4 {
        Three
    } else if v < 5 {
        Four
    } else if v < 6 {
        Five
    } else {
        unreachable!()
    }
}

This seems strange to me and the compiler: building with optimisation results in a large chain of comparisons and conditional jumps.

If instead we would generate

pub fn from_usize(v: usize) -> Scens {
    use Scens::*;
    if v == 0 {
        Zero
    } else if v == 1 {
        One
    } else if v == 2 {
        Two
    } else if v == 3 {
        Three
    } else if v == 4 {
        Four
    } else if v == 5 {
        Five
    } else {
        unreachable!()
    }
}

or the less-verbose

pub fn from_usize(v: usize) -> Scens {
    use Scens::*;
    match v {
        0 => Zero,
        1 => One,
        2 => Two,
        3 => Three,
        4 => Four,
        5 => Five,
        _ => unreachable!()
    }
}

both of these produce simpler and faster code: check if the value is in range (< 6 in this case) and then accept an answer as-is.

However I assume the if v < x + 1 implementation wasn't pick at random: is there some information about this? Is there a downside of the proposed methods? It seems very simple to switch the code over to equality check which compiler is much happier about.

These generated methods are quite hot in our code-base which is how I stumbled upon this.

Godbolt link: https://rust.godbolt.org/z/a7E3oE81s

Add Enum for tuples

It seems logical that (A, B) where A: Enum, B: Enum would be basically the same as a struct's derivation, which is a cartesian product. I don't think we're allowed to implement this ourselves as tuples are always a foreign type, but it could be implemented for up to some length of tuples in the crate.

I personally want this so that I can produce enums via this utility function I've made:

#[inline(always)]
pub fn enum_iter<E: enum_map::Enum>() -> impl DoubleEndedIterator<Item = E> + Clone {
    (0..E::LENGTH).map(|i| E::from_usize(i))
}

without having to nest the enum_iter calls if there's multiple which I want to produce from.

(Side note: the enum_iter function might also be useful to have put in.)

I could make an MR if it's an amenable feature to include.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.