diff --git a/format.go b/format.go index 12bc4f76..24f36e7b 100644 --- a/format.go +++ b/format.go @@ -15,26 +15,39 @@ // %D the TTL in seconds // %Y the type: MX, A, etc. // -// The rdata of each RR differs, we allow each field to be printed as a string. -// -// Rdata: (TODO) -// -// %0 the first rdata field -// %1 the second rdata field -// %2 the third rdata field -// .. ... -// %9 the nineth rdata field -// %R all rdata fields -// -// Non exsiting rdata fields will be printed as the empty string. +// The rdata of each RR differs, we allow each field to be accessed as a string with +// the Field function. // package dns import ( "fmt" + "reflect" "strconv" ) +// Field returns the rdata field i as a string. Fields are indexed starting from 1. +func Field(r RR, i int) string { + if i == 0 { + return "" + } + d := reflect.ValueOf(r).Elem().Field(i) + switch d.Kind() { + case reflect.String: + return d.String() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return strconv.FormatInt(d.Int(), 10) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return strconv.FormatUint(d.Uint(), 10) + } + return "" +} + +// NumField returns the number of rdata fields r has. +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': @@ -47,7 +60,6 @@ func format(r RR, f fmt.State, c rune) { f.Write([]byte(Type(r.Header().Rrtype).String())) case 's': f.Write([]byte(r.String())) - } } diff --git a/parse_test.go b/parse_test.go index c809f043..759f4df9 100644 --- a/parse_test.go +++ b/parse_test.go @@ -1341,22 +1341,31 @@ func TestNewRRSpecial(t *testing.T) { func TestPrintfVerbs(t *testing.T) { x, _ := NewRR("www.miek.nl. IN A 127.0.0.1") if fmt.Sprintf("%N", x) != "www.miek.nl." { - t.Errorf("%N does not return name") + t.Errorf("%%N does not return name") } if fmt.Sprintf("%C", x) != "IN" { - t.Errorf("%C does not return class") + t.Errorf("%%C does not return class") } if fmt.Sprintf("%D", x) != "3600" { - t.Errorf("%D does not return ttl") + t.Errorf("%%D does not return ttl") } if fmt.Sprintf("%Y", x) != "A" { - t.Errorf("%Y does not return type") + t.Errorf("%%Y does not return type") } if fmt.Sprintf("%Y %d", x, 5) != "A 5" { - t.Errorf("%N does not return name") + t.Errorf("%%N does not return name") } if fmt.Sprintf("%s", x) != "www.miek.nl.\t3600\tIN\tA\t127.0.0.1" { - t.Errorf("%s does return the correct string") + t.Errorf("%%s does return the correct string") + } +} + +func TestPrintfVerbsRdata(t *testing.T) { + x, _ := NewRR("www.miek.nl. IN MX 20 mx.miek.nl.") + if Field(x, 1) != "20" { + t.Errorf("should be 20") + } + if Field(x, 2) != "mx.miek.nl." { + t.Errorf("should be mx.miek.nl.") } - // TODO(miek): RDATA }