Proposal Details
In many wire formats (e.g., CBOR, zstandard, brotli, etc.), it is common to have fields in a integer semantically represent something else. Examples: zstd frame descriptor, window descriptor, CBOR packing for major type and "additional information", etc.
Bit fields can be trivial selected out an integer through bit-shift and mask operations, but the code is not as readable:
blockType := (blockHeader >> 1) & 3
I propose adding:
// Selects selects n bits starting at the ith bit.
// Indexing begins with the least-significant bit.
// Bit fields beyond the representation are implicitly treated as zero.
func Select(x uint, i, n uint) uint {
return (x >> i) & ((1 << n) - 1)
}
along with the 8, 16, 32, and 64 variants.
Example usage:
lastBlock := bits.Select32(blockHeader, 0, 1)
blockType := bits.Select32(blockHeader, 1, 2)
blockSize := bits.Select32(blockHeader, 3, 21)
The goal of this API is for readability of bit-twiddling code, rather than performance (which should not be affected).
Since Select is inlineable, it will practically be identical to the bitwise code that someone may write after the compiler applies constant folding.
An open API question is whether to represent a selection as:
- an offset and length as currently proposed, or
- a start offset and inclusive end offset, or
- a start offset and exclusive end offset (similar to slicing).
I chose to represent it as a length as this avoids any edge cases for when the end offset is before the start offset.
Proposal Details
In many wire formats (e.g., CBOR, zstandard, brotli, etc.), it is common to have fields in a integer semantically represent something else. Examples: zstd frame descriptor, window descriptor, CBOR packing for major type and "additional information", etc.
Bit fields can be trivial selected out an integer through bit-shift and mask operations, but the code is not as readable:
I propose adding:
along with the
8,16,32, and64variants.Example usage:
The goal of this API is for readability of bit-twiddling code, rather than performance (which should not be affected).
Since
Selectis inlineable, it will practically be identical to the bitwise code that someone may write after the compiler applies constant folding.An open API question is whether to represent a selection as:
I chose to represent it as a length as this avoids any edge cases for when the end offset is before the start offset.