@footgun/bitstream
Version:
bit oriented bit packing and unpacking
77 lines (54 loc) • 2.37 kB
Markdown
# footgun-bitstream
A bit oriented stream for packing and unpacking to a `Uint8Array`.
Useful for networking stuff, probably.
features:
* does not generate memory garbage
* data oriented design that doesn't hide stuff from you
* unit and fuzz tests
* no dependencies
* supports a lot of field types
* simple implementation, a few hundred lines
* no bounds checking bullshit to slow things down, handle your own business
# example
```javascript
import * as BitStream from '@footgun/bitstream'
// Optionally pass in a Uint8array you'd like to read/write to.
// if you don't pass one, a 1024 Uint8Array is created by default
const s = BitStream.create(new Uint8Array(2048))
// s is now initialized to a data structure you can read/write to.
// s.buf is the uint8array backing store
// s.offsetBits is the pointer to the next bit position the stream will read or write from.
// it's incremented automatically as you rad or write.
BitStream.write.uint8(s, 20) // write the number 28 as a uint8 to the stream
BitStream.write.float32(s, -49.02334976196289)
BitStream.write.uint(s, 5, 3) // write the number 5 as a 3 bit uint to the stream
// at this point s.offsetBits is set to 43 because that's how many bits we've written
BitStream.reset(s) // this resets the stream's offsetBits value back to 0
console.log(BitStream.read.uint8(s)) // prints 20
console.log(BitStream.read.float32(s)) // prints -49.02334976196289
console.log(BitStream.read.uint(s, 3)) // prints 5
```
# measuring stream bit size without allocating
Some times it's useful to know how many bits a given stream would pack to without allocating or writing the data.
You can achieve this with the `measure` operations:
```javascript
const s = BitStream.create(new Uint8Array(0)) // don't need any bytes allocated
BitStream.measure.uint8(s, 36)
BitStream.measure.uint(s, 12, 6)
BitStream.measure.str(s, "hello there, I'm a utf-8 string :o")
// at this point, s.buf is [], and s.offsetBits is 302
```
## supported types
* uint (N) arbitrary length unsigned ints where N = bitsize
* uint8
* uint16
* uint32
* uint64
* uleb128 (arbitrary length unsigned BigInts)
* float16
* float32
* float64
* unicode strings
* byte arrays
# references
Some of the original packing functions were derived from https://github.com/binaryjs/js-binarypack/blob/master/lib/binarypack.js