private void Decode(string inputFile, string outputFolder, CancellationToken cancellationToken, IProgress <CodingProgressInfo> progress)
        {
            FileDecodingInputStream inputStream = new FileDecodingInputStream(inputFile, platform);

            ITaskProgressController tpc = CreateTaskProgressController(progress, inputStream);

            try {
                if (inputStream.IsEmpty)
                {
                    return;
                }

                StreamKind code = inputStream.ReadStreamFormat();
                if (code != StreamKind.WT_CODE)
                {
                    throw new StreamFormatException();
                }

                tpc.Start();
                directoriesQueue.Enqueue(currentDirectory = outputFolder);
                BootstrapSegment bootstrapSegment = streamParser.ParseWeightsTable(inputStream);
                while (!inputStream.IsEmpty)
                {
                    switch (inputStream.ReadStreamFormat())
                    {
                    case StreamKind.FS_CODE:
                        DecodeFile(inputStream, bootstrapSegment, cancellationToken, tpc);
                        break;

                    case StreamKind.DS_CODE:
                        DecodeDirectory(inputStream);
                        break;

                    default:
                        throw new StreamFormatException();
                    }
                }
                tpc.Finish();
            }
            catch {
                tpc.Error();
                throw;
            }
            finally {
                inputStream.Dispose();
            }
        }
        private EncodingStatistics Encode(string inputPath, string outputFile, CancellationToken cancellationToken, IProgress <CodingProgressInfo> progress)
        {
            HuffmanEncoder encoder = new HuffmanEncoder();
            DirectoryEncodingInputStream directoryInputStream = new DirectoryEncodingInputStream(inputPath, fileSystemService, platform);
            FileEncodingOutputStream     outputStream         = new FileEncodingOutputStream(outputFile, platform);

            ITaskProgressController tpc = CreateTaskProgressController(progress, directoryInputStream);

            try {
                outputStream.BeginWrite();
                tpc.StartIndeterminate();
                EncodingToken encodingToken = encoder.CreateEncodingToken(directoryInputStream, cancellationToken);
                tpc.EndIndeterminate();
                streamBuilder.Initialize(platform, encodingToken, outputStream);
                streamBuilder.AddWeightsTable(new BootstrapSegment(encodingToken.WeightsTable));
                tpc.Start();
                foreach (FileSystemEntry entry in fileSystemService.EnumFileSystemEntries(inputPath))
                {
                    switch (entry.Type)
                    {
                    case FileSystemEntryType.Directory:
                        streamBuilder.AddDirectory(new DirectorySegment(entry.Name, entry.Cardinality));
                        break;

                    case FileSystemEntryType.File:
                        streamBuilder.AddFile(new FileSegment(entry.Name, entry.Path), cancellationToken, tpc);
                        break;

                    default:
                        throw new InvalidOperationException();
                    }
                }
                outputStream.EndWrite();
                tpc.Finish();
                return(new EncodingStatistics(directoryInputStream.SizeInBytes, outputStream.SizeInBytes));
            }
            catch {
                tpc.Error();
                throw;
            }
            finally {
                directoryInputStream.Dispose();
                outputStream.Dispose();
            }
        }