3 // Dedup removes identical RRs from rrs. It preserves the original ordering.
4 // The lowest TTL of any duplicates is used in the remaining one. Dedup modifies
6 // m is used to store the RRs temporary. If it is nil a new map will be allocated.
7 func Dedup(rrs []RR, m map[string]RR) []RR {
10 m = make(map[string]RR)
12 // Save the keys, so we don't have to call normalizedString twice.
13 keys := make([]*string, 0, len(rrs))
15 for _, r := range rrs {
16 key := normalizedString(r)
17 keys = append(keys, &key)
18 if mr, ok := m[key]; ok {
20 rh, mrh := r.Header(), mr.Header()
29 // If the length of the result map equals the amount of RRs we got,
30 // it means they were all different. We can then just return the original rrset.
31 if len(m) == len(rrs) {
36 for i, r := range rrs {
37 // If keys[i] lives in the map, we should copy and remove it.
38 if _, ok := m[*keys[i]]; ok {
52 // normalizedString returns a normalized string from r. The TTL
53 // is removed and the domain name is lowercased. We go from this:
54 // DomainName<TAB>TTL<TAB>CLASS<TAB>TYPE<TAB>RDATA to:
55 // lowercasename<TAB>CLASS<TAB>TYPE...
56 func normalizedString(r RR) string {
57 // A string Go DNS makes has: domainname<TAB>TTL<TAB>...
58 b := []byte(r.String())
60 // find the first non-escaped tab, then another, so we capture where the TTL lives.
62 ttlStart, ttlEnd := 0, 0
63 for i := 0; i < len(b) && ttlEnd == 0; i++ {
67 case b[i] == '\t' && !esc:
75 case b[i] >= 'A' && b[i] <= 'Z' && !esc:
83 copy(b[ttlStart:], b[ttlEnd:])
84 cut := ttlEnd - ttlStart
85 return string(b[:len(b)-cut])