1// Protocol Buffers for Go with Gadgets
2//
3// Copyright (c) 2013, The GoGo Authors. All rights reserved.
4// http://github.com/gogo/protobuf
5//
6// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are
8// met:
9//
10//     * Redistributions of source code must retain the above copyright
11// notice, this list of conditions and the following disclaimer.
12//     * Redistributions in binary form must reproduce the above
13// copyright notice, this list of conditions and the following disclaimer
14// in the documentation and/or other materials provided with the
15// distribution.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29/*
30The marshalto plugin generates a Marshal and MarshalTo method for each message.
31The `Marshal() ([]byte, error)` method results in the fact that the message
32implements the Marshaler interface.
33This allows proto.Marshal to be faster by calling the generated Marshal method rather than using reflect to Marshal the struct.
34
35If is enabled by the following extensions:
36
37  - marshaler
38  - marshaler_all
39
40Or the following extensions:
41
42  - unsafe_marshaler
43  - unsafe_marshaler_all
44
45That is if you want to use the unsafe package in your generated code.
46The speed up using the unsafe package is not very significant.
47
48The generation of marshalling tests are enabled using one of the following extensions:
49
50  - testgen
51  - testgen_all
52
53And benchmarks given it is enabled using one of the following extensions:
54
55  - benchgen
56  - benchgen_all
57
58Let us look at:
59
60  github.com/gogo/protobuf/test/example/example.proto
61
62Btw all the output can be seen at:
63
64  github.com/gogo/protobuf/test/example/*
65
66The following message:
67
68option (gogoproto.marshaler_all) = true;
69
70message B {
71	option (gogoproto.description) = true;
72	optional A A = 1 [(gogoproto.nullable) = false, (gogoproto.embed) = true];
73	repeated bytes G = 2 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uint128", (gogoproto.nullable) = false];
74}
75
76given to the marshalto plugin, will generate the following code:
77
78  func (m *B) Marshal() (dAtA []byte, err error) {
79	size := m.Size()
80	dAtA = make([]byte, size)
81	n, err := m.MarshalTo(dAtA)
82	if err != nil {
83		return nil, err
84	}
85	return dAtA[:n], nil
86  }
87
88  func (m *B) MarshalTo(dAtA []byte) (int, error) {
89	var i int
90	_ = i
91	var l int
92	_ = l
93	dAtA[i] = 0xa
94	i++
95	i = encodeVarintExample(dAtA, i, uint64(m.A.Size()))
96	n2, err := m.A.MarshalTo(dAtA[i:])
97	if err != nil {
98		return 0, err
99	}
100	i += n2
101	if len(m.G) > 0 {
102		for _, msg := range m.G {
103			dAtA[i] = 0x12
104			i++
105			i = encodeVarintExample(dAtA, i, uint64(msg.Size()))
106			n, err := msg.MarshalTo(dAtA[i:])
107			if err != nil {
108				return 0, err
109			}
110			i += n
111		}
112	}
113	if m.XXX_unrecognized != nil {
114		i += copy(dAtA[i:], m.XXX_unrecognized)
115	}
116	return i, nil
117  }
118
119As shown above Marshal calculates the size of the not yet marshalled message
120and allocates the appropriate buffer.
121This is followed by calling the MarshalTo method which requires a preallocated buffer.
122The MarshalTo method allows a user to rather preallocated a reusable buffer.
123
124The Size method is generated using the size plugin and the gogoproto.sizer, gogoproto.sizer_all extensions.
125The user can also using the generated Size method to check that his reusable buffer is still big enough.
126
127The generated tests and benchmarks will keep you safe and show that this is really a significant speed improvement.
128
129An additional message-level option `stable_marshaler` (and the file-level
130option `stable_marshaler_all`) exists which causes the generated marshalling
131code to behave deterministically. Today, this only changes the serialization of
132maps; they are serialized in sort order.
133*/
134package marshalto
135
136import (
137	"fmt"
138	"sort"
139	"strconv"
140	"strings"
141
142	"github.com/gogo/protobuf/gogoproto"
143	"github.com/gogo/protobuf/proto"
144	descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
145	"github.com/gogo/protobuf/protoc-gen-gogo/generator"
146	"github.com/gogo/protobuf/vanity"
147)
148
149type NumGen interface {
150	Next() string
151	Current() string
152}
153
154type numGen struct {
155	index int
156}
157
158func NewNumGen() NumGen {
159	return &numGen{0}
160}
161
162func (this *numGen) Next() string {
163	this.index++
164	return this.Current()
165}
166
167func (this *numGen) Current() string {
168	return strconv.Itoa(this.index)
169}
170
171type marshalto struct {
172	*generator.Generator
173	generator.PluginImports
174	atleastOne  bool
175	errorsPkg   generator.Single
176	protoPkg    generator.Single
177	sortKeysPkg generator.Single
178	mathPkg     generator.Single
179	typesPkg    generator.Single
180	binaryPkg   generator.Single
181	localName   string
182}
183
184func NewMarshal() *marshalto {
185	return &marshalto{}
186}
187
188func (p *marshalto) Name() string {
189	return "marshalto"
190}
191
192func (p *marshalto) Init(g *generator.Generator) {
193	p.Generator = g
194}
195
196func (p *marshalto) callFixed64(varName ...string) {
197	p.P(p.binaryPkg.Use(), `.LittleEndian.PutUint64(dAtA[i:], uint64(`, strings.Join(varName, ""), `))`)
198	p.P(`i += 8`)
199}
200
201func (p *marshalto) callFixed32(varName ...string) {
202	p.P(p.binaryPkg.Use(), `.LittleEndian.PutUint32(dAtA[i:], uint32(`, strings.Join(varName, ""), `))`)
203	p.P(`i += 4`)
204}
205
206func (p *marshalto) callVarint(varName ...string) {
207	p.P(`i = encodeVarint`, p.localName, `(dAtA, i, uint64(`, strings.Join(varName, ""), `))`)
208}
209
210func (p *marshalto) encodeVarint(varName string) {
211	p.P(`for `, varName, ` >= 1<<7 {`)
212	p.In()
213	p.P(`dAtA[i] = uint8(uint64(`, varName, `)&0x7f|0x80)`)
214	p.P(varName, ` >>= 7`)
215	p.P(`i++`)
216	p.Out()
217	p.P(`}`)
218	p.P(`dAtA[i] = uint8(`, varName, `)`)
219	p.P(`i++`)
220}
221
222func (p *marshalto) encodeKey(fieldNumber int32, wireType int) {
223	x := uint32(fieldNumber)<<3 | uint32(wireType)
224	i := 0
225	keybuf := make([]byte, 0)
226	for i = 0; x > 127; i++ {
227		keybuf = append(keybuf, 0x80|uint8(x&0x7F))
228		x >>= 7
229	}
230	keybuf = append(keybuf, uint8(x))
231	for _, b := range keybuf {
232		p.P(`dAtA[i] = `, fmt.Sprintf("%#v", b))
233		p.P(`i++`)
234	}
235}
236
237func keySize(fieldNumber int32, wireType int) int {
238	x := uint32(fieldNumber)<<3 | uint32(wireType)
239	size := 0
240	for size = 0; x > 127; size++ {
241		x >>= 7
242	}
243	size++
244	return size
245}
246
247func wireToType(wire string) int {
248	switch wire {
249	case "fixed64":
250		return proto.WireFixed64
251	case "fixed32":
252		return proto.WireFixed32
253	case "varint":
254		return proto.WireVarint
255	case "bytes":
256		return proto.WireBytes
257	case "group":
258		return proto.WireBytes
259	case "zigzag32":
260		return proto.WireVarint
261	case "zigzag64":
262		return proto.WireVarint
263	}
264	panic("unreachable")
265}
266
267func (p *marshalto) mapField(numGen NumGen, field *descriptor.FieldDescriptorProto, kvField *descriptor.FieldDescriptorProto, varName string, protoSizer bool) {
268	switch kvField.GetType() {
269	case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
270		p.callFixed64(p.mathPkg.Use(), `.Float64bits(float64(`, varName, `))`)
271	case descriptor.FieldDescriptorProto_TYPE_FLOAT:
272		p.callFixed32(p.mathPkg.Use(), `.Float32bits(float32(`, varName, `))`)
273	case descriptor.FieldDescriptorProto_TYPE_INT64,
274		descriptor.FieldDescriptorProto_TYPE_UINT64,
275		descriptor.FieldDescriptorProto_TYPE_INT32,
276		descriptor.FieldDescriptorProto_TYPE_UINT32,
277		descriptor.FieldDescriptorProto_TYPE_ENUM:
278		p.callVarint(varName)
279	case descriptor.FieldDescriptorProto_TYPE_FIXED64,
280		descriptor.FieldDescriptorProto_TYPE_SFIXED64:
281		p.callFixed64(varName)
282	case descriptor.FieldDescriptorProto_TYPE_FIXED32,
283		descriptor.FieldDescriptorProto_TYPE_SFIXED32:
284		p.callFixed32(varName)
285	case descriptor.FieldDescriptorProto_TYPE_BOOL:
286		p.P(`if `, varName, ` {`)
287		p.In()
288		p.P(`dAtA[i] = 1`)
289		p.Out()
290		p.P(`} else {`)
291		p.In()
292		p.P(`dAtA[i] = 0`)
293		p.Out()
294		p.P(`}`)
295		p.P(`i++`)
296	case descriptor.FieldDescriptorProto_TYPE_STRING,
297		descriptor.FieldDescriptorProto_TYPE_BYTES:
298		if gogoproto.IsCustomType(field) && kvField.IsBytes() {
299			p.callVarint(varName, `.Size()`)
300			p.P(`n`, numGen.Next(), `, err := `, varName, `.MarshalTo(dAtA[i:])`)
301			p.P(`if err != nil {`)
302			p.In()
303			p.P(`return 0, err`)
304			p.Out()
305			p.P(`}`)
306			p.P(`i+=n`, numGen.Current())
307		} else {
308			p.callVarint(`len(`, varName, `)`)
309			p.P(`i+=copy(dAtA[i:], `, varName, `)`)
310		}
311	case descriptor.FieldDescriptorProto_TYPE_SINT32:
312		p.callVarint(`(uint32(`, varName, `) << 1) ^ uint32((`, varName, ` >> 31))`)
313	case descriptor.FieldDescriptorProto_TYPE_SINT64:
314		p.callVarint(`(uint64(`, varName, `) << 1) ^ uint64((`, varName, ` >> 63))`)
315	case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
316		if gogoproto.IsStdTime(kvField) {
317			p.callVarint(p.typesPkg.Use(), `.SizeOfStdTime(*`, varName, `)`)
318			p.P(`n`, numGen.Next(), `, err := `, p.typesPkg.Use(), `.StdTimeMarshalTo(*`, varName, `, dAtA[i:])`)
319		} else if gogoproto.IsStdDuration(kvField) {
320			p.callVarint(p.typesPkg.Use(), `.SizeOfStdDuration(*`, varName, `)`)
321			p.P(`n`, numGen.Next(), `, err := `, p.typesPkg.Use(), `.StdDurationMarshalTo(*`, varName, `, dAtA[i:])`)
322		} else if gogoproto.IsStdDouble(kvField) {
323			p.callVarint(p.typesPkg.Use(), `.SizeOfStdDouble(*`, varName, `)`)
324			p.P(`n`, numGen.Next(), `, err := `, p.typesPkg.Use(), `.StdDoubleMarshalTo(*`, varName, `, dAtA[i:])`)
325		} else if gogoproto.IsStdFloat(kvField) {
326			p.callVarint(p.typesPkg.Use(), `.SizeOfStdFloat(*`, varName, `)`)
327			p.P(`n`, numGen.Next(), `, err := `, p.typesPkg.Use(), `.StdFloatMarshalTo(*`, varName, `, dAtA[i:])`)
328		} else if gogoproto.IsStdInt64(kvField) {
329			p.callVarint(p.typesPkg.Use(), `.SizeOfStdInt64(*`, varName, `)`)
330			p.P(`n`, numGen.Next(), `, err := `, p.typesPkg.Use(), `.StdInt64MarshalTo(*`, varName, `, dAtA[i:])`)
331		} else if gogoproto.IsStdUInt64(kvField) {
332			p.callVarint(p.typesPkg.Use(), `.SizeOfStdUInt64(*`, varName, `)`)
333			p.P(`n`, numGen.Next(), `, err := `, p.typesPkg.Use(), `.StdUInt64MarshalTo(*`, varName, `, dAtA[i:])`)
334		} else if gogoproto.IsStdInt32(kvField) {
335			p.callVarint(p.typesPkg.Use(), `.SizeOfStdInt32(*`, varName, `)`)
336			p.P(`n`, numGen.Next(), `, err := `, p.typesPkg.Use(), `.StdInt32MarshalTo(*`, varName, `, dAtA[i:])`)
337		} else if gogoproto.IsStdUInt32(kvField) {
338			p.callVarint(p.typesPkg.Use(), `.SizeOfStdUInt32(*`, varName, `)`)
339			p.P(`n`, numGen.Next(), `, err := `, p.typesPkg.Use(), `.StdUInt32MarshalTo(*`, varName, `, dAtA[i:])`)
340		} else if gogoproto.IsStdBool(kvField) {
341			p.callVarint(p.typesPkg.Use(), `.SizeOfStdBool(*`, varName, `)`)
342			p.P(`n`, numGen.Next(), `, err := `, p.typesPkg.Use(), `.StdBoolMarshalTo(*`, varName, `, dAtA[i:])`)
343		} else if gogoproto.IsStdString(kvField) {
344			p.callVarint(p.typesPkg.Use(), `.SizeOfStdString(*`, varName, `)`)
345			p.P(`n`, numGen.Next(), `, err := `, p.typesPkg.Use(), `.StdStringMarshalTo(*`, varName, `, dAtA[i:])`)
346		} else if gogoproto.IsStdBytes(kvField) {
347			p.callVarint(p.typesPkg.Use(), `.SizeOfStdBytes(*`, varName, `)`)
348			p.P(`n`, numGen.Next(), `, err := `, p.typesPkg.Use(), `.StdBytesMarshalTo(*`, varName, `, dAtA[i:])`)
349		} else if protoSizer {
350			p.callVarint(varName, `.ProtoSize()`)
351			p.P(`n`, numGen.Next(), `, err := `, varName, `.MarshalTo(dAtA[i:])`)
352		} else {
353			p.callVarint(varName, `.Size()`)
354			p.P(`n`, numGen.Next(), `, err := `, varName, `.MarshalTo(dAtA[i:])`)
355		}
356		p.P(`if err != nil {`)
357		p.In()
358		p.P(`return 0, err`)
359		p.Out()
360		p.P(`}`)
361		p.P(`i+=n`, numGen.Current())
362	}
363}
364
365type orderFields []*descriptor.FieldDescriptorProto
366
367func (this orderFields) Len() int {
368	return len(this)
369}
370
371func (this orderFields) Less(i, j int) bool {
372	return this[i].GetNumber() < this[j].GetNumber()
373}
374
375func (this orderFields) Swap(i, j int) {
376	this[i], this[j] = this[j], this[i]
377}
378
379func (p *marshalto) generateField(proto3 bool, numGen NumGen, file *generator.FileDescriptor, message *generator.Descriptor, field *descriptor.FieldDescriptorProto) {
380	fieldname := p.GetOneOfFieldName(message, field)
381	nullable := gogoproto.IsNullable(field)
382	repeated := field.IsRepeated()
383	required := field.IsRequired()
384
385	protoSizer := gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto)
386	doNilCheck := gogoproto.NeedsNilCheck(proto3, field)
387	if required && nullable {
388		p.P(`if m.`, fieldname, `== nil {`)
389		p.In()
390		if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
391			p.P(`return 0, new(`, p.protoPkg.Use(), `.RequiredNotSetError)`)
392		} else {
393			p.P(`return 0, `, p.protoPkg.Use(), `.NewRequiredNotSetError("`, field.GetName(), `")`)
394		}
395		p.Out()
396		p.P(`} else {`)
397	} else if repeated {
398		p.P(`if len(m.`, fieldname, `) > 0 {`)
399		p.In()
400	} else if doNilCheck {
401		p.P(`if m.`, fieldname, ` != nil {`)
402		p.In()
403	}
404	packed := field.IsPacked() || (proto3 && field.IsPacked3())
405	wireType := field.WireType()
406	fieldNumber := field.GetNumber()
407	if packed {
408		wireType = proto.WireBytes
409	}
410	switch *field.Type {
411	case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
412		if packed {
413			p.encodeKey(fieldNumber, wireType)
414			p.callVarint(`len(m.`, fieldname, `) * 8`)
415			p.P(`for _, num := range m.`, fieldname, ` {`)
416			p.In()
417			p.P(`f`, numGen.Next(), ` := `, p.mathPkg.Use(), `.Float64bits(float64(num))`)
418			p.callFixed64("f" + numGen.Current())
419			p.Out()
420			p.P(`}`)
421		} else if repeated {
422			p.P(`for _, num := range m.`, fieldname, ` {`)
423			p.In()
424			p.encodeKey(fieldNumber, wireType)
425			p.P(`f`, numGen.Next(), ` := `, p.mathPkg.Use(), `.Float64bits(float64(num))`)
426			p.callFixed64("f" + numGen.Current())
427			p.Out()
428			p.P(`}`)
429		} else if proto3 {
430			p.P(`if m.`, fieldname, ` != 0 {`)
431			p.In()
432			p.encodeKey(fieldNumber, wireType)
433			p.callFixed64(p.mathPkg.Use(), `.Float64bits(float64(m.`+fieldname, `))`)
434			p.Out()
435			p.P(`}`)
436		} else if !nullable {
437			p.encodeKey(fieldNumber, wireType)
438			p.callFixed64(p.mathPkg.Use(), `.Float64bits(float64(m.`+fieldname, `))`)
439		} else {
440			p.encodeKey(fieldNumber, wireType)
441			p.callFixed64(p.mathPkg.Use(), `.Float64bits(float64(*m.`+fieldname, `))`)
442		}
443	case descriptor.FieldDescriptorProto_TYPE_FLOAT:
444		if packed {
445			p.encodeKey(fieldNumber, wireType)
446			p.callVarint(`len(m.`, fieldname, `) * 4`)
447			p.P(`for _, num := range m.`, fieldname, ` {`)
448			p.In()
449			p.P(`f`, numGen.Next(), ` := `, p.mathPkg.Use(), `.Float32bits(float32(num))`)
450			p.callFixed32("f" + numGen.Current())
451			p.Out()
452			p.P(`}`)
453		} else if repeated {
454			p.P(`for _, num := range m.`, fieldname, ` {`)
455			p.In()
456			p.encodeKey(fieldNumber, wireType)
457			p.P(`f`, numGen.Next(), ` := `, p.mathPkg.Use(), `.Float32bits(float32(num))`)
458			p.callFixed32("f" + numGen.Current())
459			p.Out()
460			p.P(`}`)
461		} else if proto3 {
462			p.P(`if m.`, fieldname, ` != 0 {`)
463			p.In()
464			p.encodeKey(fieldNumber, wireType)
465			p.callFixed32(p.mathPkg.Use(), `.Float32bits(float32(m.`+fieldname, `))`)
466			p.Out()
467			p.P(`}`)
468		} else if !nullable {
469			p.encodeKey(fieldNumber, wireType)
470			p.callFixed32(p.mathPkg.Use(), `.Float32bits(float32(m.`+fieldname, `))`)
471		} else {
472			p.encodeKey(fieldNumber, wireType)
473			p.callFixed32(p.mathPkg.Use(), `.Float32bits(float32(*m.`+fieldname, `))`)
474		}
475	case descriptor.FieldDescriptorProto_TYPE_INT64,
476		descriptor.FieldDescriptorProto_TYPE_UINT64,
477		descriptor.FieldDescriptorProto_TYPE_INT32,
478		descriptor.FieldDescriptorProto_TYPE_UINT32,
479		descriptor.FieldDescriptorProto_TYPE_ENUM:
480		if packed {
481			jvar := "j" + numGen.Next()
482			p.P(`dAtA`, numGen.Next(), ` := make([]byte, len(m.`, fieldname, `)*10)`)
483			p.P(`var `, jvar, ` int`)
484			if *field.Type == descriptor.FieldDescriptorProto_TYPE_INT64 ||
485				*field.Type == descriptor.FieldDescriptorProto_TYPE_INT32 {
486				p.P(`for _, num1 := range m.`, fieldname, ` {`)
487				p.In()
488				p.P(`num := uint64(num1)`)
489			} else {
490				p.P(`for _, num := range m.`, fieldname, ` {`)
491				p.In()
492			}
493			p.P(`for num >= 1<<7 {`)
494			p.In()
495			p.P(`dAtA`, numGen.Current(), `[`, jvar, `] = uint8(uint64(num)&0x7f|0x80)`)
496			p.P(`num >>= 7`)
497			p.P(jvar, `++`)
498			p.Out()
499			p.P(`}`)
500			p.P(`dAtA`, numGen.Current(), `[`, jvar, `] = uint8(num)`)
501			p.P(jvar, `++`)
502			p.Out()
503			p.P(`}`)
504			p.encodeKey(fieldNumber, wireType)
505			p.callVarint(jvar)
506			p.P(`i += copy(dAtA[i:], dAtA`, numGen.Current(), `[:`, jvar, `])`)
507		} else if repeated {
508			p.P(`for _, num := range m.`, fieldname, ` {`)
509			p.In()
510			p.encodeKey(fieldNumber, wireType)
511			p.callVarint("num")
512			p.Out()
513			p.P(`}`)
514		} else if proto3 {
515			p.P(`if m.`, fieldname, ` != 0 {`)
516			p.In()
517			p.encodeKey(fieldNumber, wireType)
518			p.callVarint(`m.`, fieldname)
519			p.Out()
520			p.P(`}`)
521		} else if !nullable {
522			p.encodeKey(fieldNumber, wireType)
523			p.callVarint(`m.`, fieldname)
524		} else {
525			p.encodeKey(fieldNumber, wireType)
526			p.callVarint(`*m.`, fieldname)
527		}
528	case descriptor.FieldDescriptorProto_TYPE_FIXED64,
529		descriptor.FieldDescriptorProto_TYPE_SFIXED64:
530		if packed {
531			p.encodeKey(fieldNumber, wireType)
532			p.callVarint(`len(m.`, fieldname, `) * 8`)
533			p.P(`for _, num := range m.`, fieldname, ` {`)
534			p.In()
535			p.callFixed64("num")
536			p.Out()
537			p.P(`}`)
538		} else if repeated {
539			p.P(`for _, num := range m.`, fieldname, ` {`)
540			p.In()
541			p.encodeKey(fieldNumber, wireType)
542			p.callFixed64("num")
543			p.Out()
544			p.P(`}`)
545		} else if proto3 {
546			p.P(`if m.`, fieldname, ` != 0 {`)
547			p.In()
548			p.encodeKey(fieldNumber, wireType)
549			p.callFixed64("m." + fieldname)
550			p.Out()
551			p.P(`}`)
552		} else if !nullable {
553			p.encodeKey(fieldNumber, wireType)
554			p.callFixed64("m." + fieldname)
555		} else {
556			p.encodeKey(fieldNumber, wireType)
557			p.callFixed64("*m." + fieldname)
558		}
559	case descriptor.FieldDescriptorProto_TYPE_FIXED32,
560		descriptor.FieldDescriptorProto_TYPE_SFIXED32:
561		if packed {
562			p.encodeKey(fieldNumber, wireType)
563			p.callVarint(`len(m.`, fieldname, `) * 4`)
564			p.P(`for _, num := range m.`, fieldname, ` {`)
565			p.In()
566			p.callFixed32("num")
567			p.Out()
568			p.P(`}`)
569		} else if repeated {
570			p.P(`for _, num := range m.`, fieldname, ` {`)
571			p.In()
572			p.encodeKey(fieldNumber, wireType)
573			p.callFixed32("num")
574			p.Out()
575			p.P(`}`)
576		} else if proto3 {
577			p.P(`if m.`, fieldname, ` != 0 {`)
578			p.In()
579			p.encodeKey(fieldNumber, wireType)
580			p.callFixed32("m." + fieldname)
581			p.Out()
582			p.P(`}`)
583		} else if !nullable {
584			p.encodeKey(fieldNumber, wireType)
585			p.callFixed32("m." + fieldname)
586		} else {
587			p.encodeKey(fieldNumber, wireType)
588			p.callFixed32("*m." + fieldname)
589		}
590	case descriptor.FieldDescriptorProto_TYPE_BOOL:
591		if packed {
592			p.encodeKey(fieldNumber, wireType)
593			p.callVarint(`len(m.`, fieldname, `)`)
594			p.P(`for _, b := range m.`, fieldname, ` {`)
595			p.In()
596			p.P(`if b {`)
597			p.In()
598			p.P(`dAtA[i] = 1`)
599			p.Out()
600			p.P(`} else {`)
601			p.In()
602			p.P(`dAtA[i] = 0`)
603			p.Out()
604			p.P(`}`)
605			p.P(`i++`)
606			p.Out()
607			p.P(`}`)
608		} else if repeated {
609			p.P(`for _, b := range m.`, fieldname, ` {`)
610			p.In()
611			p.encodeKey(fieldNumber, wireType)
612			p.P(`if b {`)
613			p.In()
614			p.P(`dAtA[i] = 1`)
615			p.Out()
616			p.P(`} else {`)
617			p.In()
618			p.P(`dAtA[i] = 0`)
619			p.Out()
620			p.P(`}`)
621			p.P(`i++`)
622			p.Out()
623			p.P(`}`)
624		} else if proto3 {
625			p.P(`if m.`, fieldname, ` {`)
626			p.In()
627			p.encodeKey(fieldNumber, wireType)
628			p.P(`if m.`, fieldname, ` {`)
629			p.In()
630			p.P(`dAtA[i] = 1`)
631			p.Out()
632			p.P(`} else {`)
633			p.In()
634			p.P(`dAtA[i] = 0`)
635			p.Out()
636			p.P(`}`)
637			p.P(`i++`)
638			p.Out()
639			p.P(`}`)
640		} else if !nullable {
641			p.encodeKey(fieldNumber, wireType)
642			p.P(`if m.`, fieldname, ` {`)
643			p.In()
644			p.P(`dAtA[i] = 1`)
645			p.Out()
646			p.P(`} else {`)
647			p.In()
648			p.P(`dAtA[i] = 0`)
649			p.Out()
650			p.P(`}`)
651			p.P(`i++`)
652		} else {
653			p.encodeKey(fieldNumber, wireType)
654			p.P(`if *m.`, fieldname, ` {`)
655			p.In()
656			p.P(`dAtA[i] = 1`)
657			p.Out()
658			p.P(`} else {`)
659			p.In()
660			p.P(`dAtA[i] = 0`)
661			p.Out()
662			p.P(`}`)
663			p.P(`i++`)
664		}
665	case descriptor.FieldDescriptorProto_TYPE_STRING:
666		if repeated {
667			p.P(`for _, s := range m.`, fieldname, ` {`)
668			p.In()
669			p.encodeKey(fieldNumber, wireType)
670			p.P(`l = len(s)`)
671			p.encodeVarint("l")
672			p.P(`i+=copy(dAtA[i:], s)`)
673			p.Out()
674			p.P(`}`)
675		} else if proto3 {
676			p.P(`if len(m.`, fieldname, `) > 0 {`)
677			p.In()
678			p.encodeKey(fieldNumber, wireType)
679			p.callVarint(`len(m.`, fieldname, `)`)
680			p.P(`i+=copy(dAtA[i:], m.`, fieldname, `)`)
681			p.Out()
682			p.P(`}`)
683		} else if !nullable {
684			p.encodeKey(fieldNumber, wireType)
685			p.callVarint(`len(m.`, fieldname, `)`)
686			p.P(`i+=copy(dAtA[i:], m.`, fieldname, `)`)
687		} else {
688			p.encodeKey(fieldNumber, wireType)
689			p.callVarint(`len(*m.`, fieldname, `)`)
690			p.P(`i+=copy(dAtA[i:], *m.`, fieldname, `)`)
691		}
692	case descriptor.FieldDescriptorProto_TYPE_GROUP:
693		panic(fmt.Errorf("marshaler does not support group %v", fieldname))
694	case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
695		if p.IsMap(field) {
696			m := p.GoMapType(nil, field)
697			keygoTyp, keywire := p.GoType(nil, m.KeyField)
698			keygoAliasTyp, _ := p.GoType(nil, m.KeyAliasField)
699			// keys may not be pointers
700			keygoTyp = strings.Replace(keygoTyp, "*", "", 1)
701			keygoAliasTyp = strings.Replace(keygoAliasTyp, "*", "", 1)
702			keyCapTyp := generator.CamelCase(keygoTyp)
703			valuegoTyp, valuewire := p.GoType(nil, m.ValueField)
704			valuegoAliasTyp, _ := p.GoType(nil, m.ValueAliasField)
705			nullable, valuegoTyp, valuegoAliasTyp = generator.GoMapValueTypes(field, m.ValueField, valuegoTyp, valuegoAliasTyp)
706			keyKeySize := keySize(1, wireToType(keywire))
707			valueKeySize := keySize(2, wireToType(valuewire))
708			if gogoproto.IsStableMarshaler(file.FileDescriptorProto, message.DescriptorProto) {
709				keysName := `keysFor` + fieldname
710				p.P(keysName, ` := make([]`, keygoTyp, `, 0, len(m.`, fieldname, `))`)
711				p.P(`for k, _ := range m.`, fieldname, ` {`)
712				p.In()
713				p.P(keysName, ` = append(`, keysName, `, `, keygoTyp, `(k))`)
714				p.Out()
715				p.P(`}`)
716				p.P(p.sortKeysPkg.Use(), `.`, keyCapTyp, `s(`, keysName, `)`)
717				p.P(`for _, k := range `, keysName, ` {`)
718			} else {
719				p.P(`for k, _ := range m.`, fieldname, ` {`)
720			}
721			p.In()
722			p.encodeKey(fieldNumber, wireType)
723			sum := []string{strconv.Itoa(keyKeySize)}
724			switch m.KeyField.GetType() {
725			case descriptor.FieldDescriptorProto_TYPE_DOUBLE,
726				descriptor.FieldDescriptorProto_TYPE_FIXED64,
727				descriptor.FieldDescriptorProto_TYPE_SFIXED64:
728				sum = append(sum, `8`)
729			case descriptor.FieldDescriptorProto_TYPE_FLOAT,
730				descriptor.FieldDescriptorProto_TYPE_FIXED32,
731				descriptor.FieldDescriptorProto_TYPE_SFIXED32:
732				sum = append(sum, `4`)
733			case descriptor.FieldDescriptorProto_TYPE_INT64,
734				descriptor.FieldDescriptorProto_TYPE_UINT64,
735				descriptor.FieldDescriptorProto_TYPE_UINT32,
736				descriptor.FieldDescriptorProto_TYPE_ENUM,
737				descriptor.FieldDescriptorProto_TYPE_INT32:
738				sum = append(sum, `sov`+p.localName+`(uint64(k))`)
739			case descriptor.FieldDescriptorProto_TYPE_BOOL:
740				sum = append(sum, `1`)
741			case descriptor.FieldDescriptorProto_TYPE_STRING,
742				descriptor.FieldDescriptorProto_TYPE_BYTES:
743				sum = append(sum, `len(k)+sov`+p.localName+`(uint64(len(k)))`)
744			case descriptor.FieldDescriptorProto_TYPE_SINT32,
745				descriptor.FieldDescriptorProto_TYPE_SINT64:
746				sum = append(sum, `soz`+p.localName+`(uint64(k))`)
747			}
748			if gogoproto.IsStableMarshaler(file.FileDescriptorProto, message.DescriptorProto) {
749				p.P(`v := m.`, fieldname, `[`, keygoAliasTyp, `(k)]`)
750			} else {
751				p.P(`v := m.`, fieldname, `[k]`)
752			}
753			accessor := `v`
754			switch m.ValueField.GetType() {
755			case descriptor.FieldDescriptorProto_TYPE_DOUBLE,
756				descriptor.FieldDescriptorProto_TYPE_FIXED64,
757				descriptor.FieldDescriptorProto_TYPE_SFIXED64:
758				sum = append(sum, strconv.Itoa(valueKeySize))
759				sum = append(sum, strconv.Itoa(8))
760			case descriptor.FieldDescriptorProto_TYPE_FLOAT,
761				descriptor.FieldDescriptorProto_TYPE_FIXED32,
762				descriptor.FieldDescriptorProto_TYPE_SFIXED32:
763				sum = append(sum, strconv.Itoa(valueKeySize))
764				sum = append(sum, strconv.Itoa(4))
765			case descriptor.FieldDescriptorProto_TYPE_INT64,
766				descriptor.FieldDescriptorProto_TYPE_UINT64,
767				descriptor.FieldDescriptorProto_TYPE_UINT32,
768				descriptor.FieldDescriptorProto_TYPE_ENUM,
769				descriptor.FieldDescriptorProto_TYPE_INT32:
770				sum = append(sum, strconv.Itoa(valueKeySize))
771				sum = append(sum, `sov`+p.localName+`(uint64(v))`)
772			case descriptor.FieldDescriptorProto_TYPE_BOOL:
773				sum = append(sum, strconv.Itoa(valueKeySize))
774				sum = append(sum, `1`)
775			case descriptor.FieldDescriptorProto_TYPE_STRING:
776				sum = append(sum, strconv.Itoa(valueKeySize))
777				sum = append(sum, `len(v)+sov`+p.localName+`(uint64(len(v)))`)
778			case descriptor.FieldDescriptorProto_TYPE_BYTES:
779				if gogoproto.IsCustomType(field) {
780					p.P(`cSize := 0`)
781					if gogoproto.IsNullable(field) {
782						p.P(`if `, accessor, ` != nil {`)
783						p.In()
784					}
785					p.P(`cSize = `, accessor, `.Size()`)
786					p.P(`cSize += `, strconv.Itoa(valueKeySize), ` + sov`+p.localName+`(uint64(cSize))`)
787					if gogoproto.IsNullable(field) {
788						p.Out()
789						p.P(`}`)
790					}
791					sum = append(sum, `cSize`)
792				} else {
793					p.P(`byteSize := 0`)
794					if proto3 {
795						p.P(`if len(v) > 0 {`)
796					} else {
797						p.P(`if v != nil {`)
798					}
799					p.In()
800					p.P(`byteSize = `, strconv.Itoa(valueKeySize), ` + len(v)+sov`+p.localName+`(uint64(len(v)))`)
801					p.Out()
802					p.P(`}`)
803					sum = append(sum, `byteSize`)
804				}
805			case descriptor.FieldDescriptorProto_TYPE_SINT32,
806				descriptor.FieldDescriptorProto_TYPE_SINT64:
807				sum = append(sum, strconv.Itoa(valueKeySize))
808				sum = append(sum, `soz`+p.localName+`(uint64(v))`)
809			case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
810				if valuegoTyp != valuegoAliasTyp &&
811					!gogoproto.IsStdType(m.ValueAliasField) {
812					if nullable {
813						// cast back to the type that has the generated methods on it
814						accessor = `((` + valuegoTyp + `)(` + accessor + `))`
815					} else {
816						accessor = `((*` + valuegoTyp + `)(&` + accessor + `))`
817					}
818				} else if !nullable {
819					accessor = `(&v)`
820				}
821				p.P(`msgSize := 0`)
822				p.P(`if `, accessor, ` != nil {`)
823				p.In()
824				if gogoproto.IsStdTime(m.ValueAliasField) {
825					p.P(`msgSize = `, p.typesPkg.Use(), `.SizeOfStdTime(*`, accessor, `)`)
826				} else if gogoproto.IsStdDuration(m.ValueAliasField) {
827					p.P(`msgSize = `, p.typesPkg.Use(), `.SizeOfStdDuration(*`, accessor, `)`)
828				} else if gogoproto.IsStdDouble(m.ValueAliasField) {
829					p.P(`msgSize = `, p.typesPkg.Use(), `.SizeOfStdDouble(*`, accessor, `)`)
830				} else if gogoproto.IsStdFloat(m.ValueAliasField) {
831					p.P(`msgSize = `, p.typesPkg.Use(), `.SizeOfStdFloat(*`, accessor, `)`)
832				} else if gogoproto.IsStdInt64(m.ValueAliasField) {
833					p.P(`msgSize = `, p.typesPkg.Use(), `.SizeOfStdInt64(*`, accessor, `)`)
834				} else if gogoproto.IsStdUInt64(m.ValueAliasField) {
835					p.P(`msgSize = `, p.typesPkg.Use(), `.SizeOfStdUInt64(*`, accessor, `)`)
836				} else if gogoproto.IsStdInt32(m.ValueAliasField) {
837					p.P(`msgSize = `, p.typesPkg.Use(), `.SizeOfStdInt32(*`, accessor, `)`)
838				} else if gogoproto.IsStdUInt32(m.ValueAliasField) {
839					p.P(`msgSize = `, p.typesPkg.Use(), `.SizeOfStdUInt32(*`, accessor, `)`)
840				} else if gogoproto.IsStdBool(m.ValueAliasField) {
841					p.P(`msgSize = `, p.typesPkg.Use(), `.SizeOfStdBool(*`, accessor, `)`)
842				} else if gogoproto.IsStdString(m.ValueAliasField) {
843					p.P(`msgSize = `, p.typesPkg.Use(), `.SizeOfStdString(*`, accessor, `)`)
844				} else if gogoproto.IsStdBytes(m.ValueAliasField) {
845					p.P(`msgSize = `, p.typesPkg.Use(), `.SizeOfStdBytes(*`, accessor, `)`)
846				} else if protoSizer {
847					p.P(`msgSize = `, accessor, `.ProtoSize()`)
848				} else {
849					p.P(`msgSize = `, accessor, `.Size()`)
850				}
851				p.P(`msgSize += `, strconv.Itoa(valueKeySize), ` + sov`+p.localName+`(uint64(msgSize))`)
852				p.Out()
853				p.P(`}`)
854				sum = append(sum, `msgSize`)
855			}
856			p.P(`mapSize := `, strings.Join(sum, " + "))
857			p.callVarint("mapSize")
858			p.encodeKey(1, wireToType(keywire))
859			p.mapField(numGen, field, m.KeyField, "k", protoSizer)
860			nullableMsg := nullable && (m.ValueField.GetType() == descriptor.FieldDescriptorProto_TYPE_MESSAGE ||
861				gogoproto.IsCustomType(field) && m.ValueField.IsBytes())
862			plainBytes := m.ValueField.IsBytes() && !gogoproto.IsCustomType(field)
863			if nullableMsg {
864				p.P(`if `, accessor, ` != nil { `)
865				p.In()
866			} else if plainBytes {
867				if proto3 {
868					p.P(`if len(`, accessor, `) > 0 {`)
869				} else {
870					p.P(`if `, accessor, ` != nil {`)
871				}
872				p.In()
873			}
874			p.encodeKey(2, wireToType(valuewire))
875			p.mapField(numGen, field, m.ValueAliasField, accessor, protoSizer)
876			if nullableMsg || plainBytes {
877				p.Out()
878				p.P(`}`)
879			}
880			p.Out()
881			p.P(`}`)
882		} else if repeated {
883			p.P(`for _, msg := range m.`, fieldname, ` {`)
884			p.In()
885			p.encodeKey(fieldNumber, wireType)
886			varName := "msg"
887			if gogoproto.IsStdTime(field) {
888				if gogoproto.IsNullable(field) {
889					varName = "*" + varName
890				}
891				p.callVarint(p.typesPkg.Use(), `.SizeOfStdTime(`, varName, `)`)
892				p.P(`n, err := `, p.typesPkg.Use(), `.StdTimeMarshalTo(`, varName, `, dAtA[i:])`)
893			} else if gogoproto.IsStdDuration(field) {
894				if gogoproto.IsNullable(field) {
895					varName = "*" + varName
896				}
897				p.callVarint(p.typesPkg.Use(), `.SizeOfStdDuration(`, varName, `)`)
898				p.P(`n, err := `, p.typesPkg.Use(), `.StdDurationMarshalTo(`, varName, `, dAtA[i:])`)
899			} else if gogoproto.IsStdDouble(field) {
900				if gogoproto.IsNullable(field) {
901					varName = "*" + varName
902				}
903				p.callVarint(p.typesPkg.Use(), `.SizeOfStdDouble(`, varName, `)`)
904				p.P(`n, err := `, p.typesPkg.Use(), `.StdDoubleMarshalTo(`, varName, `, dAtA[i:])`)
905			} else if gogoproto.IsStdFloat(field) {
906				if gogoproto.IsNullable(field) {
907					varName = "*" + varName
908				}
909				p.callVarint(p.typesPkg.Use(), `.SizeOfStdFloat(`, varName, `)`)
910				p.P(`n, err := `, p.typesPkg.Use(), `.StdFloatMarshalTo(`, varName, `, dAtA[i:])`)
911			} else if gogoproto.IsStdInt64(field) {
912				if gogoproto.IsNullable(field) {
913					varName = "*" + varName
914				}
915				p.callVarint(p.typesPkg.Use(), `.SizeOfStdInt64(`, varName, `)`)
916				p.P(`n, err := `, p.typesPkg.Use(), `.StdInt64MarshalTo(`, varName, `, dAtA[i:])`)
917			} else if gogoproto.IsStdUInt64(field) {
918				if gogoproto.IsNullable(field) {
919					varName = "*" + varName
920				}
921				p.callVarint(p.typesPkg.Use(), `.SizeOfStdUInt64(`, varName, `)`)
922				p.P(`n, err := `, p.typesPkg.Use(), `.StdUInt64MarshalTo(`, varName, `, dAtA[i:])`)
923			} else if gogoproto.IsStdInt32(field) {
924				if gogoproto.IsNullable(field) {
925					varName = "*" + varName
926				}
927				p.callVarint(p.typesPkg.Use(), `.SizeOfStdInt32(`, varName, `)`)
928				p.P(`n, err := `, p.typesPkg.Use(), `.StdInt32MarshalTo(`, varName, `, dAtA[i:])`)
929			} else if gogoproto.IsStdUInt32(field) {
930				if gogoproto.IsNullable(field) {
931					varName = "*" + varName
932				}
933				p.callVarint(p.typesPkg.Use(), `.SizeOfStdUInt32(`, varName, `)`)
934				p.P(`n, err := `, p.typesPkg.Use(), `.StdUInt32MarshalTo(`, varName, `, dAtA[i:])`)
935			} else if gogoproto.IsStdBool(field) {
936				if gogoproto.IsNullable(field) {
937					varName = "*" + varName
938				}
939				p.callVarint(p.typesPkg.Use(), `.SizeOfStdBool(`, varName, `)`)
940				p.P(`n, err := `, p.typesPkg.Use(), `.StdBoolMarshalTo(`, varName, `, dAtA[i:])`)
941			} else if gogoproto.IsStdString(field) {
942				if gogoproto.IsNullable(field) {
943					varName = "*" + varName
944				}
945				p.callVarint(p.typesPkg.Use(), `.SizeOfStdString(`, varName, `)`)
946				p.P(`n, err := `, p.typesPkg.Use(), `.StdStringMarshalTo(`, varName, `, dAtA[i:])`)
947			} else if gogoproto.IsStdBytes(field) {
948				if gogoproto.IsNullable(field) {
949					varName = "*" + varName
950				}
951				p.callVarint(p.typesPkg.Use(), `.SizeOfStdBytes(`, varName, `)`)
952				p.P(`n, err := `, p.typesPkg.Use(), `.StdBytesMarshalTo(`, varName, `, dAtA[i:])`)
953			} else if protoSizer {
954				p.callVarint(varName, ".ProtoSize()")
955				p.P(`n, err := `, varName, `.MarshalTo(dAtA[i:])`)
956			} else {
957				p.callVarint(varName, ".Size()")
958				p.P(`n, err := `, varName, `.MarshalTo(dAtA[i:])`)
959			}
960			p.P(`if err != nil {`)
961			p.In()
962			p.P(`return 0, err`)
963			p.Out()
964			p.P(`}`)
965			p.P(`i+=n`)
966			p.Out()
967			p.P(`}`)
968		} else {
969			p.encodeKey(fieldNumber, wireType)
970			varName := `m.` + fieldname
971			if gogoproto.IsStdTime(field) {
972				if gogoproto.IsNullable(field) {
973					varName = "*" + varName
974				}
975				p.callVarint(p.typesPkg.Use(), `.SizeOfStdTime(`, varName, `)`)
976				p.P(`n`, numGen.Next(), `, err := `, p.typesPkg.Use(), `.StdTimeMarshalTo(`, varName, `, dAtA[i:])`)
977			} else if gogoproto.IsStdDuration(field) {
978				if gogoproto.IsNullable(field) {
979					varName = "*" + varName
980				}
981				p.callVarint(p.typesPkg.Use(), `.SizeOfStdDuration(`, varName, `)`)
982				p.P(`n`, numGen.Next(), `, err := `, p.typesPkg.Use(), `.StdDurationMarshalTo(`, varName, `, dAtA[i:])`)
983			} else if gogoproto.IsStdDouble(field) {
984				if gogoproto.IsNullable(field) {
985					varName = "*" + varName
986				}
987				p.callVarint(p.typesPkg.Use(), `.SizeOfStdDouble(`, varName, `)`)
988				p.P(`n`, numGen.Next(), `, err := `, p.typesPkg.Use(), `.StdDoubleMarshalTo(`, varName, `, dAtA[i:])`)
989			} else if gogoproto.IsStdFloat(field) {
990				if gogoproto.IsNullable(field) {
991					varName = "*" + varName
992				}
993				p.callVarint(p.typesPkg.Use(), `.SizeOfStdFloat(`, varName, `)`)
994				p.P(`n`, numGen.Next(), `, err := `, p.typesPkg.Use(), `.StdFloatMarshalTo(`, varName, `, dAtA[i:])`)
995			} else if gogoproto.IsStdInt64(field) {
996				if gogoproto.IsNullable(field) {
997					varName = "*" + varName
998				}
999				p.callVarint(p.typesPkg.Use(), `.SizeOfStdInt64(`, varName, `)`)
1000				p.P(`n`, numGen.Next(), `, err := `, p.typesPkg.Use(), `.StdInt64MarshalTo(`, varName, `, dAtA[i:])`)
1001			} else if gogoproto.IsStdUInt64(field) {
1002				if gogoproto.IsNullable(field) {
1003					varName = "*" + varName
1004				}
1005				p.callVarint(p.typesPkg.Use(), `.SizeOfStdUInt64(`, varName, `)`)
1006				p.P(`n`, numGen.Next(), `, err := `, p.typesPkg.Use(), `.StdUInt64MarshalTo(`, varName, `, dAtA[i:])`)
1007			} else if gogoproto.IsStdInt32(field) {
1008				if gogoproto.IsNullable(field) {
1009					varName = "*" + varName
1010				}
1011				p.callVarint(p.typesPkg.Use(), `.SizeOfStdInt32(`, varName, `)`)
1012				p.P(`n`, numGen.Next(), `, err := `, p.typesPkg.Use(), `.StdInt32MarshalTo(`, varName, `, dAtA[i:])`)
1013			} else if gogoproto.IsStdUInt32(field) {
1014				if gogoproto.IsNullable(field) {
1015					varName = "*" + varName
1016				}
1017				p.callVarint(p.typesPkg.Use(), `.SizeOfStdUInt32(`, varName, `)`)
1018				p.P(`n`, numGen.Next(), `, err := `, p.typesPkg.Use(), `.StdUInt32MarshalTo(`, varName, `, dAtA[i:])`)
1019			} else if gogoproto.IsStdBool(field) {
1020				if gogoproto.IsNullable(field) {
1021					varName = "*" + varName
1022				}
1023				p.callVarint(p.typesPkg.Use(), `.SizeOfStdBool(`, varName, `)`)
1024				p.P(`n`, numGen.Next(), `, err := `, p.typesPkg.Use(), `.StdBoolMarshalTo(`, varName, `, dAtA[i:])`)
1025			} else if gogoproto.IsStdString(field) {
1026				if gogoproto.IsNullable(field) {
1027					varName = "*" + varName
1028				}
1029				p.callVarint(p.typesPkg.Use(), `.SizeOfStdString(`, varName, `)`)
1030				p.P(`n`, numGen.Next(), `, err := `, p.typesPkg.Use(), `.StdStringMarshalTo(`, varName, `, dAtA[i:])`)
1031			} else if gogoproto.IsStdBytes(field) {
1032				if gogoproto.IsNullable(field) {
1033					varName = "*" + varName
1034				}
1035				p.callVarint(p.typesPkg.Use(), `.SizeOfStdBytes(`, varName, `)`)
1036				p.P(`n`, numGen.Next(), `, err := `, p.typesPkg.Use(), `.StdBytesMarshalTo(`, varName, `, dAtA[i:])`)
1037			} else if protoSizer {
1038				p.callVarint(varName, `.ProtoSize()`)
1039				p.P(`n`, numGen.Next(), `, err := `, varName, `.MarshalTo(dAtA[i:])`)
1040			} else {
1041				p.callVarint(varName, `.Size()`)
1042				p.P(`n`, numGen.Next(), `, err := `, varName, `.MarshalTo(dAtA[i:])`)
1043			}
1044			p.P(`if err != nil {`)
1045			p.In()
1046			p.P(`return 0, err`)
1047			p.Out()
1048			p.P(`}`)
1049			p.P(`i+=n`, numGen.Current())
1050		}
1051	case descriptor.FieldDescriptorProto_TYPE_BYTES:
1052		if !gogoproto.IsCustomType(field) {
1053			if repeated {
1054				p.P(`for _, b := range m.`, fieldname, ` {`)
1055				p.In()
1056				p.encodeKey(fieldNumber, wireType)
1057				p.callVarint("len(b)")
1058				p.P(`i+=copy(dAtA[i:], b)`)
1059				p.Out()
1060				p.P(`}`)
1061			} else if proto3 {
1062				p.P(`if len(m.`, fieldname, `) > 0 {`)
1063				p.In()
1064				p.encodeKey(fieldNumber, wireType)
1065				p.callVarint(`len(m.`, fieldname, `)`)
1066				p.P(`i+=copy(dAtA[i:], m.`, fieldname, `)`)
1067				p.Out()
1068				p.P(`}`)
1069			} else {
1070				p.encodeKey(fieldNumber, wireType)
1071				p.callVarint(`len(m.`, fieldname, `)`)
1072				p.P(`i+=copy(dAtA[i:], m.`, fieldname, `)`)
1073			}
1074		} else {
1075			if repeated {
1076				p.P(`for _, msg := range m.`, fieldname, ` {`)
1077				p.In()
1078				p.encodeKey(fieldNumber, wireType)
1079				if protoSizer {
1080					p.callVarint(`msg.ProtoSize()`)
1081				} else {
1082					p.callVarint(`msg.Size()`)
1083				}
1084				p.P(`n, err := msg.MarshalTo(dAtA[i:])`)
1085				p.P(`if err != nil {`)
1086				p.In()
1087				p.P(`return 0, err`)
1088				p.Out()
1089				p.P(`}`)
1090				p.P(`i+=n`)
1091				p.Out()
1092				p.P(`}`)
1093			} else {
1094				p.encodeKey(fieldNumber, wireType)
1095				if protoSizer {
1096					p.callVarint(`m.`, fieldname, `.ProtoSize()`)
1097				} else {
1098					p.callVarint(`m.`, fieldname, `.Size()`)
1099				}
1100				p.P(`n`, numGen.Next(), `, err := m.`, fieldname, `.MarshalTo(dAtA[i:])`)
1101				p.P(`if err != nil {`)
1102				p.In()
1103				p.P(`return 0, err`)
1104				p.Out()
1105				p.P(`}`)
1106				p.P(`i+=n`, numGen.Current())
1107			}
1108		}
1109	case descriptor.FieldDescriptorProto_TYPE_SINT32:
1110		if packed {
1111			datavar := "dAtA" + numGen.Next()
1112			jvar := "j" + numGen.Next()
1113			p.P(datavar, ` := make([]byte, len(m.`, fieldname, ")*5)")
1114			p.P(`var `, jvar, ` int`)
1115			p.P(`for _, num := range m.`, fieldname, ` {`)
1116			p.In()
1117			xvar := "x" + numGen.Next()
1118			p.P(xvar, ` := (uint32(num) << 1) ^ uint32((num >> 31))`)
1119			p.P(`for `, xvar, ` >= 1<<7 {`)
1120			p.In()
1121			p.P(datavar, `[`, jvar, `] = uint8(uint64(`, xvar, `)&0x7f|0x80)`)
1122			p.P(jvar, `++`)
1123			p.P(xvar, ` >>= 7`)
1124			p.Out()
1125			p.P(`}`)
1126			p.P(datavar, `[`, jvar, `] = uint8(`, xvar, `)`)
1127			p.P(jvar, `++`)
1128			p.Out()
1129			p.P(`}`)
1130			p.encodeKey(fieldNumber, wireType)
1131			p.callVarint(jvar)
1132			p.P(`i+=copy(dAtA[i:], `, datavar, `[:`, jvar, `])`)
1133		} else if repeated {
1134			p.P(`for _, num := range m.`, fieldname, ` {`)
1135			p.In()
1136			p.encodeKey(fieldNumber, wireType)
1137			p.P(`x`, numGen.Next(), ` := (uint32(num) << 1) ^ uint32((num >> 31))`)
1138			p.encodeVarint("x" + numGen.Current())
1139			p.Out()
1140			p.P(`}`)
1141		} else if proto3 {
1142			p.P(`if m.`, fieldname, ` != 0 {`)
1143			p.In()
1144			p.encodeKey(fieldNumber, wireType)
1145			p.callVarint(`(uint32(m.`, fieldname, `) << 1) ^ uint32((m.`, fieldname, ` >> 31))`)
1146			p.Out()
1147			p.P(`}`)
1148		} else if !nullable {
1149			p.encodeKey(fieldNumber, wireType)
1150			p.callVarint(`(uint32(m.`, fieldname, `) << 1) ^ uint32((m.`, fieldname, ` >> 31))`)
1151		} else {
1152			p.encodeKey(fieldNumber, wireType)
1153			p.callVarint(`(uint32(*m.`, fieldname, `) << 1) ^ uint32((*m.`, fieldname, ` >> 31))`)
1154		}
1155	case descriptor.FieldDescriptorProto_TYPE_SINT64:
1156		if packed {
1157			jvar := "j" + numGen.Next()
1158			xvar := "x" + numGen.Next()
1159			datavar := "dAtA" + numGen.Next()
1160			p.P(`var `, jvar, ` int`)
1161			p.P(datavar, ` := make([]byte, len(m.`, fieldname, `)*10)`)
1162			p.P(`for _, num := range m.`, fieldname, ` {`)
1163			p.In()
1164			p.P(xvar, ` := (uint64(num) << 1) ^ uint64((num >> 63))`)
1165			p.P(`for `, xvar, ` >= 1<<7 {`)
1166			p.In()
1167			p.P(datavar, `[`, jvar, `] = uint8(uint64(`, xvar, `)&0x7f|0x80)`)
1168			p.P(jvar, `++`)
1169			p.P(xvar, ` >>= 7`)
1170			p.Out()
1171			p.P(`}`)
1172			p.P(datavar, `[`, jvar, `] = uint8(`, xvar, `)`)
1173			p.P(jvar, `++`)
1174			p.Out()
1175			p.P(`}`)
1176			p.encodeKey(fieldNumber, wireType)
1177			p.callVarint(jvar)
1178			p.P(`i+=copy(dAtA[i:], `, datavar, `[:`, jvar, `])`)
1179		} else if repeated {
1180			p.P(`for _, num := range m.`, fieldname, ` {`)
1181			p.In()
1182			p.encodeKey(fieldNumber, wireType)
1183			p.P(`x`, numGen.Next(), ` := (uint64(num) << 1) ^ uint64((num >> 63))`)
1184			p.encodeVarint("x" + numGen.Current())
1185			p.Out()
1186			p.P(`}`)
1187		} else if proto3 {
1188			p.P(`if m.`, fieldname, ` != 0 {`)
1189			p.In()
1190			p.encodeKey(fieldNumber, wireType)
1191			p.callVarint(`(uint64(m.`, fieldname, `) << 1) ^ uint64((m.`, fieldname, ` >> 63))`)
1192			p.Out()
1193			p.P(`}`)
1194		} else if !nullable {
1195			p.encodeKey(fieldNumber, wireType)
1196			p.callVarint(`(uint64(m.`, fieldname, `) << 1) ^ uint64((m.`, fieldname, ` >> 63))`)
1197		} else {
1198			p.encodeKey(fieldNumber, wireType)
1199			p.callVarint(`(uint64(*m.`, fieldname, `) << 1) ^ uint64((*m.`, fieldname, ` >> 63))`)
1200		}
1201	default:
1202		panic("not implemented")
1203	}
1204	if (required && nullable) || repeated || doNilCheck {
1205		p.Out()
1206		p.P(`}`)
1207	}
1208}
1209
1210func (p *marshalto) Generate(file *generator.FileDescriptor) {
1211	numGen := NewNumGen()
1212	p.PluginImports = generator.NewPluginImports(p.Generator)
1213
1214	p.atleastOne = false
1215	p.localName = generator.FileName(file)
1216
1217	p.mathPkg = p.NewImport("math")
1218	p.sortKeysPkg = p.NewImport("github.com/gogo/protobuf/sortkeys")
1219	p.protoPkg = p.NewImport("github.com/gogo/protobuf/proto")
1220	if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
1221		p.protoPkg = p.NewImport("github.com/golang/protobuf/proto")
1222	}
1223	p.errorsPkg = p.NewImport("errors")
1224	p.binaryPkg = p.NewImport("encoding/binary")
1225	p.typesPkg = p.NewImport("github.com/gogo/protobuf/types")
1226
1227	for _, message := range file.Messages() {
1228		if message.DescriptorProto.GetOptions().GetMapEntry() {
1229			continue
1230		}
1231		ccTypeName := generator.CamelCaseSlice(message.TypeName())
1232		if !gogoproto.IsMarshaler(file.FileDescriptorProto, message.DescriptorProto) &&
1233			!gogoproto.IsUnsafeMarshaler(file.FileDescriptorProto, message.DescriptorProto) {
1234			continue
1235		}
1236		p.atleastOne = true
1237
1238		p.P(`func (m *`, ccTypeName, `) Marshal() (dAtA []byte, err error) {`)
1239		p.In()
1240		if gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto) {
1241			p.P(`size := m.ProtoSize()`)
1242		} else {
1243			p.P(`size := m.Size()`)
1244		}
1245		p.P(`dAtA = make([]byte, size)`)
1246		p.P(`n, err := m.MarshalTo(dAtA)`)
1247		p.P(`if err != nil {`)
1248		p.In()
1249		p.P(`return nil, err`)
1250		p.Out()
1251		p.P(`}`)
1252		p.P(`return dAtA[:n], nil`)
1253		p.Out()
1254		p.P(`}`)
1255		p.P(``)
1256		p.P(`func (m *`, ccTypeName, `) MarshalTo(dAtA []byte) (int, error) {`)
1257		p.In()
1258		p.P(`var i int`)
1259		p.P(`_ = i`)
1260		p.P(`var l int`)
1261		p.P(`_ = l`)
1262		fields := orderFields(message.GetField())
1263		sort.Sort(fields)
1264		oneofs := make(map[string]struct{})
1265		for _, field := range message.Field {
1266			oneof := field.OneofIndex != nil
1267			if !oneof {
1268				proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
1269				p.generateField(proto3, numGen, file, message, field)
1270			} else {
1271				fieldname := p.GetFieldName(message, field)
1272				if _, ok := oneofs[fieldname]; !ok {
1273					oneofs[fieldname] = struct{}{}
1274					p.P(`if m.`, fieldname, ` != nil {`)
1275					p.In()
1276					p.P(`nn`, numGen.Next(), `, err := m.`, fieldname, `.MarshalTo(dAtA[i:])`)
1277					p.P(`if err != nil {`)
1278					p.In()
1279					p.P(`return 0, err`)
1280					p.Out()
1281					p.P(`}`)
1282					p.P(`i+=nn`, numGen.Current())
1283					p.Out()
1284					p.P(`}`)
1285				}
1286			}
1287		}
1288		if message.DescriptorProto.HasExtension() {
1289			if gogoproto.HasExtensionsMap(file.FileDescriptorProto, message.DescriptorProto) {
1290				p.P(`n, err := `, p.protoPkg.Use(), `.EncodeInternalExtension(m, dAtA[i:])`)
1291				p.P(`if err != nil {`)
1292				p.In()
1293				p.P(`return 0, err`)
1294				p.Out()
1295				p.P(`}`)
1296				p.P(`i+=n`)
1297			} else {
1298				p.P(`if m.XXX_extensions != nil {`)
1299				p.In()
1300				p.P(`i+=copy(dAtA[i:], m.XXX_extensions)`)
1301				p.Out()
1302				p.P(`}`)
1303			}
1304		}
1305		if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) {
1306			p.P(`if m.XXX_unrecognized != nil {`)
1307			p.In()
1308			p.P(`i+=copy(dAtA[i:], m.XXX_unrecognized)`)
1309			p.Out()
1310			p.P(`}`)
1311		}
1312
1313		p.P(`return i, nil`)
1314		p.Out()
1315		p.P(`}`)
1316		p.P()
1317
1318		//Generate MarshalTo methods for oneof fields
1319		m := proto.Clone(message.DescriptorProto).(*descriptor.DescriptorProto)
1320		for _, field := range m.Field {
1321			oneof := field.OneofIndex != nil
1322			if !oneof {
1323				continue
1324			}
1325			ccTypeName := p.OneOfTypeName(message, field)
1326			p.P(`func (m *`, ccTypeName, `) MarshalTo(dAtA []byte) (int, error) {`)
1327			p.In()
1328			p.P(`i := 0`)
1329			vanity.TurnOffNullableForNativeTypes(field)
1330			p.generateField(false, numGen, file, message, field)
1331			p.P(`return i, nil`)
1332			p.Out()
1333			p.P(`}`)
1334		}
1335	}
1336
1337	if p.atleastOne {
1338		p.P(`func encodeVarint`, p.localName, `(dAtA []byte, offset int, v uint64) int {`)
1339		p.In()
1340		p.P(`for v >= 1<<7 {`)
1341		p.In()
1342		p.P(`dAtA[offset] = uint8(v&0x7f|0x80)`)
1343		p.P(`v >>= 7`)
1344		p.P(`offset++`)
1345		p.Out()
1346		p.P(`}`)
1347		p.P(`dAtA[offset] = uint8(v)`)
1348		p.P(`return offset+1`)
1349		p.Out()
1350		p.P(`}`)
1351	}
1352
1353}
1354
1355func init() {
1356	generator.RegisterPlugin(NewMarshal())
1357}
1358