diff --git a/osu.Game/Beatmaps/BeatmapImporter.cs b/osu.Game/Beatmaps/BeatmapImporter.cs index 14719da1bc..b497b8e8dc 100644 --- a/osu.Game/Beatmaps/BeatmapImporter.cs +++ b/osu.Game/Beatmaps/BeatmapImporter.cs @@ -319,7 +319,7 @@ namespace osu.Game.Beatmaps { DateTimeOffset dateAdded = DateTimeOffset.UtcNow; - if (reader is LegacyDirectoryArchiveReader legacyReader) + if (reader is DirectoryArchiveReader legacyReader) { var beatmaps = reader.Filenames.Where(f => f.EndsWith(".osu", StringComparison.OrdinalIgnoreCase)); diff --git a/osu.Game/Database/ImportTask.cs b/osu.Game/Database/ImportTask.cs index def20bc1fb..8f2752020b 100644 --- a/osu.Game/Database/ImportTask.cs +++ b/osu.Game/Database/ImportTask.cs @@ -46,9 +46,29 @@ namespace osu.Game.Database /// public ArchiveReader GetReader() { - return Stream != null - ? getReaderFrom(Stream) - : getReaderFrom(Path); + if (Stream == null) + { + if (ZipUtils.IsZipArchive(Path)) + return new ZipArchiveReader(File.Open(Path, FileMode.Open, FileAccess.Read, FileShare.Read), System.IO.Path.GetFileName(Path)); + if (Directory.Exists(Path)) + return new DirectoryArchiveReader(Path); + if (File.Exists(Path)) + return new SingleFileArchiveReader(Path); + + throw new InvalidFormatException($"{Path} is not a valid archive"); + } + + if (Stream is not MemoryStream memoryStream) + { + // Path used primarily in tests (converting `ManifestResourceStream`s to `MemoryStream`s). + memoryStream = new MemoryStream(Stream.ReadAllBytesToArray()); + Stream.Dispose(); + } + + if (ZipUtils.IsZipArchive(memoryStream)) + return new ZipArchiveReader(memoryStream, Path); + + return new MemoryStreamArchiveReader(memoryStream, Path); } /// @@ -60,43 +80,6 @@ namespace osu.Game.Database File.Delete(Path); } - /// - /// Creates an from a stream. - /// - /// A seekable stream containing the archive content. - /// A reader giving access to the archive's content. - private ArchiveReader getReaderFrom(Stream stream) - { - if (!(stream is MemoryStream memoryStream)) - { - // This isn't used in any current path. May need to reconsider for performance reasons (ie. if we don't expect the incoming stream to be copied out). - memoryStream = new MemoryStream(stream.ReadAllBytesToArray()); - stream.Dispose(); - } - - if (ZipUtils.IsZipArchive(memoryStream)) - return new ZipArchiveReader(memoryStream, Path); - - return new LegacyByteArrayReader(memoryStream.ToArray(), Path); - } - - /// - /// Creates an from a valid storage path. - /// - /// A file or folder path resolving the archive content. - /// A reader giving access to the archive's content. - private ArchiveReader getReaderFrom(string path) - { - if (ZipUtils.IsZipArchive(path)) - return new ZipArchiveReader(File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read), System.IO.Path.GetFileName(path)); - if (Directory.Exists(path)) - return new LegacyDirectoryArchiveReader(path); - if (File.Exists(path)) - return new LegacyFileArchiveReader(path); - - throw new InvalidFormatException($"{path} is not a valid archive"); - } - public override string ToString() => System.IO.Path.GetFileName(Path); } } diff --git a/osu.Game/IO/Archives/LegacyByteArrayReader.cs b/osu.Game/IO/Archives/ByteArrayArchiveReader.cs similarity index 84% rename from osu.Game/IO/Archives/LegacyByteArrayReader.cs rename to osu.Game/IO/Archives/ByteArrayArchiveReader.cs index 06db02b335..0e2dee3456 100644 --- a/osu.Game/IO/Archives/LegacyByteArrayReader.cs +++ b/osu.Game/IO/Archives/ByteArrayArchiveReader.cs @@ -9,11 +9,11 @@ namespace osu.Game.IO.Archives /// /// Allows reading a single file from the provided byte array. /// - public class LegacyByteArrayReader : ArchiveReader + public class ByteArrayArchiveReader : ArchiveReader { private readonly byte[] content; - public LegacyByteArrayReader(byte[] content, string filename) + public ByteArrayArchiveReader(byte[] content, string filename) : base(filename) { this.content = content; diff --git a/osu.Game/IO/Archives/LegacyDirectoryArchiveReader.cs b/osu.Game/IO/Archives/DirectoryArchiveReader.cs similarity index 85% rename from osu.Game/IO/Archives/LegacyDirectoryArchiveReader.cs rename to osu.Game/IO/Archives/DirectoryArchiveReader.cs index 1503705022..f2012b7b49 100644 --- a/osu.Game/IO/Archives/LegacyDirectoryArchiveReader.cs +++ b/osu.Game/IO/Archives/DirectoryArchiveReader.cs @@ -8,13 +8,13 @@ using System.Linq; namespace osu.Game.IO.Archives { /// - /// Reads an archive from a directory on disk. + /// Reads an archive directly from a directory on disk. /// - public class LegacyDirectoryArchiveReader : ArchiveReader + public class DirectoryArchiveReader : ArchiveReader { private readonly string path; - public LegacyDirectoryArchiveReader(string path) + public DirectoryArchiveReader(string path) : base(Path.GetFileName(path)) { // re-get full path to standardise with Directory.GetFiles return values below. diff --git a/osu.Game/IO/Archives/MemoryStreamArchiveReader.cs b/osu.Game/IO/Archives/MemoryStreamArchiveReader.cs new file mode 100644 index 0000000000..37ce1e508e --- /dev/null +++ b/osu.Game/IO/Archives/MemoryStreamArchiveReader.cs @@ -0,0 +1,30 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using System.IO; + +namespace osu.Game.IO.Archives +{ + /// + /// Allows reading a single file from the provided memory stream. + /// + public class MemoryStreamArchiveReader : ArchiveReader + { + private readonly MemoryStream stream; + + public MemoryStreamArchiveReader(MemoryStream stream, string filename) + : base(filename) + { + this.stream = stream; + } + + public override Stream GetStream(string name) => new MemoryStream(stream.GetBuffer(), 0, (int)stream.Length); + + public override void Dispose() + { + } + + public override IEnumerable Filenames => new[] { Name }; + } +} diff --git a/osu.Game/IO/Archives/LegacyFileArchiveReader.cs b/osu.Game/IO/Archives/SingleFileArchiveReader.cs similarity index 83% rename from osu.Game/IO/Archives/LegacyFileArchiveReader.cs rename to osu.Game/IO/Archives/SingleFileArchiveReader.cs index c317cae5fc..79d9c5de71 100644 --- a/osu.Game/IO/Archives/LegacyFileArchiveReader.cs +++ b/osu.Game/IO/Archives/SingleFileArchiveReader.cs @@ -7,14 +7,14 @@ using System.IO; namespace osu.Game.IO.Archives { /// - /// Reads a file on disk as an archive. + /// Reads a single file on disk as an archive. /// Note: In this case, the file is not an extractable archive, use instead. /// - public class LegacyFileArchiveReader : ArchiveReader + public class SingleFileArchiveReader : ArchiveReader { private readonly string path; - public LegacyFileArchiveReader(string path) + public SingleFileArchiveReader(string path) : base(Path.GetFileName(path)) { // re-get full path to standardise diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 8c5828fc92..60806a73c5 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -1144,14 +1144,14 @@ namespace osu.Game.Screens.Play if (DrawableRuleset.ReplayScore != null) return Task.CompletedTask; - LegacyByteArrayReader replayReader = null; + ByteArrayArchiveReader replayReader = null; if (score.ScoreInfo.Ruleset.IsLegacyRuleset()) { using (var stream = new MemoryStream()) { new LegacyScoreEncoder(score, GameplayState.Beatmap).Encode(stream); - replayReader = new LegacyByteArrayReader(stream.ToArray(), "replay.osr"); + replayReader = new ByteArrayArchiveReader(stream.ToArray(), "replay.osr"); } }