using System.Collections.Generic; using System.IO; using SabreTools.Data.Models.UDF; using SabreTools.IO; namespace SabreTools.Wrappers { public partial class UDF : WrapperBase { #region Descriptive Properties /// public override string DescriptionString => "Universal Disk Format (UDF) Volume"; #endregion #region Extension Properties /// public VolumeStructureDescriptor[] VolumeRecognitionSequence => Model.VolumeRecognitionSequence; /// public Descriptor[] VolumeDescriptorSequence => Model.VolumeDescriptorSequence; /// public FileSetDescriptor? FileSetDescriptor => Model.FileSetDescriptor; /// public Dictionary FileEntries => Model.FileEntries; /// public Dictionary Directories => Model.Directories; #endregion #region Constructors /// public UDF(Volume model, byte[] data) : base(model, data) { } /// public UDF(Volume model, byte[] data, int offset) : base(model, data, offset) { } /// public UDF(Volume model, byte[] data, int offset, int length) : base(model, data, offset, length) { } /// public UDF(Volume model, Stream data) : base(model, data) { } /// public UDF(Volume model, Stream data, long offset) : base(model, data, offset) { } /// public UDF(Volume model, Stream data, long offset, long length) : base(model, data, offset, length) { } #endregion #region Static Constructors /// /// Create a UDF Volume from a byte array and offset /// /// Byte array representing the UDF Volume /// Offset within the array to parse /// A UDF Volume wrapper on success, null on failure public static UDF? 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 UDF Volume from a Stream /// /// Stream representing the UDF Volume /// A UDF Volume wrapper on success, null on failure public static UDF? Create(Stream? data) { // If the data is invalid if (data is null || !data.CanRead || !data.CanSeek) return null; try { // Cache the current offset long currentOffset = data.Position; // The reader addresses logical sectors from the start of the stream, so it reads a view that starts here var model = new Serialization.Readers.UDF().Deserialize(new ReadOnlyViewStream(data, currentOffset)); if (model is null) return null; return new UDF(model, data, currentOffset); } catch { return null; } } #endregion } }