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