/// <summary> /// Deserialize a set of core objects from a BinaryReader. /// </summary> /// <param name="reader">Source stream</param> /// <param name="ignoreUnknownChunks">If set to true and an unknown RTTI type is encountered, read the object as /// an array of bytes. Otherwise, raise an exception.</param> public static CoreBinary FromData(BinaryReader reader, bool ignoreUnknownChunks = true) { var core = new CoreBinary(); while (reader.StreamRemainder() > 0) { #if COREFILE_DEBUG System.Diagnostics.Debugger.Log(0, "Info", $"Beginning chunk parse at {reader.BaseStream.Position:X}\n"); #endif var entry = RTTI.DeserializeType <CoreEntry>(reader); var topLevelObjectType = RTTI.GetTypeById(entry.TypeId); long expectedStreamPos = reader.BaseStream.Position + entry.ChunkSize; if (entry.ChunkSize > reader.StreamRemainder()) { throw new InvalidDataException($"Invalid chunk size {entry.ChunkSize} was supplied in Core file at offset {entry.ChunkOffset:X}"); } if (topLevelObjectType != null) { entry.ContainedObject = RTTI.DeserializeType(reader, topLevelObjectType); } else { if (!ignoreUnknownChunks) { throw new InvalidDataException($"Unknown type ID {entry.TypeId:X16} found in Core file at offset {entry.ChunkOffset:X}"); } // Invalid or unknown chunk ID hit - create an array of bytes "object" and try to continue with the rest of the file entry.ContainedObject = reader.ReadBytes(entry.ChunkSize); } #if COREFILE_DEBUG if (reader.BaseStream.Position < expectedStreamPos) { System.Diagnostics.Debugger.Log(0, "Warn", $"Short read of a chunk while deserializing object. {reader.BaseStream.Position} < {expectedStreamPos}. TypeId = {entry.TypeId:X16}\n"); } #endif // Check for overflows and underflows if (reader.BaseStream.Position > expectedStreamPos) { throw new Exception("Read past the end of a chunk while deserializing object"); } else if (reader.BaseStream.Position < expectedStreamPos) { throw new Exception("Short read of a chunk while deserializing object"); } reader.BaseStream.Position = expectedStreamPos; core._entries.Add(entry); } return(core); }
public static List <object> Load(string filePath, bool ignoreUnknownChunks = false) { var coreFileObjects = new List <object>(); using (var reader = new BinaryReader(File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))) { while (reader.BaseStream.Position != reader.BaseStream.Length) { //Console.WriteLine($"Beginning chunk parse at {reader.BaseStream.Position:X}"); var entry = RTTI.DeserializeType <Entry>(reader); long currentFilePos = reader.BaseStream.Position; long expectedFilePos = currentFilePos + entry.ChunkSize; if ((currentFilePos + entry.ChunkSize) > reader.StreamRemainder()) { throw new InvalidDataException($"Invalid chunk size {entry.ChunkSize} was supplied in Core file at offset {currentFilePos:X}"); } // TODO: This needs to be part of Entry Type topLevelObjectType = RTTI.GetTypeById(entry.TypeId); object topLevelObject = null; if (topLevelObjectType != null) { topLevelObject = RTTI.DeserializeType(reader, topLevelObjectType); } else { if (!ignoreUnknownChunks) { throw new InvalidDataException($"Unknown type ID {entry.TypeId:X16} found in Core file at offset {currentFilePos:X}"); } // Invalid or unknown chunk ID hit - create an array of bytes "object" and try to continue with the rest of the file topLevelObject = reader.ReadBytes(entry.ChunkSize); } if (reader.BaseStream.Position > expectedFilePos) { throw new Exception("Read past the end of a chunk while deserializing object"); } else if (reader.BaseStream.Position < expectedFilePos) { throw new Exception("Short read of a chunk while deserializing object"); } reader.BaseStream.Position = expectedFilePos; coreFileObjects.Add(topLevelObject); } } return(coreFileObjects); }