From 5d8dbab4c82c251f345dae12ac3480dcac30a62c Mon Sep 17 00:00:00 2001 From: Miek Gieben Date: Tue, 13 Jan 2015 10:20:34 +0000 Subject: [PATCH] Remove the fmt Formatters Formatters are not needs you can access the members just fine. However the rdata Field access function are handy and non-trivial, extend them and add a basic test. --- dns.go | 7 +---- format.go | 75 ++++++++++++++++++++++++++++----------------------- parse_test.go | 22 +++++++++++++-- types.go | 1 + 4 files changed, 64 insertions(+), 41 deletions(-) diff --git a/dns.go b/dns.go index c772f7bc..1ad78b4e 100644 --- a/dns.go +++ b/dns.go @@ -93,10 +93,7 @@ // spaces, semicolons and the at symbol are escaped. package dns -import ( - "fmt" - "strconv" -) +import "strconv" const ( year68 = 1 << 31 // For RFC1982 (Serial Arithmetic) calculations in 32 bits. @@ -123,8 +120,6 @@ type RR interface { Header() *RR_Header // String returns the text representation of the resource record. String() string - // Formatted output - Format(f fmt.State, c rune) // copy returns a copy of the RR copy() RR // len returns the length (in octets) of the uncompressed RR in wire format. diff --git a/format.go b/format.go index 2219618c..4f148b57 100644 --- a/format.go +++ b/format.go @@ -1,34 +1,15 @@ -// FORMAT -// -// The dns package implements String() for all RR types, but sometimes you will -// need more flexibility. Here we define an extra set of formatting verbs that -// can be used in the formatted I/O package fmt. -// -// Printing -// -// The verbs: -// -// Generic parts of RRs: -// -// %N the owner name of the RR -// %C the class: IN, CH, CLASS15, etc. -// %D the TTL in seconds -// %Y the type: MX, A, etc. -// -// The rdata of each RR differs, we allow each field to be accessed as a string with -// the Field function. -// package dns import ( - "fmt" "net" "reflect" "strconv" ) // Field returns the rdata field i as a string. Fields are indexed starting from 1. -// Non existing fields will return the empty string. +// Non existing fields will return the empty string. RR types that holds slice data, +// for instance the NSEC type bitmap will return a single string where the types +// are concatenated using a space. func Field(r RR, i int) string { if i == 0 { return "" @@ -44,15 +25,17 @@ func Field(r RR, i int) string { case reflect.Slice: switch reflect.ValueOf(r).Elem().Type().Field(i).Tag { case `dns:"a"`: - // println(d.Len()), Hmm store this as 16 bytes + // TODO(miek): We hmm store this as 16 bytes if d.Len() < net.IPv6len { - return "" + return net.IPv4(byte(d.Index(0).Uint()), + byte(d.Index(1).Uint()), + byte(d.Index(2).Uint()), + byte(d.Index(3).Uint())).String() } - ip := net.IPv4(byte(d.Index(12).Uint()), + return net.IPv4(byte(d.Index(12).Uint()), byte(d.Index(13).Uint()), byte(d.Index(14).Uint()), - byte(d.Index(15).Uint())) - return ip.String() + byte(d.Index(15).Uint())).String() case `dns:"aaaa"`: return net.IP{ byte(d.Index(0).Uint()), @@ -72,13 +55,38 @@ func Field(r RR, i int) string { byte(d.Index(14).Uint()), byte(d.Index(15).Uint()), }.String() - // []uint16 (nsec,wks) - // []string + case `dns:"nsec"`: + if d.Len() == 0 { + return "" + } + s := Type(d.Index(0).Uint()).String() + for i := 1; i < d.Len(); i++ { + s += " " + Type(d.Index(i).Uint()).String() + } + return s + case `dns:"wks"`: + if d.Len() == 0 { + return "" + } + s := strconv.Itoa(int(d.Index(0).Uint())) + for i := 0; i < d.Len(); i++ { + s += " " + strconv.Itoa(int(d.Index(i).Uint())) + } + return s + default: + // if it does not have a tag its a string slice + fallthrough + case `dns:"txt"`: + if d.Len() == 0 { + return "" + } + s := d.Index(0).String() + for i := 1; i < d.Len(); i++ { + s += " " + d.Index(i).String() + } + return s } - default: - println("dns: unknown field kind", k.String()) } - return "" } @@ -87,6 +95,7 @@ func NumField(r RR) int { return reflect.ValueOf(r).Elem().NumField() - 1 // Remove RR_Header } +/* func format(r RR, f fmt.State, c rune) { switch c { case 'N': @@ -118,7 +127,6 @@ func format_Header(h *RR_Header, f fmt.State, c rune) { case 's': f.Write([]byte(h.String())) default: - println(string(c)) f.Write([]byte("TODO")) } } @@ -198,3 +206,4 @@ func (rr *UINFO) Format(f fmt.State, c rune) { format(rr, f, c) } func (rr *URI) Format(f fmt.State, c rune) { format(rr, f, c) } func (rr *WKS) Format(f fmt.State, c rune) { format(rr, f, c) } func (rr *X25) Format(f fmt.State, c rune) { format(rr, f, c) } +*/ diff --git a/parse_test.go b/parse_test.go index 0f9bbae6..e189ede2 100644 --- a/parse_test.go +++ b/parse_test.go @@ -1375,9 +1375,27 @@ func TestPrintfVerbsRdata(t *testing.T) { if Field(x, 2) != "mx.miek.nl." { t.Errorf("should be mx.miek.nl.") } + x, _ = NewRR("www.miek.nl. IN A 127.0.0.1") - println(Field(x, 1)) + if Field(x, 1) != "127.0.0.1" { + t.Errorf("should be 127.0.0.1") + } x, _ = NewRR("www.miek.nl. IN AAAA ::1") - println(Field(x, 1)) + if Field(x, 1) != "::1" { + t.Errorf("should be ::1") + } + + x, _ = NewRR("www.miek.nl. IN NSEC a.miek.nl. A NS SOA MX AAAA") + if Field(x, 1) != "a.miek.nl." { + t.Errorf("should be a.miek.nl.") + } + if Field(x, 2) != "A NS SOA MX AAAA" { + t.Errorf("should be A NS SOA MX AAAA") + } + + x, _ = NewRR("www.miek.nl. IN TXT \"first\" \"second\"") + if Field(x, 1) != "first second" { + t.Errorf("should be first second") + } } diff --git a/types.go b/types.go index 16bb181b..02658533 100644 --- a/types.go +++ b/types.go @@ -1394,6 +1394,7 @@ func (rr *WKS) String() (s string) { if rr.Address != nil { s += rr.Address.String() } + // TODO(miek): missing protocol here. for i := 0; i < len(rr.BitMap); i++ { // should lookup the port s += " " + strconv.Itoa(int(rr.BitMap[i]))