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

Question: how are tuple struct enum variants encoded #7

Open
TheButlah opened this issue Jan 16, 2025 · 1 comment
Open

Question: how are tuple struct enum variants encoded #7

TheButlah opened this issue Jan 16, 2025 · 1 comment

Comments

@TheButlah
Copy link

TheButlah commented Jan 16, 2025

The documentation for the derive macro says that enum variants are encoded as a two-element array, with the first element being the variant id and the second element being the contents.

However, I couldn't find information on how/if the variant payload is encoded when it is a tuple struct.

For example, suppose, such I have an encoding like this:

#[derive(Encode, Decode)]
struct S {
    a: u8,
    b: u8,
}

#[derive(Encode, Decode)]
enum E {
    Foo(S)
    Bar(S)
}

#[cbor(transparent)] is not possible for enum variants, so I wanted to ask: is the S directly encoded into the second element of the array or is there some additional overhead involved by treating it as a tuple that wraps an S? In other words, is the tuple transparent?

@twittner
Copy link
Owner

twittner commented Jan 19, 2025

However, I couldn't find information on how/if the variant payload is encoded when it is a tuple struct.

The documentation states: "By default or if a struct has the #[cbor(array)] attribute, it will be represented as a CBOR array. Its index numbers are represened by the position of the field value in this array. [...] If a struct has the #[cbor(map)] attribute attached, then it will be represented as a CBOR map with keys corresponding to the numeric index value [...]"

This applies regardless of whether a struct is nested in an enum or not. In your example, S is encoded as a CBOR array. Encoding E results in a 2-element array, with the second element being the variant with an array of two elements.

Whenever you are not sure how types are encoded, you could also try minicbor::display to get a textual representation, e.g.

use minicbor::{Encode, Decode};

#[derive(Encode, Decode)]
struct S {
    #[n(0)] a: u8,
    #[n(1)] b: u8,
}

#[derive(Encode, Decode)]
enum E {
    #[n(0)] Foo(#[n(0)] S),
    #[n(1)] Bar(#[n(0)] S)
}

fn main() {
    let bytes = minicbor::to_vec(E::Bar(S { a: 42, b: 99 })).unwrap();
    println!("{}", minicbor::display(&bytes));
}

gives:

[1, [[42, 99]]]

#[cbor(transparent)] is not possible for enum variants, so I wanted to ask: is the S directly encoded into the second element of the array or is there some additional overhead involved by treating it as a tuple that wraps an S? In other words, is the tuple transparent?

The encoding of S is independent of E, so the section about enum encoding applies as stated. The struct members of S are currently not encoded without their array, i.e. like [1, [42, 99]] in the example above.

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