function encodeValue(op, columns) {
  if ((op.action !== "set" && op.action !== "inc") || op.value === null) {
    columns.valLen.appendValue(VALUE_TYPE.NULL)
  } else if (op.value === false) {
    columns.valLen.appendValue(VALUE_TYPE.FALSE)
  } else if (op.value === true) {
    columns.valLen.appendValue(VALUE_TYPE.TRUE)
  } else if (typeof op.value === "string") {
    const numBytes = columns.valRaw.appendRawString(op.value)
    columns.valLen.appendValue((numBytes << 4) | VALUE_TYPE.UTF8)
  } else if (ArrayBuffer.isView(op.value)) {
    const numBytes = columns.valRaw.appendRawBytes(
      new Uint8Array(op.value.buffer),
    )
    columns.valLen.appendValue((numBytes << 4) | VALUE_TYPE.BYTES)
  } else if (typeof op.value === "number") {
    let [typeTag, value] = getNumberTypeAndValue(op)
    let numBytes
    if (typeTag === VALUE_TYPE.LEB128_UINT) {
      numBytes = columns.valRaw.appendUint53(value)
    } else if (typeTag === VALUE_TYPE.IEEE754) {
      numBytes = columns.valRaw.appendRawBytes(value)
    } else {
      numBytes = columns.valRaw.appendInt53(value)
    }
    columns.valLen.appendValue((numBytes << 4) | typeTag)
  } else if (
    typeof op.datatype === "number" &&
    op.datatype >= VALUE_TYPE.MIN_UNKNOWN &&
    op.datatype <= VALUE_TYPE.MAX_UNKNOWN &&
    op.value instanceof Uint8Array
  ) {
    const numBytes = columns.valRaw.appendRawBytes(op.value)
    columns.valLen.appendValue((numBytes << 4) | op.datatype)
  } else if (op.datatype) {
    throw new RangeError(
      `Unknown datatype ${op.datatype} for value ${op.value}`,
    )
  } else {
    throw new RangeError(`Unsupported value in operation: ${op.value}`)
  }
}
Encodes the `value` property of operation `op` into the two columns
`valLen` and `valRaw`.