deku icon indicating copy to clipboard operation
deku copied to clipboard

Support existing enums

Open OliverGavin opened this issue 4 years ago • 3 comments

Hi, I have been playing around with this library and it is really nice and easy to create parsers with. I just have one minor issue; having to create my own types for existing enums like IpAddr:

use std::net::{Ipv4Addr, Ipv6Addr};

use deku::prelude::*;

#[derive(Debug, PartialEq, DekuRead, DekuWrite)]
#[deku(endian = "big")]
struct Data {
    // it would be nice to use IpAddr instead.
    // assuming IpAddr implements the From trait...
    // maybe: #[deku(type = "u32", id_from = "IpAddr", id_map = "[(1, Ipv4Addr), (2, Ipv6Addr)]")]
    ip: MyIpAddr,
}

#[derive(Debug, PartialEq, DekuRead, DekuWrite)]
#[deku(type = "u32", endian = "endian", ctx = "endian: deku::ctx::Endian")]
enum MyIpAddr {
    #[deku(id = "1")]
    V4(Ipv4Addr),
    #[deku(id = "2")]
    V6(Ipv6Addr),
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_6() {
        let input = b"\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01";
        let (_, output) = Data::from_bytes((input, 0)).unwrap();
        assert_eq!(output, Data{ ip: MyIpAddr::V6(Ipv6Addr::LOCALHOST) });
        assert_eq!(output.to_bytes().unwrap(), input)
    }
}

I am new to rust but for the particular type of enum being used here it seems like it would be straight forward to rely on the From/Into traits (which is implemented for IpAddr) and the existing support in Deku for Ipv4Addr and Ipv6Addr somehow when generating code. I know reader/writer attributes are an an option but this would be much easier.

This would probably have to be a little better generalized and maybe take more complex enum types into account such as using enums with the id already as a value on each enumeration such as this EtherType implementation. For example:

#[deku(type = "u32", id_using = "EtherType")]
etherType: EtherType,

For this particular case I can probably use this implementation anyways.

I guess the main point is that it would be nice in cases where the domain is already modeled to not have to copy (or potentially have to deal with both types) or pollute the existing types. This is similar to another issue (albeit focused on structs): https://github.com/sharksforarms/deku/issues/174

OliverGavin avatar Apr 11 '21 19:04 OliverGavin

Hey @OliverGavin I'm a bit confused on your use case. The data format you described [type:u32][value:v4 or v6] and the example code you provided is how I'd approach it too. Is the problem or annoyance the fact that you need to recreate the IpAddr enum?

Both of these use cases do seem related to https://github.com/sharksforarms/deku/issues/174

sharksforarms avatar Apr 16 '21 01:04 sharksforarms

Yeah, it just seems unnecessary to recreate enums and have the client code have to deal with potentially two different representations of the same thing. IP addresses are fairly straight forward but I wouldn't like to be duplicating other enums potentially in packages I don't control (and probably shouldn't be adding deku to).

OliverGavin avatar Apr 17 '21 09:04 OliverGavin

@OliverGavin https://github.com/sharksforarms/deku/issues/225 may be useful

sharksforarms avatar Jun 15 '21 15:06 sharksforarms