google / zerocopy

https://discord.gg/MAvWH2R6zk
Apache License 2.0
1.56k stars 98 forks source link

Support deriving AsBytes on types with type parameters #10

Open joshlf opened 2 years ago

joshlf commented 2 years ago

Migrated from https://fxbug.dev/100235

In order to accomplish this, we need to be able to emit an impl which is bounded by a const expr, which requires the unstable feature generic_const_exprs. This issue is blocked until that feature is stabilized.

bjorn3 commented 1 year ago

Would it be possible to have a special case if the type parameter has a bound on ByteOrder and only on ByteOrder by checking all implementations of ByteOrder? ByteOrder is a sealed trait, so all implementations of it are known. This would make it much easier to write code that handles file formats that can be both little and big endian.

joshlf commented 1 year ago

I'm not sure what the relevance of ByteOrder is here? The byteorder-aware types in the byteorder module implement AsBytes, but a type can satisfy the rules of AsBytes even if its type parameters do not implement ByteOrder. What's the connection you're getting at?

bjorn3 commented 1 year ago

I did like to have types like

#[derive(FromBytes)]
struct Foo<B: ByteOrder> {
    a: U32<B>,
    b: U32<B>,
}

to work with both little endian and big endian using the same type definition. However the restriction of not having any type parameters when deriving FromBytes prevents this. I thought it did be easier to allow FromBytes just for type parameters bound by ByteOrder than implementing the general case.

joshlf commented 1 year ago

That code should work fine. It's just #[derive(AsBytes)] that doesn't currently support generics (actually, on ToT, it supports generics on a struct so long as that struct is also #[repr(transparent)] or #[repr(packed)]).

bjorn3 commented 1 year ago

(actually, on ToT, it supports generics on a struct so long as that struct is also #[repr(transparent)] or #[repr(packed)]).

I see. Adding #[repr(packed)] would work for my case.

InternetOfTofu commented 1 year ago

I wonder if single field #[repr(C)] generic structs can be treated the same way as #[repr(transparent)] for this purpose?

joshlf commented 1 year ago

They could, but I'm not sure what the point would be. If you're considering adding #[derive(AsBytes)] to such a type, then:

gio256 commented 3 months ago

@joshlf I'm interested in working on this. Would you be interested in seeing an exploration of any of the following?

joshlf commented 3 months ago

Thanks for your interest! The type-level representation of size and alignment is what we'd consider. I'll warn you that the design space there is large and there are lots of thorns, and since any traits introduced will be part of our public API, we'll be very nitpicky about the exact design. That said, it would be great to have some experimentation with this at a minimum, and if you're willing to put up with our nitpickiness, then a full implementation would obviously be very welcome!

For inspiration, see: https://github.com/google/zerocopy/issues/1316#issuecomment-2120930160 (although I haven't looked closely at those examples, and I'm not sure whether they address all of our needs).