{{- /*gotype: github.com/ClickHouse/ch-go/proto/cmd/ch-gen-col.Variant*/ -}}
{{ if .GenerateUnsafe }} //go:build !(amd64 || arm64 || riscv64) || purego
{{ end }}
// Code generated by ./cmd/ch-gen-col, DO NOT EDIT.

package proto

import (
	"encoding/binary"
{{- if .IsFloat }}
	"math"
{{- end }}

	"github.com/go-faster/errors"
)

var _ = binary.LittleEndian // clickHouse uses LittleEndian

// DecodeColumn decodes {{ .Name }} rows from *Reader.
func (c *{{ .Type }}) DecodeColumn(r *Reader, rows int) error {
	if rows == 0 {
		return nil
	}
	{{- if .SingleByte }}
	data, err := r.ReadRaw(rows)
	{{- else }}
	{{- if .FixedStr }}
	const size = {{ .Bytes }}
	{{- else }}
	const size = {{ .Bits }} / 8
	{{- end }}
	data, err := r.ReadRaw(rows * size)
	{{- end }}
	if err != nil {
		return errors.Wrap(err, "read")
	}
	{{- if .Byte }}
	*c = append(*c, data...)
	{{- else if .SingleByte }}
	v := *c
	v = append(v, make([]{{ .ElemType }}, rows)...)
	for i := range data {
		v[i] = {{ .ElemType }}(data[i])
	}
	*c = v
	{{- else }}
	{{- if .DateTime }}
	v := c.Data
	{{- else }}
	v := *c
	{{- end }}
	// Move bound check out of loop.
	//
	// See https://github.com/golang/go/issues/30945.
	_ = data[len(data)-size]
	for i := 0; i <= len(data)-size; i += size {
		v = append(v,
		{{- if .IsFloat }}
			math.{{ .Name }}frombits(binary.LittleEndian.{{ .BinFunc }}(data[i:i+size])),
		{{- else if .Cast }}
			{{ .ElemType }}({{ .BinGet }}(data[i : i+size])),
		{{- else if .FixedStr }}
		    *(*{{ .ElemType }})(data[i : i+size]),
		{{- else }}
			{{ .BinGet }}(data[i : i+size]),
		{{- end }}
		)
	}
	{{- if .DateTime }}
	c.Data = v
	{{- else }}
	*c = v
	{{- end }}
	{{- end }}
	return nil
}

// EncodeColumn encodes {{ .Name }} rows to *Buffer.
func (c {{ .Type }}) EncodeColumn(b *Buffer) {
	{{- if .DateTime }}
	v := c.Data
	{{- else }}
	v := c
	{{- end }}
	if len(v) == 0 {
		return
	}
	{{- if .Byte }}
	b.Buf = append(b.Buf, v...)
	{{- else if .SingleByte }}
	start := len(b.Buf)
	b.Buf = append(b.Buf, make([]byte, len(v))...)
	for i := range v {
		b.Buf[i+start] = {{ .UnsignedType }}(v[i])
	}
	{{- else }}
	{{- if .FixedStr }}
	const size = {{ .Bytes }}
	{{- else }}
	const size = {{ .Bits }} / 8
	{{- end }}
	offset := len(b.Buf)
	b.Buf = append(b.Buf, make([]byte, size*len(v))...)
	for _, vv := range v {
		{{ .BinPut }}(
			b.Buf[offset : offset+size],
		{{- if .IsFloat }}
			math.{{ .Name }}bits(vv),
		{{- else if .FixedStr }}
            vv[:],
		{{- else if .Cast }}
			{{ .UnsignedType }}(vv),
		{{- else }}
			vv,
		{{- end }}
	)
		offset += size
	}
	{{- end }}
}

func (c {{ .Type }}) WriteColumn(w *Writer) {
	{{- if .Byte }}
		w.ChainWrite([]byte(c))
	{{- else }}
		w.ChainBuffer(c.EncodeColumn)
	{{- end }}
}
