private static DoubleValueState ReadDouble(BitBinaryReader reader, DoubleValueState state)
        {
            var firstBit = reader.ReadBit();

            if (!firstBit)
            {
                return(state);
            }

            var  secondBit = reader.ReadBit();
            long meaningFulBits;

            if (!secondBit)
            {
                var numBitsToRead = BitAggregateMagic.NumBitsInLongInteger - state.LeadingZeros - state.TrailingZeros;
                meaningFulBits = reader.ReadBits(numBitsToRead);
            }
            else
            {
                // a new block position was started since the number starts with "11".
                state.LeadingZeros = (sbyte)reader.ReadBits(NumBitsToEncodeNumLeadingZeros);
                var numBitsToRead = (sbyte)reader.ReadBits(NumBitsToEncodeNumMeaningfulBits);
                if (numBitsToRead == 0)
                {
                    // The block size is 64 bits which becomes 0 in writing into 6 bits - overflow.
                    // If the block size were indeed 0 bits, the xor value would be 0, and the actual value would be identical to the prior value,
                    // so we would have bailed out early on since firstBit would be 0.
                    numBitsToRead = (sbyte)BitAggregateMagic.NumBitsInLongInteger;
                }

                state.TrailingZeros = (sbyte)(BitAggregateMagic.NumBitsInLongInteger - state.LeadingZeros - numBitsToRead);
                meaningFulBits      = reader.ReadBits(numBitsToRead);
            }

            var xor = meaningFulBits << state.TrailingZeros;

            state.Value = BitConverter.Int64BitsToDouble(xor ^ BitConverter.DoubleToInt64Bits(state.Value));
            return(state);
        }
        /// <summary>
        /// Deserializes for one timestamp - v2.
        /// </summary>
        /// <param name="version">The serialization version.</param>
        /// <param name="reader">The bit reader.</param>
        /// <param name="definition">The definition.</param>
        /// <param name="values">The values.</param>
        /// <param name="dataPointIndex">Index of the data point.</param>
        /// <param name="currentBlockLeadingZeros">The current block leading zeros.</param>
        /// <param name="currentBlockTrailingZeros">The current block trailing zeros.</param>
        /// <param name="priorValidValues">The prior valid values.</param>
        private static void DeserializeForOneTimestampV2AndAbove(byte version, BitBinaryReader reader, TimeSeriesDefinition <MetricIdentifier> definition, List <List <double?> > values, int dataPointIndex, sbyte[] currentBlockLeadingZeros, sbyte[] currentBlockTrailingZeros, double[] priorValidValues)
        {
            var numSamplingTypes = values.Count;

            for (var s = 0; s < numSamplingTypes; s++)
            {
                if (dataPointIndex == 0)
                {
                    // very first value of the series
                    priorValidValues[s] = reader.BinaryReader.ReadDouble();
                    values[s].Add(GetNullableDouble(priorValidValues[s]));
                }
                else
                {
                    var firstBit = reader.ReadBit();
                    if (!firstBit)
                    {
                        // first bit is 0
                        values[s].Add(GetNullableDouble(priorValidValues[s]));
                    }
                    else
                    {
                        var secondBit = reader.ReadBit();

                        long meaningfulBits;
                        if (!secondBit)
                        {
                            // 2nd bit is 0 while the first is 1.
                            if (currentBlockLeadingZeros[s] < 0)
                            {
                                throw new Exception("The block has not been set so it is a bug in serialization on server");
                            }

                            var numBitsToRead = BitAggregateMagic.NumBitsInLongInteger - currentBlockLeadingZeros[s] - currentBlockTrailingZeros[s];

                            meaningfulBits = reader.ReadBits(numBitsToRead);
                        }
                        else
                        {
                            // a new block position was started since the number starts with "11".
                            currentBlockLeadingZeros[s] = (sbyte)reader.ReadBits(GetNumBitsToEncodeNumLeadingZeros(version));
                            var numBitsToRead = (sbyte)reader.ReadBits(NumBitsToEncodeNumMeaningfulBits);
                            if (numBitsToRead == 0)
                            {
                                // The block size is 64 bits which becomes 0 in writing into 6 bits - overflow.
                                // If the block size were indeed 0 bits, the xor value would be 0, and the actual value would be identical to the prior value,
                                // so we would not have reached here since firstBit would be 0.
                                numBitsToRead = (sbyte)BitAggregateMagic.NumBitsInLongInteger;
                            }

                            currentBlockTrailingZeros[s] = (sbyte)(BitAggregateMagic.NumBitsInLongInteger - currentBlockLeadingZeros[s] - numBitsToRead);

                            meaningfulBits = reader.ReadBits(numBitsToRead);
                        }

                        long xor = meaningfulBits << currentBlockTrailingZeros[s];
                        priorValidValues[s] = BitConverter.Int64BitsToDouble(xor ^ BitConverter.DoubleToInt64Bits(priorValidValues[s]));
                        values[s].Add(GetNullableDouble(priorValidValues[s]));
                    }
                }
            }
        }