//go:build ignore

// rr_generate generates zpack.go which houses 2 large unpack/pack functions.

package main

import (
	"bytes"
	"flag"
	"html/template"
	"log"

	"codeberg.org/miekg/dns/internal/generate"
)

var hdr = `
// Code generated by "go run pack_generate.go"; DO NOT EDIT.

package dns

import (
	"fmt"

	"golang.org/x/crypto/cryptobyte"
)

`

var packFunc = template.Must(template.New("packFunc").Parse(`
func zpack(rr RR, msg []byte, off int, compression map[string]uint16) (int, error) {
	switch x := rr.(type) {
{{range .}}  case *{{.}}:
	return x.pack(msg, off, compression)
{{end}} }
	// if here, we don't have the RR in our pkg, check if it does Packer.
	if x, ok := rr.(Packer); ok {
		return x.Pack(msg, off)
	}
	return 0, fmt.Errorf("dns: no pack defined")
}

`))

var unpackFunc = template.Must(template.New("unpackFunc").Parse(`
func zunpack(rr RR, data cryptobyte.String, msgBuf []byte) error {
	switch x := rr.(type) {
{{range .}}  case *{{.}}:
	return x.unpack(data, msgBuf)
{{end}} }
	// if here, we don't have the RR in our pkg, check if it does Packer.
	if x, ok := rr.(Packer); ok {
		return x.Unpack(data)
	}
	return fmt.Errorf("dns: no unpack defined")
}

`))

const out = "zpack.go"

func main() {
	flag.Parse()
	types, err := generate.Types("types.go")
	if err != nil {
		log.Fatalf("Failed to generate %s: %v", out, err)
	}

	source := &bytes.Buffer{}
	source.WriteString(hdr)

	if err := packFunc.Execute(source, types); err != nil {
		log.Fatalf("Failed to generate %s: %v", out, err)
	}

	if err := unpackFunc.Execute(source, types); err != nil {
		log.Fatalf("Failed to generate %s: %v", out, err)
	}

	generate.Write(source, out)
}
