github.com/cosmos/cosmos-proto@v1.0.0-beta.3/features/fastreflection/proto_marshal.go (about)

     1  package fastreflection
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/cosmos/cosmos-proto/generator"
     6  	"google.golang.org/protobuf/compiler/protogen"
     7  	"google.golang.org/protobuf/encoding/protowire"
     8  	"google.golang.org/protobuf/reflect/protoreflect"
     9  	"sort"
    10  	"strconv"
    11  	"strings"
    12  )
    13  
    14  type counter int
    15  
    16  func (cnt *counter) Next() string {
    17  	*cnt++
    18  	return cnt.Current()
    19  }
    20  
    21  func (cnt *counter) Current() string {
    22  	return strconv.Itoa(int(*cnt))
    23  }
    24  
    25  func (g *fastGenerator) genMarshalMethod() {
    26  
    27  	var numGen counter
    28  	// MARSHAL METHOD
    29  	g.P(`marshal := func(input `, protoifacePkg.Ident("MarshalInput"), `) (`, protoifacePkg.Ident("MarshalOutput"), `, error) {`)
    30  
    31  	// setup
    32  	g.P(`x := input.Message.Interface().(*`, g.message.GoIdent, `)`)
    33  	g.P("if x == nil {")
    34  	g.P(`return `, protoifacePkg.Ident("MarshalOutput"), `{`)
    35  	g.P(`		NoUnkeyedLiterals: input.NoUnkeyedLiterals,`)
    36  	g.P(`		Buf: input.Buf,`)
    37  	g.P("}, nil")
    38  	g.P("}")
    39  
    40  	// core
    41  	g.P("options := ", runtimePackage.Ident("MarshalInputToOptions"), "(input)")
    42  	g.P("_ = options")
    43  	g.P("size := options.Size(x)")
    44  	g.P(`dAtA := make([]byte, size)`)
    45  
    46  	// from here we need to do what MarshalToSizedBuffer was doing
    47  	g.P("i := len(dAtA)")
    48  	g.P("_ = i")
    49  	g.P("var l int")
    50  	g.P("_ = l")
    51  	g.P("if x.unknownFields != nil {")
    52  	g.P("i -= len(x.unknownFields)")
    53  	g.P("copy(dAtA[i:], x.unknownFields)")
    54  	g.P("}")
    55  
    56  	// oneofs MUST be marshalled first!
    57  	oneofs := make(map[string]struct{})
    58  	for i := len(g.message.Oneofs) - 1; i >= 0; i-- {
    59  		field := g.message.Oneofs[i]
    60  		fieldname := field.GoName
    61  		if _, ok := oneofs[fieldname]; !ok {
    62  			oneofs[fieldname] = struct{}{}
    63  			g.P("switch x := x.", fieldname, ".(type) {")
    64  			for _, ooField := range field.Fields {
    65  				g.P("case *", ooField.GoIdent, ": ")
    66  				g.marshalField(true, &numGen, ooField, true)
    67  			}
    68  			g.P("}")
    69  		}
    70  	}
    71  
    72  	// here we deep copy the message.Fields slice, since it can corrupt the order of fields
    73  	// causing issues for plugins that depend on the order
    74  	messageFields := make([]*protogen.Field, len(g.message.Fields))
    75  	for i := range g.message.Fields {
    76  		messageFields[i] = g.message.Fields[i]
    77  	}
    78  	sort.Slice(messageFields, func(i, j int) bool {
    79  		return messageFields[i].Desc.Number() < messageFields[j].Desc.Number()
    80  	})
    81  
    82  	// then we do everything else
    83  	for i := len(messageFields) - 1; i >= 0; i-- {
    84  		field := messageFields[i]
    85  		isOneof := field.Oneof != nil && !field.Oneof.Desc.IsSynthetic()
    86  		if !isOneof {
    87  			g.marshalField(true, &numGen, field, false)
    88  		}
    89  	}
    90  
    91  	g.P("if input.Buf != nil {")
    92  	g.P(`input.Buf = append(input.Buf, dAtA...)`)
    93  	g.P("} else {")
    94  	g.P("input.Buf = dAtA")
    95  	g.P("}")
    96  	g.P(`return `, protoifacePkg.Ident("MarshalOutput"), `{`)
    97  	g.P(`		NoUnkeyedLiterals: input.NoUnkeyedLiterals,`)
    98  	g.P(`		Buf: input.Buf,`)
    99  	g.P("}, nil")
   100  	g.P("}")
   101  }
   102  
   103  func (g *fastGenerator) marshalField(proto3 bool, numGen *counter, field *protogen.Field, oneof bool) {
   104  	fieldname := field.GoName
   105  	nullable := field.Message != nil || (field.Oneof != nil && field.Oneof.Desc.IsSynthetic())
   106  	repeated := field.Desc.Cardinality() == protoreflect.Repeated
   107  	if repeated && !oneof {
   108  		g.P(`if len(x.`, fieldname, `) > 0 {`)
   109  	} else if nullable && !oneof {
   110  		g.P(`if x.`, fieldname, ` != nil {`)
   111  	}
   112  	packed := field.Desc.IsPacked()
   113  	wireType := generator.ProtoWireType(field.Desc.Kind())
   114  	fieldNumber := field.Desc.Number()
   115  	if packed {
   116  		wireType = protowire.BytesType
   117  	}
   118  	switch field.Desc.Kind() {
   119  	case protoreflect.DoubleKind:
   120  		if packed {
   121  			val := g.reverseListRange(`x.`, fieldname)
   122  			g.P(`f`, numGen.Next(), ` := `, g.Ident("math", "Float64bits"), `(float64(`, val, `))`)
   123  			g.encodeFixed64("f", numGen.Current())
   124  			g.P(`}`)
   125  			g.encodeVarint(`len(x.`, fieldname, `) * 8`)
   126  			g.encodeKey(fieldNumber, wireType)
   127  		} else if repeated {
   128  			val := g.reverseListRange(`x.`, fieldname)
   129  			g.P(`f`, numGen.Next(), ` := `, g.Ident("math", "Float64bits"), `(float64(`, val, `))`)
   130  			g.encodeFixed64("f", numGen.Current())
   131  			g.encodeKey(fieldNumber, wireType)
   132  			g.P(`}`)
   133  		} else if nullable {
   134  			g.encodeFixed64(g.Ident("math", "Float64bits"), `(float64(*x.`+fieldname, `))`)
   135  			g.encodeKey(fieldNumber, wireType)
   136  		} else if proto3 {
   137  			if !oneof {
   138  				g.P(`if x.`, fieldname, ` != 0 || `, mathPackage.Ident("Signbit"), `(x.`, fieldname, `) {`)
   139  			}
   140  			g.encodeFixed64(g.Ident("math", "Float64bits"), `(float64(x.`, fieldname, `))`)
   141  			g.encodeKey(fieldNumber, wireType)
   142  			if !oneof {
   143  				g.P(`}`)
   144  			}
   145  		} else {
   146  			g.encodeFixed64(g.Ident("math", "Float64bits"), `(float64(x.`+fieldname, `))`)
   147  			g.encodeKey(fieldNumber, wireType)
   148  		}
   149  	case protoreflect.FloatKind:
   150  		if packed {
   151  			val := g.reverseListRange(`x.`, fieldname)
   152  			g.P(`f`, numGen.Next(), ` := `, g.Ident("math", "Float32bits"), `(float32(`, val, `))`)
   153  			g.encodeFixed32("f" + numGen.Current())
   154  			g.P(`}`)
   155  			g.encodeVarint(`len(x.`, fieldname, `) * 4`)
   156  			g.encodeKey(fieldNumber, wireType)
   157  		} else if repeated {
   158  			val := g.reverseListRange(`x.`, fieldname)
   159  			g.P(`f`, numGen.Next(), ` := `, g.Ident("math", "Float32bits"), `(float32(`, val, `))`)
   160  			g.encodeFixed32("f" + numGen.Current())
   161  			g.encodeKey(fieldNumber, wireType)
   162  			g.P(`}`)
   163  		} else if nullable {
   164  			g.encodeFixed32(g.Ident("math", "Float32bits"), `(float32(*x.`+fieldname, `))`)
   165  			g.encodeKey(fieldNumber, wireType)
   166  		} else if proto3 {
   167  			if !oneof {
   168  				g.P(`if x.`, fieldname, ` != 0 || `, mathPackage.Ident("Signbit"), `(float64(x.`, fieldname, `)) {`)
   169  			}
   170  			g.encodeFixed32(g.Ident("math", "Float32bits"), `(float32(x.`+fieldname, `))`)
   171  			g.encodeKey(fieldNumber, wireType)
   172  			if !oneof {
   173  				g.P(`}`)
   174  			}
   175  		} else {
   176  			g.encodeFixed32(g.Ident("math", "Float32bits"), `(float32(x.`+fieldname, `))`)
   177  			g.encodeKey(fieldNumber, wireType)
   178  		}
   179  	case protoreflect.Int64Kind, protoreflect.Uint64Kind, protoreflect.Int32Kind, protoreflect.Uint32Kind, protoreflect.EnumKind:
   180  		if packed {
   181  			jvar := "j" + numGen.Next()
   182  			total := "pksize" + numGen.Next()
   183  
   184  			g.P(`var `, total, ` int`)
   185  			g.P(`for _, num := range x.`, fieldname, ` {`)
   186  			g.P(total, ` += `, runtimePackage.Ident("Sov"), `(uint64(num))`)
   187  			g.P(`}`)
   188  
   189  			g.P(`i -= `, total)
   190  			g.P(jvar, `:= i`)
   191  
   192  			switch field.Desc.Kind() {
   193  			case protoreflect.Int64Kind, protoreflect.Int32Kind, protoreflect.EnumKind:
   194  				g.P(`for _, num1 := range x.`, fieldname, ` {`)
   195  				g.P(`num := uint64(num1)`)
   196  			default:
   197  				g.P(`for _, num := range x.`, fieldname, ` {`)
   198  			}
   199  			g.P(`for num >= 1<<7 {`)
   200  			g.P(`dAtA[`, jvar, `] = uint8(uint64(num)&0x7f|0x80)`)
   201  			g.P(`num >>= 7`)
   202  			g.P(jvar, `++`)
   203  			g.P(`}`)
   204  			g.P(`dAtA[`, jvar, `] = uint8(num)`)
   205  			g.P(jvar, `++`)
   206  			g.P(`}`)
   207  
   208  			g.encodeVarint(total)
   209  			g.encodeKey(fieldNumber, wireType)
   210  		} else if repeated {
   211  			val := g.reverseListRange(`x.`, fieldname)
   212  			g.encodeVarint(val)
   213  			g.encodeKey(fieldNumber, wireType)
   214  			g.P(`}`)
   215  		} else if nullable {
   216  			g.encodeVarint(`*x.`, fieldname)
   217  			g.encodeKey(fieldNumber, wireType)
   218  		} else if proto3 {
   219  			if !oneof {
   220  				g.P(`if x.`, fieldname, ` != 0 {`)
   221  			}
   222  			g.encodeVarint(`x.`, fieldname)
   223  			g.encodeKey(fieldNumber, wireType)
   224  			if !oneof {
   225  				g.P(`}`)
   226  			}
   227  		} else {
   228  			g.encodeVarint(`x.`, fieldname)
   229  			g.encodeKey(fieldNumber, wireType)
   230  		}
   231  	case protoreflect.Fixed64Kind, protoreflect.Sfixed64Kind:
   232  		if packed {
   233  			val := g.reverseListRange(`x.`, fieldname)
   234  			g.encodeFixed64(val)
   235  			g.P(`}`)
   236  			g.encodeVarint(`len(x.`, fieldname, `) * 8`)
   237  			g.encodeKey(fieldNumber, wireType)
   238  		} else if repeated {
   239  			val := g.reverseListRange(`x.`, fieldname)
   240  			g.encodeFixed64(val)
   241  			g.encodeKey(fieldNumber, wireType)
   242  			g.P(`}`)
   243  		} else if nullable {
   244  			g.encodeFixed64("*x.", fieldname)
   245  			g.encodeKey(fieldNumber, wireType)
   246  		} else if proto3 {
   247  			if !oneof {
   248  				g.P(`if x.`, fieldname, ` != 0 {`)
   249  			}
   250  			g.encodeFixed64("x.", fieldname)
   251  			g.encodeKey(fieldNumber, wireType)
   252  			if !oneof {
   253  				g.P(`}`)
   254  			}
   255  		} else {
   256  			g.encodeFixed64("x.", fieldname)
   257  			g.encodeKey(fieldNumber, wireType)
   258  		}
   259  	case protoreflect.Fixed32Kind, protoreflect.Sfixed32Kind:
   260  		if packed {
   261  			val := g.reverseListRange(`x.`, fieldname)
   262  			g.encodeFixed32(val)
   263  			g.P(`}`)
   264  			g.encodeVarint(`len(x.`, fieldname, `) * 4`)
   265  			g.encodeKey(fieldNumber, wireType)
   266  		} else if repeated {
   267  			val := g.reverseListRange(`x.`, fieldname)
   268  			g.encodeFixed32(val)
   269  			g.encodeKey(fieldNumber, wireType)
   270  			g.P(`}`)
   271  		} else if nullable {
   272  			g.encodeFixed32("*x." + fieldname)
   273  			g.encodeKey(fieldNumber, wireType)
   274  		} else if proto3 {
   275  			if !oneof {
   276  				g.P(`if x.`, fieldname, ` != 0 {`)
   277  			}
   278  			g.encodeFixed32("x." + fieldname)
   279  			g.encodeKey(fieldNumber, wireType)
   280  			if !oneof {
   281  				g.P(`}`)
   282  			}
   283  		} else {
   284  			g.encodeFixed32("x." + fieldname)
   285  			g.encodeKey(fieldNumber, wireType)
   286  		}
   287  	case protoreflect.BoolKind:
   288  		if packed {
   289  			val := g.reverseListRange(`x.`, fieldname)
   290  			g.P(`i--`)
   291  			g.P(`if `, val, ` {`)
   292  			g.P(`dAtA[i] = 1`)
   293  			g.P(`} else {`)
   294  			g.P(`dAtA[i] = 0`)
   295  			g.P(`}`)
   296  			g.P(`}`)
   297  			g.encodeVarint(`len(x.`, fieldname, `)`)
   298  			g.encodeKey(fieldNumber, wireType)
   299  		} else if repeated {
   300  			val := g.reverseListRange(`x.`, fieldname)
   301  			g.P(`i--`)
   302  			g.P(`if `, val, ` {`)
   303  			g.P(`dAtA[i] = 1`)
   304  			g.P(`} else {`)
   305  			g.P(`dAtA[i] = 0`)
   306  			g.P(`}`)
   307  			g.encodeKey(fieldNumber, wireType)
   308  			g.P(`}`)
   309  		} else if nullable {
   310  			g.P(`i--`)
   311  			g.P(`if *x.`, fieldname, ` {`)
   312  			g.P(`dAtA[i] = 1`)
   313  			g.P(`} else {`)
   314  			g.P(`dAtA[i] = 0`)
   315  			g.P(`}`)
   316  			g.encodeKey(fieldNumber, wireType)
   317  		} else if proto3 {
   318  			if !oneof {
   319  				g.P(`if x.`, fieldname, ` {`)
   320  			}
   321  			g.P(`i--`)
   322  			g.P(`if x.`, fieldname, ` {`)
   323  			g.P(`dAtA[i] = 1`)
   324  			g.P(`} else {`)
   325  			g.P(`dAtA[i] = 0`)
   326  			g.P(`}`)
   327  			g.encodeKey(fieldNumber, wireType)
   328  			if !oneof {
   329  				g.P(`}`)
   330  			}
   331  		} else {
   332  			g.P(`i--`)
   333  			g.P(`if x.`, fieldname, ` {`)
   334  			g.P(`dAtA[i] = 1`)
   335  			g.P(`} else {`)
   336  			g.P(`dAtA[i] = 0`)
   337  			g.P(`}`)
   338  			g.encodeKey(fieldNumber, wireType)
   339  		}
   340  	case protoreflect.StringKind:
   341  		if repeated {
   342  			val := g.reverseListRange(`x.`, fieldname)
   343  			g.P(`i -= len(`, val, `)`)
   344  			g.P(`copy(dAtA[i:], `, val, `)`)
   345  			g.encodeVarint(`len(`, val, `)`)
   346  			g.encodeKey(fieldNumber, wireType)
   347  			g.P(`}`)
   348  		} else if nullable {
   349  			g.P(`i -= len(*x.`, fieldname, `)`)
   350  			g.P(`copy(dAtA[i:], *x.`, fieldname, `)`)
   351  			g.encodeVarint(`len(*x.`, fieldname, `)`)
   352  			g.encodeKey(fieldNumber, wireType)
   353  		} else if proto3 {
   354  			if !oneof {
   355  				g.P(`if len(x.`, fieldname, `) > 0 {`)
   356  			}
   357  			g.P(`i -= len(x.`, fieldname, `)`)
   358  			g.P(`copy(dAtA[i:], x.`, fieldname, `)`)
   359  			g.encodeVarint(`len(x.`, fieldname, `)`)
   360  			g.encodeKey(fieldNumber, wireType)
   361  			if !oneof {
   362  				g.P(`}`)
   363  			}
   364  		} else {
   365  			g.P(`i -= len(x.`, fieldname, `)`)
   366  			g.P(`copy(dAtA[i:], x.`, fieldname, `)`)
   367  			g.encodeVarint(`len(x.`, fieldname, `)`)
   368  			g.encodeKey(fieldNumber, wireType)
   369  		}
   370  	case protoreflect.GroupKind:
   371  		panic(fmt.Errorf("marshaler does not support group %v", fieldname))
   372  	case protoreflect.MessageKind:
   373  		if field.Desc.IsMap() {
   374  			goTypK, _ := g.FieldGoType(field.Message.Fields[0])
   375  			goTypV, ptr := g.FieldGoType(field.Message.Fields[1])
   376  			if ptr {
   377  				goTypV = "*" + goTypV
   378  			}
   379  			keyKind := field.Message.Fields[0].Desc.Kind()
   380  			valKind := field.Message.Fields[1].Desc.Kind()
   381  
   382  			_, ok := kindToGoType[keyKind]
   383  			if !ok {
   384  				panic(fmt.Sprintf("pulsar does not support %s types as map keys", field.Desc.MapKey().Kind().String()))
   385  			}
   386  
   387  			g.P("MaRsHaLmAp := func(k ", goTypK, ", v ", goTypV, ") (", protoifacePkg.Ident("MarshalOutput"), ", error) {")
   388  			g.P(`baseI := i`)
   389  			accessor := `v`
   390  			g.mapField(field.Message.Fields[1], accessor)
   391  			g.encodeKey(2, generator.ProtoWireType(valKind))
   392  
   393  			g.mapField(field.Message.Fields[0], "k")
   394  			g.encodeKey(1, generator.ProtoWireType(keyKind))
   395  			g.encodeVarint(`baseI - i`)
   396  			g.encodeKey(fieldNumber, wireType)
   397  			g.P("return ", protoifacePkg.Ident("MarshalOutput"), "{}, nil")
   398  			g.P("}")
   399  
   400  			var val string
   401  			g.P("if options.Deterministic {")
   402  			keysName := `keysFor` + fieldname
   403  			g.P(keysName, ` := make([]`, goTypK, `, 0, len(x.`, fieldname, `))`)
   404  			g.P(`for k := range x.`, fieldname, ` {`)
   405  			g.P(keysName, ` = append(`, keysName, `, `, goTypK, `(k))`)
   406  			g.P(`}`)
   407  			g.P(g.Ident("sort", "Slice"), `(`, keysName, `, func(i, j int) bool {`)
   408  			switch keyKind {
   409  			case protoreflect.BoolKind:
   410  				g.P("return !", keysName, "[i] && ", keysName, "[j]")
   411  			default:
   412  				g.P(`return `, keysName, `[i] < `, keysName, `[j]`)
   413  			}
   414  			g.P(`})`)
   415  			val = g.reverseListRange(keysName)
   416  			g.P(`v := x.`, fieldname, `[`, goTypK, `(`, val, `)]`)
   417  			g.P("out, err := MaRsHaLmAp(", val, ", v)")
   418  			g.P("if err != nil {")
   419  			g.P("return out, err")
   420  			g.P("}")
   421  			g.P("}")
   422  			g.P("} else {")
   423  
   424  			g.P(`for k := range x.`, fieldname, ` {`)
   425  			val = "k"
   426  			g.P(`v := x.`, fieldname, `[`, val, `]`)
   427  			g.P("out, err := MaRsHaLmAp(k,v)")
   428  			g.P("if err != nil {")
   429  			g.P("return out, err")
   430  			g.P("}")
   431  			g.P("}")
   432  			g.P("}")
   433  		} else if repeated {
   434  			val := g.reverseListRange(`x.`, fieldname)
   435  			g.marshalBackward(val, true, field.Message)
   436  			g.encodeKey(fieldNumber, wireType)
   437  			g.P(`}`)
   438  		} else {
   439  			g.marshalBackward(`x.`+fieldname, true, field.Message)
   440  			g.encodeKey(fieldNumber, wireType)
   441  		}
   442  	case protoreflect.BytesKind:
   443  		if repeated {
   444  			val := g.reverseListRange(`x.`, fieldname)
   445  			g.P(`i -= len(`, val, `)`)
   446  			g.P(`copy(dAtA[i:], `, val, `)`)
   447  			g.encodeVarint(`len(`, val, `)`)
   448  			g.encodeKey(fieldNumber, wireType)
   449  			g.P(`}`)
   450  		} else if proto3 {
   451  			if !oneof {
   452  				g.P(`if len(x.`, fieldname, `) > 0 {`)
   453  			}
   454  			g.P(`i -= len(x.`, fieldname, `)`)
   455  			g.P(`copy(dAtA[i:], x.`, fieldname, `)`)
   456  			g.encodeVarint(`len(x.`, fieldname, `)`)
   457  			g.encodeKey(fieldNumber, wireType)
   458  			if !oneof {
   459  				g.P(`}`)
   460  			}
   461  		} else {
   462  			g.P(`i -= len(x.`, fieldname, `)`)
   463  			g.P(`copy(dAtA[i:], x.`, fieldname, `)`)
   464  			g.encodeVarint(`len(x.`, fieldname, `)`)
   465  			g.encodeKey(fieldNumber, wireType)
   466  		}
   467  	case protoreflect.Sint32Kind:
   468  		if packed {
   469  			jvar := "j" + numGen.Next()
   470  			total := "pksize" + numGen.Next()
   471  
   472  			g.P(`var `, total, ` int`)
   473  			g.P(`for _, num := range x.`, fieldname, ` {`)
   474  			g.P(total, ` += `, runtimePackage.Ident("Soz"), `(uint64(num))`)
   475  			g.P(`}`)
   476  			g.P(`i -= `, total)
   477  			g.P(jvar, `:= i`)
   478  
   479  			g.P(`for _, num := range x.`, fieldname, ` {`)
   480  			xvar := "x" + numGen.Next()
   481  			g.P(xvar, ` := (uint32(num) << 1) ^ uint32((num >> 31))`)
   482  			g.P(`for `, xvar, ` >= 1<<7 {`)
   483  			g.P(`dAtA[`, jvar, `] = uint8(uint64(`, xvar, `)&0x7f|0x80)`)
   484  			g.P(jvar, `++`)
   485  			g.P(xvar, ` >>= 7`)
   486  			g.P(`}`)
   487  			g.P(`dAtA[`, jvar, `] = uint8(`, xvar, `)`)
   488  			g.P(jvar, `++`)
   489  			g.P(`}`)
   490  
   491  			g.encodeVarint(total)
   492  			g.encodeKey(fieldNumber, wireType)
   493  		} else if repeated {
   494  			val := g.reverseListRange(`x.`, fieldname)
   495  			g.P(`x`, numGen.Next(), ` := (uint32(`, val, `) << 1) ^ uint32((`, val, ` >> 31))`)
   496  			g.encodeVarint(`x`, numGen.Current())
   497  			g.encodeKey(fieldNumber, wireType)
   498  			g.P(`}`)
   499  		} else if nullable {
   500  			g.encodeVarint(`(uint32(*x.`, fieldname, `) << 1) ^ uint32((*x.`, fieldname, ` >> 31))`)
   501  			g.encodeKey(fieldNumber, wireType)
   502  		} else if proto3 {
   503  			if !oneof {
   504  				g.P(`if x.`, fieldname, ` != 0 {`)
   505  			}
   506  			g.encodeVarint(`(uint32(x.`, fieldname, `) << 1) ^ uint32((x.`, fieldname, ` >> 31))`)
   507  			g.encodeKey(fieldNumber, wireType)
   508  			if !oneof {
   509  				g.P(`}`)
   510  			}
   511  		} else {
   512  			g.encodeVarint(`(uint32(x.`, fieldname, `) << 1) ^ uint32((x.`, fieldname, ` >> 31))`)
   513  			g.encodeKey(fieldNumber, wireType)
   514  		}
   515  	case protoreflect.Sint64Kind:
   516  		if packed {
   517  			jvar := "j" + numGen.Next()
   518  			total := "pksize" + numGen.Next()
   519  
   520  			g.P(`var `, total, ` int`)
   521  			g.P(`for _, num := range x.`, fieldname, ` {`)
   522  			g.P(total, ` += `, runtimePackage.Ident("Soz"), `(uint64(num))`)
   523  			g.P(`}`)
   524  			g.P(`i -= `, total)
   525  			g.P(jvar, `:= i`)
   526  
   527  			g.P(`for _, num := range x.`, fieldname, ` {`)
   528  			xvar := "x" + numGen.Next()
   529  			g.P(xvar, ` := (uint64(num) << 1) ^ uint64((num >> 63))`)
   530  			g.P(`for `, xvar, ` >= 1<<7 {`)
   531  			g.P(`dAtA[`, jvar, `] = uint8(uint64(`, xvar, `)&0x7f|0x80)`)
   532  			g.P(jvar, `++`)
   533  			g.P(xvar, ` >>= 7`)
   534  			g.P(`}`)
   535  			g.P(`dAtA[`, jvar, `] = uint8(`, xvar, `)`)
   536  			g.P(jvar, `++`)
   537  			g.P(`}`)
   538  
   539  			g.encodeVarint(total)
   540  			g.encodeKey(fieldNumber, wireType)
   541  		} else if repeated {
   542  			val := g.reverseListRange(`x.`, fieldname)
   543  			g.P(`x`, numGen.Next(), ` := (uint64(`, val, `) << 1) ^ uint64((`, val, ` >> 63))`)
   544  			g.encodeVarint("x" + numGen.Current())
   545  			g.encodeKey(fieldNumber, wireType)
   546  			g.P(`}`)
   547  		} else if nullable {
   548  			g.encodeVarint(`(uint64(*x.`, fieldname, `) << 1) ^ uint64((*x.`, fieldname, ` >> 63))`)
   549  			g.encodeKey(fieldNumber, wireType)
   550  		} else if proto3 {
   551  			if !oneof {
   552  				g.P(`if x.`, fieldname, ` != 0 {`)
   553  			}
   554  			g.encodeVarint(`(uint64(x.`, fieldname, `) << 1) ^ uint64((x.`, fieldname, ` >> 63))`)
   555  			g.encodeKey(fieldNumber, wireType)
   556  			if !oneof {
   557  				g.P(`}`)
   558  			}
   559  		} else {
   560  			g.encodeVarint(`(uint64(x.`, fieldname, `) << 1) ^ uint64((x.`, fieldname, ` >> 63))`)
   561  			g.encodeKey(fieldNumber, wireType)
   562  		}
   563  	default:
   564  		panic("not implemented")
   565  	}
   566  	if (repeated || nullable) && !oneof {
   567  		g.P(`}`)
   568  	}
   569  }
   570  
   571  func (g *fastGenerator) marshalBackward(varName string, varInt bool, message *protogen.Message) {
   572  	g.P(`encoded, err := `, "options.Marshal(", varName, ")")
   573  	g.P(`if err != nil {`)
   574  	g.P(`return `, protoifacePkg.Ident("MarshalOutput"), " {")
   575  	g.P("NoUnkeyedLiterals: input.NoUnkeyedLiterals,")
   576  	g.P("Buf: input.Buf,")
   577  	g.P("}, err")
   578  	g.P(`}`)
   579  	g.P(`i -= len(encoded)`)
   580  	g.P(`copy(dAtA[i:], encoded)`)
   581  	if varInt {
   582  		g.encodeVarint(`len(encoded)`)
   583  	}
   584  }
   585  
   586  func (g *fastGenerator) reverseListRange(expression ...string) string {
   587  	exp := strings.Join(expression, "")
   588  	g.P(`for iNdEx := len(`, exp, `) - 1; iNdEx >= 0; iNdEx-- {`)
   589  	return exp + `[iNdEx]`
   590  }
   591  
   592  func (g *fastGenerator) encodeFixed64(varName ...string) {
   593  	g.P(`i -= 8`)
   594  	g.P(g.Ident("encoding/binary", "LittleEndian"), `.PutUint64(dAtA[i:], uint64(`, strings.Join(varName, ""), `))`)
   595  }
   596  
   597  func (g *fastGenerator) encodeFixed32(varName ...string) {
   598  	g.P(`i -= 4`)
   599  	g.P(g.Ident("encoding/binary", "LittleEndian"), `.PutUint32(dAtA[i:], uint32(`, strings.Join(varName, ""), `))`)
   600  }
   601  
   602  func (g *fastGenerator) encodeVarint(varName ...string) {
   603  	g.P(`i = `, runtimePackage.Ident("EncodeVarint"), `(dAtA, i, uint64(`, strings.Join(varName, ""), `))`)
   604  }
   605  
   606  func (g *fastGenerator) encodeKey(fieldNumber protoreflect.FieldNumber, wireType protowire.Type) {
   607  	x := uint32(fieldNumber)<<3 | uint32(wireType)
   608  	i := 0
   609  	keybuf := make([]byte, 0)
   610  	for i = 0; x > 127; i++ {
   611  		keybuf = append(keybuf, 0x80|uint8(x&0x7F))
   612  		x >>= 7
   613  	}
   614  	keybuf = append(keybuf, uint8(x))
   615  	for i = len(keybuf) - 1; i >= 0; i-- {
   616  		g.P(`i--`)
   617  		g.P(`dAtA[i] = `, fmt.Sprintf("%#v", keybuf[i]))
   618  	}
   619  }
   620  
   621  func (g *fastGenerator) mapField(kvField *protogen.Field, varName string) {
   622  	switch kvField.Desc.Kind() {
   623  	case protoreflect.DoubleKind:
   624  		g.encodeFixed64(g.Ident("math", "Float64bits"), `(float64(`, varName, `))`)
   625  	case protoreflect.FloatKind:
   626  		g.encodeFixed32(g.Ident("math", "Float32bits"), `(float32(`, varName, `))`)
   627  	case protoreflect.Int64Kind, protoreflect.Uint64Kind, protoreflect.Int32Kind, protoreflect.Uint32Kind, protoreflect.EnumKind:
   628  		g.encodeVarint(varName)
   629  	case protoreflect.Fixed64Kind, protoreflect.Sfixed64Kind:
   630  		g.encodeFixed64(varName)
   631  	case protoreflect.Fixed32Kind, protoreflect.Sfixed32Kind:
   632  		g.encodeFixed32(varName)
   633  	case protoreflect.BoolKind:
   634  		g.P(`i--`)
   635  		g.P(`if `, varName, ` {`)
   636  		g.P(`dAtA[i] = 1`)
   637  		g.P(`} else {`)
   638  		g.P(`dAtA[i] = 0`)
   639  		g.P(`}`)
   640  	case protoreflect.StringKind, protoreflect.BytesKind:
   641  		g.P(`i -= len(`, varName, `)`)
   642  		g.P(`copy(dAtA[i:], `, varName, `)`)
   643  		g.encodeVarint(`len(`, varName, `)`)
   644  	case protoreflect.Sint32Kind:
   645  		g.encodeVarint(`(uint32(`, varName, `) << 1) ^ uint32((`, varName, ` >> 31))`)
   646  	case protoreflect.Sint64Kind:
   647  		g.encodeVarint(`(uint64(`, varName, `) << 1) ^ uint64((`, varName, ` >> 63))`)
   648  	case protoreflect.MessageKind:
   649  		g.marshalBackward(varName, true, kvField.Message)
   650  	}
   651  }