| OLD | NEW |
| 1 // Copyright 2015 The LUCI Authors. All rights reserved. | 1 // Copyright 2015 The LUCI Authors. All rights reserved. |
| 2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
| 3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
| 4 | 4 |
| 5 package serialize | 5 package serialize |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "bytes" | 8 "bytes" |
| 9 "errors" | 9 "errors" |
| 10 "fmt" | 10 "fmt" |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 | 44 |
| 45 // With- and WithoutContext indicate if the serialization method should include | 45 // With- and WithoutContext indicate if the serialization method should include |
| 46 // context for Keys. See KeyContext for more information. | 46 // context for Keys. See KeyContext for more information. |
| 47 const ( | 47 const ( |
| 48 WithContext KeyContext = true | 48 WithContext KeyContext = true |
| 49 WithoutContext = false | 49 WithoutContext = false |
| 50 ) | 50 ) |
| 51 | 51 |
| 52 // WriteKey encodes a key to the buffer. If context is WithContext, then this | 52 // WriteKey encodes a key to the buffer. If context is WithContext, then this |
| 53 // encoded value will include the appid and namespace of the key. | 53 // encoded value will include the appid and namespace of the key. |
| 54 func WriteKey(buf Buffer, context KeyContext, k *ds.Key) (err error) { | 54 func WriteKey(buf WriteBuffer, context KeyContext, k *ds.Key) (err error) { |
| 55 // [appid ++ namespace]? ++ [1 ++ token]* ++ NULL | 55 // [appid ++ namespace]? ++ [1 ++ token]* ++ NULL |
| 56 defer recoverTo(&err) | 56 defer recoverTo(&err) |
| 57 appid, namespace, toks := k.Split() | 57 appid, namespace, toks := k.Split() |
| 58 if context == WithContext { | 58 if context == WithContext { |
| 59 panicIf(buf.WriteByte(1)) | 59 panicIf(buf.WriteByte(1)) |
| 60 _, e := cmpbin.WriteString(buf, appid) | 60 _, e := cmpbin.WriteString(buf, appid) |
| 61 panicIf(e) | 61 panicIf(e) |
| 62 _, e = cmpbin.WriteString(buf, namespace) | 62 _, e = cmpbin.WriteString(buf, namespace) |
| 63 panicIf(e) | 63 panicIf(e) |
| 64 } else { | 64 } else { |
| 65 panicIf(buf.WriteByte(0)) | 65 panicIf(buf.WriteByte(0)) |
| 66 } | 66 } |
| 67 for _, tok := range toks { | 67 for _, tok := range toks { |
| 68 panicIf(buf.WriteByte(1)) | 68 panicIf(buf.WriteByte(1)) |
| 69 panicIf(WriteKeyTok(buf, tok)) | 69 panicIf(WriteKeyTok(buf, tok)) |
| 70 } | 70 } |
| 71 return buf.WriteByte(0) | 71 return buf.WriteByte(0) |
| 72 } | 72 } |
| 73 | 73 |
| 74 // ReadKey deserializes a key from the buffer. The value of context must match | 74 // ReadKey deserializes a key from the buffer. The value of context must match |
| 75 // the value of context that was passed to WriteKey when the key was encoded. | 75 // the value of context that was passed to WriteKey when the key was encoded. |
| 76 // If context == WithoutContext, then the appid and namespace parameters are | 76 // If context == WithoutContext, then the appid and namespace parameters are |
| 77 // used in the decoded Key. Otherwise they're ignored. | 77 // used in the decoded Key. Otherwise they're ignored. |
| 78 func ReadKey(buf Buffer, context KeyContext, inKC ds.KeyContext) (ret *ds.Key, e
rr error) { | 78 func ReadKey(buf ReadBuffer, context KeyContext, inKC ds.KeyContext) (ret *ds.Ke
y, err error) { |
| 79 defer recoverTo(&err) | 79 defer recoverTo(&err) |
| 80 actualCtx, e := buf.ReadByte() | 80 actualCtx, e := buf.ReadByte() |
| 81 panicIf(e) | 81 panicIf(e) |
| 82 | 82 |
| 83 var kc ds.KeyContext | 83 var kc ds.KeyContext |
| 84 if actualCtx == 1 { | 84 if actualCtx == 1 { |
| 85 kc.AppID, _, e = cmpbin.ReadString(buf) | 85 kc.AppID, _, e = cmpbin.ReadString(buf) |
| 86 panicIf(e) | 86 panicIf(e) |
| 87 kc.Namespace, _, e = cmpbin.ReadString(buf) | 87 kc.Namespace, _, e = cmpbin.ReadString(buf) |
| 88 panicIf(e) | 88 panicIf(e) |
| (...skipping 25 matching lines...) Expand all Loading... |
| 114 panicIf(e) | 114 panicIf(e) |
| 115 | 115 |
| 116 toks = append(toks, tok) | 116 toks = append(toks, tok) |
| 117 } | 117 } |
| 118 | 118 |
| 119 return kc.NewKeyToks(toks), nil | 119 return kc.NewKeyToks(toks), nil |
| 120 } | 120 } |
| 121 | 121 |
| 122 // WriteKeyTok writes a KeyTok to the buffer. You usually want WriteKey | 122 // WriteKeyTok writes a KeyTok to the buffer. You usually want WriteKey |
| 123 // instead of this. | 123 // instead of this. |
| 124 func WriteKeyTok(buf Buffer, tok ds.KeyTok) (err error) { | 124 func WriteKeyTok(buf WriteBuffer, tok ds.KeyTok) (err error) { |
| 125 // tok.kind ++ typ ++ [tok.stringID || tok.intID] | 125 // tok.kind ++ typ ++ [tok.stringID || tok.intID] |
| 126 defer recoverTo(&err) | 126 defer recoverTo(&err) |
| 127 _, e := cmpbin.WriteString(buf, tok.Kind) | 127 _, e := cmpbin.WriteString(buf, tok.Kind) |
| 128 panicIf(e) | 128 panicIf(e) |
| 129 if tok.StringID != "" { | 129 if tok.StringID != "" { |
| 130 panicIf(buf.WriteByte(byte(ds.PTString))) | 130 panicIf(buf.WriteByte(byte(ds.PTString))) |
| 131 _, e := cmpbin.WriteString(buf, tok.StringID) | 131 _, e := cmpbin.WriteString(buf, tok.StringID) |
| 132 panicIf(e) | 132 panicIf(e) |
| 133 } else { | 133 } else { |
| 134 panicIf(buf.WriteByte(byte(ds.PTInt))) | 134 panicIf(buf.WriteByte(byte(ds.PTInt))) |
| 135 _, e := cmpbin.WriteInt(buf, tok.IntID) | 135 _, e := cmpbin.WriteInt(buf, tok.IntID) |
| 136 panicIf(e) | 136 panicIf(e) |
| 137 } | 137 } |
| 138 return nil | 138 return nil |
| 139 } | 139 } |
| 140 | 140 |
| 141 // ReadKeyTok reads a KeyTok from the buffer. You usually want ReadKey | 141 // ReadKeyTok reads a KeyTok from the buffer. You usually want ReadKey |
| 142 // instead of this. | 142 // instead of this. |
| 143 func ReadKeyTok(buf Buffer) (ret ds.KeyTok, err error) { | 143 func ReadKeyTok(buf ReadBuffer) (ret ds.KeyTok, err error) { |
| 144 defer recoverTo(&err) | 144 defer recoverTo(&err) |
| 145 e := error(nil) | 145 e := error(nil) |
| 146 ret.Kind, _, e = cmpbin.ReadString(buf) | 146 ret.Kind, _, e = cmpbin.ReadString(buf) |
| 147 panicIf(e) | 147 panicIf(e) |
| 148 | 148 |
| 149 typ, e := buf.ReadByte() | 149 typ, e := buf.ReadByte() |
| 150 panicIf(e) | 150 panicIf(e) |
| 151 | 151 |
| 152 switch ds.PropertyType(typ) { | 152 switch ds.PropertyType(typ) { |
| 153 case ds.PTString: | 153 case ds.PTString: |
| 154 ret.StringID, _, err = cmpbin.ReadString(buf) | 154 ret.StringID, _, err = cmpbin.ReadString(buf) |
| 155 case ds.PTInt: | 155 case ds.PTInt: |
| 156 ret.IntID, _, err = cmpbin.ReadInt(buf) | 156 ret.IntID, _, err = cmpbin.ReadInt(buf) |
| 157 if err == nil && ret.IntID <= 0 { | 157 if err == nil && ret.IntID <= 0 { |
| 158 err = errors.New("helper: decoded key with empty stringI
D and zero/negative intID") | 158 err = errors.New("helper: decoded key with empty stringI
D and zero/negative intID") |
| 159 } | 159 } |
| 160 default: | 160 default: |
| 161 err = fmt.Errorf("helper: invalid type %s", ds.PropertyType(typ)
) | 161 err = fmt.Errorf("helper: invalid type %s", ds.PropertyType(typ)
) |
| 162 } | 162 } |
| 163 return | 163 return |
| 164 } | 164 } |
| 165 | 165 |
| 166 // WriteGeoPoint writes a GeoPoint to the buffer. | 166 // WriteGeoPoint writes a GeoPoint to the buffer. |
| 167 func WriteGeoPoint(buf Buffer, gp ds.GeoPoint) (err error) { | 167 func WriteGeoPoint(buf WriteBuffer, gp ds.GeoPoint) (err error) { |
| 168 defer recoverTo(&err) | 168 defer recoverTo(&err) |
| 169 _, e := cmpbin.WriteFloat64(buf, gp.Lat) | 169 _, e := cmpbin.WriteFloat64(buf, gp.Lat) |
| 170 panicIf(e) | 170 panicIf(e) |
| 171 _, e = cmpbin.WriteFloat64(buf, gp.Lng) | 171 _, e = cmpbin.WriteFloat64(buf, gp.Lng) |
| 172 return e | 172 return e |
| 173 } | 173 } |
| 174 | 174 |
| 175 // ReadGeoPoint reads a GeoPoint from the buffer. | 175 // ReadGeoPoint reads a GeoPoint from the buffer. |
| 176 func ReadGeoPoint(buf Buffer) (gp ds.GeoPoint, err error) { | 176 func ReadGeoPoint(buf ReadBuffer) (gp ds.GeoPoint, err error) { |
| 177 defer recoverTo(&err) | 177 defer recoverTo(&err) |
| 178 e := error(nil) | 178 e := error(nil) |
| 179 gp.Lat, _, e = cmpbin.ReadFloat64(buf) | 179 gp.Lat, _, e = cmpbin.ReadFloat64(buf) |
| 180 panicIf(e) | 180 panicIf(e) |
| 181 | 181 |
| 182 gp.Lng, _, e = cmpbin.ReadFloat64(buf) | 182 gp.Lng, _, e = cmpbin.ReadFloat64(buf) |
| 183 panicIf(e) | 183 panicIf(e) |
| 184 | 184 |
| 185 if !gp.Valid() { | 185 if !gp.Valid() { |
| 186 err = fmt.Errorf("helper: decoded invalid GeoPoint: %v", gp) | 186 err = fmt.Errorf("helper: decoded invalid GeoPoint: %v", gp) |
| 187 } | 187 } |
| 188 return | 188 return |
| 189 } | 189 } |
| 190 | 190 |
| 191 // WriteTime writes a time.Time to the buffer. | 191 // WriteTime writes a time.Time to the buffer. |
| 192 // | 192 // |
| 193 // The supplied time is rounded via datastore.RoundTime and written as a | 193 // The supplied time is rounded via datastore.RoundTime and written as a |
| 194 // microseconds-since-epoch integer to comform to datastore storage standards. | 194 // microseconds-since-epoch integer to comform to datastore storage standards. |
| 195 func WriteTime(buf Buffer, t time.Time) error { | 195 func WriteTime(buf WriteBuffer, t time.Time) error { |
| 196 name, off := t.Zone() | 196 name, off := t.Zone() |
| 197 if name != "UTC" || off != 0 { | 197 if name != "UTC" || off != 0 { |
| 198 panic(fmt.Errorf("helper: UTC OR DEATH: %s", t)) | 198 panic(fmt.Errorf("helper: UTC OR DEATH: %s", t)) |
| 199 } | 199 } |
| 200 | 200 |
| 201 _, err := cmpbin.WriteInt(buf, ds.TimeToInt(t)) | 201 _, err := cmpbin.WriteInt(buf, ds.TimeToInt(t)) |
| 202 return err | 202 return err |
| 203 } | 203 } |
| 204 | 204 |
| 205 // ReadTime reads a time.Time from the buffer. | 205 // ReadTime reads a time.Time from the buffer. |
| 206 func ReadTime(buf Buffer) (time.Time, error) { | 206 func ReadTime(buf ReadBuffer) (time.Time, error) { |
| 207 v, _, err := cmpbin.ReadInt(buf) | 207 v, _, err := cmpbin.ReadInt(buf) |
| 208 if err != nil { | 208 if err != nil { |
| 209 return time.Time{}, err | 209 return time.Time{}, err |
| 210 } | 210 } |
| 211 return ds.IntToTime(v), nil | 211 return ds.IntToTime(v), nil |
| 212 } | 212 } |
| 213 | 213 |
| 214 // WriteProperty writes a Property to the buffer. `context` behaves the same | 214 // WriteProperty writes a Property to the buffer. `context` behaves the same |
| 215 // way that it does for WriteKey, but only has an effect if `p` contains a | 215 // way that it does for WriteKey, but only has an effect if `p` contains a |
| 216 // Key as its IndexValue. | 216 // Key as its IndexValue. |
| 217 func WriteProperty(buf Buffer, context KeyContext, p ds.Property) error { | 217 func WriteProperty(buf WriteBuffer, context KeyContext, p ds.Property) error { |
| 218 return writePropertyImpl(buf, context, &p, false) | 218 return writePropertyImpl(buf, context, &p, false) |
| 219 } | 219 } |
| 220 | 220 |
| 221 // WriteIndexProperty writes a Property to the buffer as its native index type. | 221 // WriteIndexProperty writes a Property to the buffer as its native index type. |
| 222 // `context` behaves the same way that it does for WriteKey, but only has an | 222 // `context` behaves the same way that it does for WriteKey, but only has an |
| 223 // effect if `p` contains a Key as its IndexValue. | 223 // effect if `p` contains a Key as its IndexValue. |
| 224 func WriteIndexProperty(buf Buffer, context KeyContext, p ds.Property) error { | 224 func WriteIndexProperty(buf WriteBuffer, context KeyContext, p ds.Property) erro
r { |
| 225 return writePropertyImpl(buf, context, &p, true) | 225 return writePropertyImpl(buf, context, &p, true) |
| 226 } | 226 } |
| 227 | 227 |
| 228 // writePropertyImpl is an implementation of WriteProperty and | 228 // writePropertyImpl is an implementation of WriteProperty and |
| 229 // WriteIndexProperty. | 229 // WriteIndexProperty. |
| 230 func writePropertyImpl(buf Buffer, context KeyContext, p *ds.Property, index boo
l) (err error) { | 230 func writePropertyImpl(buf WriteBuffer, context KeyContext, p *ds.Property, inde
x bool) (err error) { |
| 231 defer recoverTo(&err) | 231 defer recoverTo(&err) |
| 232 | 232 |
| 233 it, v := p.IndexTypeAndValue() | 233 it, v := p.IndexTypeAndValue() |
| 234 if !index { | 234 if !index { |
| 235 it = p.Type() | 235 it = p.Type() |
| 236 } | 236 } |
| 237 typb := byte(it) | 237 typb := byte(it) |
| 238 if p.IndexSetting() != ds.NoIndex { | 238 if p.IndexSetting() != ds.NoIndex { |
| 239 typb |= 0x80 | 239 typb |= 0x80 |
| 240 } | 240 } |
| 241 panicIf(buf.WriteByte(typb)) | 241 panicIf(buf.WriteByte(typb)) |
| 242 | 242 |
| 243 err = writeIndexValue(buf, context, v) | 243 err = writeIndexValue(buf, context, v) |
| 244 return | 244 return |
| 245 } | 245 } |
| 246 | 246 |
| 247 // writeIndexValue writes the index value of v to buf. | 247 // writeIndexValue writes the index value of v to buf. |
| 248 // | 248 // |
| 249 // v may be one of the return types from ds.Property's GetIndexTypeAndValue | 249 // v may be one of the return types from ds.Property's GetIndexTypeAndValue |
| 250 // method. | 250 // method. |
| 251 func writeIndexValue(buf Buffer, context KeyContext, v interface{}) (err error)
{ | 251 func writeIndexValue(buf WriteBuffer, context KeyContext, v interface{}) (err er
ror) { |
| 252 switch t := v.(type) { | 252 switch t := v.(type) { |
| 253 case nil: | 253 case nil: |
| 254 case bool: | 254 case bool: |
| 255 b := byte(0) | 255 b := byte(0) |
| 256 if t { | 256 if t { |
| 257 b = 1 | 257 b = 1 |
| 258 } | 258 } |
| 259 err = buf.WriteByte(b) | 259 err = buf.WriteByte(b) |
| 260 case int64: | 260 case int64: |
| 261 _, err = cmpbin.WriteInt(buf, t) | 261 _, err = cmpbin.WriteInt(buf, t) |
| (...skipping 10 matching lines...) Expand all Loading... |
| 272 | 272 |
| 273 default: | 273 default: |
| 274 err = fmt.Errorf("unsupported type: %T", t) | 274 err = fmt.Errorf("unsupported type: %T", t) |
| 275 } | 275 } |
| 276 return | 276 return |
| 277 } | 277 } |
| 278 | 278 |
| 279 // ReadProperty reads a Property from the buffer. `context` and `kc` behave the | 279 // ReadProperty reads a Property from the buffer. `context` and `kc` behave the |
| 280 // same way they do for ReadKey, but only have an effect if the decoded property | 280 // same way they do for ReadKey, but only have an effect if the decoded property |
| 281 // has a Key value. | 281 // has a Key value. |
| 282 func ReadProperty(buf Buffer, context KeyContext, kc ds.KeyContext) (p ds.Proper
ty, err error) { | 282 func ReadProperty(buf ReadBuffer, context KeyContext, kc ds.KeyContext) (p ds.Pr
operty, err error) { |
| 283 val := interface{}(nil) | 283 val := interface{}(nil) |
| 284 b, err := buf.ReadByte() | 284 b, err := buf.ReadByte() |
| 285 if err != nil { | 285 if err != nil { |
| 286 return | 286 return |
| 287 } | 287 } |
| 288 is := ds.ShouldIndex | 288 is := ds.ShouldIndex |
| 289 if (b & 0x80) == 0 { | 289 if (b & 0x80) == 0 { |
| 290 is = ds.NoIndex | 290 is = ds.NoIndex |
| 291 } | 291 } |
| 292 switch ds.PropertyType(b & 0x7f) { | 292 switch ds.PropertyType(b & 0x7f) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 324 } | 324 } |
| 325 | 325 |
| 326 // WritePropertyMap writes an entire PropertyMap to the buffer. `context` | 326 // WritePropertyMap writes an entire PropertyMap to the buffer. `context` |
| 327 // behaves the same way that it does for WriteKey. | 327 // behaves the same way that it does for WriteKey. |
| 328 // | 328 // |
| 329 // If WritePropertyMapDeterministic is true, then the rows will be sorted by | 329 // If WritePropertyMapDeterministic is true, then the rows will be sorted by |
| 330 // property name before they're serialized to buf (mostly useful for testing, | 330 // property name before they're serialized to buf (mostly useful for testing, |
| 331 // but also potentially useful if you need to make a hash of the property data). | 331 // but also potentially useful if you need to make a hash of the property data). |
| 332 // | 332 // |
| 333 // Write skips metadata keys. | 333 // Write skips metadata keys. |
| 334 func WritePropertyMap(buf Buffer, context KeyContext, pm ds.PropertyMap) (err er
ror) { | 334 func WritePropertyMap(buf WriteBuffer, context KeyContext, pm ds.PropertyMap) (e
rr error) { |
| 335 defer recoverTo(&err) | 335 defer recoverTo(&err) |
| 336 rows := make(sort.StringSlice, 0, len(pm)) | 336 rows := make(sort.StringSlice, 0, len(pm)) |
| 337 tmpBuf := &bytes.Buffer{} | 337 tmpBuf := &bytes.Buffer{} |
| 338 pm, _ = pm.Save(false) | 338 pm, _ = pm.Save(false) |
| 339 for name, pdata := range pm { | 339 for name, pdata := range pm { |
| 340 tmpBuf.Reset() | 340 tmpBuf.Reset() |
| 341 _, e := cmpbin.WriteString(tmpBuf, name) | 341 _, e := cmpbin.WriteString(tmpBuf, name) |
| 342 panicIf(e) | 342 panicIf(e) |
| 343 | 343 |
| 344 switch t := pdata.(type) { | 344 switch t := pdata.(type) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 368 panicIf(e) | 368 panicIf(e) |
| 369 for _, r := range rows { | 369 for _, r := range rows { |
| 370 _, e := buf.WriteString(r) | 370 _, e := buf.WriteString(r) |
| 371 panicIf(e) | 371 panicIf(e) |
| 372 } | 372 } |
| 373 return | 373 return |
| 374 } | 374 } |
| 375 | 375 |
| 376 // ReadPropertyMap reads a PropertyMap from the buffer. `context` and | 376 // ReadPropertyMap reads a PropertyMap from the buffer. `context` and |
| 377 // friends behave the same way that they do for ReadKey. | 377 // friends behave the same way that they do for ReadKey. |
| 378 func ReadPropertyMap(buf Buffer, context KeyContext, kc ds.KeyContext) (pm ds.Pr
opertyMap, err error) { | 378 func ReadPropertyMap(buf ReadBuffer, context KeyContext, kc ds.KeyContext) (pm d
s.PropertyMap, err error) { |
| 379 defer recoverTo(&err) | 379 defer recoverTo(&err) |
| 380 | 380 |
| 381 numRows := uint64(0) | 381 numRows := uint64(0) |
| 382 numRows, _, e := cmpbin.ReadUint(buf) | 382 numRows, _, e := cmpbin.ReadUint(buf) |
| 383 panicIf(e) | 383 panicIf(e) |
| 384 if numRows > ReadPropertyMapReasonableLimit { | 384 if numRows > ReadPropertyMapReasonableLimit { |
| 385 err = fmt.Errorf("helper: tried to decode map with huge number o
f rows %d", numRows) | 385 err = fmt.Errorf("helper: tried to decode map with huge number o
f rows %d", numRows) |
| 386 return | 386 return |
| 387 } | 387 } |
| 388 | 388 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 413 panicIf(err) | 413 panicIf(err) |
| 414 props = append(props, prop) | 414 props = append(props, prop) |
| 415 } | 415 } |
| 416 pm[name] = props | 416 pm[name] = props |
| 417 } | 417 } |
| 418 } | 418 } |
| 419 return | 419 return |
| 420 } | 420 } |
| 421 | 421 |
| 422 // WriteIndexColumn writes an IndexColumn to the buffer. | 422 // WriteIndexColumn writes an IndexColumn to the buffer. |
| 423 func WriteIndexColumn(buf Buffer, c ds.IndexColumn) (err error) { | 423 func WriteIndexColumn(buf WriteBuffer, c ds.IndexColumn) (err error) { |
| 424 defer recoverTo(&err) | 424 defer recoverTo(&err) |
| 425 | 425 |
| 426 if !c.Descending { | 426 if !c.Descending { |
| 427 panicIf(buf.WriteByte(0)) | 427 panicIf(buf.WriteByte(0)) |
| 428 } else { | 428 } else { |
| 429 panicIf(buf.WriteByte(1)) | 429 panicIf(buf.WriteByte(1)) |
| 430 } | 430 } |
| 431 _, err = cmpbin.WriteString(buf, c.Property) | 431 _, err = cmpbin.WriteString(buf, c.Property) |
| 432 return | 432 return |
| 433 } | 433 } |
| 434 | 434 |
| 435 // ReadIndexColumn reads an IndexColumn from the buffer. | 435 // ReadIndexColumn reads an IndexColumn from the buffer. |
| 436 func ReadIndexColumn(buf Buffer) (c ds.IndexColumn, err error) { | 436 func ReadIndexColumn(buf ReadBuffer) (c ds.IndexColumn, err error) { |
| 437 defer recoverTo(&err) | 437 defer recoverTo(&err) |
| 438 | 438 |
| 439 dir, err := buf.ReadByte() | 439 dir, err := buf.ReadByte() |
| 440 panicIf(err) | 440 panicIf(err) |
| 441 | 441 |
| 442 c.Descending = dir != 0 | 442 c.Descending = dir != 0 |
| 443 c.Property, _, err = cmpbin.ReadString(buf) | 443 c.Property, _, err = cmpbin.ReadString(buf) |
| 444 return | 444 return |
| 445 } | 445 } |
| 446 | 446 |
| 447 // WriteIndexDefinition writes an IndexDefinition to the buffer | 447 // WriteIndexDefinition writes an IndexDefinition to the buffer |
| 448 func WriteIndexDefinition(buf Buffer, i ds.IndexDefinition) (err error) { | 448 func WriteIndexDefinition(buf WriteBuffer, i ds.IndexDefinition) (err error) { |
| 449 defer recoverTo(&err) | 449 defer recoverTo(&err) |
| 450 | 450 |
| 451 _, err = cmpbin.WriteString(buf, i.Kind) | 451 _, err = cmpbin.WriteString(buf, i.Kind) |
| 452 panicIf(err) | 452 panicIf(err) |
| 453 if !i.Ancestor { | 453 if !i.Ancestor { |
| 454 panicIf(buf.WriteByte(0)) | 454 panicIf(buf.WriteByte(0)) |
| 455 } else { | 455 } else { |
| 456 panicIf(buf.WriteByte(1)) | 456 panicIf(buf.WriteByte(1)) |
| 457 } | 457 } |
| 458 for _, sb := range i.SortBy { | 458 for _, sb := range i.SortBy { |
| 459 panicIf(buf.WriteByte(1)) | 459 panicIf(buf.WriteByte(1)) |
| 460 panicIf(WriteIndexColumn(buf, sb)) | 460 panicIf(WriteIndexColumn(buf, sb)) |
| 461 } | 461 } |
| 462 return buf.WriteByte(0) | 462 return buf.WriteByte(0) |
| 463 } | 463 } |
| 464 | 464 |
| 465 // ReadIndexDefinition reads an IndexDefinition from the buffer. | 465 // ReadIndexDefinition reads an IndexDefinition from the buffer. |
| 466 func ReadIndexDefinition(buf Buffer) (i ds.IndexDefinition, err error) { | 466 func ReadIndexDefinition(buf ReadBuffer) (i ds.IndexDefinition, err error) { |
| 467 defer recoverTo(&err) | 467 defer recoverTo(&err) |
| 468 | 468 |
| 469 i.Kind, _, err = cmpbin.ReadString(buf) | 469 i.Kind, _, err = cmpbin.ReadString(buf) |
| 470 panicIf(err) | 470 panicIf(err) |
| 471 | 471 |
| 472 anc, err := buf.ReadByte() | 472 anc, err := buf.ReadByte() |
| 473 panicIf(err) | 473 panicIf(err) |
| 474 | 474 |
| 475 i.Ancestor = anc == 1 | 475 i.Ancestor = anc == 1 |
| 476 | 476 |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 634 } | 634 } |
| 635 } | 635 } |
| 636 | 636 |
| 637 func recoverTo(err *error) { | 637 func recoverTo(err *error) { |
| 638 if r := recover(); r != nil { | 638 if r := recover(); r != nil { |
| 639 if rerr := r.(parseError); rerr != nil { | 639 if rerr := r.(parseError); rerr != nil { |
| 640 *err = error(rerr) | 640 *err = error(rerr) |
| 641 } | 641 } |
| 642 } | 642 } |
| 643 } | 643 } |
| OLD | NEW |