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