gentest.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // Copyright 2013 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // +build ignore
  5. // This program generates internet protocol constants by reading IANA
  6. // protocol registries.
  7. //
  8. // Usage:
  9. // go run gentest.go > iana_test.go
  10. package main
  11. import (
  12. "bytes"
  13. "encoding/xml"
  14. "fmt"
  15. "go/format"
  16. "io"
  17. "net/http"
  18. "os"
  19. "strconv"
  20. "strings"
  21. )
  22. var registries = []struct {
  23. url string
  24. parse func(io.Writer, io.Reader) error
  25. }{
  26. {
  27. "http://www.iana.org/assignments/dscp-registry/dscp-registry.xml",
  28. parseDSCPRegistry,
  29. },
  30. {
  31. "http://www.iana.org/assignments/ipv4-tos-byte/ipv4-tos-byte.xml",
  32. parseTOSTCByte,
  33. },
  34. }
  35. func main() {
  36. var bb bytes.Buffer
  37. fmt.Fprintf(&bb, "// go run gentest.go\n")
  38. fmt.Fprintf(&bb, "// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n")
  39. fmt.Fprintf(&bb, "package ipv4_test\n\n")
  40. for _, r := range registries {
  41. resp, err := http.Get(r.url)
  42. if err != nil {
  43. fmt.Fprintln(os.Stderr, err)
  44. os.Exit(1)
  45. }
  46. defer resp.Body.Close()
  47. if resp.StatusCode != http.StatusOK {
  48. fmt.Fprintf(os.Stderr, "got HTTP status code %v for %v\n", resp.StatusCode, r.url)
  49. os.Exit(1)
  50. }
  51. if err := r.parse(&bb, resp.Body); err != nil {
  52. fmt.Fprintln(os.Stderr, err)
  53. os.Exit(1)
  54. }
  55. fmt.Fprintf(&bb, "\n")
  56. }
  57. b, err := format.Source(bb.Bytes())
  58. if err != nil {
  59. fmt.Fprintln(os.Stderr, err)
  60. os.Exit(1)
  61. }
  62. os.Stdout.Write(b)
  63. }
  64. func parseDSCPRegistry(w io.Writer, r io.Reader) error {
  65. dec := xml.NewDecoder(r)
  66. var dr dscpRegistry
  67. if err := dec.Decode(&dr); err != nil {
  68. return err
  69. }
  70. drs := dr.escape()
  71. fmt.Fprintf(w, "// %s, Updated: %s\n", dr.Title, dr.Updated)
  72. fmt.Fprintf(w, "const (\n")
  73. for _, dr := range drs {
  74. fmt.Fprintf(w, "DiffServ%s = %#x", dr.Name, dr.Value)
  75. fmt.Fprintf(w, "// %s\n", dr.OrigName)
  76. }
  77. fmt.Fprintf(w, ")\n")
  78. return nil
  79. }
  80. type dscpRegistry struct {
  81. XMLName xml.Name `xml:"registry"`
  82. Title string `xml:"title"`
  83. Updated string `xml:"updated"`
  84. Note string `xml:"note"`
  85. RegTitle string `xml:"registry>title"`
  86. PoolRecords []struct {
  87. Name string `xml:"name"`
  88. Space string `xml:"space"`
  89. } `xml:"registry>record"`
  90. Records []struct {
  91. Name string `xml:"name"`
  92. Space string `xml:"space"`
  93. } `xml:"registry>registry>record"`
  94. }
  95. type canonDSCPRecord struct {
  96. OrigName string
  97. Name string
  98. Value int
  99. }
  100. func (drr *dscpRegistry) escape() []canonDSCPRecord {
  101. drs := make([]canonDSCPRecord, len(drr.Records))
  102. sr := strings.NewReplacer(
  103. "+", "",
  104. "-", "",
  105. "/", "",
  106. ".", "",
  107. " ", "",
  108. )
  109. for i, dr := range drr.Records {
  110. s := strings.TrimSpace(dr.Name)
  111. drs[i].OrigName = s
  112. drs[i].Name = sr.Replace(s)
  113. n, err := strconv.ParseUint(dr.Space, 2, 8)
  114. if err != nil {
  115. continue
  116. }
  117. drs[i].Value = int(n) << 2
  118. }
  119. return drs
  120. }
  121. func parseTOSTCByte(w io.Writer, r io.Reader) error {
  122. dec := xml.NewDecoder(r)
  123. var ttb tosTCByte
  124. if err := dec.Decode(&ttb); err != nil {
  125. return err
  126. }
  127. trs := ttb.escape()
  128. fmt.Fprintf(w, "// %s, Updated: %s\n", ttb.Title, ttb.Updated)
  129. fmt.Fprintf(w, "const (\n")
  130. for _, tr := range trs {
  131. fmt.Fprintf(w, "%s = %#x", tr.Keyword, tr.Value)
  132. fmt.Fprintf(w, "// %s\n", tr.OrigKeyword)
  133. }
  134. fmt.Fprintf(w, ")\n")
  135. return nil
  136. }
  137. type tosTCByte struct {
  138. XMLName xml.Name `xml:"registry"`
  139. Title string `xml:"title"`
  140. Updated string `xml:"updated"`
  141. Note string `xml:"note"`
  142. RegTitle string `xml:"registry>title"`
  143. Records []struct {
  144. Binary string `xml:"binary"`
  145. Keyword string `xml:"keyword"`
  146. } `xml:"registry>record"`
  147. }
  148. type canonTOSTCByteRecord struct {
  149. OrigKeyword string
  150. Keyword string
  151. Value int
  152. }
  153. func (ttb *tosTCByte) escape() []canonTOSTCByteRecord {
  154. trs := make([]canonTOSTCByteRecord, len(ttb.Records))
  155. sr := strings.NewReplacer(
  156. "Capable", "",
  157. "(", "",
  158. ")", "",
  159. "+", "",
  160. "-", "",
  161. "/", "",
  162. ".", "",
  163. " ", "",
  164. )
  165. for i, tr := range ttb.Records {
  166. s := strings.TrimSpace(tr.Keyword)
  167. trs[i].OrigKeyword = s
  168. ss := strings.Split(s, " ")
  169. if len(ss) > 1 {
  170. trs[i].Keyword = strings.Join(ss[1:], " ")
  171. } else {
  172. trs[i].Keyword = ss[0]
  173. }
  174. trs[i].Keyword = sr.Replace(trs[i].Keyword)
  175. n, err := strconv.ParseUint(tr.Binary, 2, 8)
  176. if err != nil {
  177. continue
  178. }
  179. trs[i].Value = int(n)
  180. }
  181. return trs
  182. }