using System.IO; using SabreTools.Data.Models.OperaFS; namespace SabreTools.Wrappers { public partial class OperaDiscImage : OperaFS { #region Descriptive Properties /// public override string DescriptionString => "3DO / M2 (Opera) Disc Image"; #endregion #region Constructors /// public OperaDiscImage(FileSystem model, byte[] data) : base(model, data) { } /// public OperaDiscImage(FileSystem model, byte[] data, int offset) : base(model, data, offset) { } /// public OperaDiscImage(FileSystem model, byte[] data, int offset, int length) : base(model, data, offset, length) { } /// public OperaDiscImage(FileSystem model, Stream data) : base(model, data) { } /// public OperaDiscImage(FileSystem model, Stream data, long offset) : base(model, data, offset) { } /// public OperaDiscImage(FileSystem model, Stream data, long offset, long length) : base(model, data, offset, length) { } #endregion #region Static Constructors /// /// Create a OperaDiscImage filesystem from a byte array and offset /// /// Byte array representing the OperaDiscImage filesystem /// Offset within the array to parse /// A OperaDiscImage filesystem wrapper on success, null on failure public static new OperaDiscImage? Create(byte[]? data, int offset) { // If the data is invalid if (data is null || data.Length == 0) return null; // If the offset is out of bounds if (offset < 0 || offset >= data.Length) return null; // Create a memory stream and use that var dataStream = new MemoryStream(data, offset, data.Length - offset); return Create(dataStream); } /// /// Create a OperaDiscImage filesystem from a Stream /// /// Seekable Stream representing the OperaDiscImage filesystem /// A OperaDiscImage filesystem wrapper on success, null on failure public static new OperaDiscImage? Create(Stream? data) { // If the data is invalid if (data is null || !data.CanRead || !data.CanSeek) return null; try { // Create user data sub-stream var userData = new Data.Extensions.CDROMExtensions.UserDataStream(data); // Cache the current offset long currentOffset = userData.Position; // Deserialize just the sub-stream var model = new Serialization.Readers.OperaFS().Deserialize(userData); if (model is null) return null; // Reset stream userData.Seek(currentOffset, SeekOrigin.Begin); return new OperaDiscImage(model, userData, userData.Position); } catch { return null; } } #endregion } }