/// <summary>
        /// Writes an <see cref="IPEndPoint"/> description.
        /// </summary>
        public static void Write(this IBitBuffer buffer, IPEndPoint endPoint)
        {
            if (endPoint == null)
            {
                throw new ArgumentNullException(nameof(endPoint));
            }

            buffer.Write(endPoint.Address);
            buffer.Write((ushort)endPoint.Port);
        }
        /// <summary>
        /// Writes an <see cref="IPAddress"/> .
        /// </summary>
        public static void Write(this IBitBuffer buffer, IPAddress address)
        {
            Span <byte> tmp = stackalloc byte[16];

            if (!address.TryWriteBytes(tmp, out int count))
            {
                throw new ArgumentException("Failed to get address bytes.", nameof(address));
            }
            tmp = tmp.Slice(0, count);

            buffer.Write((byte)tmp.Length);
            buffer.Write(tmp);
        }
        /// <summary>
        /// Writes a 64-bit <see cref="long"/>.
        /// </summary>
        public static void Write(this IBitBuffer buffer, long value)
        {
            Span <byte> tmp = stackalloc byte[sizeof(long)];

            BinaryPrimitives.WriteInt64LittleEndian(tmp, value);
            buffer.Write(tmp);
        }
        public static void Write(this IBitBuffer buffer, ulong value, int bitCount)
        {
            Span <byte> tmp = stackalloc byte[sizeof(ulong)];

            BinaryPrimitives.WriteUInt64LittleEndian(tmp, value);
            buffer.Write(tmp, bitCount);
        }
        public static void Write(this IBitBuffer buffer, uint value)
        {
            Span <byte> tmp = stackalloc byte[sizeof(uint)];

            BinaryPrimitives.WriteUInt32LittleEndian(tmp, value);
            buffer.Write(tmp);
        }
        /// <summary>
        /// Compress (lossy) a <see cref="float"/> in the range 0..1 using the specified amount of bits.
        /// </summary>
        public static void WriteUnit(this IBitBuffer buffer, float value, int bitCount)
        {
            LidgrenException.Assert(
                (value >= 0.0) && (value <= 1.0),
                " WriteUnitSingle() must be passed a float in the range 0 to 1; val is " + value);

            int  maxValue = (1 << bitCount) - 1;
            uint writeVal = (uint)(value * maxValue);

            buffer.Write(writeVal, bitCount);
        }
        /// <summary>
        /// Compress a <see cref="float"/> within a specified range using the specified amount of bits.
        /// </summary>
        public static void WriteRanged(this IBitBuffer buffer, float value, float min, float max, int bitCount)
        {
            LidgrenException.Assert(
                (value >= min) && (value <= max),
                " WriteRangedSingle() must be passed a float in the range MIN to MAX; val is " + value);

            float range  = max - min;
            float unit   = (value - min) / range;
            int   maxVal = (1 << bitCount) - 1;

            buffer.Write((uint)(maxVal * unit), bitCount);
        }
        /// <summary>
        /// Writes bytes from a span.
        /// </summary>
        public static void Write(this IBitBuffer buffer, ReadOnlySpan <byte> source)
        {
            if (!buffer.IsByteAligned())
            {
                buffer.Write(source, 0, source.Length * 8);
                return;
            }

            buffer.EnsureEnoughBitCapacity(source.Length * 8);
            source.CopyTo(buffer.GetBuffer().AsSpan(buffer.BytePosition));
            buffer.IncrementBitPosition(source.Length * 8);
        }
        /// <summary>
        /// Compress (lossy) a <see cref="float"/> in the range -1..1 using the specified amount of bits.
        /// </summary>
        public static void WriteSigned(this IBitBuffer buffer, float value, int bitCount)
        {
            LidgrenException.Assert(
                (value >= -1.0) && (value <= 1.0),
                " WriteSignedSingle() must be passed a float in the range -1 to 1; val is " + value);

            float unit     = (value + 1f) * 0.5f;
            int   maxVal   = (1 << bitCount) - 1;
            uint  writeVal = (uint)(unit * maxVal);

            buffer.Write(writeVal, bitCount);
        }
        /// <summary>
        /// Encodes a <see cref="NetBitArray"/> to this buffer.
        /// </summary>
        public static void Write(this IBitBuffer buffer, NetBitArray bitArray)
        {
            buffer.WriteVar(bitArray.Length);

            ReadOnlySpan <uint> values = bitArray.GetBuffer().Span;
            int bitsLeft = NetUtility.PowOf2Mod(bitArray.Length, NetBitArray.BitsPerElement);

            if (bitsLeft == 0)
            {
                for (int i = 0; i < values.Length; i++)
                {
                    buffer.Write(values[i]);
                }
            }
            else
            {
                for (int i = 0; i < values.Length - 1; i++)
                {
                    buffer.Write(values[i]);
                }

                uint last = values[^ 1];
        /// <summary>
        /// Writes an <see cref="int"/> with the least amount of bits needed for the specified range.
        /// Returns the number of bits written.
        /// </summary>
        public static int WriteRanged(this IBitBuffer buffer, int min, int max, int value)
        {
            LidgrenException.Assert(value >= min && value <= max, "Value not within min/max range!");

            uint range   = (uint)(max - min);
            int  numBits = NetBitWriter.BitsForValue(range);

            uint rvalue = (uint)(value - min);

            buffer.Write(rvalue, numBits);

            return(numBits);
        }
        public static int WriteVar(this IBitBuffer buffer, uint value)
        {
            Span <byte> tmp = stackalloc byte[NetBitWriter.MaxVarInt32Size];

            int  offset = 0;
            uint bits   = value;

            while (bits > 0x7Fu)
            {
                tmp[offset++] = (byte)(bits | ~0x7Fu);
                bits        >>= 7;
            }
            tmp[offset++] = (byte)bits;

            buffer.Write(tmp.Slice(0, offset));
            return(offset);
        }
        /// <summary>
        /// Writes a <see cref="long"/> using 1 to 64 bits.
        /// </summary>
        public static void Write(this IBitBuffer buffer, long value, int bitCount)
        {
            Span <byte> tmp = stackalloc byte[sizeof(long)];

            if (bitCount != tmp.Length * 8)
            {
                // make first bit sign
                long signBit = 1 << (bitCount - 1);
                if (value < 0)
                {
                    value = (-value - 1) | signBit;
                }
                else
                {
                    value &= ~signBit;
                }
            }

            BinaryPrimitives.WriteInt64LittleEndian(tmp, value);
            buffer.Write(tmp, bitCount);
        }
 /// <summary>
 /// Writes a <see cref="bool"/> value using 8 bits.
 /// </summary>
 public static void Write(this IBitBuffer buffer, bool value)
 {
     buffer.Write(value ? (byte)1 : (byte)0);
 }
        /// <summary>
        /// Append bits from a <see cref="IBitBuffer"/> to this buffer.
        /// The position and length of the source buffer are considered.
        /// </summary>
        public static void Write(this IBitBuffer buffer, IBitBuffer sourceBuffer)
        {
            int bitPosition = sourceBuffer.BitPosition;

            buffer.Write(sourceBuffer.GetBuffer(), bitPosition, sourceBuffer.BitLength - bitPosition);
        }
 /// <summary>
 /// Writes the current local time (<see cref="NetTime.Now"/>).
 /// </summary>
 public static void WriteLocalTime(this IBitBuffer buffer)
 {
     buffer.Write(NetTime.Now);
 }
        /// <summary>
        /// Writes a 32-bit <see cref="float"/>.
        /// </summary>
        public static void Write(this IBitBuffer buffer, float value)
        {
            int intValue = BitConverter.SingleToInt32Bits(value);

            buffer.Write(intValue);
        }
        /// <summary>
        /// Writes a 64-bit <see cref="double"/>.
        /// </summary>
        public static void Write(this IBitBuffer buffer, double value)
        {
            long intValue = BitConverter.DoubleToInt64Bits(value);

            buffer.Write(intValue);
        }
 /// <summary>
 /// Writes byte blocks with final block of UTF-8 characters from a <see cref="string"/>.
 /// </summary>
 public static void Write(this IBitBuffer buffer, string?source)
 {
     buffer.Write(source, isFinalBlock: true);
 }
 /// <summary>
 /// Writes byte blocks of UTF-8 characters from a <see cref="string"/>.
 /// </summary>
 public static void Write(this IBitBuffer buffer, string?source, bool isFinalBlock)
 {
     buffer.Write(source.AsSpan(), isFinalBlock);
 }
 /// <summary>
 /// Writes byte blocks with final block of UTF-8 characters from a span of characters.
 /// </summary>
 public static void Write(this IBitBuffer buffer, ReadOnlySpan <char> source)
 {
     buffer.Write(source, isFinalBlock: true);
 }
 public static void Write(this IBitBuffer buffer, ReadOnlySpan <byte> source, int bitCount)
 {
     buffer.Write(source, 0, bitCount);
 }