using System; using System.Text; namespace Cosmos.System.FileSystem.FAT { internal abstract class DataStructure { protected DataStructure(byte[] data) { Data = data ?? throw new ArgumentNullException(nameof(data)); } protected byte[] Data { get; } public T GetValue(Field field) => field.GetValue(Data); public void SetValue(Field field, T value) => field.SetValue(Data, value); } internal abstract class Field { public Field(int position, int length) { Position = position; Length = length; } /// /// Position, in bytes, of the field. /// public int Position { get; } /// /// Length, in bytes, of the field. /// public int Length { get; } /// /// Gets the value for this field from the data structure. /// /// A byte array which contains a data structure for which this field was defined. /// The field value. public abstract T GetValue(byte[] data); /// /// Sets the value for this field on the data structure. /// /// A byte array which contains a data structure for which this field was defined. /// The value to set this field to. public abstract void SetValue(byte[] data, T value); } internal class ByteField : Field { public ByteField(int position) : base(position, 1) { } public override byte GetValue(byte[] data) => data[Position]; public override void SetValue(byte[] data, byte value) => data[Position] = value; } internal class UInt16Field : Field { public UInt16Field(int position) : base(position, 2) { } public override ushort GetValue(byte[] data) => BitConverter.ToUInt16(data, Position); public override void SetValue(byte[] data, ushort value) { data[Position] = (byte)value; data[Position + 1] = (byte)(value >> 8); } } internal class Int32Field : Field { public Int32Field(int position) : base(position, 4) { } public override int GetValue(byte[] data) => BitConverter.ToInt32(data, Position); public override void SetValue(byte[] data, int value) { data[Position] = (byte)value; data[Position + 1] = (byte)(value >> 8); data[Position + 2] = (byte)(value >> 16); data[Position + 3] = (byte)(value >> 24); } } internal class UInt32Field : Field { public UInt32Field(int position) : base(position, 4) { } public override uint GetValue(byte[] data) => BitConverter.ToUInt32(data, Position); public override void SetValue(byte[] data, uint value) { data[Position] = (byte)value; data[Position + 1] = (byte)(value >> 8); data[Position + 2] = (byte)(value >> 16); data[Position + 3] = (byte)(value >> 24); } } internal class StringField : Field { public StringField(int position, int length, Encoding encoding) : base(position, length) { Encoding = encoding; } public Encoding Encoding { get; } public override string GetValue(byte[] data) => Encoding.GetString(data, Position, Length); public override void SetValue(byte[] data, string value) => Encoding.GetBytes(value, 0, Length, data, Position); } internal class EnumField : Field { private static readonly EnumField test = new EnumField(new Int32Field(12)); private readonly Field _innerField; public EnumField(Field innerField) : base(innerField.Position, innerField.Length) { _innerField = innerField; } public override TEnum GetValue(byte[] data) => (TEnum)(object)_innerField.GetValue(data); public override void SetValue(byte[] data, TEnum value) => _innerField.SetValue(data, (TEnumUnderlyingType)(object)value); } }