go-restruct / restruct

Rich binary (de)serialization library for Golang
https://restruct.io/
ISC License
360 stars 17 forks source link

Ability to pass buffer to `restruct.Pack` #12

Open jchv opened 7 years ago

jchv commented 7 years ago

Right now, restruct.Pack always creates a new []byte slice to store the output. While this is convenient, it is probably not ideal in all cases to do this. There are some cases where you want to reuse a buffer.

A good example would be a blob of data that is loaded into memory containing many structures. To write back to the structure, you may want to call restruct.Pack and write directly to the slice. As is, though, copying to the slice would have to be done manually, separately.

Another possible example is where high performance is desired, an area where restruct currently lacks. You could use a pool to reuse buffers that are known to be large enough to contain all of the data.

Right now a couple questions remain:

  1. What is the ideal way to implement this API? Should restruct.Pack be made less convenient, or should a new lower-level set of APIs handle this concern?

    My thoughts here are that restruct.Pack should be broken to be orthogonal, and that restruct.SizeOf should exist. Right now there's no public API to get the size, so you wouldn't know how large to make your buffer anyway. Perhaps more annoying is that you can't avoid the sizing phase even if your struct size is known ahead of time.

  2. If we hit the end of a buffer, what should happen?

    I think that it should return error. This seems desirable especially when you expect the struct to be the same size.

Breaking the API could allow for some nice features. We could add a return that specifies how many bytes were actually consumed or produced in both APIs, which may be useful for cases that involve dynamic arrays.

Making the API more orthogonal is probably the best choice, but even if that is done, there's no doubt the restruct.Pack function is still useful. So, there should probably be a wrapper that implements this functionality, making it easy to update by replacing restruct.Pack with another call. The question of what to call this new name is still open.