tuple.go
func (b *TupleBuilder) PutTupleArray(field string, value []Tuple) (wrote int, err error) {

	// field type should be
	if err = b.typeCheck(field, TupleArrayField); err != nil {
		return 0, err
	}

	// calculate total size
	var totalSize int
	var tupleSize int
	for i := 0; i < len(value); i++ {
		tupleSize = value[i].Size()

		// add tuple header
		if tupleSize < math.MaxUint8 {
			totalSize += 2
		} else if tupleSize < math.MaxUint16 {
			totalSize += 3
		} else if tupleSize < math.MaxUint32 {
			totalSize += 5
		} else {
			totalSize += 9
		}

		// add tuple size
		totalSize += tupleSize
	}

	// return error if buffer is too small
	// 8-bit total size check
	if totalSize < math.MaxUint8 && b.available() < totalSize+2 {
		return 0, xbinary.ErrOutOfRange

		// 16-bit total size check
	} else if totalSize < math.MaxUint16 && b.available() < totalSize+3 {
		return 0, xbinary.ErrOutOfRange

		// 32-bit total size check
	} else if totalSize < math.MaxUint32 && b.available() < totalSize+5 {
		return 0, xbinary.ErrOutOfRange

		// 64-bit size check
	} else if totalSize > math.MaxUint32 && b.available() < totalSize+9 {
		return 0, xbinary.ErrOutOfRange
	}

	// write array values
	for _, tuple := range value {

		size := tuple.Size() + tuple.Header.Size()
		if size < math.MaxUint8 {

			// check length
			if b.available() < size+2 {
				return wrote, xbinary.ErrOutOfRange
			}

			// write tuple
			if _, err := b.writeTuple(tuple, b.pos+wrote+2, size); err != nil {
				return wrote, err
			}

			// tuple.WriteAt(&b.buffer, int64(b.pos+2+wrote))

			// write type code
			b.buffer[b.pos+wrote] = byte(TupleArray8Code.OpCode)

			// write length
			b.buffer[b.pos+1+wrote] = byte(size)

			wrote += size + 2
		} else if size < math.MaxUint16 {
			// check length
			if b.available() < size+3 {
				return wrote, xbinary.ErrOutOfRange
			}

			// write length
			xbinary.LittleEndian.PutUint16(b.buffer, b.pos+1+wrote, uint16(size))

			// write type code
			b.buffer[b.pos+wrote] = byte(TimestampArray16Code.OpCode)

			// write tuple
			if _, err := b.writeTuple(tuple, b.pos+wrote+3, size); err != nil {
				return wrote, err
			}

			wrote += 3 + size
		} else if size < math.MaxUint32 {

			// check length
			if b.available() < size+5 {
				return wrote, xbinary.ErrOutOfRange
			}

			// write tuple
			if _, err := b.writeTuple(tuple, b.pos+wrote+5, size); err != nil {
				return wrote, err
			}

			// write length
			xbinary.LittleEndian.PutUint32(b.buffer, b.pos+1+wrote, uint32(size))

			// write type code
			b.buffer[b.pos+wrote] = byte(TimestampArray32Code.OpCode)

			wrote += 5 + size
		} else {

			// write tuple
			if _, err := b.writeTuple(tuple, b.pos+wrote+9, size); err != nil {
				return wrote, err
			}

			// write length
			xbinary.LittleEndian.PutUint64(b.buffer, b.pos+1+wrote, uint64(size))

			// write type code
			b.buffer[b.pos+wrote] = byte(TimestampArray64Code.OpCode)
			wrote += 9 + size
		}
	}

	b.offsets[field] = b.pos
	b.pos += wrote
	return
}
func (b *TupleBuilder) PutTupleArray(field string, value []Tuple) (wrote int, err error) {

	// field type should be
	if err = b.typeCheck(field, TupleArrayField); err != nil {
		return 0, err
	}

	// calculate total size
	var totalSize int
	var tupleSize int
	for i := 0; i < len(value); i++ {
		tupleSize = value[i].Size()

		// add tuple header
		if tupleSize < math.MaxUint8 {
			totalSize += 2
		} else if tupleSize < math.MaxUint16 {
			totalSize += 3
		} else if tupleSize < math.MaxUint32 {
			totalSize += 5
		} else {
			totalSize += 9
		}

		// add tuple size
		totalSize += tupleSize
	}

	// return error if buffer is too small
	// 8-bit total size check
	if totalSize < math.MaxUint8 && b.available() < totalSize+2 {
		return 0, xbinary.ErrOutOfRange

		// 16-bit total size check
	} else if totalSize < math.MaxUint16 && b.available() < totalSize+3 {
		return 0, xbinary.ErrOutOfRange

		// 32-bit total size check
	} else if totalSize < math.MaxUint32 && b.available() < totalSize+5 {
		return 0, xbinary.ErrOutOfRange

		// 64-bit size check
	} else if totalSize > math.MaxUint32 && b.available() < totalSize+9 {
		return 0, xbinary.ErrOutOfRange
	}

	// write array values
	for _, tuple := range value {

		size := tuple.Size() + tuple.Header.Size()
		if size < math.MaxUint8 {

			// check length
			if b.available() < size+2 {
				return wrote, xbinary.ErrOutOfRange
			}

			// write tuple
			if _, err := b.writeTuple(tuple, b.pos+wrote+2, size); err != nil {
				return wrote, err
			}

			// tuple.WriteAt(&b.buffer, int64(b.pos+2+wrote))

			// write type code
			b.buffer[b.pos+wrote] = byte(TupleArray8Code.OpCode)

			// write length
			b.buffer[b.pos+1+wrote] = byte(size)

			wrote += size + 2
		} else if size < math.MaxUint16 {
			// check length
			if b.available() < size+3 {
				return wrote, xbinary.ErrOutOfRange
			}

			// write length
			xbinary.LittleEndian.PutUint16(b.buffer, b.pos+1+wrote, uint16(size))

			// write type code
			b.buffer[b.pos+wrote] = byte(TimestampArray16Code.OpCode)

			// write tuple
			if _, err := b.writeTuple(tuple, b.pos+wrote+3, size); err != nil {
				return wrote, err
			}

			wrote += 3 + size
		} else if size < math.MaxUint32 {

			// check length
			if b.available() < size+5 {
				return wrote, xbinary.ErrOutOfRange
			}

			// write tuple
			if _, err := b.writeTuple(tuple, b.pos+wrote+5, size); err != nil {
				return wrote, err
			}

			// write length
			xbinary.LittleEndian.PutUint32(b.buffer, b.pos+1+wrote, uint32(size))

			// write type code
			b.buffer[b.pos+wrote] = byte(TimestampArray32Code.OpCode)

			wrote += 5 + size
		} else {

			// write tuple
			if _, err := b.writeTuple(tuple, b.pos+wrote+9, size); err != nil {
				return wrote, err
			}

			// write length
			xbinary.LittleEndian.PutUint64(b.buffer, b.pos+1+wrote, uint64(size))

			// write type code
			b.buffer[b.pos+wrote] = byte(TimestampArray64Code.OpCode)
			wrote += 9 + size
		}
	}

	b.offsets[field] = b.pos
	b.pos += wrote
	return
}
// PutTupleArray writes an array of tuples for the given field. The field type must be `TupleArrayField`, otherwise an error will be returned.