func next(b []rune, boundary rune) rune {
	if len(b) == 0 {
		panic("dns: invalid set of runes to determine next one")
	}
	m := b[0]
	for _, x := range b[1:] {
		if x >= boundary && (m < boundary || x < m) {
			m = x
		}
	}
	return m
}
next finds minimal rune (one with lowest codepoint value) that should be equal or above boundary.
package idn
import (
	"bytes"
	"strings"
	"unicode"
	"unicode/utf8"
	"github.com/miekg/dns"
)
const (
	_MIN  rune = 1
	_MAX  rune = 26
	_SKEW rune = 38
	_BASE rune = 36
	_BIAS rune = 72
	_N    rune = 128
	_DAMP rune = 700
	_DELIMITER = '-'
	_PREFIX    = "xn--"
)
func ToPunycode(s string) string {
	if !needToPunycode(s) {
		return s
	}
	tokens := dns.SplitDomainName(s)
	switch {
	case s == "":
		return ""
	case tokens == nil:  
		return "."
	case s[len(s)-1] == '.':
		tokens = append(tokens, "")
	}
	for i := range tokens {
		t := encode([]byte(tokens[i]))
		if t == nil {
			return ""
		}
		tokens[i] = string(t)
	}
	return strings.Join(tokens, ".")
}
func FromPunycode(s string) string {
	if !needFromPunycode(s) {
		return s
	}
	tokens := dns.SplitDomainName(s)
	switch {
	case s == "":
		return ""
	case tokens == nil:  
		return "."
	case s[len(s)-1] == '.':
		tokens = append(tokens, "")
	}
	for i := range tokens {
		tokens[i] = string(decode([]byte(tokens[i])))
	}
	return strings.Join(tokens, ".")
}
const errdigit = 0xffff
func digitval(code rune) rune {
	switch {
	case code >= 'A' && code <= 'Z':
		return code - 'A'
	case code >= 'a' && code <= 'z':
		return code - 'a'
	case code >= '0' && code <= '9':
		return code - '0' + 26
	}
	return errdigit
}
func lettercode(digit rune) rune {
	switch {
	case digit >= 0 && digit <= 25:
		return digit + 'a'
	case digit >= 26 && digit <= 36:
		return digit - 26 + '0'
	}
	panic("dns: not reached")
}
func adapt(delta rune, numpoints int, firsttime bool) rune {
	if firsttime {
		delta /= _DAMP
	} else {
		delta /= 2
	}
	var k rune
	for delta = delta + delta/rune(numpoints); delta > (_BASE-_MIN)*_MAX/2; k += _BASE {
		delta /= _BASE - _MIN
	}
	return k + ((_BASE-_MIN+1)*delta)/(delta+_SKEW)
}