pkg/encoding/reader.go (70 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 ( "io" ) // Reader reads bits from buffer. type Reader struct { in io.ByteReader cache byte len byte } // NewReader crate bit reader. func NewReader(in io.ByteReader) *Reader { return &Reader{ in: in, } } // ReadBool reads a bit, 1 returns true, 0 returns false. func (r *Reader) ReadBool() (bool, error) { if r.len == 0 { b, err := r.in.ReadByte() if err != nil { return false, err } r.cache = b r.len = 8 } r.len-- b := r.cache & 0x80 r.cache <<= 1 return b != 0, nil } // ReadBits read number of bits. func (r *Reader) ReadBits(numBits int) (uint64, error) { var result uint64 for ; numBits >= 8; numBits -= 8 { b, err := r.ReadByte() if err != nil { return 0, err } result = (result << 8) | uint64(b) } for ; numBits > 0; numBits-- { byt, err := r.ReadBool() if err != nil { return 0, err } result <<= 1 if byt { result |= 1 } } return result, nil } // ReadByte reads a byte. func (r *Reader) ReadByte() (byte, error) { if r.len == 0 { b, err := r.in.ReadByte() if err != nil { return b, err } r.cache = b return b, err } b, err := r.in.ReadByte() if err != nil { return b, err } result := r.cache | b>>r.len r.cache = b << (8 - r.len) return result, nil } // Reset resets the reader to read from a new slice. func (r *Reader) Reset() { r.len = 0 r.cache = 0 }