package dns

import (
	
	
	
	
	
	
	
)

// helper functions called from the generated zmsg.go

// These function are named after the tag to help pack/unpack, if there is no tag it is the name
// of the type they pack/unpack (string, int, etc). We prefix all with unpackData or packData, so packDataA or
// packDataDomainName.

func unpackDataA( []byte,  int) (net.IP, int, error) {
	if +net.IPv4len > len() {
		return nil, len(), &Error{err: "overflow unpacking a"}
	}
	return cloneSlice([ : +net.IPv4len]),  + net.IPv4len, nil
}

func packDataA( net.IP,  []byte,  int) (int, error) {
	switch len() {
	case net.IPv4len, net.IPv6len:
		// It must be a slice of 4, even if it is 16, we encode only the first 4
		if +net.IPv4len > len() {
			return len(), &Error{err: "overflow packing a"}
		}

		copy([:], .To4())
		 += net.IPv4len
	case 0:
		// Allowed, for dynamic updates.
	default:
		return len(), &Error{err: "overflow packing a"}
	}
	return , nil
}

func unpackDataAAAA( []byte,  int) (net.IP, int, error) {
	if +net.IPv6len > len() {
		return nil, len(), &Error{err: "overflow unpacking aaaa"}
	}
	return cloneSlice([ : +net.IPv6len]),  + net.IPv6len, nil
}

func packDataAAAA( net.IP,  []byte,  int) (int, error) {
	switch len() {
	case net.IPv6len:
		if +net.IPv6len > len() {
			return len(), &Error{err: "overflow packing aaaa"}
		}

		copy([:], )
		 += net.IPv6len
	case 0:
		// Allowed, dynamic updates.
	default:
		return len(), &Error{err: "overflow packing aaaa"}
	}
	return , nil
}

// unpackHeader unpacks an RR header, returning the offset to the end of the header and a
// re-sliced msg according to the expected length of the RR.
func unpackHeader( []byte,  int) ( RR_Header,  int,  []byte,  error) {
	 := RR_Header{}
	if  == len() {
		return , , , nil
	}

	.Name, ,  = UnpackDomainName(, )
	if  != nil {
		return , len(), , 
	}
	.Rrtype, ,  = unpackUint16(, )
	if  != nil {
		return , len(), , 
	}
	.Class, ,  = unpackUint16(, )
	if  != nil {
		return , len(), , 
	}
	.Ttl, ,  = unpackUint32(, )
	if  != nil {
		return , len(), , 
	}
	.Rdlength, ,  = unpackUint16(, )
	if  != nil {
		return , len(), , 
	}
	,  = truncateMsgFromRdlength(, , .Rdlength)
	return , , , 
}

// packHeader packs an RR header, returning the offset to the end of the header.
// See PackDomainName for documentation about the compression.
func ( RR_Header) ( []byte,  int,  compressionMap,  bool) (int, error) {
	if  == len() {
		return , nil
	}

	,  := packDomainName(.Name, , , , )
	if  != nil {
		return len(), 
	}
	,  = packUint16(.Rrtype, , )
	if  != nil {
		return len(), 
	}
	,  = packUint16(.Class, , )
	if  != nil {
		return len(), 
	}
	,  = packUint32(.Ttl, , )
	if  != nil {
		return len(), 
	}
	,  = packUint16(0, , ) // The RDLENGTH field will be set later in packRR.
	if  != nil {
		return len(), 
	}
	return , nil
}

// helper helper functions.

// truncateMsgFromRdLength truncates msg to match the expected length of the RR.
// Returns an error if msg is smaller than the expected size.
func truncateMsgFromRdlength( []byte,  int,  uint16) ( []byte,  error) {
	 :=  + int()
	if  > len() {
		return , &Error{err: "overflowing header size"}
	}
	return [:], nil
}

var base32HexNoPadEncoding = base32.HexEncoding.WithPadding(base32.NoPadding)

func fromBase32( []byte) ( []byte,  error) {
	for ,  := range  {
		if  >= 'a' &&  <= 'z' {
			[] =  - 32
		}
	}
	 := base32HexNoPadEncoding.DecodedLen(len())
	 = make([]byte, )
	,  := base32HexNoPadEncoding.Decode(, )
	 = [:]
	return
}

func toBase32( []byte) string {
	return base32HexNoPadEncoding.EncodeToString()
}

func fromBase64( []byte) ( []byte,  error) {
	 := base64.StdEncoding.DecodedLen(len())
	 = make([]byte, )
	,  := base64.StdEncoding.Decode(, )
	 = [:]
	return
}

func toBase64( []byte) string { return base64.StdEncoding.EncodeToString() }

// dynamicUpdate returns true if the Rdlength is zero.
func noRdata( RR_Header) bool { return .Rdlength == 0 }

func unpackUint8( []byte,  int) ( uint8,  int,  error) {
	if +1 > len() {
		return 0, len(), &Error{err: "overflow unpacking uint8"}
	}
	return [],  + 1, nil
}

func packUint8( uint8,  []byte,  int) ( int,  error) {
	if +1 > len() {
		return len(), &Error{err: "overflow packing uint8"}
	}
	[] = 
	return  + 1, nil
}

func unpackUint16( []byte,  int) ( uint16,  int,  error) {
	if +2 > len() {
		return 0, len(), &Error{err: "overflow unpacking uint16"}
	}
	return binary.BigEndian.Uint16([:]),  + 2, nil
}

func packUint16( uint16,  []byte,  int) ( int,  error) {
	if +2 > len() {
		return len(), &Error{err: "overflow packing uint16"}
	}
	binary.BigEndian.PutUint16([:], )
	return  + 2, nil
}

func unpackUint32( []byte,  int) ( uint32,  int,  error) {
	if +4 > len() {
		return 0, len(), &Error{err: "overflow unpacking uint32"}
	}
	return binary.BigEndian.Uint32([:]),  + 4, nil
}

func packUint32( uint32,  []byte,  int) ( int,  error) {
	if +4 > len() {
		return len(), &Error{err: "overflow packing uint32"}
	}
	binary.BigEndian.PutUint32([:], )
	return  + 4, nil
}

func unpackUint48( []byte,  int) ( uint64,  int,  error) {
	if +6 > len() {
		return 0, len(), &Error{err: "overflow unpacking uint64 as uint48"}
	}
	// Used in TSIG where the last 48 bits are occupied, so for now, assume a uint48 (6 bytes)
	 = uint64([])<<40 | uint64([+1])<<32 | uint64([+2])<<24 | uint64([+3])<<16 |
		uint64([+4])<<8 | uint64([+5])
	 += 6
	return , , nil
}

func packUint48( uint64,  []byte,  int) ( int,  error) {
	if +6 > len() {
		return len(), &Error{err: "overflow packing uint64 as uint48"}
	}
	[] = byte( >> 40)
	[+1] = byte( >> 32)
	[+2] = byte( >> 24)
	[+3] = byte( >> 16)
	[+4] = byte( >> 8)
	[+5] = byte()
	 += 6
	return , nil
}

func unpackUint64( []byte,  int) ( uint64,  int,  error) {
	if +8 > len() {
		return 0, len(), &Error{err: "overflow unpacking uint64"}
	}
	return binary.BigEndian.Uint64([:]),  + 8, nil
}

func packUint64( uint64,  []byte,  int) ( int,  error) {
	if +8 > len() {
		return len(), &Error{err: "overflow packing uint64"}
	}
	binary.BigEndian.PutUint64([:], )
	 += 8
	return , nil
}

func unpackString( []byte,  int) (string, int, error) {
	if +1 > len() {
		return "", , &Error{err: "overflow unpacking txt"}
	}
	 := int([])
	++
	if + > len() {
		return "", , &Error{err: "overflow unpacking txt"}
	}
	var  strings.Builder
	 := 0
	for ,  := range [ : +] {
		switch {
		case  == '"' ||  == '\\':
			if  == 0 {
				.Grow( * 2)
			}
			.Write([+ : +])
			.WriteByte('\\')
			.WriteByte()
			 =  + 1
		case  < ' ' ||  > '~': // unprintable
			if  == 0 {
				.Grow( * 2)
			}
			.Write([+ : +])
			.WriteString(escapeByte())
			 =  + 1
		}
	}
	if  == 0 { // no escaping needed
		return string([ : +]),  + , nil
	}
	.Write([+ : +])
	return .String(),  + , nil
}

func packString( string,  []byte,  int) (int, error) {
	,  := packTxtString(, , )
	if  != nil {
		return len(), 
	}
	return , nil
}

func unpackStringBase32( []byte, ,  int) (string, int, error) {
	if  > len() {
		return "", len(), &Error{err: "overflow unpacking base32"}
	}
	 := toBase32([:])
	return , , nil
}

func packStringBase32( string,  []byte,  int) (int, error) {
	,  := fromBase32([]byte())
	if  != nil {
		return len(), 
	}
	if +len() > len() {
		return len(), &Error{err: "overflow packing base32"}
	}
	copy([:+len()], )
	 += len()
	return , nil
}

func unpackStringBase64( []byte, ,  int) (string, int, error) {
	// Rest of the RR is base64 encoded value, so we don't need an explicit length
	// to be set. Thus far all RR's that have base64 encoded fields have those as their
	// last one. What we do need is the end of the RR!
	if  > len() {
		return "", len(), &Error{err: "overflow unpacking base64"}
	}
	 := toBase64([:])
	return , , nil
}

func packStringBase64( string,  []byte,  int) (int, error) {
	,  := fromBase64([]byte())
	if  != nil {
		return len(), 
	}
	if +len() > len() {
		return len(), &Error{err: "overflow packing base64"}
	}
	copy([:+len()], )
	 += len()
	return , nil
}

func unpackStringHex( []byte, ,  int) (string, int, error) {
	// Rest of the RR is hex encoded value, so we don't need an explicit length
	// to be set. NSEC and TSIG have hex fields with a length field.
	// What we do need is the end of the RR!
	if  > len() {
		return "", len(), &Error{err: "overflow unpacking hex"}
	}

	 := hex.EncodeToString([:])
	return , , nil
}

func packStringHex( string,  []byte,  int) (int, error) {
	,  := hex.DecodeString()
	if  != nil {
		return len(), 
	}
	if +len() > len() {
		return len(), &Error{err: "overflow packing hex"}
	}
	copy([:+len()], )
	 += len()
	return , nil
}

func unpackStringAny( []byte, ,  int) (string, int, error) {
	if  > len() {
		return "", len(), &Error{err: "overflow unpacking anything"}
	}
	return string([:]), , nil
}

func packStringAny( string,  []byte,  int) (int, error) {
	if +len() > len() {
		return len(), &Error{err: "overflow packing anything"}
	}
	copy([:+len()], )
	 += len()
	return , nil
}

func unpackStringTxt( []byte,  int) ([]string, int, error) {
	, ,  := unpackTxt(, )
	if  != nil {
		return nil, len(), 
	}
	return , , nil
}

func packStringTxt( []string,  []byte,  int) (int, error) {
	,  := packTxt(, , )
	if  != nil {
		return len(), 
	}
	return , nil
}

func unpackDataOpt( []byte,  int) ([]EDNS0, int, error) {
	var  []EDNS0
	for  < len() {
		if +4 > len() {
			return nil, len(), &Error{err: "overflow unpacking opt"}
		}
		 := binary.BigEndian.Uint16([:])
		 += 2
		 := binary.BigEndian.Uint16([:])
		 += 2
		if +int() > len() {
			return nil, len(), &Error{err: "overflow unpacking opt"}
		}
		 := makeDataOpt()
		if  := .unpack([ : +int()]);  != nil {
			return nil, len(), 
		}
		 = append(, )
		 += int()
	}
	return , , nil
}

func packDataOpt( []EDNS0,  []byte,  int) (int, error) {
	for ,  := range  {
		,  := .pack()
		if  != nil || +4 > len() {
			return len(), &Error{err: "overflow packing opt"}
		}
		binary.BigEndian.PutUint16([:], .Option())      // Option code
		binary.BigEndian.PutUint16([+2:], uint16(len())) // Length
		 += 4
		if +len() > len() {
			return len(), &Error{err: "overflow packing opt"}
		}
		// Actual data
		copy([:+len()], )
		 += len()
	}
	return , nil
}

func unpackStringOctet( []byte,  int) (string, int, error) {
	 := string([:])
	return , len(), nil
}

func packStringOctet( string,  []byte,  int) (int, error) {
	,  := packOctetString(, , )
	if  != nil {
		return len(), 
	}
	return , nil
}

func unpackDataNsec( []byte,  int) ([]uint16, int, error) {
	var  []uint16
	, ,  := 0, 0, -1
	for  < len() {
		if +2 > len() {
			return , len(), &Error{err: "overflow unpacking NSEC(3)"}
		}
		 = int([])
		 = int([+1])
		 += 2
		if  <=  {
			// RFC 4034: Blocks are present in the NSEC RR RDATA in
			// increasing numerical order.
			return , len(), &Error{err: "out of order NSEC(3) block in type bitmap"}
		}
		if  == 0 {
			// RFC 4034: Blocks with no types present MUST NOT be included.
			return , len(), &Error{err: "empty NSEC(3) block in type bitmap"}
		}
		if  > 32 {
			return , len(), &Error{err: "NSEC(3) block too long in type bitmap"}
		}
		if + > len() {
			return , len(), &Error{err: "overflowing NSEC(3) block in type bitmap"}
		}

		// Walk the bytes in the window and extract the type bits
		for ,  := range [ : +] {
			// Check the bits one by one, and set the type
			if &0x80 == 0x80 {
				 = append(, uint16(*256+*8+0))
			}
			if &0x40 == 0x40 {
				 = append(, uint16(*256+*8+1))
			}
			if &0x20 == 0x20 {
				 = append(, uint16(*256+*8+2))
			}
			if &0x10 == 0x10 {
				 = append(, uint16(*256+*8+3))
			}
			if &0x8 == 0x8 {
				 = append(, uint16(*256+*8+4))
			}
			if &0x4 == 0x4 {
				 = append(, uint16(*256+*8+5))
			}
			if &0x2 == 0x2 {
				 = append(, uint16(*256+*8+6))
			}
			if &0x1 == 0x1 {
				 = append(, uint16(*256+*8+7))
			}
		}
		 += 
		 = 
	}
	return , , nil
}

// typeBitMapLen is a helper function which computes the "maximum" length of
// a the NSEC Type BitMap field.
func typeBitMapLen( []uint16) int {
	var  int
	var ,  uint16
	for ,  := range  {
		 :=  / 256
		 := (-*256)/8 + 1
		if  >  &&  != 0 { // New window, jump to the new offset
			 += int() + 2
			 = 0
		}
		if  <  ||  <  {
			// packDataNsec would return Error{err: "nsec bits out of order"} here, but
			// when computing the length, we want do be liberal.
			continue
		}
		,  = , 
	}
	 += int() + 2
	return 
}

func packDataNsec( []uint16,  []byte,  int) (int, error) {
	if len() == 0 {
		return , nil
	}
	if  > len() {
		return , &Error{err: "overflow packing nsec"}
	}
	 := [:]
	if  := typeBitMapLen();  < len() {
		 = [:]
	}
	for  := range  {
		[] = 0
	}
	var ,  uint16
	for ,  := range  {
		 :=  / 256
		 := (-*256)/8 + 1
		if  >  &&  != 0 { // New window, jump to the new offset
			 += int() + 2
			 = 0
		}
		if  <  ||  <  {
			return len(), &Error{err: "nsec bits out of order"}
		}
		if +2+int() > len() {
			return len(), &Error{err: "overflow packing nsec"}
		}
		// Setting the window #
		[] = byte()
		// Setting the octets length
		[+1] = byte()
		// Setting the bit value for the type in the right octet
		[+1+int()] |= byte(1 << (7 - %8))
		,  = , 
	}
	 += int() + 2
	return , nil
}

func unpackDataSVCB( []byte,  int) ([]SVCBKeyValue, int, error) {
	var  []SVCBKeyValue
	var  uint16
	var  uint16
	var  error
	for  < len() {
		, ,  = unpackUint16(, )
		if  != nil {
			return nil, len(), &Error{err: "overflow unpacking SVCB"}
		}
		, ,  = unpackUint16(, )
		if  != nil || +int() > len() {
			return nil, len(), &Error{err: "overflow unpacking SVCB"}
		}
		 := makeSVCBKeyValue(SVCBKey())
		if  == nil {
			return nil, len(), &Error{err: "bad SVCB key"}
		}
		if  := .unpack([ : +int()]);  != nil {
			return nil, len(), 
		}
		if len() > 0 && .Key() <= [len()-1].Key() {
			return nil, len(), &Error{err: "SVCB keys not in strictly increasing order"}
		}
		 = append(, )
		 += int()
	}
	return , , nil
}

func packDataSVCB( []SVCBKeyValue,  []byte,  int) (int, error) {
	 = cloneSlice()
	sort.Slice(, func(,  int) bool {
		return [].Key() < [].Key()
	})
	 := svcb_RESERVED
	for ,  := range  {
		if .Key() ==  {
			return len(), &Error{err: "repeated SVCB keys are not allowed"}
		}
		 = .Key()
		,  := .pack()
		if  != nil {
			return len(), 
		}
		,  = packUint16(uint16(.Key()), , )
		if  != nil {
			return len(), &Error{err: "overflow packing SVCB"}
		}
		,  = packUint16(uint16(len()), , )
		if  != nil || +len() > len() {
			return len(), &Error{err: "overflow packing SVCB"}
		}
		copy([:+len()], )
		 += len()
	}
	return , nil
}

func unpackDataDomainNames( []byte, ,  int) ([]string, int, error) {
	var (
		 []string
		       string
		     error
	)
	if  > len() {
		return nil, len(), &Error{err: "overflow unpacking domain names"}
	}
	for  <  {
		, ,  = UnpackDomainName(, )
		if  != nil {
			return , len(), 
		}
		 = append(, )
	}
	return , , nil
}

func packDataDomainNames( []string,  []byte,  int,  compressionMap,  bool) (int, error) {
	var  error
	for ,  := range  {
		,  = packDomainName(, , , , )
		if  != nil {
			return len(), 
		}
	}
	return , nil
}

func packDataApl( []APLPrefix,  []byte,  int) (int, error) {
	var  error
	for  := range  {
		,  = packDataAplPrefix(&[], , )
		if  != nil {
			return len(), 
		}
	}
	return , nil
}

func packDataAplPrefix( *APLPrefix,  []byte,  int) (int, error) {
	if len(.Network.IP) != len(.Network.Mask) {
		return len(), &Error{err: "address and mask lengths don't match"}
	}

	var  error
	,  := .Network.Mask.Size()
	 := .Network.IP.Mask(.Network.Mask)[:(+7)/8]

	switch len(.Network.IP) {
	case net.IPv4len:
		,  = packUint16(1, , )
	case net.IPv6len:
		,  = packUint16(2, , )
	default:
		 = &Error{err: "unrecognized address family"}
	}
	if  != nil {
		return len(), 
	}

	,  = packUint8(uint8(), , )
	if  != nil {
		return len(), 
	}

	var  uint8
	if .Negation {
		 = 0x80
	}

	// trim trailing zero bytes as specified in RFC3123 Sections 4.1 and 4.2.
	 := len() - 1
	for ;  >= 0 && [] == 0; -- {
	}
	 = [:+1]

	 := uint8(len()) & 0x7f
	,  = packUint8(|, , )
	if  != nil {
		return len(), 
	}

	if +len() > len() {
		return len(), &Error{err: "overflow packing APL prefix"}
	}
	 += copy([:], )

	return , nil
}

func unpackDataApl( []byte,  int) ([]APLPrefix, int, error) {
	var  []APLPrefix
	for  < len() {
		, ,  := unpackDataAplPrefix(, )
		if  != nil {
			return nil, len(), 
		}
		 = 
		 = append(, )
	}
	return , , nil
}

func unpackDataAplPrefix( []byte,  int) (APLPrefix, int, error) {
	, ,  := unpackUint16(, )
	if  != nil {
		return APLPrefix{}, len(), &Error{err: "overflow unpacking APL prefix"}
	}
	, ,  := unpackUint8(, )
	if  != nil {
		return APLPrefix{}, len(), &Error{err: "overflow unpacking APL prefix"}
	}
	, ,  := unpackUint8(, )
	if  != nil {
		return APLPrefix{}, len(), &Error{err: "overflow unpacking APL prefix"}
	}

	var  []byte
	switch  {
	case 1:
		 = make([]byte, net.IPv4len)
	case 2:
		 = make([]byte, net.IPv6len)
	default:
		return APLPrefix{}, len(), &Error{err: "unrecognized APL address family"}
	}
	if int() > 8*len() {
		return APLPrefix{}, len(), &Error{err: "APL prefix too long"}
	}
	 := int( & 0x7f)
	if  > len() {
		return APLPrefix{}, len(), &Error{err: "APL length too long"}
	}
	if + > len() {
		return APLPrefix{}, len(), &Error{err: "overflow unpacking APL address"}
	}

	// Address MUST NOT contain trailing zero bytes per RFC3123 Sections 4.1 and 4.2.
	 += copy(, [:+])
	if  > 0 {
		 := [-1]
		if  == 0 {
			return APLPrefix{}, len(), &Error{err: "extra APL address bits"}
		}
	}
	 := net.IPNet{
		IP:   ,
		Mask: net.CIDRMask(int(), 8*len()),
	}

	return APLPrefix{
		Negation: ( & 0x80) != 0,
		Network:  ,
	}, , nil
}

func unpackIPSECGateway( []byte,  int,  uint8) (net.IP, string, int, error) {
	var  net.IP
	var  string
	var  error

	switch  {
	case IPSECGatewayNone: // do nothing
	case IPSECGatewayIPv4:
		, ,  = unpackDataA(, )
	case IPSECGatewayIPv6:
		, ,  = unpackDataAAAA(, )
	case IPSECGatewayHost:
		, ,  = UnpackDomainName(, )
	}

	return , , , 
}

func packIPSECGateway( net.IP,  string,  []byte,  int,  uint8,  compressionMap,  bool) (int, error) {
	var  error

	switch  {
	case IPSECGatewayNone: // do nothing
	case IPSECGatewayIPv4:
		,  = packDataA(, , )
	case IPSECGatewayIPv6:
		,  = packDataAAAA(, , )
	case IPSECGatewayHost:
		,  = packDomainName(, , , , )
	}

	return , 
}