OverviewFilesCommitsIssuesDocsReleasesPeers

mirall-cli / node_modules / compact-encoding-bitfield / index.js

70 lines · javascript ref:
const c = require('compact-encoding')

module.exports = function bitfield(length) {
  if (length > 64) {
    throw new RangeError('Bitfield cannot be larger than 64 bits')
  }

  let byteLength
  if (length < 8) byteLength = 1
  else if (length <= 16) byteLength = 2
  else if (length <= 32) byteLength = 4
  else byteLength = 8

  return {
    preencode(state) {
      state.end++ // Length byte, used for data when byteLength === 1

      if (byteLength === 1);
      else if (byteLength === 2) c.uint16.preencode(state)
      else if (byteLength === 4) c.uint32.preencode(state)
      else c.uint64.preencode(state)
    },

    encode(state, b) {
      if (byteLength === 1);
      else if (byteLength === 2) c.uint8.encode(state, 0xfd)
      else if (byteLength === 4) c.uint8.encode(state, 0xfe)
      else c.uint8.encode(state, 0xff)

      if (typeof b === 'number') {
        if (byteLength === 1) c.uint8.encode(state, b)
        else if (byteLength === 2) c.uint16.encode(state, b)
        else if (byteLength === 4) c.uint32.encode(state, b)
        else c.uint64.encode(state, b)
      } else {
        state.buffer.set(b, state.start)

        if (b.byteLength < byteLength) {
          // Zero-fill the rest of the byte length.
          state.buffer.fill(
            0,
            state.start + b.byteLength,
            state.start + byteLength
          )
        }

        state.start += byteLength
      }
    },

    decode(state) {
      const byte = state.buffer[state.start]

      let byteLength
      if (byte <= 0xfc) byteLength = 1
      else if (byte === 0xfd) byteLength = 2
      else if (byte === 0xfe) byteLength = 4
      else byteLength = 8

      if (byteLength > 1) state.start++ // Skip the length byte

      if (state.end - state.start < byteLength) throw new Error('Out of bounds')

      const b = state.buffer.subarray(state.start, (state.start += byteLength))

      return length <= 8 ? b.subarray(0, 1) : b
    }
  }
}