diff --git a/.editorconfig b/.editorconfig index 84d50536e..5acefbd37 100644 --- a/.editorconfig +++ b/.editorconfig @@ -147,6 +147,7 @@ dotnet_diagnostic.IDE0008.severity = none # using var # csharp_style_var_for_built_in_types = true:suggestion # suggest using var (implied) variables # csharp_style_var_when_type_is_apparent = true:suggestion # suggest using var (implied) variables # csharp_style_var_elsewhere = true:suggestion # suggest using var (implied) variables +dotnet_diagnostic.RCS1123.severity = none # ReSharper properties resharper_apply_auto_detected_rules=false diff --git a/Projects/Server/Serialization/BinaryFileReader.cs b/Projects/Server/Serialization/BinaryFileReader.cs index 7a6ac2fde..f540f8e2e 100644 --- a/Projects/Server/Serialization/BinaryFileReader.cs +++ b/Projects/Server/Serialization/BinaryFileReader.cs @@ -21,6 +21,15 @@ using System.Text; namespace Server; +/// +/// Read bits of data from a serialized file in a managed environment. +/// +/// Uses the following components collectively: +///

+///

+///

+///
+///
public sealed unsafe class BinaryFileReader : IDisposable, IGenericReader { private readonly bool _usePrefixes; @@ -28,6 +37,19 @@ public sealed unsafe class BinaryFileReader : IDisposable, IGenericReader private readonly MemoryMappedViewStream _accessor; private readonly UnmanagedDataReader _reader; + /// + /// Read bits of data from a serialized file in a managed environment. + ///
Encoding is UTF8 if left null.
+ /// + /// Uses the following components collectively: + ///

+ ///

+ ///

+ ///
+ ///
+ /// Full file path of the file to be deserialized. + /// Sets if strings should be read with itern. + /// Set an encoding. By default UTF8 public BinaryFileReader(string path, bool usePrefixes = true, Encoding encoding = null) { _usePrefixes = usePrefixes; @@ -47,6 +69,9 @@ public sealed unsafe class BinaryFileReader : IDisposable, IGenericReader } } + /// + /// How many bits deep into the file is the reader at currently. + /// public long Position => _reader.Position; public void Dispose() @@ -56,54 +81,118 @@ public sealed unsafe class BinaryFileReader : IDisposable, IGenericReader _mmf?.Dispose(); } + /// + /// If usePrefixes is true, return a ReadString(intern) else ReadStringRaw(intern). + /// + /// A string value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public string ReadString(bool intern = false) => _usePrefixes ? _reader.ReadString(intern) : _reader.ReadStringRaw(intern); - + /// + /// Returns the next set of bits that make up a string. + /// + /// Next string value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public string ReadStringRaw(bool intern = false) => _reader.ReadStringRaw(intern); - + /// + /// Read the next 64 bits to make up a long (int64). + /// + /// Next long value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public long ReadLong() => _reader.ReadLong(); - + /// + /// Read the next 64 bits to make up an unsigned long (uint64). + /// + /// Next ulong value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public ulong ReadULong() => _reader.ReadULong(); - + /// + /// Read the next 32 bits to make up an int (int32). + /// + /// Next int value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public int ReadInt() => _reader.ReadInt(); - + /// + /// Read the next 32 bits to make up an unsigned int (uint32). + /// + /// Next uint value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public uint ReadUInt() => _reader.ReadUInt(); - + /// + /// Read the next 16 bits to make up a short (int16). + /// + /// Next short value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public short ReadShort() => _reader.ReadShort(); - + /// + /// Read the next 16 bits to make up an unsigned short (int16). + /// + /// Next ushort value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public ushort ReadUShort() => _reader.ReadUShort(); - + /// + /// Read the next 8 bits to make up a float point double. + /// + /// Next double value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public double ReadDouble() => _reader.ReadDouble(); - + /// + /// Read the next 4 bits to make up a float point. + /// + /// Next float value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public float ReadFloat() => _reader.ReadFloat(); - + /// + /// Read the next 8 bits to make up a byte. + /// + /// Next byte value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public byte ReadByte() => _reader.ReadByte(); - + /// + /// Read the next 8 bits to make up a signed byte. + /// + /// Next sbyte value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public sbyte ReadSByte() => _reader.ReadSByte(); - + /// + /// Read the next 1 bit to make up a boolean. + /// + /// Next bool value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool ReadBool() => _reader.ReadBool(); - + /// + /// Read the next 32 bytes to make up a . + /// + /// Next uint value cast as a struct. [MethodImpl(MethodImplOptions.AggressiveInlining)] public Serial ReadSerial() => _reader.ReadSerial(); + /// + /// Reads the next Byte which helps determin how to read the following Type. + ///
If the byte returns 1 => and translate into a Type via the
+ ///
If the byte returns 2 =>
+ ///
else return null
+ ///
+ /// Next Type value [MethodImpl(MethodImplOptions.AggressiveInlining)] public Type ReadType() => _reader.ReadType(); + /// + /// Reads the next set of bytes to fill the buffer. + /// + /// A reference span that will be filled with the next set of bytes. + /// The length of the buffer. + /// Thrown if the buffer is larger than the remaining data to read in the file. [MethodImpl(MethodImplOptions.AggressiveInlining)] public int Read(Span buffer) => _reader.Read(buffer); + /// + /// Sets the current position of the stream to a specified value. + /// + /// The new position, relative to the parameter. + /// The reference point for the parameter. It can be one of the values of . + /// The new position in the stream, in bytes. + /// Thrown when the or the resulting position is out of the valid range. + /// Thrown if the stream does not support seeking. [MethodImpl(MethodImplOptions.AggressiveInlining)] public long Seek(long offset, SeekOrigin origin) => _reader.Seek(offset, origin); } diff --git a/Projects/Server/Serialization/UnmanagedDataReader.cs b/Projects/Server/Serialization/UnmanagedDataReader.cs index ed9675abb..9babb86fd 100644 --- a/Projects/Server/Serialization/UnmanagedDataReader.cs +++ b/Projects/Server/Serialization/UnmanagedDataReader.cs @@ -25,19 +25,31 @@ using Server.Text; namespace Server; +/// +/// Read bits of data raw from a serialized file using Little-endian. +/// public unsafe class UnmanagedDataReader : IGenericReader { private static readonly ILogger logger = LogFactory.GetLogger(typeof(UnmanagedDataReader)); private readonly byte* _ptr; - private long _position; private readonly long _size; private readonly Dictionary _typesDb; private readonly Encoding _encoding; - public long Position => _position; + /// + /// How many bits deep into the file is the reader at currently. + /// + public long Position { get; private set; } + /// + /// Read bits of data raw from a serialized file using Little-endian. + /// + /// The starting address for reading bits. + /// The total size of memory to be read. + /// The custom type dictionary. Will throw an error if left null ReadType is called. + /// by default. public UnmanagedDataReader(byte* ptr, long size, Dictionary typesDb = null, Encoding encoding = null) { _encoding = encoding ?? TextEncoding.UTF8; @@ -46,9 +58,19 @@ public unsafe class UnmanagedDataReader : IGenericReader _size = size; } + /// + /// Reads the next bit as a bool. If that bit is true, return an else null. + /// + /// + /// Next string value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public string ReadString(bool intern = false) => ReadBool() ? ReadStringRaw(intern) : null; + /// + /// Returns the next set of bits that make up a string. + /// + /// + /// Next string value. public string ReadStringRaw(bool intern = false) { // ReadEncodedInt @@ -57,7 +79,7 @@ public unsafe class UnmanagedDataReader : IGenericReader do { - b = *(_ptr + _position++); + b = *(_ptr + Position++); length |= (b & 0x7F) << shift; shift += 7; } @@ -68,95 +90,153 @@ public unsafe class UnmanagedDataReader : IGenericReader return "".Intern(); } - var str = TextEncoding.GetString(new ReadOnlySpan(_ptr + _position, length), _encoding); - _position += length; + var str = TextEncoding.GetString(new ReadOnlySpan(_ptr + Position, length), _encoding); + Position += length; return intern ? str.Intern() : str; } + /// + /// Read the next 64 bits to make up a long (int64). + /// + /// Next long value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public long ReadLong() { - var v = BinaryPrimitives.ReadInt64LittleEndian(new ReadOnlySpan(_ptr + _position, sizeof(long))); - _position += sizeof(long); + var v = BinaryPrimitives.ReadInt64LittleEndian(new ReadOnlySpan(_ptr + Position, sizeof(long))); + Position += sizeof(long); return v; } + /// + /// Read the next 64 bits to make up an unsigned long (uint64). + /// + /// Next ulong value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public ulong ReadULong() { - var v = BinaryPrimitives.ReadUInt64LittleEndian(new ReadOnlySpan(_ptr + _position, sizeof(ulong))); - _position += sizeof(ulong); + var v = BinaryPrimitives.ReadUInt64LittleEndian(new ReadOnlySpan(_ptr + Position, sizeof(ulong))); + Position += sizeof(ulong); return v; } + /// + /// Read the next 32 bits to make up an int (int32). + /// + /// Next int value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public int ReadInt() { - var v = BinaryPrimitives.ReadInt32LittleEndian(new ReadOnlySpan(_ptr + _position, sizeof(int))); - _position += sizeof(int); + var v = BinaryPrimitives.ReadInt32LittleEndian(new ReadOnlySpan(_ptr + Position, sizeof(int))); + Position += sizeof(int); return v; } + /// + /// Read the next 32 bits to make up an unsigned int (uint32). + /// + /// Next uint value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public uint ReadUInt() { - var v = BinaryPrimitives.ReadUInt32LittleEndian(new ReadOnlySpan(_ptr + _position, sizeof(uint))); - _position += sizeof(uint); + var v = BinaryPrimitives.ReadUInt32LittleEndian(new ReadOnlySpan(_ptr + Position, sizeof(uint))); + Position += sizeof(uint); return v; } + /// + /// Read the next 16 bits to make up a short (int16). + /// + /// Next short value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public short ReadShort() { - var v = BinaryPrimitives.ReadInt16LittleEndian(new ReadOnlySpan(_ptr + _position, sizeof(short))); - _position += sizeof(short); + var v = BinaryPrimitives.ReadInt16LittleEndian(new ReadOnlySpan(_ptr + Position, sizeof(short))); + Position += sizeof(short); return v; } + /// + /// Read the next 16 bits to make up an unsigned short (int16). + /// + /// Next ushort value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public ushort ReadUShort() { - var v = BinaryPrimitives.ReadUInt16LittleEndian(new ReadOnlySpan(_ptr + _position, sizeof(ushort))); - _position += sizeof(ushort); + var v = BinaryPrimitives.ReadUInt16LittleEndian(new ReadOnlySpan(_ptr + Position, sizeof(ushort))); + Position += sizeof(ushort); return v; } + /// + /// Read the next 8 bits to make up a float point double. + /// + /// Next double value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public double ReadDouble() { - var v = BinaryPrimitives.ReadDoubleLittleEndian(new ReadOnlySpan(_ptr + _position, sizeof(double))); - _position += sizeof(double); + var v = BinaryPrimitives.ReadDoubleLittleEndian(new ReadOnlySpan(_ptr + Position, sizeof(double))); + Position += sizeof(double); return v; } + /// + /// Read the next 4 bits to make up a float point. + /// + /// Next float value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public float ReadFloat() { - var v = BinaryPrimitives.ReadSingleLittleEndian(new ReadOnlySpan(_ptr + _position, sizeof(float))); - _position += sizeof(float); + var v = BinaryPrimitives.ReadSingleLittleEndian(new ReadOnlySpan(_ptr + Position, sizeof(float))); + Position += sizeof(float); return v; } + /// + /// Read the next 8 bits to make up a byte. + /// + /// Next byte value. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public byte ReadByte() => *(_ptr + _position++); - + public byte ReadByte() => *(_ptr + Position++); + /// + /// Read the next 8 bits to make up a signed byte. + /// + /// Next sbyte value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public sbyte ReadSByte() => (sbyte)ReadByte(); - + /// + /// Read the next Byte and return true if it's value returns zero. + /// + /// Next bool value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool ReadBool() => ReadByte() != 0; + /// + /// Read the next 32 bytes to make up a . + /// + /// Next uint value cast as a struct. [MethodImpl(MethodImplOptions.AggressiveInlining)] public Serial ReadSerial() => (Serial)ReadUInt(); + /// + /// Reads the next Byte which helps determin how to read the following Type. + ///
If the byte returns 1 => and translate into a Type via the
+ ///
If the byte returns 2 =>
+ ///
else return null
+ ///
+ /// Next Type value public Type ReadType() => ReadByte() switch { - 0 => null, 1 => AssemblyHandler.FindTypeByFullName(ReadStringRaw()), // Backward compatibility - 2 => ReadTypeByHash() + 2 => ReadTypeByHash(), + _ => null, }; + /// + /// Reads the next to create a hash and convert that into a Type using the . + /// Will log an if typesDb is null or typesDb doesn't contain the hash and return null + /// + /// Next Type value public Type ReadTypeByHash() { var hash = ReadULong(); @@ -205,19 +285,33 @@ public unsafe class UnmanagedDataReader : IGenericReader return t; } + /// + /// Reads the next set of bytes to fill the buffer. + /// + /// A reference span that will be filled with the next set of bytes. + /// The length of the buffer. + /// Thrown if the buffer is larger than the remaining data to read in the file. public int Read(Span buffer) { var length = buffer.Length; - if (length > _size - _position) + if (length > _size - Position) { throw new OutOfMemoryException(); } - new ReadOnlySpan(_ptr + _position, length).CopyTo(buffer); - _position += length; + new ReadOnlySpan(_ptr + Position, length).CopyTo(buffer); + Position += length; return length; } + /// + /// Sets the current position of the stream to a specified value. + /// + /// The new position, relative to the parameter. + /// The reference point for the parameter. It can be one of the values of . + /// The new position in the stream, in bytes. + /// Thrown when the or the resulting position is out of the valid range. + /// Thrown if the stream does not support seeking. public virtual long Seek(long offset, SeekOrigin origin) { Debug.Assert( @@ -229,18 +323,16 @@ public unsafe class UnmanagedDataReader : IGenericReader "Attempting to seek to an invalid position using SeekOrigin.Begin" ); Debug.Assert( - origin != SeekOrigin.Current || _position + offset >= 0 && _position + offset < _size, + origin != SeekOrigin.Current || Position + offset >= 0 && Position + offset < _size, "Attempting to seek to an invalid position using SeekOrigin.Current" ); - var position = Math.Max(0L, origin switch + Position = Math.Max(0L, origin switch { - SeekOrigin.Current => _position + offset, + SeekOrigin.Current => Position + offset, SeekOrigin.End => _size + offset, _ => offset // Begin }); - - _position = position; - return _position; + return Position; } } diff --git a/Rules.ruleset b/Rules.ruleset index 32bd4e62c..84b14555f 100644 --- a/Rules.ruleset +++ b/Rules.ruleset @@ -1,496 +1,499 @@  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file