private static void ReadMembers(DeserializationState state, ClassRecord record) { record.TypeName = state.array.Read7BitLengthPrefixedString(ref state.idx); var cap = state.array.ReadInt32LEFromBytes(ref state.idx); record.Members.Capacity = cap; for (var i = 0; i < cap; ++i) { var member = new ClassRecordMember(); member.Name = state.array.Read7BitLengthPrefixedString(ref state.idx); record.Members.Add(member); } }
private static AbstractRecord ReadSingleRecord(DeserializationState state) { AbstractRecord retVal; if (state.nullCount > 0) { --state.nullCount; retVal = null; } else { ClassRecord cRecord; ArrayRecord aRecord; var recType = (RecordTypeEnumeration)state.array.ReadByteFromBytes(ref state.idx); switch (recType) { case RecordTypeEnumeration.SerializedStreamHeader: state.array.Skip(ref state.idx, 16); // Skip the header of 4 ints retVal = null; break; case RecordTypeEnumeration.ClassWithID: cRecord = NewRecord <ClassRecord>(state); var refID = state.array.ReadInt32LEFromBytes(ref state.idx); var refRecord = (ClassRecord)state.records[refID]; // Copy metadata from referenced object cRecord.AssemblyName = refRecord.AssemblyName; cRecord.TypeName = refRecord.TypeName; cRecord.Members.Capacity = refRecord.Members.Count; for (var i = 0; i < refRecord.Members.Count; ++i) { var member = new ClassRecordMember(); var refMember = refRecord.Members[i]; member.AssemblyName = refMember.AssemblyName; member.TypeName = refMember.TypeName; member.Name = refMember.Name; cRecord.Members.Add(member); } // Read values ReadMemberValues(state, cRecord); retVal = cRecord; break; case RecordTypeEnumeration.SystemClassWithMembers: cRecord = NewRecord <ClassRecord>(state); ReadMembers(state, cRecord); ReadMemberValues(state, cRecord); retVal = cRecord; break; case RecordTypeEnumeration.ClassWithMembers: cRecord = NewRecord <ClassRecord>(state); ReadMembers(state, cRecord); cRecord.AssemblyName = state.assemblies[state.array.ReadInt32LEFromBytes(ref state.idx)]; ReadMemberValues(state, cRecord); retVal = cRecord; break; case RecordTypeEnumeration.SystemClassWithMembersAndTypes: cRecord = NewRecord <ClassRecord>(state); ReadMembers(state, cRecord); ReadMemberTypes(state, cRecord); ReadMemberValues(state, cRecord); retVal = cRecord; break; case RecordTypeEnumeration.ClassWithMembersAndTypes: cRecord = NewRecord <ClassRecord>(state); ReadMembers(state, cRecord); ReadMemberTypes(state, cRecord); cRecord.AssemblyName = state.assemblies[state.array.ReadInt32LEFromBytes(ref state.idx)]; ReadMemberValues(state, cRecord); retVal = cRecord; break; case RecordTypeEnumeration.BinaryObjectString: var strRecord = NewRecord <StringRecord>(state); strRecord.StringValue = state.array.Read7BitLengthPrefixedString(ref state.idx); retVal = strRecord; break; case RecordTypeEnumeration.BinaryArray: aRecord = NewRecord <ArrayRecord>(state); ReadArrayInformation(state, aRecord); ReadArrayValues(state, aRecord); retVal = aRecord; break; case RecordTypeEnumeration.MemberPrimitiveTyped: var pRecord = new PrimitiveWrapperRecord(); pRecord.Value = ReadPrimitiveValue(state, (PrimitiveTypeEnumeration)state.array.ReadByteFromBytes(ref state.idx)); retVal = pRecord; break; case RecordTypeEnumeration.MemberReference: retVal = new RecordPlaceholder(state.array.ReadInt32LEFromBytes(ref state.idx)); break; case RecordTypeEnumeration.ObjectNull: retVal = null; break; case RecordTypeEnumeration.MessageEnd: state.recordsEnded = true; retVal = null; break; case RecordTypeEnumeration.BinaryLibrary: // VS2012 should guarantee that first parameter will be executed first state.assemblies.Add(state.array.ReadInt32LEFromBytes(ref state.idx), state.array.Read7BitLengthPrefixedString(ref state.idx)); retVal = null; break; case RecordTypeEnumeration.ObjectNullMultiple256: state.nullCount = state.array.ReadByteFromBytes(ref state.idx) - 1; // Returning the first null retVal = null; break; case RecordTypeEnumeration.ObjectNullMultiple: state.nullCount = state.array.ReadInt32LEFromBytes(ref state.idx) - 1; // Returning the first null retVal = null; break; case RecordTypeEnumeration.ArraySinglePrimitive: aRecord = NewRecord <ArrayRecord>(state); state.typeInfos.Add(aRecord, BinaryTypeEnumeration.Primitive); ReadArrayLengths(state, aRecord); ReadAdditionalTypeInfo(state, aRecord); ReadArrayValues(state, aRecord); retVal = aRecord; break; case RecordTypeEnumeration.ArraySingleObject: aRecord = NewRecord <ArrayRecord>(state); state.typeInfos.Add(aRecord, BinaryTypeEnumeration.Object); ReadArrayLengths(state, aRecord); ReadArrayValues(state, aRecord); retVal = aRecord; break; case RecordTypeEnumeration.ArraySingleString: aRecord = NewRecord <ArrayRecord>(state); state.typeInfos.Add(aRecord, BinaryTypeEnumeration.String); ReadArrayLengths(state, aRecord); ReadArrayValues(state, aRecord); retVal = aRecord; break; case RecordTypeEnumeration.MethodCall: throw new NotImplementedException(); // TODO case RecordTypeEnumeration.MethodReturn: throw new NotImplementedException(); // TODO default: throw new InvalidOperationException("Unsupported record type: " + recType + "."); } } return(retVal); }