pkg/encoding/writer.go (81 lines of code) (raw):
// Licensed to Apache Software Foundation (ASF) under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Apache Software Foundation (ASF) licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package encoding
import (
"encoding/binary"
)
// Writer writes bits to an io.BufferWriter.
type Writer struct {
out BufferWriter
cache byte
available byte
}
// NewWriter create bit writer.
func NewWriter() *Writer {
return new(Writer)
}
// Reset writes to a new writer.
func (w *Writer) Reset(buffer BufferWriter) {
w.out = buffer
w.cache = 0
w.available = 8
}
// WriteBool writes a boolean value
// true: 1
// false: 0
func (w *Writer) WriteBool(b bool) {
if b {
w.cache |= 1 << (w.available - 1)
}
w.available--
if w.available == 0 {
// WriteByte never returns error
_ = w.out.WriteByte(w.cache)
w.cache = 0
w.available = 8
}
}
// WriteBits writes number of bits.
func (w *Writer) WriteBits(u uint64, numBits int) {
u <<= 64 - uint(numBits)
for ; numBits >= 8; numBits -= 8 {
byt := byte(u >> 56)
_ = w.WriteByte(byt)
u <<= 8
}
remainder := byte(u >> 56)
for ; numBits > 0; numBits-- {
w.WriteBool((remainder & 0x80) != 0)
remainder <<= 1
}
}
// WriteByte write a byte.
func (w *Writer) WriteByte(b byte) error {
if err := w.out.WriteByte(w.cache | (b >> (8 - w.available))); err != nil {
return err
}
w.cache = b << w.available
return nil
}
// Flush flushes the currently in-process byte.
func (w *Writer) Flush() {
if w.available != 8 {
_ = w.out.WriteByte(w.cache)
}
w.Reset(w.out)
}
// Packer writes data into a buffer.
type Packer struct {
buf BufferWriter
scratch [binary.MaxVarintLen64]byte
}
// NewPacker returns a new Writer.
func NewPacker(buf BufferWriter) *Packer {
return &Packer{
buf: buf,
}
}
// Write binaries to the buffer.
func (w *Packer) Write(p []byte) {
_, _ = w.buf.Write(p)
}
// PutUint16 puts uint16 data into the buffer.
func (w *Packer) PutUint16(v uint16) {
binary.LittleEndian.PutUint16(w.scratch[:], v)
_, _ = w.buf.Write(w.scratch[:2])
}
// PutUint32 puts uint32 data into the buffer.
func (w *Packer) PutUint32(v uint32) {
binary.LittleEndian.PutUint32(w.scratch[:], v)
_, _ = w.buf.Write(w.scratch[:4])
}
// PutUint64 puts uint64 data into the buffer.
func (w *Packer) PutUint64(v uint64) {
binary.LittleEndian.PutUint64(w.scratch[:], v)
_, _ = w.buf.Write(w.scratch[:8])
}
// Bytes outputs the data in the buffer.
func (w *Packer) Bytes() []byte {
return w.buf.Bytes()
}