{{.DocText "// "}}
package {{.NameNative}}

// Code generated by colf(1); DO NOT EDIT.
// The compiler used schema file {{.SchemaFileList}}.

import (
	"encoding/binary"
	"fmt"
	"io"
{{- if .HasFloat}}
	"math"
{{- end}}
{{- if .HasTimestamp}}
	"time"
{{- end}}
{{- range .Refs}}
	"{{.Name}}"
{{- end}}
)

var intconv = binary.BigEndian

// Colfer configuration attributes
var (
	// ColferSizeMax is the upper limit for serial byte sizes.
	ColferSizeMax = {{.SizeMax}}
{{- if .HasList}}
	// ColferListMax is the upper limit for the number of elements in a list.
	ColferListMax = {{.ListMax}}
{{- end}}
)

// ColferMax signals an upper limit breach.
type ColferMax string

// Error honors the error interface.
func (m ColferMax) Error() string { return string(m) }

// ColferError signals a data mismatch as as a byte index.
type ColferError int

// Error honors the error interface.
func (i ColferError) Error() string {
	return fmt.Sprintf("colfer: unknown header at byte %d", i)
}

// ColferTail signals data continuation as a byte index.
type ColferTail int

// Error honors the error interface.
func (i ColferTail) Error() string {
	return fmt.Sprintf("colfer: data continuation at byte %d", i)
}
{{range .Structs}}
{{.DocText "// "}}
type {{.NameNative}} struct {
{{range .Fields}}{{.DocText "\t// "}}
	{{.NameNative}}	{{if .TypeList}}[]{{end}}{{if .TypeRef}}*{{end}}{{.TypeNative}}{{range .TagAdd}} {{.}}{{end}}
{{end}}}

// MarshalTo encodes o as Colfer into buf and returns the number of bytes written.
// If the buffer is too small, MarshalTo will panic.
{{- range .Fields}}{{if and .TypeList .TypeRef}}
// All nil entries in o.{{.NameNative}} will be replaced with a new value.
{{- end}}{{end}}
func (o *{{.NameNative}}) MarshalTo(buf []byte) int {
	var i int
{{range .Fields}}{{template "marshal-field" .}}{{end}}
	buf[i] = 0x7f
	i++
	return i
}

// MarshalLen returns the Colfer serial byte size.
// The error return option is ColferMax.
func (o *{{.NameNative}}) MarshalLen() (int, error) {
	l := 1
{{range .Fields}}{{template "marshal-field-len" .}}{{end}}
	if l > ColferSizeMax {
		return l, ColferMax(fmt.Sprintf("colfer: struct {{.String}} exceeds %d bytes", ColferSizeMax))
	}
	return l, nil
}

// MarshalBinary encodes o as Colfer conform encoding.BinaryMarshaler.
{{- range .Fields}}{{if and .TypeList .TypeRef}}
// All nil entries in o.{{.NameNative}} will be replaced with a new value.
{{- end}}{{end}}
// The error return option is ColferMax.
func (o *{{.NameNative}}) MarshalBinary() (data []byte, err error) {
	l, err := o.MarshalLen()
	if err != nil {
		return nil, err
	}
	data = make([]byte, l)
	o.MarshalTo(data)
	return data, nil
}

// Unmarshal decodes data as Colfer and returns the number of bytes read.
// The error return options are io.EOF, ColferError and ColferMax.
func (o *{{.NameNative}}) Unmarshal(data []byte) (int, error) {
	if len(data) == 0 {
		return 0, io.EOF
	}
	header := data[0]
	i := 1
{{range .Fields}}{{template "unmarshal-field" .}}{{end}}
	if header != 0x7f {
		return 0, ColferError(i - 1)
	}
	if i < ColferSizeMax {
		return i, nil
	}
eof:
	if i >= ColferSizeMax {
		return 0, ColferMax(fmt.Sprintf("colfer: struct {{.String}} size exceeds %d bytes", ColferSizeMax))
	}
	return 0, io.EOF
}

// UnmarshalBinary decodes data as Colfer conform encoding.BinaryUnmarshaler.
// The error return options are io.EOF, ColferError, ColferTail and ColferMax.
func (o *{{.NameNative}}) UnmarshalBinary(data []byte) error {
	i, err := o.Unmarshal(data)
	if i < len(data) && err == nil {
		return ColferTail(i)
	}
	return err
}
{{end}}
