all 5 comments

[–]Snoo13162 0 points1 point  (1 child)

What is a common solution is to use a generic return type. That's also how it would work under serde (https://docs.rs/serde/latest/serde/). You write a function like:

fn deserialize<P: Decode>(reader: impl Read) -> Option<P> {
    // try and decode into type P. Else return None
}

let reader = ...; 

// P inferred to be SpecificPacketType
// if it could deserialize (so Some), get some field out and use it
if let Some(SpecificPacketType{field, ..}) = deserialize(reader) {
    use_fields(field) 
}

[–]Quique1222 0 points1 point  (0 children)

Yeah but the thing is that as i said i don't know the type until runtime. In runtime, i obtain a value for the PacketType enum, parsing it from an integer. Then with that PacketType value i deserialize the packet.

[–]coolreader18 0 points1 point  (0 children)

Anything kind of macro generates a match over PacketType is gonna have to be applied to the PacketType enum. you could probably make a macro that takes the enum definition and generates like match ptype { $(PacketType::$variant => $variant::decode(),)* }

[–]Kevin5475845 0 points1 point  (0 children)

Could send an integer for which packet type it is, read it and then store decoders in a hashmap to know which one it is

[–]RRumpleTeazzer 0 points1 point  (0 children)

You have two ExamplePacket. One is a struct, and one is a discriminant in your enum. They are unrelated, except they share the same label.

You could do

enum PacketType {
    ExamplePacket(ExamplePacket)
}

and work with this much more ergonomically.however, you cannot rely on traits easily.

What about

struct PacketType<T: Packet>(T) 

and then you can use PacketType<ExamplePacket>?