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() }