github.com/m3db/m3@v1.5.0/src/x/serialize/decoder.go (about) 1 // Copyright (c) 2018 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package serialize 22 23 import ( 24 "errors" 25 "fmt" 26 27 "github.com/m3db/m3/src/x/checked" 28 "github.com/m3db/m3/src/x/ident" 29 ) 30 31 var ( 32 // ErrIncorrectHeader is an error when encoded tag byte sequence doesn't start with 33 // an expected magic number. 34 ErrIncorrectHeader = errors.New("header magic number does not match expected value") 35 errInvalidByteStreamIDDecoding = errors.New("internal error, invalid byte stream while decoding ID") 36 errInvalidByteStreamUintDecoding = errors.New("internal error, invalid byte stream while decoding uint") 37 ) 38 39 type decoder struct { 40 checkedData checked.Bytes 41 data []byte 42 nextCalls int 43 length int 44 remaining int 45 err error 46 47 current ident.Tag 48 currentTagName checked.Bytes 49 currentTagValue checked.Bytes 50 51 opts TagDecoderOptions 52 pool TagDecoderPool 53 } 54 55 func newTagDecoder(opts TagDecoderOptions, pool TagDecoderPool) TagDecoder { 56 tagName := opts.CheckedBytesWrapperPool().Get(nil) 57 tagValue := opts.CheckedBytesWrapperPool().Get(nil) 58 tag := ident.Tag{ 59 Name: ident.BinaryID(tagName), 60 Value: ident.BinaryID(tagValue), 61 } 62 return &decoder{ 63 opts: opts, 64 pool: pool, 65 current: tag, 66 currentTagName: tagName, 67 currentTagValue: tagValue, 68 } 69 } 70 71 func (d *decoder) Reset(b checked.Bytes) { 72 d.resetForReuse() 73 d.checkedData = b 74 d.checkedData.IncRef() 75 d.data = d.checkedData.Bytes() 76 77 header, err := d.decodeUInt16() 78 if err != nil { 79 d.err = err 80 return 81 } 82 83 if header != HeaderMagicNumber { 84 d.err = ErrIncorrectHeader 85 return 86 } 87 88 length, err := d.decodeUInt16() 89 if err != nil { 90 d.err = err 91 return 92 } 93 94 if limit := d.opts.TagSerializationLimits().MaxNumberTags(); length > limit { 95 d.err = fmt.Errorf("too many tags [ limit = %d, observed = %d ]", limit, length) 96 return 97 } 98 99 d.length = int(length) 100 d.remaining = int(length) 101 } 102 103 func (d *decoder) Next() bool { 104 d.releaseCurrent() 105 d.nextCalls++ 106 if d.err != nil || d.remaining <= 0 { 107 return false 108 } 109 110 if err := d.decodeTag(); err != nil { 111 d.err = err 112 return false 113 } 114 115 d.remaining-- 116 return true 117 } 118 119 func (d *decoder) Current() ident.Tag { 120 return d.current 121 } 122 123 func (d *decoder) CurrentIndex() int { 124 return d.Len() - d.Remaining() 125 } 126 127 func (d *decoder) decodeTag() error { 128 if err := d.decodeIDInto(d.currentTagName); err != nil { 129 return err 130 } 131 // safe to call Bytes() as d.current.Name has inc'd a ref 132 if len(d.currentTagName.Bytes()) == 0 { 133 d.releaseCurrent() 134 return ErrEmptyTagNameLiteral 135 } 136 137 if err := d.decodeIDInto(d.currentTagValue); err != nil { 138 d.releaseCurrent() 139 return err 140 } 141 142 return nil 143 } 144 145 func (d *decoder) decodeIDInto(b checked.Bytes) error { 146 l, err := d.decodeUInt16() 147 if err != nil { 148 return err 149 } 150 151 if limit := d.opts.TagSerializationLimits().MaxTagLiteralLength(); l > limit { 152 return fmt.Errorf("tag literal too long [ limit = %d, observed = %d ]", limit, int(l)) 153 } 154 155 if len(d.data) < int(l) { 156 return errInvalidByteStreamIDDecoding 157 } 158 159 // incRef to indicate another checked.Bytes has a 160 // reference to the original bytes 161 d.checkedData.IncRef() 162 b.IncRef() 163 b.Reset(d.data[:l]) 164 b.DecRef() 165 d.data = d.data[l:] 166 167 return nil 168 } 169 170 func (d *decoder) decodeUInt16() (uint16, error) { 171 if len(d.data) < 2 { 172 return 0, errInvalidByteStreamUintDecoding 173 } 174 175 n := decodeUInt16(d.data) 176 d.data = d.data[2:] 177 return n, nil 178 } 179 180 func (d *decoder) Err() error { 181 return d.err 182 } 183 184 func (d *decoder) Len() int { 185 return d.length 186 } 187 188 func (d *decoder) Remaining() int { 189 return d.remaining 190 } 191 192 func (d *decoder) releaseCurrent() { 193 d.currentTagName.IncRef() 194 if b := d.currentTagName.Bytes(); b != nil { 195 d.checkedData.DecRef() 196 } 197 d.currentTagName.Reset(nil) 198 d.currentTagName.DecRef() 199 200 d.currentTagValue.IncRef() 201 if b := d.currentTagValue.Bytes(); b != nil { 202 d.checkedData.DecRef() 203 } 204 d.currentTagValue.Reset(nil) 205 d.currentTagValue.DecRef() 206 } 207 208 func (d *decoder) resetForReuse() { 209 d.releaseCurrent() 210 d.data = nil 211 d.err = nil 212 d.remaining = 0 213 d.nextCalls = 0 214 if d.checkedData != nil { 215 d.checkedData.DecRef() 216 if d.checkedData.NumRef() == 0 { 217 d.checkedData.Finalize() 218 } 219 d.checkedData = nil 220 } 221 } 222 223 func (d *decoder) Close() { 224 d.resetForReuse() 225 if d.pool == nil { 226 return 227 } 228 d.pool.Put(d) 229 } 230 231 func (d *decoder) Duplicate() ident.TagIterator { 232 iter := d.pool.Get() 233 if d.checkedData == nil { 234 return iter 235 } 236 iter.Reset(d.checkedData) 237 for i := 0; i < d.nextCalls; i++ { 238 iter.Next() 239 } 240 return iter 241 } 242 243 func (d *decoder) Rewind() { 244 if d.checkedData == nil { 245 return 246 } 247 d.checkedData.IncRef() 248 d.Reset(d.checkedData) 249 d.checkedData.DecRef() 250 }