func (k *tsmKeyIterator) combineString(dedup bool) blocks {
	if dedup {
		for len(k.mergedStringValues) < k.size && len(k.blocks) > 0 {
			for len(k.blocks) > 0 && k.blocks[0].read() {
				k.blocks = k.blocks[1:]
			}
			if len(k.blocks) == 0 {
				break
			}
			first := k.blocks[0]
			minTime := first.minTime
			maxTime := first.maxTime
			for i := 0; i < len(k.blocks); i++ {
				if k.blocks[i].overlapsTimeRange(minTime, maxTime) && !k.blocks[i].read() {
					if k.blocks[i].minTime < minTime {
						minTime = k.blocks[i].minTime
					}
					if k.blocks[i].maxTime > minTime && k.blocks[i].maxTime < maxTime {
						maxTime = k.blocks[i].maxTime
					}
				}
			}
			for i := 0; i < len(k.blocks); i++ {
				if !k.blocks[i].overlapsTimeRange(minTime, maxTime) || k.blocks[i].read() {
					continue
				}
				v, err := DecodeStringBlock(k.blocks[i].b, &[]StringValue{})
				if err != nil {
					k.err = err
					return nil
				}
				v = StringValues(v).Exclude(k.blocks[i].readMin, k.blocks[i].readMax)
				v = StringValues(v).Include(minTime, maxTime)
				if len(v) > 0 {
					k.blocks[i].markRead(v[0].UnixNano(), v[len(v)-1].UnixNano())
				}
				for _, ts := range k.blocks[i].tombstones {
					v = StringValues(v).Exclude(ts.Min, ts.Max)
				}
				k.mergedStringValues = k.mergedStringValues.Merge(v)
			}
		}
		return k.chunkString(nil)
	} else {
		var i int
		for i < len(k.blocks) {
			if k.blocks[i].read() {
				i++
				continue
			}
			if BlockCount(k.blocks[i].b) >= k.size {
				k.merged = append(k.merged, k.blocks[i])
			} else {
				break
			}
			i++
		}
		if k.fast {
			for i < len(k.blocks) {
				if k.blocks[i].read() {
					i++
					continue
				}
				k.merged = append(k.merged, k.blocks[i])
				i++
			}
		}
		if i == len(k.blocks)-1 {
			if !k.blocks[i].read() {
				k.merged = append(k.merged, k.blocks[i])
			}
			i++
		}
		for i < len(k.blocks) && len(k.mergedStringValues) < k.size {
			if k.blocks[i].read() {
				i++
				continue
			}
			v, err := DecodeStringBlock(k.blocks[i].b, &[]StringValue{})
			if err != nil {
				k.err = err
				return nil
			}
			for _, ts := range k.blocks[i].tombstones {
				v = StringValues(v).Exclude(ts.Min, ts.Max)
			}
			k.blocks[i].markRead(k.blocks[i].minTime, k.blocks[i].maxTime)
			k.mergedStringValues = k.mergedStringValues.Merge(v)
			i++
		}
		k.blocks = k.blocks[i:]
		return k.chunkString(k.merged)
	}
}
combine returns a new set of blocks using the current blocks in the buffers.  If dedup
is true, all the blocks will be decoded, dedup and sorted in in order.  If dedup is false,
only blocks that are smaller than the chunk size will be decoded and combined.
package tsm1
import "sort"
func (k *tsmKeyIterator) mergeFloat() {
	if len(k.blocks) == 0 && len(k.merged) == 0 && len(k.mergedFloatValues) == 0 {
		return
	}
	sort.Stable(k.blocks)
	dedup := len(k.mergedFloatValues) != 0
	if len(k.blocks) > 0 && !dedup {
		dedup = len(k.blocks[0].tombstones) > 0 || k.blocks[0].partiallyRead()
		for i := 1; !dedup && i < len(k.blocks); i++ {
			dedup = k.blocks[i].partiallyRead() ||
				k.blocks[i].overlapsTimeRange(k.blocks[i-1].minTime, k.blocks[i-1].maxTime) ||
				len(k.blocks[i].tombstones) > 0
		}
	}
	k.merged = k.combineFloat(dedup)
}
func (k *tsmKeyIterator) combineFloat(dedup bool) blocks {
	if dedup {
		for len(k.mergedFloatValues) < k.size && len(k.blocks) > 0 {
			for len(k.blocks) > 0 && k.blocks[0].read() {
				k.blocks = k.blocks[1:]
			}
			if len(k.blocks) == 0 {
				break
			}
			first := k.blocks[0]
			minTime := first.minTime
			maxTime := first.maxTime
			for i := 0; i < len(k.blocks); i++ {
				if k.blocks[i].overlapsTimeRange(minTime, maxTime) && !k.blocks[i].read() {
					if k.blocks[i].minTime < minTime {
						minTime = k.blocks[i].minTime
					}
					if k.blocks[i].maxTime > minTime && k.blocks[i].maxTime < maxTime {
						maxTime = k.blocks[i].maxTime
					}
				}
			}
			for i := 0; i < len(k.blocks); i++ {
				if !k.blocks[i].overlapsTimeRange(minTime, maxTime) || k.blocks[i].read() {
					continue
				}
				v, err := DecodeFloatBlock(k.blocks[i].b, &[]FloatValue{})
				if err != nil {
					k.err = err
					return nil
				}
				v = FloatValues(v).Exclude(k.blocks[i].readMin, k.blocks[i].readMax)
				v = FloatValues(v).Include(minTime, maxTime)
				if len(v) > 0 {
					k.blocks[i].markRead(v[0].UnixNano(), v[len(v)-1].UnixNano())
				}
				for _, ts := range k.blocks[i].tombstones {
					v = FloatValues(v).Exclude(ts.Min, ts.Max)
				}
				k.mergedFloatValues = k.mergedFloatValues.Merge(v)
			}
		}
		return k.chunkFloat(nil)
	} else {
		var i int
		for i < len(k.blocks) {
			if k.blocks[i].read() {
				i++
				continue
			}
			if BlockCount(k.blocks[i].b) >= k.size {
				k.merged = append(k.merged, k.blocks[i])
			} else {
				break
			}
			i++
		}
		if k.fast {
			for i < len(k.blocks) {
				if k.blocks[i].read() {
					i++
					continue
				}
				k.merged = append(k.merged, k.blocks[i])
				i++
			}
		}
		if i == len(k.blocks)-1 {
			if !k.blocks[i].read() {
				k.merged = append(k.merged, k.blocks[i])
			}
			i++
		}
		for i < len(k.blocks) && len(k.mergedFloatValues) < k.size {
			if k.blocks[i].read() {
				i++
				continue
			}
			v, err := DecodeFloatBlock(k.blocks[i].b, &[]FloatValue{})
			if err != nil {
				k.err = err
				return nil
			}
			for _, ts := range k.blocks[i].tombstones {
				v = FloatValues(v).Exclude(ts.Min, ts.Max)
			}
			k.blocks[i].markRead(k.blocks[i].minTime, k.blocks[i].maxTime)
			k.mergedFloatValues = k.mergedFloatValues.Merge(v)
			i++
		}
		k.blocks = k.blocks[i:]
		return k.chunkFloat(k.merged)
	}
}
func (k *tsmKeyIterator) chunkFloat(dst blocks) blocks {
	if len(k.mergedFloatValues) > k.size {
		values := k.mergedFloatValues[:k.size]
		cb, err := FloatValues(values).Encode(nil)
		if err != nil {
			k.err = err
			return nil
		}
		dst = append(dst, &block{
			minTime: values[0].UnixNano(),
			maxTime: values[len(values)-1].UnixNano(),
			key:     k.key,
			b:       cb,
		})
		k.mergedFloatValues = k.mergedFloatValues[k.size:]
		return dst
	}
	if len(k.mergedFloatValues) > 0 {
		cb, err := FloatValues(k.mergedFloatValues).Encode(nil)
		if err != nil {
			k.err = err
			return nil
		}
		dst = append(dst, &block{
			minTime: k.mergedFloatValues[0].UnixNano(),
			maxTime: k.mergedFloatValues[len(k.mergedFloatValues)-1].UnixNano(),
			key:     k.key,
			b:       cb,
		})
		k.mergedFloatValues = k.mergedFloatValues[:0]
	}
	return dst
}
func (k *tsmKeyIterator) mergeInteger() {
	if len(k.blocks) == 0 && len(k.merged) == 0 && len(k.mergedIntegerValues) == 0 {
		return
	}
	sort.Stable(k.blocks)
	dedup := len(k.mergedIntegerValues) != 0
	if len(k.blocks) > 0 && !dedup {
		dedup = len(k.blocks[0].tombstones) > 0 || k.blocks[0].partiallyRead()
		for i := 1; !dedup && i < len(k.blocks); i++ {
			dedup = k.blocks[i].partiallyRead() ||
				k.blocks[i].overlapsTimeRange(k.blocks[i-1].minTime, k.blocks[i-1].maxTime) ||
				len(k.blocks[i].tombstones) > 0
		}
	}
	k.merged = k.combineInteger(dedup)
}
func (k *tsmKeyIterator) combineInteger(dedup bool) blocks {
	if dedup {
		for len(k.mergedIntegerValues) < k.size && len(k.blocks) > 0 {
			for len(k.blocks) > 0 && k.blocks[0].read() {
				k.blocks = k.blocks[1:]
			}
			if len(k.blocks) == 0 {
				break
			}
			first := k.blocks[0]
			minTime := first.minTime
			maxTime := first.maxTime
			for i := 0; i < len(k.blocks); i++ {
				if k.blocks[i].overlapsTimeRange(minTime, maxTime) && !k.blocks[i].read() {
					if k.blocks[i].minTime < minTime {
						minTime = k.blocks[i].minTime
					}
					if k.blocks[i].maxTime > minTime && k.blocks[i].maxTime < maxTime {
						maxTime = k.blocks[i].maxTime
					}
				}
			}
			for i := 0; i < len(k.blocks); i++ {
				if !k.blocks[i].overlapsTimeRange(minTime, maxTime) || k.blocks[i].read() {
					continue
				}
				v, err := DecodeIntegerBlock(k.blocks[i].b, &[]IntegerValue{})
				if err != nil {
					k.err = err
					return nil
				}
				v = IntegerValues(v).Exclude(k.blocks[i].readMin, k.blocks[i].readMax)
				v = IntegerValues(v).Include(minTime, maxTime)
				if len(v) > 0 {
					k.blocks[i].markRead(v[0].UnixNano(), v[len(v)-1].UnixNano())
				}
				for _, ts := range k.blocks[i].tombstones {
					v = IntegerValues(v).Exclude(ts.Min, ts.Max)
				}
				k.mergedIntegerValues = k.mergedIntegerValues.Merge(v)
			}
		}
		return k.chunkInteger(nil)
	} else {
		var i int
		for i < len(k.blocks) {
			if k.blocks[i].read() {
				i++
				continue
			}
			if BlockCount(k.blocks[i].b) >= k.size {
				k.merged = append(k.merged, k.blocks[i])
			} else {
				break
			}
			i++
		}
		if k.fast {
			for i < len(k.blocks) {
				if k.blocks[i].read() {
					i++
					continue
				}
				k.merged = append(k.merged, k.blocks[i])
				i++
			}
		}
		if i == len(k.blocks)-1 {
			if !k.blocks[i].read() {
				k.merged = append(k.merged, k.blocks[i])
			}
			i++
		}
		for i < len(k.blocks) && len(k.mergedIntegerValues) < k.size {
			if k.blocks[i].read() {
				i++
				continue
			}
			v, err := DecodeIntegerBlock(k.blocks[i].b, &[]IntegerValue{})
			if err != nil {
				k.err = err
				return nil
			}
			for _, ts := range k.blocks[i].tombstones {
				v = IntegerValues(v).Exclude(ts.Min, ts.Max)
			}
			k.blocks[i].markRead(k.blocks[i].minTime, k.blocks[i].maxTime)
			k.mergedIntegerValues = k.mergedIntegerValues.Merge(v)
			i++
		}
		k.blocks = k.blocks[i:]
		return k.chunkInteger(k.merged)
	}
}
func (k *tsmKeyIterator) chunkInteger(dst blocks) blocks {
	if len(k.mergedIntegerValues) > k.size {
		values := k.mergedIntegerValues[:k.size]
		cb, err := IntegerValues(values).Encode(nil)
		if err != nil {
			k.err = err
			return nil
		}
		dst = append(dst, &block{
			minTime: values[0].UnixNano(),
			maxTime: values[len(values)-1].UnixNano(),
			key:     k.key,
			b:       cb,
		})
		k.mergedIntegerValues = k.mergedIntegerValues[k.size:]
		return dst
	}
	if len(k.mergedIntegerValues) > 0 {
		cb, err := IntegerValues(k.mergedIntegerValues).Encode(nil)
		if err != nil {
			k.err = err
			return nil
		}
		dst = append(dst, &block{
			minTime: k.mergedIntegerValues[0].UnixNano(),
			maxTime: k.mergedIntegerValues[len(k.mergedIntegerValues)-1].UnixNano(),
			key:     k.key,
			b:       cb,
		})
		k.mergedIntegerValues = k.mergedIntegerValues[:0]
	}
	return dst
}
func (k *tsmKeyIterator) mergeUnsigned() {
	if len(k.blocks) == 0 && len(k.merged) == 0 && len(k.mergedUnsignedValues) == 0 {
		return
	}
	sort.Stable(k.blocks)
	dedup := len(k.mergedUnsignedValues) != 0
	if len(k.blocks) > 0 && !dedup {
		dedup = len(k.blocks[0].tombstones) > 0 || k.blocks[0].partiallyRead()
		for i := 1; !dedup && i < len(k.blocks); i++ {
			dedup = k.blocks[i].partiallyRead() ||
				k.blocks[i].overlapsTimeRange(k.blocks[i-1].minTime, k.blocks[i-1].maxTime) ||
				len(k.blocks[i].tombstones) > 0
		}
	}
	k.merged = k.combineUnsigned(dedup)
}
func (k *tsmKeyIterator) combineUnsigned(dedup bool) blocks {
	if dedup {
		for len(k.mergedUnsignedValues) < k.size && len(k.blocks) > 0 {
			for len(k.blocks) > 0 && k.blocks[0].read() {
				k.blocks = k.blocks[1:]
			}
			if len(k.blocks) == 0 {
				break
			}
			first := k.blocks[0]
			minTime := first.minTime
			maxTime := first.maxTime
			for i := 0; i < len(k.blocks); i++ {
				if k.blocks[i].overlapsTimeRange(minTime, maxTime) && !k.blocks[i].read() {
					if k.blocks[i].minTime < minTime {
						minTime = k.blocks[i].minTime
					}
					if k.blocks[i].maxTime > minTime && k.blocks[i].maxTime < maxTime {
						maxTime = k.blocks[i].maxTime
					}
				}
			}
			for i := 0; i < len(k.blocks); i++ {
				if !k.blocks[i].overlapsTimeRange(minTime, maxTime) || k.blocks[i].read() {
					continue
				}
				v, err := DecodeUnsignedBlock(k.blocks[i].b, &[]UnsignedValue{})
				if err != nil {
					k.err = err
					return nil
				}
				v = UnsignedValues(v).Exclude(k.blocks[i].readMin, k.blocks[i].readMax)
				v = UnsignedValues(v).Include(minTime, maxTime)
				if len(v) > 0 {
					k.blocks[i].markRead(v[0].UnixNano(), v[len(v)-1].UnixNano())
				}
				for _, ts := range k.blocks[i].tombstones {
					v = UnsignedValues(v).Exclude(ts.Min, ts.Max)
				}
				k.mergedUnsignedValues = k.mergedUnsignedValues.Merge(v)
			}
		}
		return k.chunkUnsigned(nil)
	} else {
		var i int
		for i < len(k.blocks) {
			if k.blocks[i].read() {
				i++
				continue
			}
			if BlockCount(k.blocks[i].b) >= k.size {
				k.merged = append(k.merged, k.blocks[i])
			} else {
				break
			}
			i++
		}
		if k.fast {
			for i < len(k.blocks) {
				if k.blocks[i].read() {
					i++
					continue
				}
				k.merged = append(k.merged, k.blocks[i])
				i++
			}
		}
		if i == len(k.blocks)-1 {
			if !k.blocks[i].read() {
				k.merged = append(k.merged, k.blocks[i])
			}
			i++
		}
		for i < len(k.blocks) && len(k.mergedUnsignedValues) < k.size {
			if k.blocks[i].read() {
				i++
				continue
			}
			v, err := DecodeUnsignedBlock(k.blocks[i].b, &[]UnsignedValue{})
			if err != nil {
				k.err = err
				return nil
			}
			for _, ts := range k.blocks[i].tombstones {
				v = UnsignedValues(v).Exclude(ts.Min, ts.Max)
			}
			k.blocks[i].markRead(k.blocks[i].minTime, k.blocks[i].maxTime)
			k.mergedUnsignedValues = k.mergedUnsignedValues.Merge(v)
			i++
		}
		k.blocks = k.blocks[i:]
		return k.chunkUnsigned(k.merged)
	}
}
func (k *tsmKeyIterator) chunkUnsigned(dst blocks) blocks {
	if len(k.mergedUnsignedValues) > k.size {
		values := k.mergedUnsignedValues[:k.size]
		cb, err := UnsignedValues(values).Encode(nil)
		if err != nil {
			k.err = err
			return nil
		}
		dst = append(dst, &block{
			minTime: values[0].UnixNano(),
			maxTime: values[len(values)-1].UnixNano(),
			key:     k.key,
			b:       cb,
		})
		k.mergedUnsignedValues = k.mergedUnsignedValues[k.size:]
		return dst
	}
	if len(k.mergedUnsignedValues) > 0 {
		cb, err := UnsignedValues(k.mergedUnsignedValues).Encode(nil)
		if err != nil {
			k.err = err
			return nil
		}
		dst = append(dst, &block{
			minTime: k.mergedUnsignedValues[0].UnixNano(),
			maxTime: k.mergedUnsignedValues[len(k.mergedUnsignedValues)-1].UnixNano(),
			key:     k.key,
			b:       cb,
		})
		k.mergedUnsignedValues = k.mergedUnsignedValues[:0]
	}
	return dst
}
func (k *tsmKeyIterator) mergeString() {
	if len(k.blocks) == 0 && len(k.merged) == 0 && len(k.mergedStringValues) == 0 {
		return
	}
	sort.Stable(k.blocks)
	dedup := len(k.mergedStringValues) != 0
	if len(k.blocks) > 0 && !dedup {
		dedup = len(k.blocks[0].tombstones) > 0 || k.blocks[0].partiallyRead()
		for i := 1; !dedup && i < len(k.blocks); i++ {
			dedup = k.blocks[i].partiallyRead() ||
				k.blocks[i].overlapsTimeRange(k.blocks[i-1].minTime, k.blocks[i-1].maxTime) ||
				len(k.blocks[i].tombstones) > 0
		}
	}
	k.merged = k.combineString(dedup)
}