@@ -19,6 +19,8 @@ const (
1919 runtimePackage = protogen .GoImportPath ("github.com/cosmos/cosmos-proto/runtime/zeropb" )
2020)
2121
22+ const unsafeOptimizations = true
23+
2224func init () {
2325 generator .RegisterFeature ("zeropb" , func (gen * generator.GeneratedFile , _ * protogen.Plugin ) generator.FeatureGenerator {
2426 return zeropbFeature {
@@ -179,8 +181,6 @@ func (g zeropbFeature) generateMarshalPrimitive(f *protogen.Field, name, offset
179181 }
180182}
181183
182- const unsafeOptimizations = true
183-
184184func (g zeropbFeature ) generateUnmarshal (m * protogen.Message ) {
185185 g .gen .P ("func (x *" , m .GoIdent , ") UnmarshalZeroPB(buf []byte) (err error) {" )
186186 g .gen .P (" defer func() {" )
@@ -190,21 +190,71 @@ func (g zeropbFeature) generateUnmarshal(m *protogen.Message) {
190190 g .gen .P (" }()" )
191191 g .gen .P (" var mem []byte" )
192192 if unsafeOptimizations {
193- g .gen .P ("mem = make([]byte, 251)" )
193+ g .gen .P ("memSize := _" , m .GoIdent , "UnmarshalZeroPBSize(buf, 0)" )
194+ g .gen .P ("mem = make([]byte, memSize)" )
194195 }
195196 g .gen .P (" x.unmarshalZeroPB(buf, 0, " , runtimePackage .Ident ("NewBuffer" ), "(mem))" )
196197 g .gen .P (" return nil" )
197198 g .gen .P ("}" )
198199 g .gen .P ()
199- g .gen .P ("func (x * " , m .GoIdent , ") unmarshalZeroPB (buf []byte, n uint16, mem *" , runtimePackage . Ident ( "Buffer" ), " ) {" )
200+ g .gen .P ("func _ " , m .GoIdent , "UnmarshalZeroPBSize (buf []byte, n uint16) (size uint16 ) {" )
200201 offset := 0
202+ for _ , f := range m .Fields {
203+ g .generateUnmarshalFieldSize (f , m .GoIdent , offset )
204+ offset += fieldSize (f )
205+ }
206+ g .gen .P (" return" )
207+ g .gen .P ("}" )
208+ g .gen .P ("func (x *" , m .GoIdent , ") unmarshalZeroPB(buf []byte, n uint16, mem *" , runtimePackage .Ident ("Buffer" ), ") {" )
209+ offset = 0
201210 for _ , f := range m .Fields {
202211 g .generateUnmarshalField (f , offset )
203212 offset += fieldSize (f )
204213 }
205214 g .gen .P ("}" )
206215}
207216
217+ func (g zeropbFeature ) generateUnmarshalFieldSize (f * protogen.Field , typ protogen.GoIdent , offset int ) {
218+ d := f .Desc
219+ switch {
220+ case d .IsList ():
221+ g .gen .P ("n_" , d .Index (), ", len_" , d .Index (), " := " , runtimePackage .Ident ("ReadSlice" ), "(buf, n+" , offset , ")" )
222+ g .gen .P ("_ = n_" , d .Index ())
223+ g .gen .P ("size += len_" , d .Index (), "*uint16(" , unsafePackage .Ident ("Sizeof" ), "((" , typ , "{})." , f .GoName , "[0]))" )
224+ g .gen .P ("for i := uint16(0); i < len_" , d .Index (), "; i++ {" )
225+ // Skip segment header.
226+ g .generateUnmarshalPrimitiveSize (f , fmt .Sprintf ("n_%d+%d+uint16(i)*%d" , d .Index (), segmentHeaderSize , fieldElemSize (f )))
227+ g .gen .P ("}" )
228+ case d .IsMap ():
229+ g .gen .P ("n_" , d .Index (), ", len_" , d .Index (), " := " , runtimePackage .Ident ("ReadSlice" ), "(buf, n+" , offset , ")" )
230+ g .gen .P ("{" )
231+ g .gen .P (" n := n_" , d .Index (), "; _ = n" )
232+ g .gen .P (" for i := uint16(0); i < len_" , d .Index (), "; i++ {" )
233+ g .generateUnmarshalPrimitiveSize (f .Message .Fields [0 ], "n" )
234+ g .gen .P (" n += " , fieldSize (f .Message .Fields [0 ]))
235+ g .generateUnmarshalPrimitiveSize (f .Message .Fields [1 ], "n" )
236+ g .gen .P (" n += " , fieldSize (f .Message .Fields [1 ]))
237+ g .gen .P (" }" )
238+ g .gen .P ("}" )
239+ case d .ContainingOneof () != nil :
240+ g .gen .P ("// TODO: field " , f .GoName )
241+ default :
242+ g .generateUnmarshalPrimitiveSize (f , fmt .Sprintf ("n+%d" , offset ))
243+ }
244+ }
245+
246+ func (g zeropbFeature ) generateUnmarshalPrimitiveSize (f * protogen.Field , offset string ) {
247+ switch d := f .Desc ; d .Kind () {
248+ case protoreflect .StringKind , protoreflect .BytesKind :
249+ g .gen .P ("_, len_" , d .Index (), " := " , runtimePackage .Ident ("ReadSlice" ), "(buf, " , offset , ")" )
250+ g .gen .P ("size += len_" , d .Index (), "*uint16(" , unsafePackage .Ident ("Sizeof" ), "(byte(0)))" )
251+ case protoreflect .MessageKind :
252+ g .gen .P ("size += uint16(" , unsafePackage .Ident ("Sizeof" ), "(" , f .Message .GoIdent , "{}))" )
253+ g .gen .P ("size += _" , f .Message .GoIdent , "UnmarshalZeroPBSize(buf, " , offset , ")" )
254+ default :
255+ }
256+ }
257+
208258func (g zeropbFeature ) generateUnmarshalField (f * protogen.Field , offset int ) {
209259 d := f .Desc
210260 switch {
@@ -217,11 +267,8 @@ func (g zeropbFeature) generateUnmarshalField(f *protogen.Field, offset int) {
217267 } else {
218268 g .gen .P ("x." , f .GoName , " = make([]" , typ , ", len_" , d .Index (), ")" )
219269 }
220- g .gen .P ("{" )
221- g .gen .P (" for i := range x." , f .GoName , "{" )
222- // Skip segment header.
223- g .generateUnmarshalPrimitive (f , "x." + f .GoName + "[i]" , fmt .Sprintf ("n_%d+4+uint16(i)*%d" , d .Index (), fieldElemSize (f )))
224- g .gen .P (" }" )
270+ g .gen .P ("for i := range x." , f .GoName , "{" )
271+ g .generateUnmarshalPrimitive (f , "x." + f .GoName + "[i]" , fmt .Sprintf ("n_%d+%d+uint16(i)*%d" , d .Index (), segmentHeaderSize , fieldElemSize (f )))
225272 g .gen .P ("}" )
226273 case d .IsMap ():
227274 g .gen .P ("n_" , d .Index (), ", len_" , d .Index (), " := " , runtimePackage .Ident ("ReadSlice" ), "(buf, n+" , offset , ")" )
@@ -280,7 +327,7 @@ func (g zeropbFeature) generateUnmarshalPrimitive(f *protogen.Field, name, offse
280327 if d .Kind () == protoreflect .BytesKind {
281328 g .gen .P (name , " = mem_" , d .Index (), ".Buf" )
282329 } else {
283- g .gen .P (name , " = " , unsafePackage .Ident ("String" ), "(unsafe. SliceData(mem_" , d .Index (), ".Buf), len(mem_" , d .Index (), ".Buf))" )
330+ g .gen .P (name , " = " , unsafePackage .Ident ("String" ), "(" , unsafePackage . Ident ( " SliceData" ), " (mem_" , d .Index (), ".Buf), len(mem_" , d .Index (), ".Buf))" )
284331 }
285332 } else {
286333 if d .Kind () == protoreflect .BytesKind {
0 commit comments