func DomainPart(domain string, part int) (string, error) {
	if part == 0 {
		return "", fmt.Errorf("invalid part")
	}
	domain, err := NormaliseDomain(domain)
	if err != nil {
		return "", err
	}
	parts := strings.Split(domain, ".")
	if len(parts) < abs(part) {
		return "", fmt.Errorf("not enough parts")
	}
	if part < 0 {
		return parts[len(parts)+part], nil
	}
	return parts[part-1], nil
}
DomainPart obtains a part of a name
Positive parts start at the lowest-level of the domain and work towards the
top-level domain.  Negative parts start at the top-level domain and work
towards the lowest-level domain.
For example, with a domain bar.foo.com the following parts will be returned:
Number | part
1 |  bar
2 |  foo
3 |  com
-1 |  com
-2 |  foo
-3 |  bar
package ens
import (
	"fmt"
	"strings"
)
func DomainLevel(name string) (level int) {
	return len(strings.Split(name, ".")) - 1
}
func NormaliseDomain(domain string) (string, error) {
	wildcard := false
	if strings.HasPrefix(domain, "*.") {
		wildcard = true
		domain = domain[2:]
	}
	output, err := p.ToUnicode(strings.ToLower(domain))
	if err != nil {
		return "", err
	}
	if strings.HasPrefix(domain, ".") && !strings.HasPrefix(output, ".") {
		output = "." + output
	}
	if wildcard {
		output = "*." + output
	}
	return output, nil
}
func NormaliseDomainStrict(domain string) (string, error) {
	wildcard := false
	if strings.HasPrefix(domain, "*.") {
		wildcard = true
		domain = domain[2:]
	}
	output, err := pStrict.ToUnicode(strings.ToLower(domain))
	if err != nil {
		return "", err
	}
	if strings.HasPrefix(domain, ".") && !strings.HasPrefix(output, ".") {
		output = "." + output
	}
	if wildcard {
		output = "*." + output
	}
	return output, nil
}
func Tld(domain string) string {
	domain, err := NormaliseDomain(domain)
	if err != nil {
		return domain
	}
	tld, err := DomainPart(domain, -1)
	if err != nil {
		return domain
	}
	return tld
}
func Domain(domain string) string {
	if idx := strings.IndexByte(domain, '.'); idx >= 0 {
		return domain[idx+1:]
	}
	return ""
}