/// <summary>
        /// Reads a <see cref="System.Decimal"/> value.
        /// </summary>
        /// <param name="stream">Stream to read the value from.</param>
        /// <returns>The read value.</returns>
        internal decimal ReadPrimitive_Decimal(Stream stream)
        {
            const int elementSize = sizeof(decimal);
            int       bytesRead   = stream.Read(TempBuffer_Buffer, 0, elementSize);

            if (bytesRead < elementSize)
            {
                throw new SerializationException("Unexpected end of stream.");
            }
#if NETSTANDARD2_0 || NETSTANDARD2_1 || NET461
            Buffer.BlockCopy(TempBuffer_Buffer, 0, TempBuffer_Int32, 0, elementSize);
            if (mDeserializingLittleEndian != BitConverter.IsLittleEndian)
            {
                EndiannessHelper.SwapBytes(ref TempBuffer_Int32[0]);
                EndiannessHelper.SwapBytes(ref TempBuffer_Int32[1]);
                EndiannessHelper.SwapBytes(ref TempBuffer_Int32[2]);
                EndiannessHelper.SwapBytes(ref TempBuffer_Int32[3]);
            }

            return(new decimal(TempBuffer_Int32));
#elif NET5_0_OR_GREATER
            var intBuffer = MemoryMarshal.Cast <byte, int>(TempBuffer_Buffer.AsSpan(0, elementSize));
            if (mDeserializingLittleEndian != BitConverter.IsLittleEndian)
            {
                EndiannessHelper.SwapBytes(ref intBuffer[0]);
                EndiannessHelper.SwapBytes(ref intBuffer[1]);
                EndiannessHelper.SwapBytes(ref intBuffer[2]);
                EndiannessHelper.SwapBytes(ref intBuffer[3]);
            }

            return(new decimal(intBuffer));
#else
                        #error Unhandled .NET framework
#endif
        }
        /// <summary>
        /// Reads a <see cref="System.DateTime"/> object.
        /// </summary>
        /// <param name="stream">Stream to read the DateTime object from.</param>
        /// <returns>The read <see cref="System.DateTime"/> object.</returns>
        internal DateTime ReadPrimitive_DateTime(Stream stream)
        {
            const int elementSize = sizeof(long);             // binary representation of a DateTime
            int       bytesRead   = stream.Read(TempBuffer_Buffer, 0, elementSize);

            if (bytesRead < elementSize)
            {
                throw new SerializationException("Unexpected end of stream.");
            }
            long value = MemoryMarshal.Read <long>(TempBuffer_Buffer);

            if (mDeserializingLittleEndian != BitConverter.IsLittleEndian)
            {
                EndiannessHelper.SwapBytes(ref value);
            }
            return(DateTime.FromBinary(value));
        }
        /// <summary>
        /// Reads a <see cref="System.Char"/> value (native encoding).
        /// </summary>
        /// <param name="stream">Stream to read the value from.</param>
        /// <returns>The read value.</returns>
        internal char ReadPrimitive_Char_Native(Stream stream)
        {
            const int bytesToRead = 2;
            int       bytesRead   = stream.Read(TempBuffer_Buffer, 0, bytesToRead);

            if (bytesRead < bytesToRead)
            {
                throw new SerializationException("Unexpected end of stream.");
            }
            char value = MemoryMarshal.Read <char>(TempBuffer_Buffer);

            if (mDeserializingLittleEndian != BitConverter.IsLittleEndian)
            {
                EndiannessHelper.SwapBytes(ref value);
            }
            return(value);
        }
        /// <summary>
        /// Reads a <see cref="System.Double"/> value.
        /// </summary>
        /// <param name="stream">Stream to read the value from.</param>
        /// <returns>The read value.</returns>
        internal double ReadPrimitive_Double(Stream stream)
        {
            const int elementSize = sizeof(double);
            int       bytesRead   = stream.Read(TempBuffer_Buffer, 0, elementSize);

            if (bytesRead < elementSize)
            {
                throw new SerializationException("Unexpected end of stream.");
            }
            double value = MemoryMarshal.Read <double>(TempBuffer_Buffer);

            if (mDeserializingLittleEndian != BitConverter.IsLittleEndian)
            {
                EndiannessHelper.SwapBytes(ref value);
            }
            return(value);
        }
        /// <summary>
        /// Reads a <see cref="System.DateTimeOffset"/> object.
        /// </summary>
        /// <param name="stream">Stream to read the DateTimeOffset object from.</param>
        /// <returns>The read <see cref="System.DateTimeOffset"/> object.</returns>
        internal DateTimeOffset ReadPrimitive_DateTimeOffset(Stream stream)
        {
            const int elementSize = 2 * sizeof(long);
            int       bytesRead   = stream.Read(TempBuffer_Buffer, 0, elementSize);

            if (bytesRead < elementSize)
            {
                throw new SerializationException("Unexpected end of stream.");
            }
            long dateTimeTicks       = MemoryMarshal.Read <long>(TempBuffer_Buffer);
            long timezoneOffsetTicks = MemoryMarshal.Read <long>(TempBuffer_Buffer.AsSpan().Slice(8));

            if (mDeserializingLittleEndian != BitConverter.IsLittleEndian)
            {
                EndiannessHelper.SwapBytes(ref dateTimeTicks);
                EndiannessHelper.SwapBytes(ref timezoneOffsetTicks);
            }

            return(new DateTimeOffset(dateTimeTicks, new TimeSpan(timezoneOffsetTicks)));
        }
        /// <summary>
        /// Reads a <see cref="System.String"/> object (UTF-16 encoding).
        /// </summary>
        /// <param name="stream">Stream to read the string object from.</param>
        /// <returns>The read string.</returns>
        internal unsafe string ReadPrimitive_String_UTF16(Stream stream)
        {
            // read the number of UTF-16 code units
            int codeUnitCount = Leb128EncodingHelper.ReadInt32(stream);
            int size          = codeUnitCount * sizeof(char);

            // read encoded string
            EnsureTemporaryByteBufferSize(size);
            int bytesRead = stream.Read(TempBuffer_Buffer, 0, size);

            if (bytesRead < size)
            {
                throw new SerializationException("Unexpected end of stream.");
            }

            // swap bytes to fix endianness issues, if necessary
            var buffer = MemoryMarshal.Cast <byte, char>(TempBuffer_Buffer.AsSpan(0, bytesRead));

            if (mDeserializingLittleEndian != BitConverter.IsLittleEndian)
            {
                for (int i = 0; i < buffer.Length; i++)
                {
                    EndiannessHelper.SwapBytes(ref buffer[i]);
                }
            }

            // create a string from the buffer
#if NETSTANDARD2_0 || NET461
            string s;
            fixed(char *p = buffer)
            {
                s = new string(p, 0, buffer.Length);
            }
#elif NETSTANDARD2_1_OR_GREATER || NET5_0_OR_GREATER
            string s = new string(buffer);
#else
                        #error Unhandled .NET framework
#endif
            mDeserializedObjectIdTable.Add(mNextDeserializedObjectId++, s);
            return(s);
        }