/// <summary> /// Writes the <paramref name="chunk"/> to the file. /// </summary> /// <param name="chunk">Must not be null.</param> /// <returns>Returns the header information for the chunk that has just been written.</returns> public FileChunkHeader WriteNextChunk(object chunk) { Check.IfArgumentNull(chunk, nameof(chunk)); // find chunk id var chunkId = ChunkAttribute.GetChunkId(chunk); if (String.IsNullOrEmpty(chunkId)) { var msg = String.Format( CultureInfo.InvariantCulture, "No Chunk Attribute was found for the specified runtime object of type '{0}'.", chunk.GetType().FullName); throw new ArgumentException(msg); } if (chunkId.HasWildcard()) { // TODO: this must be pluggable in some way // for now only digits chunkId = chunkId.Merge("0000"); } var chunkTypeId = new FourCharacterCode(chunkId); var chunkHandler = _handlerMgr.GetChunkHandler(chunkTypeId); if (!chunkHandler.CanWrite(chunk)) { var msg = String.Format( CultureInfo.InvariantCulture, "The chunk handler '{0}' cannot write the specified runtime object.", chunkHandler.ChunkId); throw new ArgumentException(msg); } int stackPos = Context.HeaderStack.Count; var header = PushNewHeader(chunkTypeId); chunkHandler.Write(Context, chunk); // wind down the stack to the level it was before we started. while (Context.HeaderStack.Count > stackPos) { var poppedHeader = PopHeader(); WriteChunkHeader(poppedHeader); } return(header); }
/// <summary> /// Reads the next chunk from the <paramref name="stream"/>. /// </summary> /// <param name="stream">Must not be null.</param> /// <returns>Returns null when there was no runtime chunk type found to represent the chunk read.</returns> public object ReadNextChunk(Stream stream) { Check.IfArgumentNull(stream, nameof(stream)); object chunkObject = null; var chunk = ReadChunkHeader(stream); if (chunk != null) { Context.ChunkStack.PushChunk(chunk); var chunkHandler = _handlerMgr.GetChunkHandler(chunk.ChunkId); if (chunkHandler.CanRead(chunk)) { chunkObject = chunkHandler.Read(Context); chunk.RuntimeInstance = chunkObject; } // makes sure all of the chunk is 'read' (skipped) // and aligns the stream position ready for the next chunk. SkipChunk(chunk); var poppedChunk = Context.ChunkStack.PopChunk(); if (poppedChunk != null && !Object.ReferenceEquals(poppedChunk, chunk)) { throw new InvalidOperationException("The Chunk Stack has been corrupted."); } } return(chunkObject); }