Save serializes the object graph rooted at obj.
(obj reflect.Value)
| 747 | |
| 748 | // Save serializes the object graph rooted at obj. |
| 749 | func (es *encodeState) Save(obj reflect.Value) { |
| 750 | es.stats.init() |
| 751 | defer es.stats.fini(func(id typeID) string { |
| 752 | return es.pendingTypes[id-1].Name |
| 753 | }) |
| 754 | |
| 755 | // Resolve the first object, which should queue a pile of additional |
| 756 | // objects on the pending list. All queued objects should be fully |
| 757 | // resolved, and we should be able to serialize after this call. |
| 758 | var root wire.Ref |
| 759 | es.resolve(obj.Addr(), &root) |
| 760 | |
| 761 | // Encode the graph. |
| 762 | var oes *objectEncodeState |
| 763 | if err := safely(func() { |
| 764 | for oes = es.deferred.Front(); oes != nil; oes = es.deferred.Front() { |
| 765 | // Remove and encode the object. Note that as a result |
| 766 | // of this encoding, the object may be enqueued on the |
| 767 | // deferred list yet again. That's expected, and why it |
| 768 | // is removed first. |
| 769 | es.deferred.Remove(oes) |
| 770 | es.encodeObject(oes.obj, oes.how, &oes.encoded) |
| 771 | } |
| 772 | }); err != nil { |
| 773 | // Include the object in the error message, if available. |
| 774 | if oes != nil && oes.obj.IsValid() { |
| 775 | Failf("encoding error: %w\nfor object %#v", err, oes.obj.Interface()) |
| 776 | } |
| 777 | Failf("encoding error: %w", err) |
| 778 | } |
| 779 | |
| 780 | // Check that we have objects to serialize. |
| 781 | if len(es.pending) == 0 { |
| 782 | Failf("pending is empty?") |
| 783 | } |
| 784 | |
| 785 | // Write the header with the number of objects. |
| 786 | if err := WriteHeader(&es.w, uint64(len(es.pending)), true); err != nil { |
| 787 | Failf("error writing header: %w", err) |
| 788 | } |
| 789 | |
| 790 | // Serialize all pending types and pending objects. Note that we don't |
| 791 | // bother removing from this list as we walk it because that just |
| 792 | // wastes time. It will not change after this point. |
| 793 | if err := safely(func() { |
| 794 | for _, wt := range es.pendingTypes { |
| 795 | // Encode the type. |
| 796 | wire.Save(&es.w, &wt) |
| 797 | } |
| 798 | // Emit objects in ID order. |
| 799 | ids := make([]objectID, 0, len(es.pending)) |
| 800 | for id := range es.pending { |
| 801 | ids = append(ids, id) |
| 802 | } |
| 803 | sort.Slice(ids, func(i, j int) bool { |
| 804 | return ids[i] < ids[j] |
| 805 | }) |
| 806 | for _, id := range ids { |
no test coverage detected