Debian package metadata parser
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

marshal.go 2.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. package dpkg
  2. import (
  3. "bufio"
  4. "bytes"
  5. "fmt"
  6. "io"
  7. "reflect"
  8. "strconv"
  9. "strings"
  10. )
  11. func parseKeyValue(kv string) (k, v string) {
  12. kv = strings.TrimRight(kv, "\n")
  13. if len(kv) == 0 {
  14. return
  15. } else if kv[0] == ' ' {
  16. return "", kv
  17. }
  18. sep := strings.Index(kv, ":")
  19. return kv[:sep], strings.TrimLeft(kv[sep+1:], " \t")
  20. }
  21. // Unmarshal a RFC822 style block
  22. func Unmarshal(b []byte, d interface{}) error {
  23. rd := reflect.ValueOf(d)
  24. if rd.Kind() != reflect.Ptr || rd.IsNil() {
  25. return fmt.Errorf(`dpkg: unmarshal to non-struct pointer type %v`, reflect.TypeOf(d))
  26. }
  27. var (
  28. fieldName = make(map[string]string)
  29. valueElem = rd.Elem()
  30. valueType = valueElem.Type()
  31. )
  32. if valueElem.Kind() != reflect.Struct {
  33. return fmt.Errorf(`dpkg: unmarshal to non-struct pointer type %T`, d)
  34. }
  35. // Map struct field names to RFC822 "header" keys.
  36. for i := 0; i < valueElem.NumField(); i++ {
  37. field := valueType.Field(i)
  38. if alias, ok := field.Tag.Lookup("dpkg"); ok {
  39. fieldName[alias] = field.Name
  40. } else {
  41. fieldName[field.Name] = field.Name
  42. }
  43. }
  44. // Map all RFC822 style "headers" in the supplied byte slice to key-value pairs.
  45. var (
  46. kv = make(map[string]string)
  47. prev string
  48. bb = bufio.NewReader(bytes.NewBuffer(b))
  49. )
  50. for {
  51. line, err := bb.ReadString('\n')
  52. if err != nil {
  53. if err == io.EOF {
  54. break
  55. }
  56. return err
  57. }
  58. k, v := parseKeyValue(line)
  59. if k == "" {
  60. if v == "" {
  61. // Empty line denotes end of section
  62. break
  63. }
  64. // Continuation for value of previous key
  65. if prev != "" {
  66. kv[prev] += "\n" + v
  67. }
  68. } else {
  69. if v != "" {
  70. kv[k] = v
  71. }
  72. prev = k
  73. }
  74. }
  75. // Now map the key-value pairs onto the passed struct.
  76. for k, v := range kv {
  77. n, ok := fieldName[k]
  78. if !ok {
  79. // Unknown key, ignore?
  80. continue
  81. }
  82. var (
  83. val = reflect.ValueOf(d).Elem().FieldByName(n)
  84. ptr = val.Addr().Interface()
  85. err error
  86. )
  87. // Check if the value supports the Field interface.
  88. if field, ok := ptr.(Field); ok {
  89. if err = field.Parse(v); err != nil {
  90. return err
  91. }
  92. if err = field.Check(); err != nil {
  93. return err
  94. }
  95. continue
  96. }
  97. // Parse ordinary Go types.
  98. switch typ := ptr.(type) {
  99. case *bool:
  100. *typ = strings.TrimSpace(v) == "yes"
  101. case *int64:
  102. var n int64
  103. if n, err = strconv.ParseInt(v, 10, 64); err != nil {
  104. return err
  105. }
  106. *typ = n
  107. case *string:
  108. *typ = v
  109. default:
  110. return fmt.Errorf(`dpkg: don't know how to unmarshal to field type %T`, typ)
  111. }
  112. }
  113. return nil
  114. }