func (p *Parser) Start(msg []byte) (Header, error) {
	if p.msg != nil {
		*p = Parser{}
	}
	p.msg = msg
	var err error
	if p.off, err = p.header.unpack(msg, 0); err != nil {
		return Header{}, &nestedError{"unpacking header", err}
	}
	p.section = sectionQuestions
	return p.header.header(), nil
}
Start parses the header and enables the parsing of Questions.
package dnsmessage
import (
	"errors"
)
type Type uint16
const (
	TypeA     Type = 1
	TypeNS    Type = 2
	TypeCNAME Type = 5
	TypeSOA   Type = 6
	TypePTR   Type = 12
	TypeMX    Type = 15
	TypeTXT   Type = 16
	TypeAAAA  Type = 28
	TypeSRV   Type = 33
	TypeOPT   Type = 41
	TypeWKS   Type = 11
	TypeHINFO Type = 13
	TypeMINFO Type = 14
	TypeAXFR  Type = 252
	TypeALL   Type = 255
)
var typeNames = map[Type]string{
	TypeA:     "TypeA",
	TypeNS:    "TypeNS",
	TypeCNAME: "TypeCNAME",
	TypeSOA:   "TypeSOA",
	TypePTR:   "TypePTR",
	TypeMX:    "TypeMX",
	TypeTXT:   "TypeTXT",
	TypeAAAA:  "TypeAAAA",
	TypeSRV:   "TypeSRV",
	TypeOPT:   "TypeOPT",
	TypeWKS:   "TypeWKS",
	TypeHINFO: "TypeHINFO",
	TypeMINFO: "TypeMINFO",
	TypeAXFR:  "TypeAXFR",
	TypeALL:   "TypeALL",
}
func (t Type) String() string {
	if n, ok := typeNames[t]; ok {
		return n
	}
	return printUint16(uint16(t))
}
func (t Type) GoString() string {
	if n, ok := typeNames[t]; ok {
		return "dnsmessage." + n
	}
	return printUint16(uint16(t))
}
type Class uint16
const (
	ClassINET   Class = 1
	ClassCSNET  Class = 2
	ClassCHAOS  Class = 3
	ClassHESIOD Class = 4
	ClassANY Class = 255
)
var classNames = map[Class]string{
	ClassINET:   "ClassINET",
	ClassCSNET:  "ClassCSNET",
	ClassCHAOS:  "ClassCHAOS",
	ClassHESIOD: "ClassHESIOD",
	ClassANY:    "ClassANY",
}
func (c Class) String() string {
	if n, ok := classNames[c]; ok {
		return n
	}
	return printUint16(uint16(c))
}
func (c Class) GoString() string {
	if n, ok := classNames[c]; ok {
		return "dnsmessage." + n
	}
	return printUint16(uint16(c))
}
type OpCode uint16
func (o OpCode) GoString() string {
	return printUint16(uint16(o))
}
type RCode uint16
const (
	RCodeSuccess        RCode = 0
	RCodeFormatError    RCode = 1
	RCodeServerFailure  RCode = 2
	RCodeNameError      RCode = 3
	RCodeNotImplemented RCode = 4
	RCodeRefused        RCode = 5
)
var rCodeNames = map[RCode]string{
	RCodeSuccess:        "RCodeSuccess",
	RCodeFormatError:    "RCodeFormatError",
	RCodeServerFailure:  "RCodeServerFailure",
	RCodeNameError:      "RCodeNameError",
	RCodeNotImplemented: "RCodeNotImplemented",
	RCodeRefused:        "RCodeRefused",
}
func (r RCode) String() string {
	if n, ok := rCodeNames[r]; ok {
		return n
	}
	return printUint16(uint16(r))
}
func (r RCode) GoString() string {
	if n, ok := rCodeNames[r]; ok {
		return "dnsmessage." + n
	}
	return printUint16(uint16(r))
}
func printPaddedUint8(i uint8) string {
	b := byte(i)
	return string([]byte{
		b/100 + '0',
		b/10%10 + '0',
		b%10 + '0',
	})
}
func printUint8Bytes(buf []byte, i uint8) []byte {
	b := byte(i)
	if i >= 100 {
		buf = append(buf, b/100+'0')
	}
	if i >= 10 {
		buf = append(buf, b/10%10+'0')
	}
	return append(buf, b%10+'0')
}
func printByteSlice(b []byte) string {
	if len(b) == 0 {
		return ""
	}
	buf := make([]byte, 0, 5*len(b))
	buf = printUint8Bytes(buf, uint8(b[0]))
	for _, n := range b[1:] {
		buf = append(buf, ',', ' ')
		buf = printUint8Bytes(buf, uint8(n))
	}
	return string(buf)
}
const hexDigits = "0123456789abcdef"
func printString(str []byte) string {
	buf := make([]byte, 0, len(str))
	for i := 0; i < len(str); i++ {
		c := str[i]
		if c == '.' || c == '-' || c == ' ' ||
			'A' <= c && c <= 'Z' ||
			'a' <= c && c <= 'z' ||
			'0' <= c && c <= '9' {
			buf = append(buf, c)
			continue
		}
		upper := c >> 4
		lower := (c << 4) >> 4
		buf = append(
			buf,
			'\\',
			'x',
			hexDigits[upper],
			hexDigits[lower],
		)
	}
	return string(buf)
}
func printUint16(i uint16) string {
	return printUint32(uint32(i))
}
func printUint32(i uint32) string {
	buf := make([]byte, 10)
	for b, d := buf, uint32(1000000000); d > 0; d /= 10 {
		b[0] = byte(i/d%10 + '0')
		if b[0] == '0' && len(b) == len(buf) && len(buf) > 1 {
			buf = buf[1:]
		}
		b = b[1:]
		i %= d
	}
	return string(buf)
}
func printBool(b bool) string {
	if b {
		return "true"
	}
	return "false"
}
var (
	ErrNotStarted = errors.New("parsing/packing of this type isn't available yet")
	ErrSectionDone = errors.New("parsing/packing of this section has completed")
	errBaseLen            = errors.New("insufficient data for base length type")
	errCalcLen            = errors.New("insufficient data for calculated length type")
	errReserved           = errors.New("segment prefix is reserved")
	errTooManyPtr         = errors.New("too many pointers (>10)")
	errInvalidPtr         = errors.New("invalid pointer")
	errNilResouceBody     = errors.New("nil resource body")
	errResourceLen        = errors.New("insufficient data for resource body length")
	errSegTooLong         = errors.New("segment length too long")
	errZeroSegLen         = errors.New("zero length segment")
	errResTooLong         = errors.New("resource length too long")
	errTooManyQuestions   = errors.New("too many Questions to pack (>65535)")
	errTooManyAnswers     = errors.New("too many Answers to pack (>65535)")
	errTooManyAuthorities = errors.New("too many Authorities to pack (>65535)")
	errTooManyAdditionals = errors.New("too many Additionals to pack (>65535)")
	errNonCanonicalName   = errors.New("name is not in canonical format (it must end with a .)")
	errStringTooLong      = errors.New("character string exceeds maximum length (255)")
	errCompressedSRV      = errors.New("compressed name in SRV resource data")
)
const (
	packStartingCap = 512
	uint16Len = 2
	uint32Len = 4
	headerLen = 6 * uint16Len
)
type nestedError struct {
	s string
	err error
}
func (e *nestedError) Error() string {
	return e.s + ": " + e.err.Error()
}
type Header struct {
	ID                 uint16
	Response           bool
	OpCode             OpCode
	Authoritative      bool
	Truncated          bool
	RecursionDesired   bool
	RecursionAvailable bool
	RCode              RCode
}
func (m *Header) pack() (id uint16, bits uint16) {
	id = m.ID
	bits = uint16(m.OpCode)<<11 | uint16(m.RCode)
	if m.RecursionAvailable {
		bits |= headerBitRA
	}
	if m.RecursionDesired {
		bits |= headerBitRD
	}
	if m.Truncated {
		bits |= headerBitTC
	}
	if m.Authoritative {
		bits |= headerBitAA
	}
	if m.Response {
		bits |= headerBitQR
	}
	return
}
func (m *Header) GoString() string {
	return "dnsmessage.Header{" +
		"ID: " + printUint16(m.ID) + ", " +
		"Response: " + printBool(m.Response) + ", " +
		"OpCode: " + m.OpCode.GoString() + ", " +
		"Authoritative: " + printBool(m.Authoritative) + ", " +
		"Truncated: " + printBool(m.Truncated) + ", " +
		"RecursionDesired: " + printBool(m.RecursionDesired) + ", " +
		"RecursionAvailable: " + printBool(m.RecursionAvailable) + ", " +
		"RCode: " + m.RCode.GoString() + "}"
}
type Message struct {
	Header
	Questions   []Question
	Answers     []Resource
	Authorities []Resource
	Additionals []Resource
}
type section uint8
const (
	sectionNotStarted section = iota
	sectionHeader
	sectionQuestions
	sectionAnswers
	sectionAuthorities
	sectionAdditionals
	sectionDone
	headerBitQR = 1 << 15  
	headerBitAA = 1 << 10  
	headerBitTC = 1 << 9   
	headerBitRD = 1 << 8   
	headerBitRA = 1 << 7   
)
var sectionNames = map[section]string{
	sectionHeader:      "header",
	sectionQuestions:   "Question",
	sectionAnswers:     "Answer",
	sectionAuthorities: "Authority",
	sectionAdditionals: "Additional",
}
type header struct {
	id          uint16
	bits        uint16
	questions   uint16
	answers     uint16
	authorities uint16
	additionals uint16
}
func (h *header) count(sec section) uint16 {
	switch sec {
	case sectionQuestions:
		return h.questions
	case sectionAnswers:
		return h.answers
	case sectionAuthorities:
		return h.authorities
	case sectionAdditionals:
		return h.additionals
	}
	return 0
}
func (h *header) pack(msg []byte) []byte {
	msg = packUint16(msg, h.id)
	msg = packUint16(msg, h.bits)
	msg = packUint16(msg, h.questions)
	msg = packUint16(msg, h.answers)
	msg = packUint16(msg, h.authorities)
	return packUint16(msg, h.additionals)
}
func (h *header) unpack(msg []byte, off int) (int, error) {
	newOff := off
	var err error
	if h.id, newOff, err = unpackUint16(msg, newOff); err != nil {
		return off, &nestedError{"id", err}
	}
	if h.bits, newOff, err = unpackUint16(msg, newOff); err != nil {
		return off, &nestedError{"bits", err}
	}
	if h.questions, newOff, err = unpackUint16(msg, newOff); err != nil {
		return off, &nestedError{"questions", err}
	}
	if h.answers, newOff, err = unpackUint16(msg, newOff); err != nil {
		return off, &nestedError{"answers", err}
	}
	if h.authorities, newOff, err = unpackUint16(msg, newOff); err != nil {
		return off, &nestedError{"authorities", err}
	}
	if h.additionals, newOff, err = unpackUint16(msg, newOff); err != nil {
		return off, &nestedError{"additionals", err}
	}
	return newOff, nil
}
func (h *header) header() Header {
	return Header{
		ID:                 h.id,
		Response:           (h.bits & headerBitQR) != 0,
		OpCode:             OpCode(h.bits>>11) & 0xF,
		Authoritative:      (h.bits & headerBitAA) != 0,
		Truncated:          (h.bits & headerBitTC) != 0,
		RecursionDesired:   (h.bits & headerBitRD) != 0,
		RecursionAvailable: (h.bits & headerBitRA) != 0,
		RCode:              RCode(h.bits & 0xF),
	}
}
type Resource struct {
	Header ResourceHeader
	Body   ResourceBody
}
func (r *Resource) GoString() string {
	return "dnsmessage.Resource{" +
		"Header: " + r.Header.GoString() +
		", Body: &" + r.Body.GoString() +
		"}"
}
type ResourceBody interface {
	pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error)
	realType() Type
	GoString() string
}
func (r *Resource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
	if r.Body == nil {
		return msg, errNilResouceBody
	}
	oldMsg := msg
	r.Header.Type = r.Body.realType()
	msg, lenOff, err := r.Header.pack(msg, compression, compressionOff)
	if err != nil {
		return msg, &nestedError{"ResourceHeader", err}
	}
	preLen := len(msg)
	msg, err = r.Body.pack(msg, compression, compressionOff)
	if err != nil {
		return msg, &nestedError{"content", err}
	}
	if err := r.Header.fixLen(msg, lenOff, preLen); err != nil {
		return oldMsg, err
	}
	return msg, nil
}
type Parser struct {
	msg    []byte
	header header
	section        section
	off            int
	index          int
	resHeaderValid bool
	resHeader      ResourceHeader
}