Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] Copy custom archived multibyte discriminants for enums with custom repr #482

Open
novacrazy opened this issue Mar 24, 2024 · 0 comments
Milestone

Comments

@novacrazy
Copy link
Contributor

I'm using rkyv in an RPC system where I have a Procedure enum that's basically:

#[repr(u16)]
enum Procedure {
    DoThingA(Box<ThingAData>) = 100,
    DoThingB(Box<ThingBData>) = 200,
    // many more...
}

where commands are grouped together and have custom discriminant values. My idea was to have the discriminants be constant, but allow room in between for more to be added in a way that is meaningful to humans. By keeping them constant in such a simple structure, it would be easy for CheckBytes to validate it even if more are added in the future, helping with stability when I update distributed systems gradually in a production environment.

Unfortunately, unless I'm missing something, rkyv currently generates new linear u8 discriminants for the Tag and Archived values/discriminants, due to its own compatibility concerns regarding Endianness and alignment.

To solve the Endian issue, I came up with the idea to double the width of my discriminants and mirror their bytes so the value is the same between Big/Little endian, and thereby making the Tag/Archived enum #[repr(u32)] (and maybe #[repr(u32, align(4))]), and immune to that cross-platform difference.

I implemented this manually Here, but would like a way to enable copying the raw multibyte discriminants into the Tag/Archived enum from the derive macros, as that would make my own code much more maintainable.

I could turn the enum in that referenced code into something that only generates:

#[repr(u32, align(4))]
#[derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
enum Procedure {
    DoThingA(Box<ThingAData>) = mirror_tag(100),
    DoThingB(Box<ThingBData>) = mirror_tag(200),
    // many more...
}

and rkyv could copy that repr information and custom discriminant expressions onto the Tag/Archived enum.

This could either be done via an attribute such as #[unsafe_archive_repr(u32, align(4))] (as suggested in Discord), or a variation of that which will assert at compile time if the discriminants are cross-Endian-safe, likely via checking of the Tag variants are mirrored.

So in essence, I'd like for rkyv to provide a way to specify the repr of the resulting Archived enum/tags, and copy the expressions that generate the discriminant values from the originating struct, such that I can create RPC enums that can maintain backwards compatibility in an elegant way.

@novacrazy novacrazy changed the title [Feature Request] Copy custom archived multibyte discriminants for enums [Feature Request] Copy custom archived multibyte discriminants for enums with custom repr Mar 24, 2024
@djkoloski djkoloski added this to the v0.8 milestone Mar 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants