/// <inheritdoc />
        public override UpdateFieldValueCollection Read(IWireStreamReaderStrategy source)
        {
            //Update fields are sent with an inital byte size
            byte size = source.ReadByte();

            if (size == 0)
            {
                return(new UpdateFieldValueCollection(new WireReadyBitArray(0), Array.Empty <byte>()));
            }

            //TODO: Reduce allocation somehow.
            byte[] bytes = source.ReadBytes(size * sizeof(int));

            WireReadyBitArray mask = new WireReadyBitArray(bytes);

            //We know how many bytes the bitarray is suppose to be
            //but to know how many values are read we need to compute the bit size
            int updateValueSize = GetCardinality(mask.InternalArray);

            AssertSizeIsCorrect(mask, updateValueSize);

            //Once we have the mask AND the bytes we can construct the update values
            byte[] updateValueBytes = source.ReadBytes(updateValueSize * sizeof(int));

            return(new UpdateFieldValueCollection(mask, updateValueBytes));
        }
        public override UpdateFieldValueCollection Read(Span <byte> buffer, ref int offset)
        {
            //Update fields are sent with an inital byte size
            byte size = BytePrimitiveSerializerStrategy.Instance.Read(buffer, ref offset);

            if (size == 0)
            {
                return(new UpdateFieldValueCollection(new WireReadyBitArray(0), Array.Empty <byte>()));
            }

            //TODO: Reduce allocation somehow.
            byte[] bytes = buffer.Slice(offset, size * sizeof(int)).ToArray();
            offset += size * sizeof(int);

            WireReadyBitArray mask = new WireReadyBitArray(bytes);

            //We know how many bytes the bitarray is suppose to be
            //but to know how many values are read we need to compute the bit size
            int updateValueSize = GetCardinality(mask.InternalArray);

            AssertSizeIsCorrect(mask, updateValueSize);

            //TODO: Reduce allocations somehow.
            //Once we have the mask AND the bytes we can construct the update values
            byte[] updateValueBytes = buffer.Slice(offset, updateValueSize * sizeof(int)).ToArray();
            offset += updateValueSize * sizeof(int);

            return(new UpdateFieldValueCollection(mask, updateValueBytes));
        }
        public static void Set_InvalidIndex_ThrowsArgumentOutOfRangeException()
        {
            WireReadyBitArray WireReadyBitArray = new WireReadyBitArray(16);

            Assert.Throws <ArgumentOutOfRangeException>(() => WireReadyBitArray.Set(-1, true));
            Assert.Throws <ArgumentOutOfRangeException>(() => WireReadyBitArray.Set(WireReadyBitArray.Length, true));

            Assert.Throws <ArgumentOutOfRangeException>(() => WireReadyBitArray[-1] = true);
            Assert.Throws <ArgumentOutOfRangeException>(() => WireReadyBitArray[WireReadyBitArray.Length] = true);
        }
        public static void Get_Set(bool def, bool[] newValues)
        {
            WireReadyBitArray WireReadyBitArray = new WireReadyBitArray(newValues.Length, def);

            for (int i = 0; i < newValues.Length; i++)
            {
                WireReadyBitArray.Set(i, newValues[i]);
                Assert.AreEqual(newValues[i], WireReadyBitArray[i]);
                Assert.AreEqual(newValues[i], WireReadyBitArray.Get(i));
            }
        }
        /*=========================================================================
        ** Allocates a new BitArray with the same length and bit values as bits.
        **
        ** Exceptions: ArgumentException if bits == null.
        ** =========================================================================*/
        public WireReadyBitArray(WireReadyBitArray bits)
        {
            if (bits == null)
            {
                throw new ArgumentNullException(nameof(bits));
            }

            int arrayLength = bits.InternalArray.Length;

            //TODO: This could be slower for some lengths: https://stackoverflow.com/a/33865267
            InternalArray = new byte[arrayLength];
            Buffer.BlockCopy(bits.InternalArray, 0, InternalArray, 0, arrayLength);
        }
        public static void Get_InvalidIndex_ThrowsArgumentOutOfRangeException()
        {
            WireReadyBitArray bitArray = new WireReadyBitArray(16);

            Assert.Throws <ArgumentOutOfRangeException>(() => bitArray.Get(-1));
            Assert.Throws <ArgumentOutOfRangeException>(() => bitArray.Get(bitArray.Length));

            Assert.Throws <ArgumentOutOfRangeException>(() =>
            {
                var l = bitArray[-1];
            });
            Assert.Throws <ArgumentOutOfRangeException>(() =>
            {
                var l = bitArray[bitArray.Length];
            });
        }
        private static void AssertSizeIsCorrect(WireReadyBitArray mask, int updateValueSize)
        {
            int count = 0;

            for (int i = 0; i < mask.Length; i++)
            {
                if (mask[i])
                {
                    count++;
                }
            }

            if (updateValueSize != count)
            {
                throw new InvalidOperationException($"Failed Standford: {updateValueSize} i: {count}");
            }
        }
        public static void SetAll(int size, bool defaultValue)
        {
            WireReadyBitArray WireReadyBitArray = new WireReadyBitArray(size, defaultValue);

            WireReadyBitArray.SetAll(!defaultValue);
            for (int i = 0; i < WireReadyBitArray.Length; i++)
            {
                Assert.AreEqual(!defaultValue, WireReadyBitArray[i]);
                Assert.AreEqual(!defaultValue, WireReadyBitArray.Get(i));
            }

            WireReadyBitArray.SetAll(defaultValue);
            for (int i = 0; i < WireReadyBitArray.Length; i++)
            {
                Assert.AreEqual(defaultValue, WireReadyBitArray[i]);
                Assert.AreEqual(defaultValue, WireReadyBitArray.Get(i));
            }
        }
 /// <inheritdoc />
 public UpdateFieldValueCollection([NotNull] WireReadyBitArray updateMask, [NotNull] byte[] updateDiffValues)
 {
     UpdateMask       = updateMask ?? throw new ArgumentNullException(nameof(updateMask));
     UpdateDiffValues = updateDiffValues ?? throw new ArgumentNullException(nameof(updateDiffValues));
 }