protected async override Task ExecuteEncodeAsync(ImageConfiguration configuration, Stream output) { var chunkLayoutBuilder = new ChunkLayoutBuilder(); var chunkWriter = new ChunkWriter(EncodingConfiguration); chunkLayoutBuilder.Append( GenerateChunk(StructureType.Metadata, configuration, new Metadata(configuration.Metadata)), chunkWriter, new MetadataSerializer()); IList <IList <File> > groupedFiles = _fileGroupingService.GroupFiles(configuration.Files, EncodingConfiguration.FileGroupSize); IDictionary <File, Output.File> mappedFiles = MapFiles(configuration.Files); ICollection <Directory> mappedDirectories = MapDirectories(mappedFiles, configuration.Directories).Values; var fileGroupSerializer = new FileGroupContentsSerializer(EncodingConfiguration); var fileGroups = new List <FileGroup>(); var fileStreams = new List <Stream>(); foreach (var group in groupedFiles) { fileGroups.Add(new FileGroup(group.Select(file => mappedFiles[file]))); var fileGroupStreams = group.Select(file => file.GetStream()).ToList(); fileStreams.AddRange(fileGroupStreams); chunkLayoutBuilder.Append(GenerateChunk( StructureType.FileGroupContents, configuration, new FileGroupContents(new CombinedStream(fileGroupStreams))), chunkWriter, fileGroupSerializer); } chunkLayoutBuilder.Prepend( GenerateChunk(StructureType.FileLayout, configuration, new FileLayout(mappedDirectories, fileGroups)), chunkWriter, new FileLayoutSerializer()); ChunkLayout chunkLayout = await chunkLayoutBuilder.BuildAsync(); var chunkLayoutBytes = await new ChunkLayoutSerializer().SerializeToBytesAsync(chunkLayout); long totalLength = CalculateTotalLength(chunkLayoutBytes, chunkLayout) + 1; //Plus one to force room for padding using (Stream imageStream = await CreateImageWriterStreamAsync(configuration, output, totalLength)) { await WriteBodyData(imageStream, chunkLayoutBytes, chunkLayoutBuilder); } fileStreams.ForEach(stream => stream.Close()); }
protected override async Task <IReadOnlyDictionary <File, Stream> > _DecodeFileContentsAsync(DataInfo dataInfo, Stream imageReaderStream, IEnumerable <File> files) { var fileContents = new Dictionary <File, Stream>(); var fileLookup = new HashSet <File>(files); var fileGroupSerializer = new FileGroupContentsSerializer(DecodingConfiguration); int fileGroupIndex = 0; // Skip file layout and metadata chunk foreach (ChunkInfo chunkInfo in dataInfo.ChunkLayout.OrderedChunkInfo.Skip(2)) { if (chunkInfo.Type == StructureType.FileGroupContents) { FileGroup group = dataInfo.FileLayout.OrderdFileGroups.ElementAt(fileGroupIndex); fileGroupIndex++; List <File> filesToDecode = group.Files.Where(fileLookup.Contains).ToList(); if (filesToDecode.Count > 0) { FileGroupContents fileGroupContents = (await _chunkReader.ReadChunkAsync(imageReaderStream, chunkInfo, fileGroupSerializer)).Body; foreach (File file in filesToDecode) { Stream fileContentStream = fileGroupContents.FileContentStreams; var startOffset = group.Files .TakeWhile(aFile => aFile != file) .Sum(aFile => aFile.Length); fileContents.Add(file, new SubStream(fileContentStream, startOffset, file.Length)); } continue; } } await _chunkReader.SkipChunkAsync(imageReaderStream, chunkInfo); } return(fileContents); }