github.com/aacfactory/avro@v1.2.12/internal/base/reader.go (about)

     1  package base
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"io"
     7  	"strings"
     8  	"unsafe"
     9  )
    10  
    11  const (
    12  	maxIntBufSize  = 5
    13  	maxLongBufSize = 10
    14  )
    15  
    16  // ReaderFunc is a function used to customize the Reader.
    17  type ReaderFunc func(r *Reader)
    18  
    19  // WithReaderConfig specifies the configuration to use with a reader.
    20  func WithReaderConfig(cfg API) ReaderFunc {
    21  	return func(r *Reader) {
    22  		r.cfg = cfg.(*frozenConfig)
    23  	}
    24  }
    25  
    26  // Reader is an Avro specific io.Reader.
    27  type Reader struct {
    28  	cfg    *frozenConfig
    29  	reader io.Reader
    30  	slab   []byte
    31  	buf    []byte
    32  	head   int
    33  	tail   int
    34  	Error  error
    35  }
    36  
    37  // NewReader creates a new Reader.
    38  func NewReader(r io.Reader, bufSize int, opts ...ReaderFunc) *Reader {
    39  	reader := &Reader{
    40  		cfg:    DefaultConfig.(*frozenConfig),
    41  		reader: r,
    42  		buf:    make([]byte, bufSize),
    43  		head:   0,
    44  		tail:   0,
    45  	}
    46  
    47  	for _, opt := range opts {
    48  		opt(reader)
    49  	}
    50  
    51  	return reader
    52  }
    53  
    54  // Reset resets a Reader with a new byte array attached.
    55  func (r *Reader) Reset(b []byte) *Reader {
    56  	r.reader = nil
    57  	r.buf = b
    58  	r.head = 0
    59  	r.tail = len(b)
    60  	return r
    61  }
    62  
    63  // ReportError record a error in iterator instance with current position.
    64  func (r *Reader) ReportError(operation, msg string) {
    65  	if r.Error != nil && !errors.Is(r.Error, io.EOF) {
    66  		return
    67  	}
    68  
    69  	r.Error = fmt.Errorf("avro: %s: %s", operation, msg)
    70  }
    71  
    72  func (r *Reader) loadMore() bool {
    73  	if r.reader == nil {
    74  		if r.Error == nil {
    75  			r.head = r.tail
    76  			r.Error = io.EOF
    77  		}
    78  		return false
    79  	}
    80  
    81  	for {
    82  		n, err := r.reader.Read(r.buf)
    83  		if n == 0 {
    84  			if err != nil {
    85  				if r.Error == nil {
    86  					r.Error = err
    87  				}
    88  				return false
    89  			}
    90  			continue
    91  		}
    92  
    93  		r.head = 0
    94  		r.tail = n
    95  		return true
    96  	}
    97  }
    98  
    99  func (r *Reader) readByte() byte {
   100  	if r.head == r.tail {
   101  		if !r.loadMore() {
   102  			return 0
   103  		}
   104  	}
   105  
   106  	b := r.buf[r.head]
   107  	r.head++
   108  
   109  	return b
   110  }
   111  
   112  // Read reads data into the given bytes.
   113  func (r *Reader) Read(b []byte) {
   114  	size := len(b)
   115  	read := 0
   116  
   117  	for read < size {
   118  		if r.head == r.tail {
   119  			if !r.loadMore() {
   120  				return
   121  			}
   122  		}
   123  
   124  		n := copy(b[read:], r.buf[r.head:r.tail])
   125  		r.head += n
   126  		read += n
   127  	}
   128  }
   129  
   130  // ReadBool reads a Bool from the Reader.
   131  func (r *Reader) ReadBool() bool {
   132  	b := r.readByte()
   133  
   134  	if b != 0 && b != 1 {
   135  		r.ReportError("ReadBool", "invalid bool")
   136  	}
   137  	return b == 1
   138  }
   139  
   140  // ReadInt reads an Int from the Reader.
   141  func (r *Reader) ReadInt() int32 {
   142  	var val uint32
   143  	var offset int8
   144  
   145  	for r.Error == nil {
   146  		if offset == maxIntBufSize {
   147  			r.ReportError("ReadInt", "int overflow")
   148  			return 0
   149  		}
   150  
   151  		b := r.readByte()
   152  		val |= uint32(b&0x7F) << uint(7*offset)
   153  		if b&0x80 == 0 {
   154  			break
   155  		}
   156  		offset++
   157  	}
   158  
   159  	return int32((val >> 1) ^ -(val & 1))
   160  }
   161  
   162  // ReadLong reads a Long from the Reader.
   163  func (r *Reader) ReadLong() int64 {
   164  	var val uint64
   165  	var offset int8
   166  
   167  	for r.Error == nil {
   168  		if offset == maxLongBufSize {
   169  			r.ReportError("ReadLong", "long overflow")
   170  			return 0
   171  		}
   172  
   173  		b := r.readByte()
   174  		val |= uint64(b&0x7F) << uint(7*offset)
   175  		if b&0x80 == 0 {
   176  			break
   177  		}
   178  		offset++
   179  	}
   180  
   181  	return int64((val >> 1) ^ -(val & 1))
   182  }
   183  
   184  // ReadFloat reads a Float from the Reader.
   185  func (r *Reader) ReadFloat() float32 {
   186  	var buf [4]byte
   187  	r.Read(buf[:])
   188  
   189  	float := *(*float32)(unsafe.Pointer(&buf[0]))
   190  	return float
   191  }
   192  
   193  // ReadDouble reads a Double from the Reader.
   194  func (r *Reader) ReadDouble() float64 {
   195  	var buf [8]byte
   196  	r.Read(buf[:])
   197  
   198  	float := *(*float64)(unsafe.Pointer(&buf[0]))
   199  	return float
   200  }
   201  
   202  // ReadBytes reads Bytes from the Reader.
   203  func (r *Reader) ReadBytes() []byte {
   204  	return r.readBytes("bytes")
   205  }
   206  
   207  // ReadString reads a String from the Reader.
   208  func (r *Reader) ReadString() string {
   209  	b := r.readBytes("string")
   210  	if len(b) == 0 {
   211  		return ""
   212  	}
   213  
   214  	return *(*string)(unsafe.Pointer(&b))
   215  }
   216  
   217  func (r *Reader) readBytes(op string) []byte {
   218  	size := int(r.ReadLong())
   219  	if size < 0 {
   220  		fnName := "Read" + strings.ToTitle(op)
   221  		r.ReportError(fnName, "invalid "+op+" length")
   222  		return nil
   223  	}
   224  	if size == 0 {
   225  		return []byte{}
   226  	}
   227  	if max := r.cfg.getMaxByteSliceSize(); max > 0 && size > max {
   228  		fnName := "Read" + strings.ToTitle(op)
   229  		r.ReportError(fnName, "size is greater than `Config.MaxByteSliceSize`")
   230  		return nil
   231  	}
   232  
   233  	// The bytes are entirely in the buffer and of a reasonable size.
   234  	// Use the byte slab.
   235  	if r.head+size <= r.tail && size <= 1024 {
   236  		if cap(r.slab) < size {
   237  			r.slab = make([]byte, 1024)
   238  		}
   239  		dst := r.slab[:size]
   240  		r.slab = r.slab[size:]
   241  		copy(dst, r.buf[r.head:r.head+size])
   242  		r.head += size
   243  		return dst
   244  	}
   245  
   246  	buf := make([]byte, size)
   247  	r.Read(buf)
   248  	return buf
   249  }
   250  
   251  // ReadBlockHeader reads a Block Header from the Reader.
   252  func (r *Reader) ReadBlockHeader() (int64, int64) {
   253  	length := r.ReadLong()
   254  	if length < 0 {
   255  		size := r.ReadLong()
   256  
   257  		return -length, size
   258  	}
   259  
   260  	return length, 0
   261  }