public object Read(object value, ProtoReader source) { ProtoReader.ExpectRoot(source); if (_protoCompatibility) { return(_serializer.Read(value, source)); } int typeKey; object obj; int expectedRefKey; var rootToken = ProtoReader.StartSubItem(source); int formatVersion = source.ReadFieldHeader(); if (formatVersion != CurrentFormatVersion) { throw new ProtoException("Wrong format version, required " + CurrentFormatVersion + " but actual " + formatVersion); } var r = _serializer.Read(value, source); while (ProtoReader.TryGetNextLateReference(out typeKey, out obj, out expectedRefKey, source)) { int actualRefKey; do { actualRefKey = source.ReadFieldHeader() - 1; if (actualRefKey != expectedRefKey) { if (actualRefKey <= -1) { throw new ProtoException("Expected field for late reference"); } // should go only up if (actualRefKey > expectedRefKey) { throw new ProtoException("Mismatched order of late reference objects"); } source.SkipField(); // refKey < num } } while (actualRefKey < expectedRefKey); object lateObj = ProtoReader.ReadObject(obj, typeKey, source); if (!ReferenceEquals(lateObj, obj)) { throw new ProtoException("Late reference changed during deserializing"); } } ProtoReader.EndSubItem(rootToken, true, source); return(r); }