func (ip *ip4) Decode(b []byte, pos *int, sniffer dns.WireDecodeSniffer) (err error) {
	p := *pos
	if p+4 > len(b) {
		return fmt.Errorf("(*rr.ip4).Decode() - buffer underflow")
	}
	p0 := &b[p]
	*ip = ip4(net.IPv4(b[p], b[p+1], b[p+2], b[p+3]))
	*pos = p + 4
	if sniffer != nil {
		sniffer(p0, &b[*pos-1], dns.SniffIPV4, ip)
	}
	return
}
Implementation of dns.Wirer
package rr
import (
	"bytes"
	"crypto"
	_ "crypto/sha256"
	"encoding/hex"
	"errors"
	"fmt"
	"github.com/cznic/dns"
	"github.com/cznic/strutil"
	"log"
	"net"
	"strconv"
	"strings"
	"time"
)
const asserts = false
var sha256 = crypto.SHA256
func init() {
	if asserts {
		println("WARNING: cznic/dns/rr - assertions enabled")
	}
}
func quote(s string) string {
	return dns.CharString(s).Quoted()
}
type A struct {
	Address net.IP  
}
func (rd *A) Encode(b *dns.Wirebuf) {
	ip4(rd.Address).Encode(b)
}
func (rd *A) Decode(b []byte, pos *int, sniffer dns.WireDecodeSniffer) (err error) {
	p0 := &b[*pos]
	if err = (*ip4)(&rd.Address).Decode(b, pos, sniffer); err != nil {
		return
	}
	if sniffer != nil {
		sniffer(p0, &b[*pos-1], dns.SniffRDataA, rd)
	}
	return
}
func (rd *A) String() string {
	return rd.Address.String()
}
type AAAA struct {
	Address net.IP  
}
func (rd *AAAA) Encode(b *dns.Wirebuf) {
	ip6(rd.Address).Encode(b)
}
func (rd *AAAA) Decode(b []byte, pos *int, sniffer dns.WireDecodeSniffer) (err error) {
	p0 := &b[*pos]
	if err = (*ip6)(&rd.Address).Decode(b, pos, sniffer); err != nil {
		return
	}
	if sniffer != nil {
		sniffer(p0, &b[*pos-1], dns.SniffRDataAAAA, rd)
	}
	return
}
func (rd *AAAA) String() string {
	return rd.Address.String()
}
type AFSDB struct {
	SubType uint16
	Hostname string
}
func (rd *AFSDB) Encode(b *dns.Wirebuf) {
	(dns.Octets2)(rd.SubType).Encode(b)
	(dns.DomainName)(rd.Hostname).Encode(b)
}
func (rd *AFSDB) Decode(b []byte, pos *int, sniffer dns.WireDecodeSniffer) (err error) {
	p0 := &b[*pos]
	if err = (*dns.Octets2)(&rd.SubType).Decode(b, pos, sniffer); err != nil {
		return
	}
	if err = (*dns.DomainName)(&rd.Hostname).Decode(b, pos, sniffer); err != nil {
		return
	}
	if sniffer != nil {
		sniffer(p0, &b[*pos-1], dns.SniffRDataAFSDB, rd)
	}
	return
}
func (rd *AFSDB) String() string {
	return fmt.Sprintf("%d %s", rd.SubType, rd.Hostname)
}
type CertType uint16
const (
	CertReserved0 CertType = iota
	CertPKIX
	CertSPKI
	CertPGP
	CertIPKIX
	CertIPGP
	CertACPKIX
	CertIACPKIX
	CertURI = iota + 244
	CertOID
	CertReserved255
	CertExperimental65280 = 65280
	CertExperimental65534 = 65534
	CertReserved          = 65535
)
type CERT struct {
	Type CertType
	KeyTag uint16
	Algorithm AlgorithmType
	Cert []byte
}
func (rd *CERT) Encode(b *dns.Wirebuf) {
	dns.Octets2(rd.Type).Encode(b)
	dns.Octets2(rd.KeyTag).Encode(b)
	dns.Octet(rd.Algorithm).Encode(b)
	b.Buf = append(b.Buf, rd.Cert...)
}
func (rd *CERT) Decode(b []byte, pos *int, sniffer dns.WireDecodeSniffer) (err error) {
	p0 := &b[*pos]
	if err = (*dns.Octets2)(&rd.Type).Decode(b, pos, sniffer); err != nil {
		return
	}
	if err = (*dns.Octets2)(&rd.KeyTag).Decode(b, pos, sniffer); err != nil {
		return
	}
	if err = (*dns.Octet)(&rd.Algorithm).Decode(b, pos, sniffer); err != nil {
		return
	}
	n := len(b) - *pos
	if n <= 0 {
		return fmt.Errorf("(*CERT).Decode: no certificate data")
	}
	rd.Cert = make([]byte, n)
	copy(rd.Cert, b[*pos:])
	*pos += n
	if sniffer != nil {
		sniffer(p0, &b[*pos-1], dns.SniffRDataCERT, rd)
	}
	return
}
func (rd *CERT) String() string {
	return fmt.Sprintf("%d %d %d %s",
		rd.Type,
		rd.KeyTag,
		rd.Algorithm,
		strutil.Base64Encode(rd.Cert),
	)
}
type CNAME struct {
	Name string
}
func (rd CNAME) Encode(b *dns.Wirebuf) {
	(dns.DomainName)(rd.Name).Encode(b)
}
func (rd *CNAME) Decode(b []byte, pos *int, sniffer dns.WireDecodeSniffer) (err error) {
	p0 := &b[*pos]
	if err = (*dns.DomainName)(&rd.Name).Decode(b, pos, sniffer); err != nil {
		return
	}
	if sniffer != nil {
		sniffer(p0, &b[*pos-1], dns.SniffRDataCNAME, rd)
	}
	return
}
func (rd CNAME) String() string {
	return rd.Name
}
type DHCID struct {
	Data []byte
}
func (rd *DHCID) SetData(identifierType uint16, identifier []byte, fqdn string) {
	w := dns.NewWirebuf()
	w.Buf = identifier
	w.DisableCompression()
	dns.DomainName(dns.RootedName(fqdn)).Encode(w)
	h := sha256.New()
	h.Write(w.Buf)
	rd.Data = h.Sum([]byte{byte(identifierType >> 8), byte(identifierType), 1})
}
func (rd DHCID) Encode(b *dns.Wirebuf) {
	b.Buf = append(b.Buf, rd.Data...)
}
func (rd *DHCID) Decode(b []byte, pos *int, sniffer dns.WireDecodeSniffer) (err error) {
	p0 := &b[*pos]
	n := len(b) - *pos
	if n <= 0 {
		return fmt.Errorf("(*DHCID).Decode: no key data")
	}
	rd.Data = make([]byte, n)
	copy(rd.Data, b[*pos:])
	*pos += n
	if sniffer != nil {
		sniffer(p0, &b[*pos-1], dns.SniffRDataDHCID, rd)
	}
	return
}
func (rd DHCID) String() string {
	return string(strutil.Base64Encode(rd.Data))
}
type DNAME struct {
	Name string
}
func (rd DNAME) Encode(b *dns.Wirebuf) {
	(dns.DomainName)(rd.Name).Encode(b)
}
func (rd *DNAME) Decode(b []byte, pos *int, sniffer dns.WireDecodeSniffer) (err error) {
	p0 := &b[*pos]
	if err = (*dns.DomainName)(&rd.Name).Decode(b, pos, sniffer); err != nil {
		return
	}
	if sniffer != nil {
		sniffer(p0, &b[*pos-1], dns.SniffRDataDNAME, rd)
	}
	return
}
func (rd DNAME) String() string {
	return rd.Name
}
type AlgorithmType byte
const (
	AlgorithmReserved0 AlgorithmType = iota
	AlgorithmRSA_MD5
	AlgorithmDiffie_Hellman
	AlgorithmDSA_SHA1
	AlgorithmElliptic
	AlgorithmRSA_SHA1
	AlgorithmIndirect AlgorithmType = iota + 246  
	AlgorithmPrivateDNS
	AlgorithmPrivateOID
	AlgorithmReserved1255
)
type Class uint16
const (
	CLASS_NONE Class = iota
	CLASS_IN          
	CLASS_CS          
	CLASS_CH          
	CLASS_HS          
)
var classStr = map[Class]string{
	CLASS_NONE: "",
	CLASS_IN:   "IN",
	CLASS_CS:   "CS",
	CLASS_CH:   "CH",
	CLASS_HS:   "HS",
}
func (c Class) String() (s string) {
	var ok bool
	if s, ok = classStr[c]; !ok {
		return fmt.Sprintf("CLASS%d", uint16(c))
	}
	return
}
func (c Class) Encode(b *dns.Wirebuf) {
	dns.Octets2(c).Encode(b)
}
func (c *Class) Decode(b []byte, pos *int, sniffer dns.WireDecodeSniffer) (err error) {
	p0 := &b[*pos]
	if err = (*dns.Octets2)(c).Decode(b, pos, sniffer); err != nil {
		return
	}
	if sniffer != nil {
		sniffer(p0, &b[*pos-1], dns.SniffClass, *c)
	}
	return
}
type DLV struct {
	KeyTag uint16
	Algorithm AlgorithmType
	DigestType HashAlgorithm
	Digest []byte
}
func (rd *DLV) Encode(b *dns.Wirebuf) {
	dns.Octets2(rd.KeyTag).Encode(b)
	dns.Octet(rd.Algorithm).Encode(b)
	dns.Octet(rd.DigestType).Encode(b)
	b.Buf = append(b.Buf, rd.Digest...)
}
func (rd *DLV) Decode(b []byte, pos *int, sniffer dns.WireDecodeSniffer) (err error) {
	p0 := &b[*pos]
	if err = (*dns.Octets2)(&rd.KeyTag).Decode(b, pos, sniffer); err != nil {
		return
	}
	if err = (*dns.Octet)(&rd.Algorithm).Decode(b, pos, sniffer); err != nil {
		return
	}
	if err = (*dns.Octet)(&rd.DigestType).Decode(b, pos, sniffer); err != nil {
		return
	}
	var n int
	switch rd.DigestType {
	case HashAlgorithmSHA1:
		n = 20
	default:
		return fmt.Errorf("unsupported digest type %d", rd.DigestType)
	}
	end := *pos + n
	if end > len(b) {
		return fmt.Errorf("(*rr.DLV).Decode() - buffer underflow")
	}
	rd.Digest = append([]byte{}, b[*pos:end]...)
	*pos = end
	if sniffer != nil {
		sniffer(p0, &b[*pos-1], dns.SniffRDataDLV, rd)
	}
	return
}
func (rd *DLV) String() string {
	if asserts && len(rd.Digest) == 0 {
		panic("internal error")
	}
	return fmt.Sprintf("%d %d %d %s", rd.KeyTag, rd.Algorithm, rd.DigestType, hex.EncodeToString(rd.Digest))
}
type DNSKEY struct {
	Flags uint16
	Protocol byte
	Algorithm AlgorithmType
	Key []byte
}
func NewDNSKEY(Flags uint16, Algorithm AlgorithmType, Key []byte) *DNSKEY {
	return &DNSKEY{Flags, 3, Algorithm, Key}
}
func (rd *DNSKEY) Encode(b *dns.Wirebuf) {
	dns.Octets2(rd.Flags).Encode(b)
	dns.Octet(rd.Protocol).Encode(b)
	dns.Octet(rd.Algorithm).Encode(b)
	b.Buf = append(b.Buf, rd.Key...)
}
func (rd *DNSKEY) Decode(b []byte, pos *int, sniffer dns.WireDecodeSniffer) (err error) {
	p0 := &b[*pos]
	if err = (*dns.Octets2)(&rd.Flags).Decode(b, pos, sniffer); err != nil {
		return
	}
	if err = (*dns.Octet)(&rd.Protocol).Decode(b, pos, sniffer); err != nil {
		return
	}
	if err = (*dns.Octet)(&rd.Algorithm).Decode(b, pos, sniffer); err != nil {
		return
	}
	n := len(b) - *pos
	if n <= 0 {
		return fmt.Errorf("(*DNSKEY).Decode: no key data")
	}
	rd.Key = make([]byte, n)
	copy(rd.Key, b[*pos:])
	*pos += n
	if sniffer != nil {
		sniffer(p0, &b[*pos-1], dns.SniffRDataDNSKEY, rd)
	}
	return
}
func (rd *DNSKEY) String() string {
	return fmt.Sprintf("%d %d %d %s", rd.Flags, rd.Protocol, rd.Algorithm, strutil.Base64Encode(rd.Key))
}
type DS struct {
	KeyTag uint16
	Algorithm AlgorithmType
	DigestType HashAlgorithm
	Digest []byte
}
func (rd *DS) Encode(b *dns.Wirebuf) {
	dns.Octets2(rd.KeyTag).Encode(b)
	dns.Octet(rd.Algorithm).Encode(b)
	dns.Octet(rd.DigestType).Encode(b)
	b.Buf = append(b.Buf, rd.Digest...)
}
func (rd *DS) Decode(b []byte, pos *int, sniffer dns.WireDecodeSniffer) (err error) {
	p0 := &b[*pos]
	if err = (*dns.Octets2)(&rd.KeyTag).Decode(b, pos, sniffer); err != nil {
		return
	}
	if err = (*dns.Octet)(&rd.Algorithm).Decode(b, pos, sniffer); err != nil {
		return
	}
	if err = (*dns.Octet)(&rd.DigestType).Decode(b, pos, sniffer); err != nil {
		return
	}
	var n int
	switch rd.DigestType {
	case HashAlgorithmSHA1:
		n = 20
	default:
		return fmt.Errorf("unsupported digest type %d", rd.DigestType)
	}
	end := *pos + n
	if end > len(b) {
		return fmt.Errorf("(*rr.DS).Decode() - buffer underflow")
	}
	rd.Digest = append([]byte{}, b[*pos:end]...)
	*pos = end
	if sniffer != nil {
		sniffer(p0, &b[*pos-1], dns.SniffRDataDS, rd)
	}
	return
}
func (rd *DS) String() string {
	if asserts && len(rd.Digest) == 0 {
		panic("internal error")
	}
	return fmt.Sprintf("%d %d %d %s", rd.KeyTag, rd.Algorithm, rd.DigestType, hex.EncodeToString(rd.Digest))
}
type ip4 net.IP
func (ip ip4) Encode(b *dns.Wirebuf) {
	b4 := net.IP(ip).To4()
	if asserts {
		if b4 == nil {
			panic(fmt.Errorf("%s is not an IPv4 address", net.IP(ip)))
		}
	}
	b.Buf = append(b.Buf, b4...)
}