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.
This commit is contained in:
Miek Gieben 2015-01-13 10:20:34 +00:00
parent 9c3a117004
commit 5d8dbab4c8
4 changed files with 64 additions and 41 deletions

7
dns.go
View File

@ -93,10 +93,7 @@
// spaces, semicolons and the at symbol are escaped. // spaces, semicolons and the at symbol are escaped.
package dns package dns
import ( import "strconv"
"fmt"
"strconv"
)
const ( const (
year68 = 1 << 31 // For RFC1982 (Serial Arithmetic) calculations in 32 bits. year68 = 1 << 31 // For RFC1982 (Serial Arithmetic) calculations in 32 bits.
@ -123,8 +120,6 @@ type RR interface {
Header() *RR_Header Header() *RR_Header
// String returns the text representation of the resource record. // String returns the text representation of the resource record.
String() string String() string
// Formatted output
Format(f fmt.State, c rune)
// copy returns a copy of the RR // copy returns a copy of the RR
copy() RR copy() RR
// len returns the length (in octets) of the uncompressed RR in wire format. // len returns the length (in octets) of the uncompressed RR in wire format.

View File

@ -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 package dns
import ( import (
"fmt"
"net" "net"
"reflect" "reflect"
"strconv" "strconv"
) )
// Field returns the rdata field i as a string. Fields are indexed starting from 1. // 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 { func Field(r RR, i int) string {
if i == 0 { if i == 0 {
return "" return ""
@ -44,15 +25,17 @@ func Field(r RR, i int) string {
case reflect.Slice: case reflect.Slice:
switch reflect.ValueOf(r).Elem().Type().Field(i).Tag { switch reflect.ValueOf(r).Elem().Type().Field(i).Tag {
case `dns:"a"`: 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 { 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(13).Uint()),
byte(d.Index(14).Uint()), byte(d.Index(14).Uint()),
byte(d.Index(15).Uint())) byte(d.Index(15).Uint())).String()
return ip.String()
case `dns:"aaaa"`: case `dns:"aaaa"`:
return net.IP{ return net.IP{
byte(d.Index(0).Uint()), byte(d.Index(0).Uint()),
@ -72,13 +55,38 @@ func Field(r RR, i int) string {
byte(d.Index(14).Uint()), byte(d.Index(14).Uint()),
byte(d.Index(15).Uint()), byte(d.Index(15).Uint()),
}.String() }.String()
// []uint16 (nsec,wks) case `dns:"nsec"`:
// []string 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 "" return ""
} }
@ -87,6 +95,7 @@ func NumField(r RR) int {
return reflect.ValueOf(r).Elem().NumField() - 1 // Remove RR_Header return reflect.ValueOf(r).Elem().NumField() - 1 // Remove RR_Header
} }
/*
func format(r RR, f fmt.State, c rune) { func format(r RR, f fmt.State, c rune) {
switch c { switch c {
case 'N': case 'N':
@ -118,7 +127,6 @@ func format_Header(h *RR_Header, f fmt.State, c rune) {
case 's': case 's':
f.Write([]byte(h.String())) f.Write([]byte(h.String()))
default: default:
println(string(c))
f.Write([]byte("TODO")) 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 *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 *WKS) Format(f fmt.State, c rune) { format(rr, f, c) }
func (rr *X25) Format(f fmt.State, c rune) { format(rr, f, c) } func (rr *X25) Format(f fmt.State, c rune) { format(rr, f, c) }
*/

View File

@ -1375,9 +1375,27 @@ func TestPrintfVerbsRdata(t *testing.T) {
if Field(x, 2) != "mx.miek.nl." { if Field(x, 2) != "mx.miek.nl." {
t.Errorf("should be mx.miek.nl.") t.Errorf("should be mx.miek.nl.")
} }
x, _ = NewRR("www.miek.nl. IN A 127.0.0.1") 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") 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")
}
} }

View File

@ -1394,6 +1394,7 @@ func (rr *WKS) String() (s string) {
if rr.Address != nil { if rr.Address != nil {
s += rr.Address.String() s += rr.Address.String()
} }
// TODO(miek): missing protocol here.
for i := 0; i < len(rr.BitMap); i++ { for i := 0; i < len(rr.BitMap); i++ {
// should lookup the port // should lookup the port
s += " " + strconv.Itoa(int(rr.BitMap[i])) s += " " + strconv.Itoa(int(rr.BitMap[i]))