encode.go 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. // Copyright 2018 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. package textpb
  5. import (
  6. "fmt"
  7. "sort"
  8. "github.com/golang/protobuf/v2/internal/encoding/text"
  9. "github.com/golang/protobuf/v2/internal/encoding/wire"
  10. "github.com/golang/protobuf/v2/internal/errors"
  11. "github.com/golang/protobuf/v2/internal/pragma"
  12. "github.com/golang/protobuf/v2/proto"
  13. pref "github.com/golang/protobuf/v2/reflect/protoreflect"
  14. )
  15. // Marshal writes the given proto.Message in textproto format using default options.
  16. // TODO: may want to describe when Marshal returns error.
  17. func Marshal(m proto.Message) ([]byte, error) {
  18. return MarshalOptions{}.Marshal(m)
  19. }
  20. // MarshalOptions is a configurable text format marshaler.
  21. type MarshalOptions struct {
  22. pragma.NoUnkeyedLiterals
  23. // Set Compact to true to have output in a single line with no line breaks.
  24. Compact bool
  25. }
  26. // Marshal writes the given proto.Message in textproto format using options in MarshalOptions object.
  27. func (o MarshalOptions) Marshal(m proto.Message) ([]byte, error) {
  28. var nerr errors.NonFatal
  29. var v text.Value
  30. var err error
  31. v, err = o.marshalMessage(m.ProtoReflect())
  32. if !nerr.Merge(err) {
  33. return nil, err
  34. }
  35. indent := " "
  36. if o.Compact {
  37. indent = ""
  38. }
  39. delims := [2]byte{'{', '}'}
  40. const outputASCII = false
  41. b, err := text.Marshal(v, indent, delims, outputASCII)
  42. if !nerr.Merge(err) {
  43. return nil, err
  44. }
  45. return b, nerr.E
  46. }
  47. // marshalMessage converts a protoreflect.Message to a text.Value.
  48. func (o MarshalOptions) marshalMessage(m pref.Message) (text.Value, error) {
  49. var nerr errors.NonFatal
  50. var msgFields [][2]text.Value
  51. // Handle known fields.
  52. msgType := m.Type()
  53. fieldDescs := msgType.Fields()
  54. knownFields := m.KnownFields()
  55. size := fieldDescs.Len()
  56. for i := 0; i < size; i++ {
  57. fd := fieldDescs.Get(i)
  58. num := fd.Number()
  59. if !knownFields.Has(num) {
  60. if fd.Cardinality() == pref.Required {
  61. // Treat unset required fields as a non-fatal error.
  62. nerr.AppendRequiredNotSet(string(fd.FullName()))
  63. }
  64. continue
  65. }
  66. tname := text.ValueOf(fd.Name())
  67. pval := knownFields.Get(num)
  68. var err error
  69. msgFields, err = o.appendField(msgFields, tname, pval, fd)
  70. if !nerr.Merge(err) {
  71. return text.Value{}, err
  72. }
  73. }
  74. // Handle extensions.
  75. var err error
  76. msgFields, err = o.appendExtensions(msgFields, knownFields)
  77. if !nerr.Merge(err) {
  78. return text.Value{}, err
  79. }
  80. // Handle unknown fields.
  81. // TODO: Provide option to exclude or include unknown fields.
  82. m.UnknownFields().Range(func(_ pref.FieldNumber, raw pref.RawFields) bool {
  83. msgFields = appendUnknown(msgFields, raw)
  84. return true
  85. })
  86. return text.ValueOf(msgFields), nerr.E
  87. }
  88. // appendField marshals a protoreflect.Value and appends it to the given [][2]text.Value.
  89. func (o MarshalOptions) appendField(msgFields [][2]text.Value, tname text.Value, pval pref.Value, fd pref.FieldDescriptor) ([][2]text.Value, error) {
  90. var nerr errors.NonFatal
  91. if fd.Cardinality() == pref.Repeated {
  92. // Map or repeated fields.
  93. var items []text.Value
  94. var err error
  95. if fd.IsMap() {
  96. items, err = o.marshalMap(pval.Map(), fd)
  97. if !nerr.Merge(err) {
  98. return msgFields, err
  99. }
  100. } else {
  101. items, err = o.marshalList(pval.List(), fd)
  102. if !nerr.Merge(err) {
  103. return msgFields, err
  104. }
  105. }
  106. // Add each item as key: value field.
  107. for _, item := range items {
  108. msgFields = append(msgFields, [2]text.Value{tname, item})
  109. }
  110. } else {
  111. // Required or optional fields.
  112. tval, err := o.marshalSingular(pval, fd)
  113. if !nerr.Merge(err) {
  114. return msgFields, err
  115. }
  116. msgFields = append(msgFields, [2]text.Value{tname, tval})
  117. }
  118. return msgFields, nerr.E
  119. }
  120. // marshalSingular converts a non-repeated field value to text.Value.
  121. // This includes all scalar types, enums, messages, and groups.
  122. func (o MarshalOptions) marshalSingular(val pref.Value, fd pref.FieldDescriptor) (text.Value, error) {
  123. kind := fd.Kind()
  124. switch kind {
  125. case pref.BoolKind,
  126. pref.Int32Kind, pref.Sint32Kind, pref.Uint32Kind,
  127. pref.Int64Kind, pref.Sint64Kind, pref.Uint64Kind,
  128. pref.Sfixed32Kind, pref.Fixed32Kind,
  129. pref.Sfixed64Kind, pref.Fixed64Kind,
  130. pref.FloatKind, pref.DoubleKind,
  131. pref.StringKind, pref.BytesKind:
  132. return text.ValueOf(val.Interface()), nil
  133. case pref.EnumKind:
  134. num := val.Enum()
  135. if desc := fd.EnumType().Values().ByNumber(num); desc != nil {
  136. return text.ValueOf(desc.Name()), nil
  137. }
  138. // Use numeric value if there is no enum description.
  139. return text.ValueOf(int32(num)), nil
  140. case pref.MessageKind, pref.GroupKind:
  141. return o.marshalMessage(val.Message())
  142. }
  143. return text.Value{}, errors.New("%v has unknown kind: %v", fd.FullName(), kind)
  144. }
  145. // marshalList converts a protoreflect.List to []text.Value.
  146. func (o MarshalOptions) marshalList(list pref.List, fd pref.FieldDescriptor) ([]text.Value, error) {
  147. var nerr errors.NonFatal
  148. size := list.Len()
  149. values := make([]text.Value, 0, size)
  150. for i := 0; i < size; i++ {
  151. item := list.Get(i)
  152. val, err := o.marshalSingular(item, fd)
  153. if !nerr.Merge(err) {
  154. // Return already marshaled values.
  155. return values, err
  156. }
  157. values = append(values, val)
  158. }
  159. return values, nerr.E
  160. }
  161. var (
  162. mapKeyName = text.ValueOf(pref.Name("key"))
  163. mapValueName = text.ValueOf(pref.Name("value"))
  164. )
  165. // marshalMap converts a protoreflect.Map to []text.Value.
  166. func (o MarshalOptions) marshalMap(mmap pref.Map, fd pref.FieldDescriptor) ([]text.Value, error) {
  167. var nerr errors.NonFatal
  168. // values is a list of messages.
  169. values := make([]text.Value, 0, mmap.Len())
  170. msgFields := fd.MessageType().Fields()
  171. keyType := msgFields.ByNumber(1)
  172. valType := msgFields.ByNumber(2)
  173. mmap.Range(func(key pref.MapKey, val pref.Value) bool {
  174. keyTxtVal, err := o.marshalSingular(key.Value(), keyType)
  175. if !nerr.Merge(err) {
  176. return false
  177. }
  178. valTxtVal, err := o.marshalSingular(val, valType)
  179. if !nerr.Merge(err) {
  180. return false
  181. }
  182. // Map entry (message) contains 2 fields, first field for key and second field for value.
  183. msg := text.ValueOf([][2]text.Value{
  184. {mapKeyName, keyTxtVal},
  185. {mapValueName, valTxtVal},
  186. })
  187. values = append(values, msg)
  188. return true
  189. })
  190. sortMap(keyType.Kind(), values)
  191. return values, nerr.E
  192. }
  193. // sortMap orders list based on value of key field for deterministic output.
  194. // TODO: Improve sort comparison of text.Value for map keys.
  195. func sortMap(keyKind pref.Kind, values []text.Value) {
  196. less := func(i, j int) bool {
  197. mi := values[i].Message()
  198. mj := values[j].Message()
  199. return mi[0][1].String() < mj[0][1].String()
  200. }
  201. switch keyKind {
  202. case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
  203. less = func(i, j int) bool {
  204. mi := values[i].Message()
  205. mj := values[j].Message()
  206. ni, _ := mi[0][1].Int(false)
  207. nj, _ := mj[0][1].Int(false)
  208. return ni < nj
  209. }
  210. case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
  211. less = func(i, j int) bool {
  212. mi := values[i].Message()
  213. mj := values[j].Message()
  214. ni, _ := mi[0][1].Int(true)
  215. nj, _ := mj[0][1].Int(true)
  216. return ni < nj
  217. }
  218. case pref.Uint32Kind, pref.Fixed32Kind:
  219. less = func(i, j int) bool {
  220. mi := values[i].Message()
  221. mj := values[j].Message()
  222. ni, _ := mi[0][1].Uint(false)
  223. nj, _ := mj[0][1].Uint(false)
  224. return ni < nj
  225. }
  226. case pref.Uint64Kind, pref.Fixed64Kind:
  227. less = func(i, j int) bool {
  228. mi := values[i].Message()
  229. mj := values[j].Message()
  230. ni, _ := mi[0][1].Uint(true)
  231. nj, _ := mj[0][1].Uint(true)
  232. return ni < nj
  233. }
  234. }
  235. sort.Slice(values, less)
  236. }
  237. // appendExtensions marshals extension fields and appends them to the given [][2]text.Value.
  238. func (o MarshalOptions) appendExtensions(msgFields [][2]text.Value, knownFields pref.KnownFields) ([][2]text.Value, error) {
  239. var nerr errors.NonFatal
  240. xtTypes := knownFields.ExtensionTypes()
  241. xtFields := make([][2]text.Value, 0, xtTypes.Len())
  242. var err error
  243. xtTypes.Range(func(xt pref.ExtensionType) bool {
  244. // TODO: Handle MessageSet. Field name should be message_set_extension
  245. // of message type without any fields and has message option
  246. // message_set_wire_format=true.
  247. num := xt.Number()
  248. if knownFields.Has(num) {
  249. // Use string type to produce [name] format.
  250. tname := text.ValueOf(string(xt.FullName()))
  251. pval := knownFields.Get(num)
  252. xtFields, err = o.appendField(xtFields, tname, pval, xt)
  253. if err != nil {
  254. return false
  255. }
  256. }
  257. return true
  258. })
  259. if !nerr.Merge(err) {
  260. return msgFields, err
  261. }
  262. // Sort extensions lexicographically and append to output.
  263. sort.SliceStable(xtFields, func(i, j int) bool {
  264. return xtFields[i][0].String() < xtFields[j][0].String()
  265. })
  266. return append(msgFields, xtFields...), nerr.E
  267. }
  268. // appendUnknown parses the given []byte and appends field(s) into the given fields slice.
  269. // This function assumes proper encoding in the given []byte.
  270. func appendUnknown(fields [][2]text.Value, b []byte) [][2]text.Value {
  271. for len(b) > 0 {
  272. var value interface{}
  273. num, wtype, n := wire.ConsumeTag(b)
  274. b = b[n:]
  275. switch wtype {
  276. case wire.VarintType:
  277. value, n = wire.ConsumeVarint(b)
  278. case wire.Fixed32Type:
  279. value, n = wire.ConsumeFixed32(b)
  280. case wire.Fixed64Type:
  281. value, n = wire.ConsumeFixed64(b)
  282. case wire.BytesType:
  283. value, n = wire.ConsumeBytes(b)
  284. case wire.StartGroupType:
  285. var v []byte
  286. v, n = wire.ConsumeGroup(num, b)
  287. var msg [][2]text.Value
  288. value = appendUnknown(msg, v)
  289. default:
  290. panic(fmt.Sprintf("error parsing unknown field wire type: %v", wtype))
  291. }
  292. fields = append(fields, [2]text.Value{text.ValueOf(uint32(num)), text.ValueOf(value)})
  293. b = b[n:]
  294. }
  295. return fields
  296. }