sharksforarms / deku

Declarative binary reading and writing: bit-level, symmetric, serialization/deserialization
Apache License 2.0
1.15k stars 55 forks source link

Request for Enhancement: Remove need for #[deku(id = "N)] in exhaustive defininition of discriminants of enum. #251

Open dorianprill opened 2 years ago

dorianprill commented 2 years ago

I have an enum with 256 variants for which the discriminant is defined for all of them. Currently deku requires me to annotate every variant with #[deku(id = "N)] although the discriminant is already defined in the code, which feels very redundant. Here is a minimal example, which does not work without the id annotation:

#![feature(arbitrary_enum_discriminant)]
use deku::prelude::*;
#[derive(Debug, PartialEq, DekuRead, DekuWrite)]
#[deku(type = "u8")]
#[repr(u8)]
pub enum ServerMessage {
    #[deku(id = "0")]
    GameLoading = 0x00,
    #[deku(id = "1")]
    GameFlags {
        difficulty: u8,
        arena_flags: u32,
        is_expansion: u8,
        is_ladder: u8,
    } = 0x01,
    #[deku(id = "2")]
    LoadSuccessful = 0x02,
    #[deku(id = "3")]
    LoadAct {
        act: u8,
        map_id: u32,
        area_id: u16,
        automap: u32,
    } = 0x03,
    //...
    // messages defined until discriminant 0xFF
}

fn main() {
}

If i omit #[deku(id = "N)] i get the following error:

 --> src/main.rs:3:28
  |
3 | #[derive(Debug, PartialEq, DekuRead, DekuWrite)]
  |                            ^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
  |
  = note: this error originates in the derive macro `DekuRead` (in Nightly builds, run with -Z macro-backtrace for more info)

Would it be possible to check if the enum discriminants are exhaustively defined and remove the need for #[deku(id = "N)] in this case?

sharksforarms commented 2 years ago

Interesting! It may be possible to extend the way deku get's an id value if none is specified.

Relevant code section: https://github.com/sharksforarms/deku/blob/31ffd8db236e5153f57c66fac7db85acb277947a/deku-derive/src/macros/deku_read.rs#L182-L188

I suspect we'd need to actually look at the declaration and extract the discriminant value as oppose to generating runtime code since the only way of getting this value is by having a value construction of an enum (which we don't have when reading): https://doc.rust-lang.org/beta/unstable-book/language-features/arbitrary-enum-discriminant.html