encode.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. package oscar
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "errors"
  6. "io"
  7. "reflect"
  8. )
  9. func Marshal(v any, w io.Writer) error {
  10. return marshal(reflect.TypeOf(v), reflect.ValueOf(v), "", w)
  11. }
  12. func marshal(t reflect.Type, v reflect.Value, tag reflect.StructTag, w io.Writer) error {
  13. switch t.Kind() {
  14. case reflect.Struct:
  15. switch sVal := v.Interface().(type) {
  16. case TLVRestBlock:
  17. if err := sVal.WriteTLV(w); err != nil {
  18. return err
  19. }
  20. case TLVLBlock:
  21. if err := sVal.WriteTLV(w); err != nil {
  22. return err
  23. }
  24. case TLVBlock:
  25. if err := sVal.WriteTLV(w); err != nil {
  26. return err
  27. }
  28. default:
  29. for i := 0; i < t.NumField(); i++ {
  30. if err := marshal(t.Field(i).Type, v.Field(i), t.Field(i).Tag, w); err != nil {
  31. return err
  32. }
  33. }
  34. }
  35. case reflect.String:
  36. if l, ok := tag.Lookup("len_prefix"); ok {
  37. switch l {
  38. case "uint8":
  39. if err := binary.Write(w, binary.BigEndian, uint8(len(v.String()))); err != nil {
  40. return err
  41. }
  42. case "uint16":
  43. if err := binary.Write(w, binary.BigEndian, uint16(len(v.String()))); err != nil {
  44. return err
  45. }
  46. default:
  47. panic("length not set")
  48. }
  49. }
  50. if err := binary.Write(w, binary.BigEndian, []byte(v.String())); err != nil {
  51. return err
  52. }
  53. case reflect.Slice:
  54. // todo: only write to temporary buffer if len_prefix is set
  55. buf := &bytes.Buffer{}
  56. if t.Elem().Kind() == reflect.Struct {
  57. for j := 0; j < v.Len(); j++ {
  58. element := v.Index(j)
  59. if err := Marshal(element.Interface(), buf); err != nil {
  60. return err
  61. }
  62. }
  63. } else {
  64. if err := binary.Write(buf, binary.BigEndian, v.Interface()); err != nil {
  65. return err
  66. }
  67. }
  68. //todo what if both len_prefix and count_prefix are set?
  69. if l, ok := tag.Lookup("len_prefix"); ok {
  70. switch l {
  71. case "uint8":
  72. if err := binary.Write(w, binary.BigEndian, uint8(buf.Len())); err != nil {
  73. return err
  74. }
  75. case "uint16":
  76. if err := binary.Write(w, binary.BigEndian, uint16(buf.Len())); err != nil {
  77. return err
  78. }
  79. }
  80. }
  81. if l, ok := tag.Lookup("count_prefix"); ok {
  82. switch l {
  83. case "uint8":
  84. if err := binary.Write(w, binary.BigEndian, uint8(v.Len())); err != nil {
  85. return err
  86. }
  87. case "uint16":
  88. if err := binary.Write(w, binary.BigEndian, uint16(v.Len())); err != nil {
  89. return err
  90. }
  91. }
  92. }
  93. if _, err := w.Write(buf.Bytes()); err != nil {
  94. return err
  95. }
  96. case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Array:
  97. if err := binary.Write(w, binary.BigEndian, v.Interface()); err != nil {
  98. return err
  99. }
  100. default:
  101. return errors.New("unsupported type for marshalling")
  102. }
  103. return nil
  104. }