-
Notifications
You must be signed in to change notification settings - Fork 37
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
Add little-endian support #46
base: master
Are you sure you want to change the base?
Conversation
This is an interesting approach, and thanks for taking the initiative to implement it. I have a couple thoughts:
|
These are all good questions. This implementation is something I put together in a few hours as a proof of concept, and I wanted to see whether you thought this approach makes sense before I spent a lot more time on it. I have now also pushed my original experiments with the monomorphization approach, so you can see what that looks like: it is on the MonomorphizationI am also still not sure whether the runtime branching is the most idiomatic Rust way to implement this. It is definitely unusual to have a runtime check every time a raw NBT field is read from the input, and it might be that the monomorphization approach makes more sense in the end. My main reasoning was that when you have a client library that uses both the little-endian and big-endian encodings, they would get essentially two complete copies of the library, each copy specialized for one encoding. Of course, generating specialized code is exactly the point of monomorphization, but the question is where to draw the monomorphization "boundary". In the runtime-checking based implementation, we get two copies of some small functions, whereas if we propagate the type parameters up to the top-level library functions, we get two copies of most of the library. Getting (at worst) two copies of the library might not be so bad since (1) the library is not that large, so there wouldn't be a large explosion in code size. (2) most client libraries would only use one encoding, since they probably wouldn't have to deal with Java and Bedrock Edition formats at the same time, hence they only get one copy without any unnecessary runtime checks. (3) It might also be possible to avoid two copies being generated by using a trait object (i.e., Another argument for having the endianness be a runtime parameter instead of a type parameter is that type parameters are more annoying to pass around. In Rust, when you want to explicitly specify one type parameter, you have to specify all of them (although some can be inferred). By restructuring the external API somewhat, it is possible to avoid having to write the additional type parameters everywhere, for instance by having the endianness be specified once on a struct, like so: struct Foo<E: ByteOrder> {
_marker: PhantomData<E>,
}
impl<E: ByteOrder> Foo<E> {
fn from_reader<R: io::Read>(...) {
}
} API changesThe main external API change is that all of the serialization/deserialization functions, like Internally, the main change is that functions like There are also some more minor changes, such as replacing Styling and name changesI think that the name changes you might be referring to are the changes in the With regards to the style changes, I replaced |
This pull request adds support for little-endian encoding (#21), which is what Bedrock Edition uses for encoding NBT data. The encoding (i.e., big endian or little endian) is determined by a parameter passed to the serialization/deserialization functions at runtime.
Initially, I implemented it differently, by having the encoding be a compile-time type parameter (making functions generic over <B: ByteOrder>), but this led to a proliferation of type parameters, and would essentially lead to two copies of the library being generated during monomorphization. Therefore, I thought the runtime encoding selection makes the most sense.
I also fixed the tests and benchmarks, but didn't add any new tests/documentation yet. I would be glad to hear if you have any comments or suggestions about my approach and implementation.