github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/state/decode.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package state 16 17 import ( 18 "bytes" 19 "context" 20 "fmt" 21 "math" 22 "reflect" 23 24 "github.com/nicocha30/gvisor-ligolo/pkg/state/wire" 25 ) 26 27 // internalCallback is a interface called on object completion. 28 // 29 // There are two implementations: objectDecodeState & userCallback. 30 type internalCallback interface { 31 // source returns the dependent object. May be nil. 32 source() *objectDecodeState 33 34 // callbackRun executes the callback. 35 callbackRun() 36 } 37 38 // userCallback is an implementation of internalCallback. 39 type userCallback func() 40 41 // source implements internalCallback.source. 42 func (userCallback) source() *objectDecodeState { 43 return nil 44 } 45 46 // callbackRun implements internalCallback.callbackRun. 47 func (uc userCallback) callbackRun() { 48 uc() 49 } 50 51 // objectDecodeState represents an object that may be in the process of being 52 // decoded. Specifically, it represents either a decoded object, or an an 53 // interest in a future object that will be decoded. When that interest is 54 // registered (via register), the storage for the object will be created, but 55 // it will not be decoded until the object is encountered in the stream. 56 type objectDecodeState struct { 57 // id is the id for this object. 58 id objectID 59 60 // typ is the id for this typeID. This may be zero if this is not a 61 // type-registered structure. 62 typ typeID 63 64 // obj is the object. This may or may not be valid yet, depending on 65 // whether complete returns true. However, regardless of whether the 66 // object is valid, obj contains a final storage location for the 67 // object. This is immutable. 68 // 69 // Note that this must be addressable (obj.Addr() must not panic). 70 // 71 // The obj passed to the decode methods below will equal this obj only 72 // in the case of decoding the top-level object. However, the passed 73 // obj may represent individual fields, elements of a slice, etc. that 74 // are effectively embedded within the reflect.Value below but with 75 // distinct types. 76 obj reflect.Value 77 78 // blockedBy is the number of dependencies this object has. 79 blockedBy int 80 81 // callbacksInline is inline storage for callbacks. 82 callbacksInline [2]internalCallback 83 84 // callbacks is a set of callbacks to execute on load. 85 callbacks []internalCallback 86 87 completeEntry 88 } 89 90 // addCallback adds a callback to the objectDecodeState. 91 func (ods *objectDecodeState) addCallback(ic internalCallback) { 92 if ods.callbacks == nil { 93 ods.callbacks = ods.callbacksInline[:0] 94 } 95 ods.callbacks = append(ods.callbacks, ic) 96 } 97 98 // findCycleFor returns when the given object is found in the blocking set. 99 func (ods *objectDecodeState) findCycleFor(target *objectDecodeState) []*objectDecodeState { 100 for _, ic := range ods.callbacks { 101 other := ic.source() 102 if other != nil && other == target { 103 return []*objectDecodeState{target} 104 } else if childList := other.findCycleFor(target); childList != nil { 105 return append(childList, other) 106 } 107 } 108 109 // This should not occur. 110 Failf("no deadlock found?") 111 panic("unreachable") 112 } 113 114 // findCycle finds a dependency cycle. 115 func (ods *objectDecodeState) findCycle() []*objectDecodeState { 116 return append(ods.findCycleFor(ods), ods) 117 } 118 119 // source implements internalCallback.source. 120 func (ods *objectDecodeState) source() *objectDecodeState { 121 return ods 122 } 123 124 // callbackRun implements internalCallback.callbackRun. 125 func (ods *objectDecodeState) callbackRun() { 126 ods.blockedBy-- 127 } 128 129 // decodeState is a graph of objects in the process of being decoded. 130 // 131 // The decode process involves loading the breadth-first graph generated by 132 // encode. This graph is read in it's entirety, ensuring that all object 133 // storage is complete. 134 // 135 // As the graph is being serialized, a set of completion callbacks are 136 // executed. These completion callbacks should form a set of acyclic subgraphs 137 // over the original one. After decoding is complete, the objects are scanned 138 // to ensure that all callbacks are executed, otherwise the callback graph was 139 // not acyclic. 140 type decodeState struct { 141 // ctx is the decode context. 142 ctx context.Context 143 144 // r is the input stream. 145 r wire.Reader 146 147 // types is the type database. 148 types typeDecodeDatabase 149 150 // objectByID is the set of objects in progress. 151 objectsByID []*objectDecodeState 152 153 // deferred are objects that have been read, by no interest has been 154 // registered yet. These will be decoded once interest in registered. 155 deferred map[objectID]wire.Object 156 157 // pending is the set of objects that are not yet complete. 158 pending completeList 159 160 // stats tracks time data. 161 stats Stats 162 } 163 164 // lookup looks up an object in decodeState or returns nil if no such object 165 // has been previously registered. 166 func (ds *decodeState) lookup(id objectID) *objectDecodeState { 167 if len(ds.objectsByID) < int(id) { 168 return nil 169 } 170 return ds.objectsByID[id-1] 171 } 172 173 // checkComplete checks for completion. 174 func (ds *decodeState) checkComplete(ods *objectDecodeState) bool { 175 // Still blocked? 176 if ods.blockedBy > 0 { 177 return false 178 } 179 180 // Track stats if relevant. 181 if ods.callbacks != nil && ods.typ != 0 { 182 ds.stats.start(ods.typ) 183 defer ds.stats.done() 184 } 185 186 // Fire all callbacks. 187 for _, ic := range ods.callbacks { 188 ic.callbackRun() 189 } 190 191 // Mark completed. 192 cbs := ods.callbacks 193 ods.callbacks = nil 194 ds.pending.Remove(ods) 195 196 // Recursively check others. 197 for _, ic := range cbs { 198 if other := ic.source(); other != nil && other.blockedBy == 0 { 199 ds.checkComplete(other) 200 } 201 } 202 203 return true // All set. 204 } 205 206 // wait registers a dependency on an object. 207 // 208 // As a special case, we always allow _useable_ references back to the first 209 // decoding object because it may have fields that are already decoded. We also 210 // allow trivial self reference, since they can be handled internally. 211 func (ds *decodeState) wait(waiter *objectDecodeState, id objectID, callback func()) { 212 switch id { 213 case waiter.id: 214 // Trivial self reference. 215 fallthrough 216 case 1: 217 // Root object; see above. 218 if callback != nil { 219 callback() 220 } 221 return 222 } 223 224 // Mark as blocked. 225 waiter.blockedBy++ 226 227 // No nil can be returned here. 228 other := ds.lookup(id) 229 if callback != nil { 230 // Add the additional user callback. 231 other.addCallback(userCallback(callback)) 232 } 233 234 // Mark waiter as unblocked. 235 other.addCallback(waiter) 236 } 237 238 // waitObject notes a blocking relationship. 239 func (ds *decodeState) waitObject(ods *objectDecodeState, encoded wire.Object, callback func()) { 240 if rv, ok := encoded.(*wire.Ref); ok && rv.Root != 0 { 241 // Refs can encode pointers and maps. 242 ds.wait(ods, objectID(rv.Root), callback) 243 } else if sv, ok := encoded.(*wire.Slice); ok && sv.Ref.Root != 0 { 244 // See decodeObject; we need to wait for the array (if non-nil). 245 ds.wait(ods, objectID(sv.Ref.Root), callback) 246 } else if iv, ok := encoded.(*wire.Interface); ok { 247 // It's an interface (wait recurisvely). 248 ds.waitObject(ods, iv.Value, callback) 249 } else if callback != nil { 250 // Nothing to wait for: execute the callback immediately. 251 callback() 252 } 253 } 254 255 // walkChild returns a child object from obj, given an accessor path. This is 256 // the decode-side equivalent to traverse in encode.go. 257 // 258 // For the purposes of this function, a child object is either a field within a 259 // struct or an array element, with one such indirection per element in 260 // path. The returned value may be an unexported field, so it may not be 261 // directly assignable. See decode_unsafe.go. 262 func walkChild(path []wire.Dot, obj reflect.Value) reflect.Value { 263 // See wire.Ref.Dots. The path here is specified in reverse order. 264 for i := len(path) - 1; i >= 0; i-- { 265 switch pc := path[i].(type) { 266 case *wire.FieldName: // Must be a pointer. 267 if obj.Kind() != reflect.Struct { 268 Failf("next component in child path is a field name, but the current object is not a struct. Path: %v, current obj: %#v", path, obj) 269 } 270 obj = obj.FieldByName(string(*pc)) 271 case wire.Index: // Embedded. 272 if obj.Kind() != reflect.Array { 273 Failf("next component in child path is an array index, but the current object is not an array. Path: %v, current obj: %#v", path, obj) 274 } 275 obj = obj.Index(int(pc)) 276 default: 277 panic("unreachable: switch should be exhaustive") 278 } 279 } 280 return obj 281 } 282 283 // register registers a decode with a type. 284 // 285 // This type is only used to instantiate a new object if it has not been 286 // registered previously. This depends on the type provided if none is 287 // available in the object itself. 288 func (ds *decodeState) register(r *wire.Ref, typ reflect.Type) reflect.Value { 289 // Grow the objectsByID slice. 290 id := objectID(r.Root) 291 if len(ds.objectsByID) < int(id) { 292 ds.objectsByID = append(ds.objectsByID, make([]*objectDecodeState, int(id)-len(ds.objectsByID))...) 293 } 294 295 // Does this object already exist? 296 ods := ds.objectsByID[id-1] 297 if ods != nil { 298 return walkChild(r.Dots, ods.obj) 299 } 300 301 // Create the object. 302 if len(r.Dots) != 0 { 303 typ = ds.findType(r.Type) 304 } 305 v := reflect.New(typ) 306 ods = &objectDecodeState{ 307 id: id, 308 obj: v.Elem(), 309 } 310 ds.objectsByID[id-1] = ods 311 ds.pending.PushBack(ods) 312 313 // Process any deferred objects & callbacks. 314 if encoded, ok := ds.deferred[id]; ok { 315 delete(ds.deferred, id) 316 ds.decodeObject(ods, ods.obj, encoded) 317 } 318 319 return walkChild(r.Dots, ods.obj) 320 } 321 322 // objectDecoder is for decoding structs. 323 type objectDecoder struct { 324 // ds is decodeState. 325 ds *decodeState 326 327 // ods is current object being decoded. 328 ods *objectDecodeState 329 330 // reconciledTypeEntry is the reconciled type information. 331 rte *reconciledTypeEntry 332 333 // encoded is the encoded object state. 334 encoded *wire.Struct 335 } 336 337 // load is helper for the public methods on Source. 338 func (od *objectDecoder) load(slot int, objPtr reflect.Value, wait bool, fn func()) { 339 // Note that we have reconciled the type and may remap the fields here 340 // to match what's expected by the decoder. The "slot" parameter here 341 // is in terms of the local type, where the fields in the encoded 342 // object are in terms of the wire object's type, which might be in a 343 // different order (but will have the same fields). 344 v := *od.encoded.Field(od.rte.FieldOrder[slot]) 345 od.ds.decodeObject(od.ods, objPtr.Elem(), v) 346 if wait { 347 // Mark this individual object a blocker. 348 od.ds.waitObject(od.ods, v, fn) 349 } 350 } 351 352 // aterLoad implements Source.AfterLoad. 353 func (od *objectDecoder) afterLoad(fn func()) { 354 // Queue the local callback; this will execute when all of the above 355 // data dependencies have been cleared. 356 od.ods.addCallback(userCallback(fn)) 357 } 358 359 // decodeStruct decodes a struct value. 360 func (ds *decodeState) decodeStruct(ods *objectDecodeState, obj reflect.Value, encoded *wire.Struct) { 361 if encoded.TypeID == 0 { 362 // Allow anonymous empty structs, but only if the encoded 363 // object also has no fields. 364 if encoded.Fields() == 0 && obj.NumField() == 0 { 365 return 366 } 367 368 // Propagate an error. 369 Failf("empty struct on wire %#v has field mismatch with type %q", encoded, obj.Type().Name()) 370 } 371 372 // Lookup the object type. 373 rte := ds.types.Lookup(typeID(encoded.TypeID), obj.Type()) 374 ods.typ = typeID(encoded.TypeID) 375 376 // Invoke the loader. 377 od := objectDecoder{ 378 ds: ds, 379 ods: ods, 380 rte: rte, 381 encoded: encoded, 382 } 383 ds.stats.start(ods.typ) 384 defer ds.stats.done() 385 if sl, ok := obj.Addr().Interface().(SaverLoader); ok { 386 // Note: may be a registered empty struct which does not 387 // implement the saver/loader interfaces. 388 sl.StateLoad(Source{internal: od}) 389 } 390 } 391 392 // decodeMap decodes a map value. 393 func (ds *decodeState) decodeMap(ods *objectDecodeState, obj reflect.Value, encoded *wire.Map) { 394 if obj.IsNil() { 395 // See pointerTo. 396 obj.Set(reflect.MakeMap(obj.Type())) 397 } 398 for i := 0; i < len(encoded.Keys); i++ { 399 // Decode the objects. 400 kv := reflect.New(obj.Type().Key()).Elem() 401 vv := reflect.New(obj.Type().Elem()).Elem() 402 ds.decodeObject(ods, kv, encoded.Keys[i]) 403 ds.decodeObject(ods, vv, encoded.Values[i]) 404 ds.waitObject(ods, encoded.Keys[i], nil) 405 ds.waitObject(ods, encoded.Values[i], nil) 406 407 // Set in the map. 408 obj.SetMapIndex(kv, vv) 409 } 410 } 411 412 // decodeArray decodes an array value. 413 func (ds *decodeState) decodeArray(ods *objectDecodeState, obj reflect.Value, encoded *wire.Array) { 414 if len(encoded.Contents) != obj.Len() { 415 Failf("mismatching array length expect=%d, actual=%d", obj.Len(), len(encoded.Contents)) 416 } 417 // Decode the contents into the array. 418 for i := 0; i < len(encoded.Contents); i++ { 419 ds.decodeObject(ods, obj.Index(i), encoded.Contents[i]) 420 ds.waitObject(ods, encoded.Contents[i], nil) 421 } 422 } 423 424 // findType finds the type for the given wire.TypeSpecs. 425 func (ds *decodeState) findType(t wire.TypeSpec) reflect.Type { 426 switch x := t.(type) { 427 case wire.TypeID: 428 typ := ds.types.LookupType(typeID(x)) 429 rte := ds.types.Lookup(typeID(x), typ) 430 return rte.LocalType 431 case *wire.TypeSpecPointer: 432 return reflect.PtrTo(ds.findType(x.Type)) 433 case *wire.TypeSpecArray: 434 return reflect.ArrayOf(int(x.Count), ds.findType(x.Type)) 435 case *wire.TypeSpecSlice: 436 return reflect.SliceOf(ds.findType(x.Type)) 437 case *wire.TypeSpecMap: 438 return reflect.MapOf(ds.findType(x.Key), ds.findType(x.Value)) 439 default: 440 // Should not happen. 441 Failf("unknown type %#v", t) 442 } 443 panic("unreachable") 444 } 445 446 // decodeInterface decodes an interface value. 447 func (ds *decodeState) decodeInterface(ods *objectDecodeState, obj reflect.Value, encoded *wire.Interface) { 448 if _, ok := encoded.Type.(wire.TypeSpecNil); ok { 449 // Special case; the nil object. Just decode directly, which 450 // will read nil from the wire (if encoded correctly). 451 ds.decodeObject(ods, obj, encoded.Value) 452 return 453 } 454 455 // We now need to resolve the actual type. 456 typ := ds.findType(encoded.Type) 457 458 // We need to imbue type information here, then we can proceed to 459 // decode normally. In order to avoid issues with setting value-types, 460 // we create a new non-interface version of this object. We will then 461 // set the interface object to be equal to whatever we decode. 462 origObj := obj 463 obj = reflect.New(typ).Elem() 464 defer origObj.Set(obj) 465 466 // With the object now having sufficient type information to actually 467 // have Set called on it, we can proceed to decode the value. 468 ds.decodeObject(ods, obj, encoded.Value) 469 } 470 471 // isFloatEq determines if x and y represent the same value. 472 func isFloatEq(x float64, y float64) bool { 473 switch { 474 case math.IsNaN(x): 475 return math.IsNaN(y) 476 case math.IsInf(x, 1): 477 return math.IsInf(y, 1) 478 case math.IsInf(x, -1): 479 return math.IsInf(y, -1) 480 default: 481 return x == y 482 } 483 } 484 485 // isComplexEq determines if x and y represent the same value. 486 func isComplexEq(x complex128, y complex128) bool { 487 return isFloatEq(real(x), real(y)) && isFloatEq(imag(x), imag(y)) 488 } 489 490 // decodeObject decodes a object value. 491 func (ds *decodeState) decodeObject(ods *objectDecodeState, obj reflect.Value, encoded wire.Object) { 492 switch x := encoded.(type) { 493 case wire.Nil: // Fast path: first. 494 // We leave obj alone here. That's because if obj represents an 495 // interface, it may have been imbued with type information in 496 // decodeInterface, and we don't want to destroy that. 497 case *wire.Ref: 498 // Nil pointers may be encoded in a "forceValue" context. For 499 // those we just leave it alone as the value will already be 500 // correct (nil). 501 if id := objectID(x.Root); id == 0 { 502 return 503 } 504 505 // Note that if this is a map type, we go through a level of 506 // indirection to allow for map aliasing. 507 if obj.Kind() == reflect.Map { 508 v := ds.register(x, obj.Type()) 509 if v.IsNil() { 510 // Note that we don't want to clobber the map 511 // if has already been decoded by decodeMap. We 512 // just make it so that we have a consistent 513 // reference when that eventually does happen. 514 v.Set(reflect.MakeMap(v.Type())) 515 } 516 obj.Set(v) 517 return 518 } 519 520 // Normal assignment: authoritative only if no dots. 521 v := ds.register(x, obj.Type().Elem()) 522 obj.Set(reflectValueRWAddr(v)) 523 case wire.Bool: 524 obj.SetBool(bool(x)) 525 case wire.Int: 526 obj.SetInt(int64(x)) 527 if obj.Int() != int64(x) { 528 Failf("signed integer truncated from %v to %v", int64(x), obj.Int()) 529 } 530 case wire.Uint: 531 obj.SetUint(uint64(x)) 532 if obj.Uint() != uint64(x) { 533 Failf("unsigned integer truncated from %v to %v", uint64(x), obj.Uint()) 534 } 535 case wire.Float32: 536 obj.SetFloat(float64(x)) 537 case wire.Float64: 538 obj.SetFloat(float64(x)) 539 if !isFloatEq(obj.Float(), float64(x)) { 540 Failf("floating point number truncated from %v to %v", float64(x), obj.Float()) 541 } 542 case *wire.Complex64: 543 obj.SetComplex(complex128(*x)) 544 case *wire.Complex128: 545 obj.SetComplex(complex128(*x)) 546 if !isComplexEq(obj.Complex(), complex128(*x)) { 547 Failf("complex number truncated from %v to %v", complex128(*x), obj.Complex()) 548 } 549 case *wire.String: 550 obj.SetString(string(*x)) 551 case *wire.Slice: 552 // See *wire.Ref above; same applies. 553 if id := objectID(x.Ref.Root); id == 0 { 554 return 555 } 556 // Note that it's fine to slice the array here and assume that 557 // contents will still be filled in later on. 558 typ := reflect.ArrayOf(int(x.Capacity), obj.Type().Elem()) // The object type. 559 v := ds.register(&x.Ref, typ) 560 obj.Set(reflectValueRWSlice3(v, 0, int(x.Length), int(x.Capacity))) 561 case *wire.Array: 562 ds.decodeArray(ods, obj, x) 563 case *wire.Struct: 564 ds.decodeStruct(ods, obj, x) 565 case *wire.Map: 566 ds.decodeMap(ods, obj, x) 567 case *wire.Interface: 568 ds.decodeInterface(ods, obj, x) 569 default: 570 // Shoud not happen, not propagated as an error. 571 Failf("unknown object %#v for %q", encoded, obj.Type().Name()) 572 } 573 } 574 575 // Load deserializes the object graph rooted at obj. 576 // 577 // This function may panic and should be run in safely(). 578 func (ds *decodeState) Load(obj reflect.Value) { 579 ds.stats.init() 580 defer ds.stats.fini(func(id typeID) string { 581 return ds.types.LookupName(id) 582 }) 583 584 // Create the root object. 585 rootOds := &objectDecodeState{ 586 id: 1, 587 obj: obj, 588 } 589 ds.objectsByID = append(ds.objectsByID, rootOds) 590 ds.pending.PushBack(rootOds) 591 592 // Read the number of objects. 593 numObjects, object, err := ReadHeader(ds.r) 594 if err != nil { 595 Failf("header error: %w", err) 596 } 597 if !object { 598 Failf("object missing") 599 } 600 601 // Decode all objects. 602 var ( 603 encoded wire.Object 604 ods *objectDecodeState 605 id objectID 606 tid = typeID(1) 607 ) 608 if err := safely(func() { 609 // Decode all objects in the stream. 610 // 611 // Note that the structure of this decoding loop should match the raw 612 // decoding loop in state/pretty/pretty.printer.printStream(). 613 for i := uint64(0); i < numObjects; { 614 // Unmarshal either a type object or object ID. 615 encoded = wire.Load(ds.r) 616 switch we := encoded.(type) { 617 case *wire.Type: 618 ds.types.Register(we) 619 tid++ 620 encoded = nil 621 continue 622 case wire.Uint: 623 id = objectID(we) 624 i++ 625 // Unmarshal and resolve the actual object. 626 encoded = wire.Load(ds.r) 627 ods = ds.lookup(id) 628 if ods != nil { 629 // Decode the object. 630 ds.decodeObject(ods, ods.obj, encoded) 631 } else { 632 // If an object hasn't had interest registered 633 // previously or isn't yet valid, we deferred 634 // decoding until interest is registered. 635 ds.deferred[id] = encoded 636 } 637 // For error handling. 638 ods = nil 639 encoded = nil 640 default: 641 Failf("wanted type or object ID, got %T", encoded) 642 } 643 } 644 }); err != nil { 645 // Include as much information as we can, taking into account 646 // the possible state transitions above. 647 if ods != nil { 648 Failf("error decoding object ID %d (%T) from %#v: %w", id, ods.obj.Interface(), encoded, err) 649 } else if encoded != nil { 650 Failf("error decoding from %#v: %w", encoded, err) 651 } else { 652 Failf("general decoding error: %w", err) 653 } 654 } 655 656 // Check if we have any deferred objects. 657 numDeferred := 0 658 for id, encoded := range ds.deferred { 659 numDeferred++ 660 if s, ok := encoded.(*wire.Struct); ok && s.TypeID != 0 { 661 typ := ds.types.LookupType(typeID(s.TypeID)) 662 Failf("unused deferred object: ID %d, type %v", id, typ) 663 } else { 664 Failf("unused deferred object: ID %d, %#v", id, encoded) 665 } 666 } 667 if numDeferred != 0 { 668 Failf("still had %d deferred objects", numDeferred) 669 } 670 671 // Scan and fire all callbacks. We iterate over the list of incomplete 672 // objects until all have been finished. We stop iterating if no 673 // objects become complete (there is a dependency cycle). 674 // 675 // Note that we iterate backwards here, because there will be a strong 676 // tendendcy for blocking relationships to go from earlier objects to 677 // later (deeper) objects in the graph. This will reduce the number of 678 // iterations required to finish all objects. 679 if err := safely(func() { 680 for ds.pending.Back() != nil { 681 thisCycle := false 682 for ods = ds.pending.Back(); ods != nil; { 683 if ds.checkComplete(ods) { 684 thisCycle = true 685 break 686 } 687 ods = ods.Prev() 688 } 689 if !thisCycle { 690 break 691 } 692 } 693 }); err != nil { 694 Failf("error executing callbacks for %#v: %w", ods.obj.Interface(), err) 695 } 696 697 // Check if we have any remaining dependency cycles. If there are any 698 // objects left in the pending list, then it must be due to a cycle. 699 if ods := ds.pending.Front(); ods != nil { 700 // This must be the result of a dependency cycle. 701 cycle := ods.findCycle() 702 var buf bytes.Buffer 703 buf.WriteString("dependency cycle: {") 704 for i, cycleOS := range cycle { 705 if i > 0 { 706 buf.WriteString(" => ") 707 } 708 fmt.Fprintf(&buf, "%q", cycleOS.obj.Type()) 709 } 710 buf.WriteString("}") 711 Failf("incomplete graph: %s", string(buf.Bytes())) 712 } 713 } 714 715 // ReadHeader reads an object header. 716 // 717 // Each object written to the statefile is prefixed with a header. See 718 // WriteHeader for more information; these functions are exported to allow 719 // non-state writes to the file to play nice with debugging tools. 720 func ReadHeader(r wire.Reader) (length uint64, object bool, err error) { 721 // Read the header. 722 err = safely(func() { 723 length = wire.LoadUint(r) 724 }) 725 if err != nil { 726 // On the header, pass raw I/O errors. 727 if sErr, ok := err.(*ErrState); ok { 728 return 0, false, sErr.Unwrap() 729 } 730 } 731 732 // Decode whether the object is valid. 733 object = length&objectFlag != 0 734 length &^= objectFlag 735 return 736 }