using PacketIO; namespace Archiver.Lib; public static class ArchiveDecoder { public static async ValueTask Decode(string inputPath, string outputPath) { if (!File.Exists(inputPath)) { throw new FileNotFoundException($"{inputPath} does not exist", inputPath); } FileAttributes attributes = File.GetAttributes(inputPath); if (attributes.HasFlag(FileAttributes.Directory)) { throw new IOException("Target does not file."); } using (FileStream fs = new FileStream(inputPath, FileMode.Open)) { byte[] buffer = new byte[ArchiveEncoder.CreateFileHeader().Length]; await fs.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false); if (!buffer.SequenceEqual(ArchiveEncoder.CreateFileHeader())) { throw new IOException("Not supported file type."); } await ReadFile(fs, outputPath).ConfigureAwait(false); } } private static async ValueTask ReadFile(Stream stream, string outputPath) { IPacketFile? file = await TreePacketFile.ReadTreeFile(stream).ConfigureAwait(false); if (file is null) { return; } await OutputFile(file, outputPath).ConfigureAwait(false); await ReadFile(stream, outputPath).ConfigureAwait(false); } private static async ValueTask OutputFile(IPacketFile file, string outputPath) { switch (file.GetFileType()) { case PacketFileType.Directory: { string dirPath = Path.Combine(outputPath, file.GetFileName()); if (!Directory.Exists(dirPath)) { Directory.CreateDirectory(dirPath); } foreach (IPacketFile inFile in file.EnumerableFiles()) { await OutputFile(inFile, dirPath).ConfigureAwait(false); } break; } case PacketFileType.File: { string filePath = Path.Combine(outputPath, file.GetFileName()); using (FileStream outputStream = new FileStream(filePath, FileMode.OpenOrCreate)) { PacketFile pfile = (PacketFile) file; byte[] buffer = new byte[8192]; int c; do { c = await pfile.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false); await outputStream.WriteAsync(buffer, 0, c).ConfigureAwait(false); } while (c > 0); } break; } } file.Dispose(); } }