encode.go 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. // Copyright 2019 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 impl
  5. import (
  6. "math"
  7. "sort"
  8. "sync/atomic"
  9. "google.golang.org/protobuf/internal/flags"
  10. "google.golang.org/protobuf/internal/protolazy"
  11. "google.golang.org/protobuf/proto"
  12. piface "google.golang.org/protobuf/runtime/protoiface"
  13. )
  14. type marshalOptions struct {
  15. flags piface.MarshalInputFlags
  16. }
  17. func (o marshalOptions) Options() proto.MarshalOptions {
  18. return proto.MarshalOptions{
  19. AllowPartial: true,
  20. Deterministic: o.Deterministic(),
  21. UseCachedSize: o.UseCachedSize(),
  22. }
  23. }
  24. func (o marshalOptions) Deterministic() bool { return o.flags&piface.MarshalDeterministic != 0 }
  25. func (o marshalOptions) UseCachedSize() bool { return o.flags&piface.MarshalUseCachedSize != 0 }
  26. // size is protoreflect.Methods.Size.
  27. func (mi *MessageInfo) size(in piface.SizeInput) piface.SizeOutput {
  28. var p pointer
  29. if ms, ok := in.Message.(*messageState); ok {
  30. p = ms.pointer()
  31. } else {
  32. p = in.Message.(*messageReflectWrapper).pointer()
  33. }
  34. size := mi.sizePointer(p, marshalOptions{
  35. flags: in.Flags,
  36. })
  37. return piface.SizeOutput{Size: size}
  38. }
  39. func (mi *MessageInfo) sizePointer(p pointer, opts marshalOptions) (size int) {
  40. mi.init()
  41. if p.IsNil() {
  42. return 0
  43. }
  44. if opts.UseCachedSize() && mi.sizecacheOffset.IsValid() {
  45. // The size cache contains the size + 1, to allow the
  46. // zero value to be invalid, while also allowing for a
  47. // 0 size to be cached.
  48. if size := atomic.LoadInt32(p.Apply(mi.sizecacheOffset).Int32()); size > 0 {
  49. return int(size - 1)
  50. }
  51. }
  52. return mi.sizePointerSlow(p, opts)
  53. }
  54. func (mi *MessageInfo) sizePointerSlow(p pointer, opts marshalOptions) (size int) {
  55. if flags.ProtoLegacy && mi.isMessageSet {
  56. size = sizeMessageSet(mi, p, opts)
  57. if mi.sizecacheOffset.IsValid() {
  58. atomic.StoreInt32(p.Apply(mi.sizecacheOffset).Int32(), int32(size+1))
  59. }
  60. return size
  61. }
  62. if mi.extensionOffset.IsValid() {
  63. e := p.Apply(mi.extensionOffset).Extensions()
  64. size += mi.sizeExtensions(e, opts)
  65. }
  66. var lazy **protolazy.XXX_lazyUnmarshalInfo
  67. var presence presence
  68. if mi.presenceOffset.IsValid() {
  69. presence = p.Apply(mi.presenceOffset).PresenceInfo()
  70. if mi.lazyOffset.IsValid() {
  71. lazy = p.Apply(mi.lazyOffset).LazyInfoPtr()
  72. }
  73. }
  74. for _, f := range mi.orderedCoderFields {
  75. if f.funcs.size == nil {
  76. continue
  77. }
  78. fptr := p.Apply(f.offset)
  79. if f.presenceIndex != noPresence {
  80. if !presence.Present(f.presenceIndex) {
  81. continue
  82. }
  83. if f.isLazy && fptr.AtomicGetPointer().IsNil() {
  84. if lazyFields(opts) {
  85. size += (*lazy).SizeField(uint32(f.num))
  86. continue
  87. } else {
  88. mi.lazyUnmarshal(p, f.num)
  89. }
  90. }
  91. size += f.funcs.size(fptr, f, opts)
  92. continue
  93. }
  94. if f.isPointer && fptr.Elem().IsNil() {
  95. continue
  96. }
  97. size += f.funcs.size(fptr, f, opts)
  98. }
  99. if mi.unknownOffset.IsValid() {
  100. if u := mi.getUnknownBytes(p); u != nil {
  101. size += len(*u)
  102. }
  103. }
  104. if mi.sizecacheOffset.IsValid() {
  105. if size > (math.MaxInt32 - 1) {
  106. // The size is too large for the int32 sizecache field.
  107. // We will need to recompute the size when encoding;
  108. // unfortunately expensive, but better than invalid output.
  109. atomic.StoreInt32(p.Apply(mi.sizecacheOffset).Int32(), 0)
  110. } else {
  111. // The size cache contains the size + 1, to allow the
  112. // zero value to be invalid, while also allowing for a
  113. // 0 size to be cached.
  114. atomic.StoreInt32(p.Apply(mi.sizecacheOffset).Int32(), int32(size+1))
  115. }
  116. }
  117. return size
  118. }
  119. // marshal is protoreflect.Methods.Marshal.
  120. func (mi *MessageInfo) marshal(in piface.MarshalInput) (out piface.MarshalOutput, err error) {
  121. var p pointer
  122. if ms, ok := in.Message.(*messageState); ok {
  123. p = ms.pointer()
  124. } else {
  125. p = in.Message.(*messageReflectWrapper).pointer()
  126. }
  127. b, err := mi.marshalAppendPointer(in.Buf, p, marshalOptions{
  128. flags: in.Flags,
  129. })
  130. return piface.MarshalOutput{Buf: b}, err
  131. }
  132. func (mi *MessageInfo) marshalAppendPointer(b []byte, p pointer, opts marshalOptions) ([]byte, error) {
  133. mi.init()
  134. if p.IsNil() {
  135. return b, nil
  136. }
  137. if flags.ProtoLegacy && mi.isMessageSet {
  138. return marshalMessageSet(mi, b, p, opts)
  139. }
  140. var err error
  141. // The old marshaler encodes extensions at beginning.
  142. if mi.extensionOffset.IsValid() {
  143. e := p.Apply(mi.extensionOffset).Extensions()
  144. // TODO: Special handling for MessageSet?
  145. b, err = mi.appendExtensions(b, e, opts)
  146. if err != nil {
  147. return b, err
  148. }
  149. }
  150. var lazy **protolazy.XXX_lazyUnmarshalInfo
  151. var presence presence
  152. if mi.presenceOffset.IsValid() {
  153. presence = p.Apply(mi.presenceOffset).PresenceInfo()
  154. if mi.lazyOffset.IsValid() {
  155. lazy = p.Apply(mi.lazyOffset).LazyInfoPtr()
  156. }
  157. }
  158. for _, f := range mi.orderedCoderFields {
  159. if f.funcs.marshal == nil {
  160. continue
  161. }
  162. fptr := p.Apply(f.offset)
  163. if f.presenceIndex != noPresence {
  164. if !presence.Present(f.presenceIndex) {
  165. continue
  166. }
  167. if f.isLazy {
  168. // Be careful, this field needs to be read atomically, like for a get
  169. if f.isPointer && fptr.AtomicGetPointer().IsNil() {
  170. if lazyFields(opts) {
  171. b, _ = (*lazy).AppendField(b, uint32(f.num))
  172. continue
  173. } else {
  174. mi.lazyUnmarshal(p, f.num)
  175. }
  176. }
  177. b, err = f.funcs.marshal(b, fptr, f, opts)
  178. if err != nil {
  179. return b, err
  180. }
  181. continue
  182. } else if f.isPointer && fptr.Elem().IsNil() {
  183. continue
  184. }
  185. b, err = f.funcs.marshal(b, fptr, f, opts)
  186. if err != nil {
  187. return b, err
  188. }
  189. continue
  190. }
  191. if f.isPointer && fptr.Elem().IsNil() {
  192. continue
  193. }
  194. b, err = f.funcs.marshal(b, fptr, f, opts)
  195. if err != nil {
  196. return b, err
  197. }
  198. }
  199. if mi.unknownOffset.IsValid() && !mi.isMessageSet {
  200. if u := mi.getUnknownBytes(p); u != nil {
  201. b = append(b, (*u)...)
  202. }
  203. }
  204. return b, nil
  205. }
  206. // fullyLazyExtensions returns true if we should attempt to keep extensions lazy over size and marshal.
  207. func fullyLazyExtensions(opts marshalOptions) bool {
  208. // When deterministic marshaling is requested, force an unmarshal for lazy
  209. // extensions to produce a deterministic result, instead of passing through
  210. // bytes lazily that may or may not match what Go Protobuf would produce.
  211. return opts.flags&piface.MarshalDeterministic == 0
  212. }
  213. // lazyFields returns true if we should attempt to keep fields lazy over size and marshal.
  214. func lazyFields(opts marshalOptions) bool {
  215. // When deterministic marshaling is requested, force an unmarshal for lazy
  216. // fields to produce a deterministic result, instead of passing through
  217. // bytes lazily that may or may not match what Go Protobuf would produce.
  218. return opts.flags&piface.MarshalDeterministic == 0
  219. }
  220. func (mi *MessageInfo) sizeExtensions(ext *map[int32]ExtensionField, opts marshalOptions) (n int) {
  221. if ext == nil {
  222. return 0
  223. }
  224. for _, x := range *ext {
  225. xi := getExtensionFieldInfo(x.Type())
  226. if xi.funcs.size == nil {
  227. continue
  228. }
  229. if fullyLazyExtensions(opts) {
  230. // Don't expand the extension, instead use the buffer to calculate size
  231. if lb := x.lazyBuffer(); lb != nil {
  232. // We got hold of the buffer, so it's still lazy.
  233. n += len(lb)
  234. continue
  235. }
  236. }
  237. n += xi.funcs.size(x.Value(), xi.tagsize, opts)
  238. }
  239. return n
  240. }
  241. func (mi *MessageInfo) appendExtensions(b []byte, ext *map[int32]ExtensionField, opts marshalOptions) ([]byte, error) {
  242. if ext == nil {
  243. return b, nil
  244. }
  245. switch len(*ext) {
  246. case 0:
  247. return b, nil
  248. case 1:
  249. // Fast-path for one extension: Don't bother sorting the keys.
  250. var err error
  251. for _, x := range *ext {
  252. xi := getExtensionFieldInfo(x.Type())
  253. if fullyLazyExtensions(opts) {
  254. // Don't expand the extension if it's still in wire format, instead use the buffer content.
  255. if lb := x.lazyBuffer(); lb != nil {
  256. b = append(b, lb...)
  257. continue
  258. }
  259. }
  260. b, err = xi.funcs.marshal(b, x.Value(), xi.wiretag, opts)
  261. }
  262. return b, err
  263. default:
  264. // Sort the keys to provide a deterministic encoding.
  265. // Not sure this is required, but the old code does it.
  266. keys := make([]int, 0, len(*ext))
  267. for k := range *ext {
  268. keys = append(keys, int(k))
  269. }
  270. sort.Ints(keys)
  271. var err error
  272. for _, k := range keys {
  273. x := (*ext)[int32(k)]
  274. xi := getExtensionFieldInfo(x.Type())
  275. if fullyLazyExtensions(opts) {
  276. // Don't expand the extension if it's still in wire format, instead use the buffer content.
  277. if lb := x.lazyBuffer(); lb != nil {
  278. b = append(b, lb...)
  279. continue
  280. }
  281. }
  282. b, err = xi.funcs.marshal(b, x.Value(), xi.wiretag, opts)
  283. if err != nil {
  284. return b, err
  285. }
  286. }
  287. return b, nil
  288. }
  289. }