Naively this struct contains 5 bytes of data: x and y both need a one-byte discriminant + a one-byte payload, and z is one byte. This is confirmed by std::mem::size_of::<S>().
But, since each Option only uses one bit of its discriminant, you could actually save a byte by storing x's and yâs discriminant bits in the same byte. You could store up to eight Option discriminants in the same byte in this manner. One could consider this an advanced niche optimization: an Optionâs discriminant byte has a niche that another Option can make use of. Is there any way to enable this optimization?
The representation you propose is incompatible with being able to create references such as &mut s.x. In principle, it could exist â #[repr(packed)] already prohibits references â but there is nothing like it in the language now.
Side nit: default layouts are unspecified, not guaranteed to be optimal in any particular way, and not guaranteed to not change.[1] So you can't necessarily draw solid conclusions from the size today.
If the bytes only need to represent up to 255 distinct values, rather than 256, then you can make use of NonZero<T> through Option<NonZero<u8>> which does allow taking references. If the value you don't need is 56, you can just wrapping sub or xor with 56 before storing in the NonZero<u8> and do the reverse upon retrieval.