diff --git a/cmd/protoc-gen-go-pulsar/main.go b/cmd/protoc-gen-go-pulsar/main.go index 8fc27ae..891e481 100644 --- a/cmd/protoc-gen-go-pulsar/main.go +++ b/cmd/protoc-gen-go-pulsar/main.go @@ -8,6 +8,7 @@ import ( _ "github.com/cosmos/cosmos-proto/features/fastreflection" _ "github.com/cosmos/cosmos-proto/features/protoc" + _ "github.com/cosmos/cosmos-proto/features/zeropb" "github.com/cosmos/cosmos-proto/generator" "google.golang.org/protobuf/reflect/protoreflect" diff --git a/features/protoc/main.go b/features/protoc/main.go index 3cc5a1a..62aad90 100644 --- a/features/protoc/main.go +++ b/features/protoc/main.go @@ -1448,7 +1448,7 @@ func genMessageField(g *generator.GeneratedFile, f *fileInfo, m *messageInfo, fi sf.append(oneof.GoName) return } - goType, pointer := fieldGoType(g, f, field) + goType, pointer := FieldGoType(g, field) if pointer { goType = "*" + goType } @@ -1490,7 +1490,7 @@ func genMessageDefaultDecls(g *generator.GeneratedFile, f *fileInfo, m *messageI continue } name := "Default_" + m.GoIdent.GoName + "_" + field.GoName - goType, _ := fieldGoType(g, f, field) + goType, _ := FieldGoType(g, field) defVal := field.Desc.Default() switch field.Desc.Kind() { case protoreflect.StringKind: @@ -1610,7 +1610,7 @@ func genMessageGetterMethods(g *generator.GeneratedFile, f *fileInfo, m *message } // Getter for message field. - goType, pointer := fieldGoType(g, f, field) + goType, pointer := FieldGoType(g, field) defaultValue := fieldDefaultValue(g, f, m, field) g.Annotate(m.GoIdent.GoName+".Get"+field.GoName, field.Location) leadingComments := appendDeprecationSuffix("", @@ -1679,10 +1679,27 @@ func genMessageSetterMethods(g *generator.GeneratedFile, f *fileInfo, m *message } } -// fieldGoType returns the Go type used for a field. +// FieldGoType returns the Go type used for a field. // // If it returns pointer=true, the struct field is a pointer to the type. -func fieldGoType(g *generator.GeneratedFile, f *fileInfo, field *protogen.Field) (goType string, pointer bool) { +func FieldGoType(g *generator.GeneratedFile, field *protogen.Field) (goType string, pointer bool) { + switch { + case field.Desc.IsList(): + typ, _ := FieldGoElemType(g, field) + return "[]" + typ, false + case field.Desc.IsMap(): + keyType, _ := FieldGoType(g, field.Message.Fields[0]) + valType, _ := FieldGoType(g, field.Message.Fields[1]) + return fmt.Sprintf("map[%v]%v", keyType, valType), false + } + return FieldGoElemType(g, field) +} + +// FieldElemGoType returns the Go element type used for a field. It is not valid for +// map fields. +// +// If it returns pointer=true, the struct field is a pointer to the type. +func FieldGoElemType(g *generator.GeneratedFile, field *protogen.Field) (goType string, pointer bool) { if field.Desc.IsWeak() { return "struct{}", false } @@ -1714,14 +1731,6 @@ func fieldGoType(g *generator.GeneratedFile, f *fileInfo, field *protogen.Field) goType = "*" + g.QualifiedGoIdent(field.Message.GoIdent) pointer = false // pointer captured as part of the type } - switch { - case field.Desc.IsList(): - return "[]" + goType, false - case field.Desc.IsMap(): - keyType, _ := fieldGoType(g, f, field.Message.Fields[0]) - valType, _ := fieldGoType(g, f, field.Message.Fields[1]) - return fmt.Sprintf("map[%v]%v", keyType, valType), false - } return goType, pointer } @@ -1779,7 +1788,7 @@ func genExtensions(g *generator.GeneratedFile, f *fileInfo) { for _, x := range f.allExtensions { g.P("{") g.P("ExtendedType: (*", x.Extendee.GoIdent, ")(nil),") - goType, pointer := fieldGoType(g, f, x.Extension) + goType, pointer := FieldGoType(g, x.Extension) if pointer { goType = "*" + goType } @@ -1852,7 +1861,7 @@ func genMessageOneofWrapperTypes(g *generator.GeneratedFile, f *fileInfo, m *mes g.Annotate(field.GoIdent.GoName, field.Location) g.Annotate(field.GoIdent.GoName+"."+field.GoName, field.Location) g.P("type ", field.GoIdent, " struct {") - goType, _ := fieldGoType(g, f, field) + goType, _ := FieldGoType(g, field) tags := structTags{ {"protobuf", fieldProtobufTagValue(field)}, } diff --git a/features/zeropb/zeropb.go b/features/zeropb/zeropb.go new file mode 100644 index 0000000..bf1aa72 --- /dev/null +++ b/features/zeropb/zeropb.go @@ -0,0 +1,393 @@ +package zeropb + +import ( + "fmt" + "strconv" + + "github.com/cosmos/cosmos-proto/features/protoc" + "github.com/cosmos/cosmos-proto/generator" + "google.golang.org/protobuf/compiler/protogen" + "google.golang.org/protobuf/reflect/protoreflect" +) + +const ( + errorsPackage = protogen.GoImportPath("errors") + mathPackage = protogen.GoImportPath("math") + binaryPackage = protogen.GoImportPath("encoding/binary") + unsafePackage = protogen.GoImportPath("unsafe") + + runtimePackage = protogen.GoImportPath("github.com/cosmos/cosmos-proto/runtime/zeropb") +) + +const unsafeOptimizations = true + +func init() { + generator.RegisterFeature("zeropb", func(gen *generator.GeneratedFile, _ *protogen.Plugin) generator.FeatureGenerator { + return zeropbFeature{ + gen: gen, + } + }) +} + +type zeropbFeature struct { + gen *generator.GeneratedFile +} + +func (g zeropbFeature) GenerateFile(file *protogen.File, _ *protogen.Plugin) bool { + for _, m := range file.Messages { + g.generateMessage(file, m) + } + return true // only do this once +} + +func (g zeropbFeature) GenerateHelpers() {} + +func (g zeropbFeature) generateMessage(f *protogen.File, m *protogen.Message) { + g.generateMarshal(m) + g.generateUnmarshal(m) +} + +func (g zeropbFeature) generateMarshal(m *protogen.Message) { + g.gen.P("func (x *", m.GoIdent, ") MarshalZeroPB(buf []byte) (n int, err error) {") + g.gen.P(" defer func() {") + g.gen.P(" if e := recover(); e != nil {") + g.gen.P(" err = ", errorsPackage.Ident("New"), `("buffer overflow")`) + g.gen.P(" }") + g.gen.P(" }()") + g.gen.P(" b := ", runtimePackage.Ident("NewBuffer"), "(buf)") + g.gen.P(" x.marshalZeroPB(b, b.Alloc(", structSize(m), "))") + g.gen.P(" return int(b.Allocated()), nil") + g.gen.P("}") + g.gen.P() + g.gen.P("func (x *", m.GoIdent, ") marshalZeroPB(b *", runtimePackage.Ident("Buffer"), ", buf ", runtimePackage.Ident("Allocation"), ") {") + g.gen.P(" if x == nil {") + g.gen.P(" return") + g.gen.P(" }") + offset := 0 + for _, f := range m.Fields { + g.generateMarshalField(f, offset) + offset += fieldSize(f) + } + g.gen.P("}") +} + +const ( + sliceSize = 2 * 2 + segmentHeaderSize = 1 + 1 + 2 +) + +func structSize(m *protogen.Message) int { + n := 0 + for _, f := range m.Fields { + d := f.Desc + switch { + case d.IsList(), d.IsMap(): + n += sliceSize + default: + n += fieldSize(f) + } + } + return n +} + +func fieldSize(f *protogen.Field) int { + d := f.Desc + switch { + case d.IsList(), d.IsMap(): + return 4 + } + return fieldElemSize(f) +} + +func fieldElemSize(f *protogen.Field) int { + d := f.Desc + switch d.Kind() { + case protoreflect.FloatKind: + return 4 + case protoreflect.DoubleKind: + return 8 + case protoreflect.Sfixed32Kind, protoreflect.Fixed32Kind, protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Uint32Kind, protoreflect.EnumKind: + return 4 + case protoreflect.Sfixed64Kind, protoreflect.Fixed64Kind, protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Uint64Kind: + return 8 + case protoreflect.BoolKind: + return 4 + case protoreflect.StringKind, protoreflect.BytesKind: + return sliceSize + case protoreflect.MessageKind: + return structSize(f.Message) + } + return 0 +} + +func (g zeropbFeature) generateMarshalField(f *protogen.Field, offset int) { + d := f.Desc + switch { + case d.IsList(): + g.gen.P("rem_", d.Index(), " := x.", f.GoName) + g.gen.P("var link_", d.Index(), " zeropb.Allocation") + g.gen.P("for len(rem_", d.Index(), ") > 0 {") + g.gen.P(" seg := rem_", d.Index()) + g.gen.P(" if len(seg) > 255 {") + g.gen.P(" seg = seg[:255]") + g.gen.P(" }") + g.gen.P(" rem_", d.Index(), " = rem_", d.Index(), "[len(seg):]") + g.gen.P(" buf_", d.Index(), " := b.Alloc(len(seg)*", fieldElemSize(f), "+", segmentHeaderSize, ")") + g.gen.P(" if link_", d.Index(), ".Buf == nil {") + // Write relative offset and len. + g.gen.P(binaryPackage.Ident("LittleEndian"), ".PutUint16(buf.Buf[", offset, ":], buf_", d.Index(), ".Offset-buf.Offset-", offset, ")") + g.gen.P(binaryPackage.Ident("LittleEndian"), ".PutUint16(buf.Buf[", offset, "+2:], uint16(len(x.", f.GoName, ")))") + g.gen.P(" } else {") + // Write segment link offset. + g.gen.P(binaryPackage.Ident("LittleEndian"), ".PutUint16(link_", d.Index(), ".Buf[2:], buf_", d.Index(), ".Offset-link_", d.Index(), ".Offset-2)") + g.gen.P(" }") + g.gen.P(" {") + g.gen.P(" buf := buf_", d.Index()) + // Write a segment header. + g.gen.P(" buf.Buf[0] = byte(len(seg))") + g.gen.P(" buf.Buf[1] = byte(len(seg))") + g.gen.P(" link_", d.Index(), " = buf") + g.gen.P(" for i, e := range seg {") + g.generateMarshalPrimitive(f, "e", fmt.Sprintf("uint16(i)*%d+4", fieldElemSize(f))) + g.gen.P(" }") + g.gen.P(" }") + g.gen.P("}") + case d.IsMap(): + sz := fieldSize(f.Message.Fields[0]) + fieldSize(f.Message.Fields[1]) + g.gen.P("buf_", d.Index(), " := b.AllocRel(len(x.", f.GoName, ")*", sz, ", buf, ", offset, ", uint16(len(x."+f.GoName+")))") + g.gen.P("{") + g.gen.P(" var n uint16") + g.gen.P(" buf := buf_", d.Index()) + g.gen.P(" for k, v := range x.", f.GoName, " {") + g.generateMarshalPrimitive(f.Message.Fields[0], "k", "n") + g.gen.P(" n += ", fieldSize(f.Message.Fields[0])) + g.generateMarshalPrimitive(f.Message.Fields[1], "v", "n") + g.gen.P(" n += ", fieldSize(f.Message.Fields[1])) + g.gen.P(" }") + g.gen.P("}") + case d.ContainingOneof() != nil: + g.gen.P("// TODO: field ", f.GoName) + return + default: + g.generateMarshalPrimitive(f, "x."+f.GoName, strconv.Itoa(offset)) + } +} + +func (g zeropbFeature) generateMarshalPrimitive(f *protogen.Field, name, offset string) { + d := f.Desc + switch d.Kind() { + case protoreflect.FloatKind: + g.gen.P("binary.LittleEndian.PutUint32(buf.Buf[", offset, ":], ", mathPackage.Ident("Float32bits"), "(", name, "))") + case protoreflect.DoubleKind: + g.gen.P("binary.LittleEndian.PutUint64(buf.Buf[", offset, ":], ", mathPackage.Ident("Float64bits"), "(", name, "))") + case protoreflect.Sfixed32Kind, protoreflect.Fixed32Kind, protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Uint32Kind, protoreflect.EnumKind: + g.gen.P("binary.LittleEndian.PutUint32(buf.Buf[", offset, ":], uint32(", name, "))") + case protoreflect.Sfixed64Kind, protoreflect.Fixed64Kind, protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Uint64Kind: + g.gen.P("binary.LittleEndian.PutUint64(buf.Buf[", offset, ":], uint64(", name, "))") + case protoreflect.BoolKind: + g.gen.P("bool_", d.Index(), " := uint32(0)") + g.gen.P("if ", name, " {") + g.gen.P(" bool_", d.Index(), " = 1") + g.gen.P("}") + g.gen.P("binary.LittleEndian.PutUint32(buf.Buf[", offset, ":], bool_", d.Index(), ")") + case protoreflect.StringKind, protoreflect.BytesKind: + g.gen.P("buf_", d.Index(), " := b.AllocRel(len(", name, "), buf, ", offset, ", uint16(len(", name, ")))") + g.gen.P("copy(buf_", d.Index(), ".Buf, ", name, ")") + case protoreflect.MessageKind: + g.gen.P(name, ".marshalZeroPB(b, buf.Slice(", offset, "))") + default: + g.gen.P("// TODO: field ", name) + g.gen.P("_ = ", name) + } +} + +func (g zeropbFeature) generateUnmarshal(m *protogen.Message) { + g.gen.P("func (x *", m.GoIdent, ") UnmarshalZeroPB(buf []byte) (err error) {") + g.gen.P(" defer func() {") + g.gen.P(" if e := recover(); e != nil {") + g.gen.P(" err = ", errorsPackage.Ident("New"), `("buffer underflow")`) + g.gen.P(" }") + g.gen.P(" }()") + g.gen.P(" var mem []byte") + if unsafeOptimizations { + g.gen.P("memSize := _", m.GoIdent, "UnmarshalZeroPBSize(buf, 0)") + g.gen.P("mem = make([]byte, memSize)") + } + g.gen.P(" x.unmarshalZeroPB(buf, 0, ", runtimePackage.Ident("NewBuffer"), "(mem))") + g.gen.P(" return nil") + g.gen.P("}") + g.gen.P() + g.gen.P("func _", m.GoIdent, "UnmarshalZeroPBSize(buf []byte, n uint16) (size uint16) {") + offset := 0 + for _, f := range m.Fields { + g.generateUnmarshalFieldSize(f, m.GoIdent, offset) + offset += fieldSize(f) + } + g.gen.P(" return") + g.gen.P("}") + g.gen.P("func (x *", m.GoIdent, ") unmarshalZeroPB(buf []byte, n uint16, mem *", runtimePackage.Ident("Buffer"), ") {") + offset = 0 + for _, f := range m.Fields { + g.generateUnmarshalField(f, offset) + offset += fieldSize(f) + } + g.gen.P("}") +} + +func (g zeropbFeature) generateUnmarshalFieldSize(f *protogen.Field, typ protogen.GoIdent, offset int) { + d := f.Desc + switch { + case d.IsList(): + g.gen.P("n_", d.Index(), ", len_", d.Index(), " := ", runtimePackage.Ident("ReadSlice"), "(buf, n+", offset, ")") + g.gen.P("{") + g.gen.P(" n, len := n_", d.Index(), ", len_", d.Index()) + g.gen.P(" size += len*uint16(", unsafePackage.Ident("Sizeof"), "((", typ, "{}).", f.GoName, "[0]))") + g.gen.P(" i8 := byte(0)") + g.gen.P(" segLen := buf[n]") + g.gen.P(" for i := uint16(0); i < len; i++ {") + g.gen.P(" if i8 == segLen {") + g.gen.P(" i8 = 0") + // Read continuation link. + g.gen.P(" n = ", runtimePackage.Ident("ReadOffset"), "(buf, n+2)") + g.gen.P(" segLen = buf[n]") + g.gen.P(" }") + g.generateUnmarshalPrimitiveSize(f, fmt.Sprintf("n+%d+uint16(i8)*%d", segmentHeaderSize, fieldElemSize(f))) + g.gen.P(" i8++") + g.gen.P(" }") + g.gen.P("}") + case d.IsMap(): + g.gen.P("n_", d.Index(), ", len_", d.Index(), " := ", runtimePackage.Ident("ReadSlice"), "(buf, n+", offset, ")") + g.gen.P("{") + g.gen.P(" n := n_", d.Index(), "; _ = n") + g.gen.P(" for i := uint16(0); i < len_", d.Index(), "; i++ {") + g.generateUnmarshalPrimitiveSize(f.Message.Fields[0], "n") + g.gen.P(" n += ", fieldSize(f.Message.Fields[0])) + g.generateUnmarshalPrimitiveSize(f.Message.Fields[1], "n") + g.gen.P(" n += ", fieldSize(f.Message.Fields[1])) + g.gen.P(" }") + g.gen.P("}") + case d.ContainingOneof() != nil: + g.gen.P("// TODO: field ", f.GoName) + default: + g.generateUnmarshalPrimitiveSize(f, fmt.Sprintf("n+%d", offset)) + } +} + +func (g zeropbFeature) generateUnmarshalPrimitiveSize(f *protogen.Field, offset string) { + switch d := f.Desc; d.Kind() { + case protoreflect.StringKind, protoreflect.BytesKind: + g.gen.P("_, len_", d.Index(), " := ", runtimePackage.Ident("ReadSlice"), "(buf, ", offset, ")") + g.gen.P("size += len_", d.Index(), "*uint16(", unsafePackage.Ident("Sizeof"), "(byte(0)))") + case protoreflect.MessageKind: + g.gen.P("size += uint16(", unsafePackage.Ident("Sizeof"), "(", f.Message.GoIdent, "{}))") + g.gen.P("size += _", f.Message.GoIdent, "UnmarshalZeroPBSize(buf, ", offset, ")") + default: + } +} + +func (g zeropbFeature) generateUnmarshalField(f *protogen.Field, offset int) { + d := f.Desc + switch { + case d.IsList(): + g.gen.P("n_", d.Index(), ", len_", d.Index(), " := ", runtimePackage.Ident("ReadSlice"), "(buf, n+", offset, ")") + typ, _ := protoc.FieldGoElemType(g.gen, f) + if unsafeOptimizations { + g.gen.P("mem_", d.Index(), " := mem.Alloc(int(len_", d.Index(), ")*int(", unsafePackage.Ident("Sizeof"), "(x.", f.GoName, "[0])))") + g.gen.P("x.", f.GoName, " = ", unsafePackage.Ident("Slice"), "((*", typ, ")(", unsafePackage.Ident("Pointer"), "(", unsafePackage.Ident("SliceData"), "(mem_", d.Index(), ".Buf))), len_", d.Index(), ")") + } else { + g.gen.P("x.", f.GoName, " = make([]", typ, ", len_", d.Index(), ")") + } + g.gen.P("{") + g.gen.P(" n, len := n_", d.Index(), ", len_", d.Index(), "; _ = len") + g.gen.P(" i8 := byte(0)") + g.gen.P(" segLen := buf[n]") + g.gen.P(" for i := range x.", f.GoName, "{") + g.gen.P(" if i8 == segLen {") + g.gen.P(" i8 = 0") + // Read continuation link. + g.gen.P(" n = ", runtimePackage.Ident("ReadOffset"), "(buf, n+2)") + g.gen.P(" segLen = buf[n]") + g.gen.P(" }") + g.generateUnmarshalPrimitive(f, "x."+f.GoName+"[i]", fmt.Sprintf("n+%d+uint16(i8)*%d", segmentHeaderSize, fieldElemSize(f))) + g.gen.P(" i8++") + g.gen.P(" }") + g.gen.P("}") + case d.IsMap(): + g.gen.P("n_", d.Index(), ", len_", d.Index(), " := ", runtimePackage.Ident("ReadSlice"), "(buf, n+", offset, ")") + typ, _ := protoc.FieldGoType(g.gen, f) + g.gen.P("x.", f.GoName, " = make(", typ, ", len_", d.Index(), ")") + keyType, _ := protoc.FieldGoType(g.gen, f.Message.Fields[0]) + valType, _ := protoc.FieldGoType(g.gen, f.Message.Fields[1]) + g.gen.P("{") + g.gen.P(" n := n_", d.Index()) + g.gen.P(" for i := uint16(0); i < len_", d.Index(), "; i++ {") + g.gen.P(" var k ", keyType) + g.gen.P(" var v ", valType) + g.generateUnmarshalPrimitive(f.Message.Fields[0], "k", "n") + g.gen.P(" n += ", fieldSize(f.Message.Fields[0])) + g.generateUnmarshalPrimitive(f.Message.Fields[1], "v", "n") + g.gen.P(" n += ", fieldSize(f.Message.Fields[1])) + g.gen.P(" x.", f.GoName, "[k] = v") + g.gen.P(" }") + g.gen.P("}") + case d.ContainingOneof() != nil: + g.gen.P("// TODO: field ", f.GoName) + default: + g.generateUnmarshalPrimitive(f, "x."+f.GoName, fmt.Sprintf("n+%d", offset)) + } +} + +func (g zeropbFeature) generateUnmarshalPrimitive(f *protogen.Field, name, offset string) { + switch d := f.Desc; d.Kind() { + case protoreflect.FloatKind: + g.gen.P(name, " = float32(", mathPackage.Ident("Float32frombits"), "(", binaryPackage.Ident("LittleEndian"), ".Uint32(buf[", offset, ":])))") + case protoreflect.DoubleKind: + g.gen.P(name, " = float64(", mathPackage.Ident("Float64frombits"), "(", binaryPackage.Ident("LittleEndian"), ".Uint64(buf[", offset, ":])))") + case protoreflect.Sfixed32Kind, protoreflect.Int32Kind, protoreflect.Sint32Kind: + g.gen.P(name, " = int32(", binaryPackage.Ident("LittleEndian"), ".Uint32(buf[", offset, ":]))") + case protoreflect.Fixed32Kind, protoreflect.Uint32Kind: + g.gen.P(name, " = ", binaryPackage.Ident("LittleEndian"), ".Uint32(buf[", offset, ":])") + case protoreflect.Sfixed64Kind, protoreflect.Int64Kind, protoreflect.Sint64Kind: + g.gen.P(name, " = int64(", binaryPackage.Ident("LittleEndian"), ".Uint64(buf[", offset, ":]))") + case protoreflect.Fixed64Kind, protoreflect.Uint64Kind: + g.gen.P(name, " = ", binaryPackage.Ident("LittleEndian"), ".Uint64(buf[", offset, ":])") + case protoreflect.EnumKind: + typ := g.gen.QualifiedGoIdent(f.Enum.GoIdent) + g.gen.P(name, " = ", typ, "(", binaryPackage.Ident("LittleEndian"), ".Uint32(buf[", offset, ":]))") + case protoreflect.BoolKind: + g.gen.P("bool_", d.Index(), " := ", binaryPackage.Ident("LittleEndian"), ".Uint32(buf[", offset, ":])") + g.gen.P(name, " = false") + g.gen.P("if bool_", d.Index(), " != 0 {") + g.gen.P(" ", name, " = true") + g.gen.P("}") + case protoreflect.StringKind, protoreflect.BytesKind: + g.gen.P("n_", d.Index(), ", len_", d.Index(), " := ", runtimePackage.Ident("ReadSlice"), "(buf, ", offset, ")") + g.gen.P("buf_", d.Index(), " := buf[n_", d.Index(), ":n_", d.Index(), "+len_", d.Index(), "]") + if unsafeOptimizations { + g.gen.P("mem_", d.Index(), " := mem.Alloc(int(len_", d.Index(), ")*int(", unsafePackage.Ident("Sizeof"), "(", name, "[0])))") + g.gen.P("copy(mem_", d.Index(), ".Buf, buf_", d.Index(), ")") + if d.Kind() == protoreflect.BytesKind { + g.gen.P(name, " = mem_", d.Index(), ".Buf") + } else { + g.gen.P(name, " = ", unsafePackage.Ident("String"), "(", unsafePackage.Ident("SliceData"), "(mem_", d.Index(), ".Buf), len(mem_", d.Index(), ".Buf))") + } + } else { + if d.Kind() == protoreflect.BytesKind { + g.gen.P(name, " = append([]byte{}, buf_", d.Index(), "...)") + } else { + g.gen.P(name, " = string(buf_", d.Index(), ")") + } + } + case protoreflect.MessageKind: + typ := g.gen.QualifiedGoIdent(f.Message.GoIdent) + if unsafeOptimizations { + g.gen.P("mem_", d.Index(), " := mem.Alloc(int(", unsafePackage.Ident("Sizeof"), "(*", name, ")))") + g.gen.P(name, " = (*", typ, ")(", unsafePackage.Ident("Pointer"), "(", unsafePackage.Ident("SliceData"), "(mem_", d.Index(), ".Buf)))") + } else { + g.gen.P(name, " = new(", typ, ")") + } + g.gen.P(name, ".unmarshalZeroPB(buf, ", offset, ", mem)") + default: + g.gen.P("// TODO: field ", name) + } +} diff --git a/go.mod b/go.mod index e78f2bf..f68ef66 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/cosmos/cosmos-proto -go 1.18 +go 1.20 require ( github.com/google/go-cmp v0.6.0 diff --git a/internal/testprotos/test3/test.pulsar.go b/internal/testprotos/test3/test.pulsar.go index 1721a4a..49d00e0 100644 --- a/internal/testprotos/test3/test.pulsar.go +++ b/internal/testprotos/test3/test.pulsar.go @@ -3,6 +3,7 @@ package test3 import ( binary "encoding/binary" + errors "errors" fmt "fmt" runtime "github.com/cosmos/cosmos-proto/runtime" protoreflect "google.golang.org/protobuf/reflect/protoreflect" @@ -11222,7 +11223,7 @@ func (x *fastReflection_ForeignMessage) ProtoMethods() *protoiface.Methods { // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.0 -// protoc v3.18.1 +// protoc v4.24.4 // source: internal/testprotos/test3/test.proto const ( @@ -11402,6 +11403,7 @@ type TestAllTypes struct { MapStringNestedMessage map[string]*TestAllTypes_NestedMessage `protobuf:"bytes,71,rep,name=map_string_nested_message,json=mapStringNestedMessage,proto3" json:"map_string_nested_message,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` MapStringNestedEnum map[string]TestAllTypes_NestedEnum `protobuf:"bytes,73,rep,name=map_string_nested_enum,json=mapStringNestedEnum,proto3" json:"map_string_nested_enum,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3,enum=goproto.proto.test3.TestAllTypes_NestedEnum"` // Types that are assignable to OneofField: + // // *TestAllTypes_OneofUint32 // *TestAllTypes_OneofNestedMessage // *TestAllTypes_OneofString @@ -12616,3 +12618,1071 @@ func file_internal_testprotos_test3_test_proto_init() { file_internal_testprotos_test3_test_proto_goTypes = nil file_internal_testprotos_test3_test_proto_depIdxs = nil } +func (x *TestAllTypes) MarshalZeroPB(buf []byte) (n int, err error) { + defer func() { + if e := recover(); e != nil { + err = errors.New("buffer overflow") + } + }() + binary.LittleEndian.PutUint32(buf[n:], uint32(x.SingularInt32)) + n += 4 + binary.LittleEndian.PutUint64(buf[n:], uint64(x.SingularInt64)) + n += 8 + binary.LittleEndian.PutUint32(buf[n:], uint32(x.SingularUint32)) + n += 4 + binary.LittleEndian.PutUint64(buf[n:], uint64(x.SingularUint64)) + n += 8 + binary.LittleEndian.PutUint32(buf[n:], uint32(x.SingularSint32)) + n += 4 + binary.LittleEndian.PutUint64(buf[n:], uint64(x.SingularSint64)) + n += 8 + binary.LittleEndian.PutUint32(buf[n:], uint32(x.SingularFixed32)) + n += 4 + binary.LittleEndian.PutUint64(buf[n:], uint64(x.SingularFixed64)) + n += 8 + binary.LittleEndian.PutUint32(buf[n:], uint32(x.SingularSfixed32)) + n += 4 + binary.LittleEndian.PutUint64(buf[n:], uint64(x.SingularSfixed64)) + n += 8 + binary.LittleEndian.PutUint32(buf[n:], math.Float32bits(x.SingularFloat)) + n += 4 + binary.LittleEndian.PutUint64(buf[n:], math.Float64bits(x.SingularDouble)) + n += 8 + bool_12 := uint32(0) + if x.SingularBool { + bool_12 = 1 + } + binary.LittleEndian.PutUint32(buf[n:], bool_12) + n += 4 + len_13 := uint16(len(x.SingularString)) + if len(x.SingularString) != int(len_13) { + return n, errors.New("field x.SingularString is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_13) + n += 2 + copy(buf[n:n+len(x.SingularString)], x.SingularString) + n += len(x.SingularString) + len_14 := uint16(len(x.SingularBytes)) + if len(x.SingularBytes) != int(len_14) { + return n, errors.New("field x.SingularBytes is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_14) + n += 2 + copy(buf[n:n+len(x.SingularBytes)], x.SingularBytes) + n += len(x.SingularBytes) + n_15, err := x.SingularNestedMessage.MarshalZeroPB(buf[n:]) + n += n_15 + if err != nil { + return n, err + } + n_16, err := x.SingularForeignMessage.MarshalZeroPB(buf[n:]) + n += n_16 + if err != nil { + return n, err + } + n_17, err := x.SingularImportMessage.MarshalZeroPB(buf[n:]) + n += n_17 + if err != nil { + return n, err + } + binary.LittleEndian.PutUint32(buf[n:], uint32(x.SingularNestedEnum)) + n += 4 + binary.LittleEndian.PutUint32(buf[n:], uint32(x.SingularForeignEnum)) + n += 4 + binary.LittleEndian.PutUint32(buf[n:], uint32(x.SingularImportEnum)) + n += 4 + len_21 := uint16(len(x.RepeatedInt32)) + if len(x.RepeatedInt32) != int(len_21) { + return n, errors.New("field RepeatedInt32 is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_21) + n += 2 + for _, e := range x.RepeatedInt32 { + binary.LittleEndian.PutUint32(buf[n:], uint32(e)) + n += 4 + } + len_22 := uint16(len(x.RepeatedInt64)) + if len(x.RepeatedInt64) != int(len_22) { + return n, errors.New("field RepeatedInt64 is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_22) + n += 2 + for _, e := range x.RepeatedInt64 { + binary.LittleEndian.PutUint64(buf[n:], uint64(e)) + n += 8 + } + len_23 := uint16(len(x.RepeatedUint32)) + if len(x.RepeatedUint32) != int(len_23) { + return n, errors.New("field RepeatedUint32 is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_23) + n += 2 + for _, e := range x.RepeatedUint32 { + binary.LittleEndian.PutUint32(buf[n:], uint32(e)) + n += 4 + } + len_24 := uint16(len(x.RepeatedUint64)) + if len(x.RepeatedUint64) != int(len_24) { + return n, errors.New("field RepeatedUint64 is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_24) + n += 2 + for _, e := range x.RepeatedUint64 { + binary.LittleEndian.PutUint64(buf[n:], uint64(e)) + n += 8 + } + len_25 := uint16(len(x.RepeatedSint32)) + if len(x.RepeatedSint32) != int(len_25) { + return n, errors.New("field RepeatedSint32 is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_25) + n += 2 + for _, e := range x.RepeatedSint32 { + binary.LittleEndian.PutUint32(buf[n:], uint32(e)) + n += 4 + } + len_26 := uint16(len(x.RepeatedSint64)) + if len(x.RepeatedSint64) != int(len_26) { + return n, errors.New("field RepeatedSint64 is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_26) + n += 2 + for _, e := range x.RepeatedSint64 { + binary.LittleEndian.PutUint64(buf[n:], uint64(e)) + n += 8 + } + len_27 := uint16(len(x.RepeatedFixed32)) + if len(x.RepeatedFixed32) != int(len_27) { + return n, errors.New("field RepeatedFixed32 is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_27) + n += 2 + for _, e := range x.RepeatedFixed32 { + binary.LittleEndian.PutUint32(buf[n:], uint32(e)) + n += 4 + } + len_28 := uint16(len(x.RepeatedFixed64)) + if len(x.RepeatedFixed64) != int(len_28) { + return n, errors.New("field RepeatedFixed64 is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_28) + n += 2 + for _, e := range x.RepeatedFixed64 { + binary.LittleEndian.PutUint64(buf[n:], uint64(e)) + n += 8 + } + len_29 := uint16(len(x.RepeatedSfixed32)) + if len(x.RepeatedSfixed32) != int(len_29) { + return n, errors.New("field RepeatedSfixed32 is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_29) + n += 2 + for _, e := range x.RepeatedSfixed32 { + binary.LittleEndian.PutUint32(buf[n:], uint32(e)) + n += 4 + } + len_30 := uint16(len(x.RepeatedSfixed64)) + if len(x.RepeatedSfixed64) != int(len_30) { + return n, errors.New("field RepeatedSfixed64 is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_30) + n += 2 + for _, e := range x.RepeatedSfixed64 { + binary.LittleEndian.PutUint64(buf[n:], uint64(e)) + n += 8 + } + len_31 := uint16(len(x.RepeatedFloat)) + if len(x.RepeatedFloat) != int(len_31) { + return n, errors.New("field RepeatedFloat is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_31) + n += 2 + for _, e := range x.RepeatedFloat { + binary.LittleEndian.PutUint32(buf[n:], math.Float32bits(e)) + n += 4 + } + len_32 := uint16(len(x.RepeatedDouble)) + if len(x.RepeatedDouble) != int(len_32) { + return n, errors.New("field RepeatedDouble is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_32) + n += 2 + for _, e := range x.RepeatedDouble { + binary.LittleEndian.PutUint64(buf[n:], math.Float64bits(e)) + n += 8 + } + len_33 := uint16(len(x.RepeatedBool)) + if len(x.RepeatedBool) != int(len_33) { + return n, errors.New("field RepeatedBool is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_33) + n += 2 + for _, e := range x.RepeatedBool { + bool_33 := uint32(0) + if e { + bool_33 = 1 + } + binary.LittleEndian.PutUint32(buf[n:], bool_33) + n += 4 + } + len_34 := uint16(len(x.RepeatedString)) + if len(x.RepeatedString) != int(len_34) { + return n, errors.New("field RepeatedString is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_34) + n += 2 + for _, e := range x.RepeatedString { + len_34 := uint16(len(e)) + if len(e) != int(len_34) { + return n, errors.New("field e is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_34) + n += 2 + copy(buf[n:n+len(e)], e) + n += len(e) + } + len_35 := uint16(len(x.RepeatedBytes)) + if len(x.RepeatedBytes) != int(len_35) { + return n, errors.New("field RepeatedBytes is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_35) + n += 2 + for _, e := range x.RepeatedBytes { + len_35 := uint16(len(e)) + if len(e) != int(len_35) { + return n, errors.New("field e is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_35) + n += 2 + copy(buf[n:n+len(e)], e) + n += len(e) + } + len_36 := uint16(len(x.RepeatedNestedMessage)) + if len(x.RepeatedNestedMessage) != int(len_36) { + return n, errors.New("field RepeatedNestedMessage is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_36) + n += 2 + for _, e := range x.RepeatedNestedMessage { + n_36, err := e.MarshalZeroPB(buf[n:]) + n += n_36 + if err != nil { + return n, err + } + } + len_37 := uint16(len(x.RepeatedForeignMessage)) + if len(x.RepeatedForeignMessage) != int(len_37) { + return n, errors.New("field RepeatedForeignMessage is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_37) + n += 2 + for _, e := range x.RepeatedForeignMessage { + n_37, err := e.MarshalZeroPB(buf[n:]) + n += n_37 + if err != nil { + return n, err + } + } + len_38 := uint16(len(x.RepeatedImportmessage)) + if len(x.RepeatedImportmessage) != int(len_38) { + return n, errors.New("field RepeatedImportmessage is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_38) + n += 2 + for _, e := range x.RepeatedImportmessage { + n_38, err := e.MarshalZeroPB(buf[n:]) + n += n_38 + if err != nil { + return n, err + } + } + len_39 := uint16(len(x.RepeatedNestedEnum)) + if len(x.RepeatedNestedEnum) != int(len_39) { + return n, errors.New("field RepeatedNestedEnum is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_39) + n += 2 + for _, e := range x.RepeatedNestedEnum { + binary.LittleEndian.PutUint32(buf[n:], uint32(e)) + n += 4 + } + len_40 := uint16(len(x.RepeatedForeignEnum)) + if len(x.RepeatedForeignEnum) != int(len_40) { + return n, errors.New("field RepeatedForeignEnum is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_40) + n += 2 + for _, e := range x.RepeatedForeignEnum { + binary.LittleEndian.PutUint32(buf[n:], uint32(e)) + n += 4 + } + len_41 := uint16(len(x.RepeatedImportenum)) + if len(x.RepeatedImportenum) != int(len_41) { + return n, errors.New("field RepeatedImportenum is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_41) + n += 2 + for _, e := range x.RepeatedImportenum { + binary.LittleEndian.PutUint32(buf[n:], uint32(e)) + n += 4 + } + len_42 := uint16(len(x.MapInt32Int32)) + if len(x.MapInt32Int32) != int(len_42) { + return n, errors.New("field MapInt32Int32 is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_42) + n += 2 + for k, v := range x.MapInt32Int32 { + binary.LittleEndian.PutUint32(buf[n:], uint32(k)) + n += 4 + binary.LittleEndian.PutUint32(buf[n:], uint32(v)) + n += 4 + } + len_43 := uint16(len(x.MapInt64Int64)) + if len(x.MapInt64Int64) != int(len_43) { + return n, errors.New("field MapInt64Int64 is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_43) + n += 2 + for k, v := range x.MapInt64Int64 { + binary.LittleEndian.PutUint64(buf[n:], uint64(k)) + n += 8 + binary.LittleEndian.PutUint64(buf[n:], uint64(v)) + n += 8 + } + len_44 := uint16(len(x.MapUint32Uint32)) + if len(x.MapUint32Uint32) != int(len_44) { + return n, errors.New("field MapUint32Uint32 is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_44) + n += 2 + for k, v := range x.MapUint32Uint32 { + binary.LittleEndian.PutUint32(buf[n:], uint32(k)) + n += 4 + binary.LittleEndian.PutUint32(buf[n:], uint32(v)) + n += 4 + } + len_45 := uint16(len(x.MapUint64Uint64)) + if len(x.MapUint64Uint64) != int(len_45) { + return n, errors.New("field MapUint64Uint64 is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_45) + n += 2 + for k, v := range x.MapUint64Uint64 { + binary.LittleEndian.PutUint64(buf[n:], uint64(k)) + n += 8 + binary.LittleEndian.PutUint64(buf[n:], uint64(v)) + n += 8 + } + len_46 := uint16(len(x.MapSint32Sint32)) + if len(x.MapSint32Sint32) != int(len_46) { + return n, errors.New("field MapSint32Sint32 is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_46) + n += 2 + for k, v := range x.MapSint32Sint32 { + binary.LittleEndian.PutUint32(buf[n:], uint32(k)) + n += 4 + binary.LittleEndian.PutUint32(buf[n:], uint32(v)) + n += 4 + } + len_47 := uint16(len(x.MapSint64Sint64)) + if len(x.MapSint64Sint64) != int(len_47) { + return n, errors.New("field MapSint64Sint64 is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_47) + n += 2 + for k, v := range x.MapSint64Sint64 { + binary.LittleEndian.PutUint64(buf[n:], uint64(k)) + n += 8 + binary.LittleEndian.PutUint64(buf[n:], uint64(v)) + n += 8 + } + len_48 := uint16(len(x.MapFixed32Fixed32)) + if len(x.MapFixed32Fixed32) != int(len_48) { + return n, errors.New("field MapFixed32Fixed32 is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_48) + n += 2 + for k, v := range x.MapFixed32Fixed32 { + binary.LittleEndian.PutUint32(buf[n:], uint32(k)) + n += 4 + binary.LittleEndian.PutUint32(buf[n:], uint32(v)) + n += 4 + } + len_49 := uint16(len(x.MapFixed64Fixed64)) + if len(x.MapFixed64Fixed64) != int(len_49) { + return n, errors.New("field MapFixed64Fixed64 is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_49) + n += 2 + for k, v := range x.MapFixed64Fixed64 { + binary.LittleEndian.PutUint64(buf[n:], uint64(k)) + n += 8 + binary.LittleEndian.PutUint64(buf[n:], uint64(v)) + n += 8 + } + len_50 := uint16(len(x.MapSfixed32Sfixed32)) + if len(x.MapSfixed32Sfixed32) != int(len_50) { + return n, errors.New("field MapSfixed32Sfixed32 is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_50) + n += 2 + for k, v := range x.MapSfixed32Sfixed32 { + binary.LittleEndian.PutUint32(buf[n:], uint32(k)) + n += 4 + binary.LittleEndian.PutUint32(buf[n:], uint32(v)) + n += 4 + } + len_51 := uint16(len(x.MapSfixed64Sfixed64)) + if len(x.MapSfixed64Sfixed64) != int(len_51) { + return n, errors.New("field MapSfixed64Sfixed64 is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_51) + n += 2 + for k, v := range x.MapSfixed64Sfixed64 { + binary.LittleEndian.PutUint64(buf[n:], uint64(k)) + n += 8 + binary.LittleEndian.PutUint64(buf[n:], uint64(v)) + n += 8 + } + len_52 := uint16(len(x.MapInt32Float)) + if len(x.MapInt32Float) != int(len_52) { + return n, errors.New("field MapInt32Float is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_52) + n += 2 + for k, v := range x.MapInt32Float { + binary.LittleEndian.PutUint32(buf[n:], uint32(k)) + n += 4 + binary.LittleEndian.PutUint32(buf[n:], math.Float32bits(v)) + n += 4 + } + len_53 := uint16(len(x.MapInt32Double)) + if len(x.MapInt32Double) != int(len_53) { + return n, errors.New("field MapInt32Double is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_53) + n += 2 + for k, v := range x.MapInt32Double { + binary.LittleEndian.PutUint32(buf[n:], uint32(k)) + n += 4 + binary.LittleEndian.PutUint64(buf[n:], math.Float64bits(v)) + n += 8 + } + len_54 := uint16(len(x.MapBoolBool)) + if len(x.MapBoolBool) != int(len_54) { + return n, errors.New("field MapBoolBool is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_54) + n += 2 + for k, v := range x.MapBoolBool { + bool_0 := uint32(0) + if k { + bool_0 = 1 + } + binary.LittleEndian.PutUint32(buf[n:], bool_0) + n += 4 + bool_1 := uint32(0) + if v { + bool_1 = 1 + } + binary.LittleEndian.PutUint32(buf[n:], bool_1) + n += 4 + } + len_55 := uint16(len(x.MapStringString)) + if len(x.MapStringString) != int(len_55) { + return n, errors.New("field MapStringString is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_55) + n += 2 + for k, v := range x.MapStringString { + len_0 := uint16(len(k)) + if len(k) != int(len_0) { + return n, errors.New("field k is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_0) + n += 2 + copy(buf[n:n+len(k)], k) + n += len(k) + len_1 := uint16(len(v)) + if len(v) != int(len_1) { + return n, errors.New("field v is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_1) + n += 2 + copy(buf[n:n+len(v)], v) + n += len(v) + } + len_56 := uint16(len(x.MapStringBytes)) + if len(x.MapStringBytes) != int(len_56) { + return n, errors.New("field MapStringBytes is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_56) + n += 2 + for k, v := range x.MapStringBytes { + len_0 := uint16(len(k)) + if len(k) != int(len_0) { + return n, errors.New("field k is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_0) + n += 2 + copy(buf[n:n+len(k)], k) + n += len(k) + len_1 := uint16(len(v)) + if len(v) != int(len_1) { + return n, errors.New("field v is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_1) + n += 2 + copy(buf[n:n+len(v)], v) + n += len(v) + } + len_57 := uint16(len(x.MapStringNestedMessage)) + if len(x.MapStringNestedMessage) != int(len_57) { + return n, errors.New("field MapStringNestedMessage is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_57) + n += 2 + for k, v := range x.MapStringNestedMessage { + len_0 := uint16(len(k)) + if len(k) != int(len_0) { + return n, errors.New("field k is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_0) + n += 2 + copy(buf[n:n+len(k)], k) + n += len(k) + n_1, err := v.MarshalZeroPB(buf[n:]) + n += n_1 + if err != nil { + return n, err + } + } + len_58 := uint16(len(x.MapStringNestedEnum)) + if len(x.MapStringNestedEnum) != int(len_58) { + return n, errors.New("field MapStringNestedEnum is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_58) + n += 2 + for k, v := range x.MapStringNestedEnum { + len_0 := uint16(len(k)) + if len(k) != int(len_0) { + return n, errors.New("field k is too long") + } + binary.LittleEndian.PutUint16(buf[n:], len_0) + n += 2 + copy(buf[n:n+len(k)], k) + n += len(k) + binary.LittleEndian.PutUint32(buf[n:], uint32(v)) + n += 4 + } + // TODO: field OneofUint32 + // TODO: field OneofNestedMessage + // TODO: field OneofString + // TODO: field OneofBytes + // TODO: field OneofBool + // TODO: field OneofUint64 + // TODO: field OneofFloat + // TODO: field OneofDouble + // TODO: field OneofEnum + return n, nil +} +func (x *TestAllTypes) UnmarshalZeroPB(buf []byte) (n int, err error) { + defer func() { + if e := recover(); e != nil { + err = errors.New("buffer underflow") + } + }() + x.SingularInt32 = int32(binary.LittleEndian.Uint32(buf[n:])) + n += 4 + x.SingularInt64 = int64(binary.LittleEndian.Uint64(buf[n:])) + n += 8 + x.SingularUint32 = binary.LittleEndian.Uint32(buf[n:]) + n += 4 + x.SingularUint64 = binary.LittleEndian.Uint64(buf[n:]) + n += 8 + x.SingularSint32 = int32(binary.LittleEndian.Uint32(buf[n:])) + n += 4 + x.SingularSint64 = int64(binary.LittleEndian.Uint64(buf[n:])) + n += 8 + x.SingularFixed32 = binary.LittleEndian.Uint32(buf[n:]) + n += 4 + x.SingularFixed64 = binary.LittleEndian.Uint64(buf[n:]) + n += 8 + x.SingularSfixed32 = int32(binary.LittleEndian.Uint32(buf[n:])) + n += 4 + x.SingularSfixed64 = int64(binary.LittleEndian.Uint64(buf[n:])) + n += 8 + x.SingularFloat = float32(math.Float32frombits(binary.LittleEndian.Uint32(buf[n:]))) + n += 4 + x.SingularDouble = float64(math.Float64frombits(binary.LittleEndian.Uint64(buf[n:]))) + n += 8 + bool_12 := binary.LittleEndian.Uint32(buf[n:]) + x.SingularBool = false + if bool_12 != 0 { + x.SingularBool = true + } + n += 4 + len_13 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.SingularString = string(buf[n : n+len_13]) + n += len_13 + len_14 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.SingularBytes = append([]byte{}, buf[n:n+len_14]...) + n += len_14 + x.SingularNestedMessage = new(goproto.proto.test3.TestAllTypes.NestedMessage) + n_15, err := x.SingularNestedMessage.UnmarshalZeroPB(buf[n:]) + n += n_15 + if err != nil { + return n, err + } + x.SingularForeignMessage = new(goproto.proto.test3.ForeignMessage) + n_16, err := x.SingularForeignMessage.UnmarshalZeroPB(buf[n:]) + n += n_16 + if err != nil { + return n, err + } + x.SingularImportMessage = new(goproto.proto.test3.ImportMessage) + n_17, err := x.SingularImportMessage.UnmarshalZeroPB(buf[n:]) + n += n_17 + if err != nil { + return n, err + } + x.SingularNestedEnum = goproto.proto.test3.TestAllTypes.NestedEnum(binary.LittleEndian.Uint32(buf[n:])) + n += 4 + x.SingularForeignEnum = goproto.proto.test3.ForeignEnum(binary.LittleEndian.Uint32(buf[n:])) + n += 4 + x.SingularImportEnum = goproto.proto.test3.ImportEnum(binary.LittleEndian.Uint32(buf[n:])) + n += 4 + len_21 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.RepeatedInt32 = make([]int32, len_21) + for i := range x.RepeatedInt32 { + x.RepeatedInt32[i] = int32(binary.LittleEndian.Uint32(buf[n:])) + n += 4 + } + len_22 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.RepeatedInt64 = make([]int64, len_22) + for i := range x.RepeatedInt64 { + x.RepeatedInt64[i] = int64(binary.LittleEndian.Uint64(buf[n:])) + n += 8 + } + len_23 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.RepeatedUint32 = make([]uint32, len_23) + for i := range x.RepeatedUint32 { + x.RepeatedUint32[i] = binary.LittleEndian.Uint32(buf[n:]) + n += 4 + } + len_24 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.RepeatedUint64 = make([]uint64, len_24) + for i := range x.RepeatedUint64 { + x.RepeatedUint64[i] = binary.LittleEndian.Uint64(buf[n:]) + n += 8 + } + len_25 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.RepeatedSint32 = make([]int32, len_25) + for i := range x.RepeatedSint32 { + x.RepeatedSint32[i] = int32(binary.LittleEndian.Uint32(buf[n:])) + n += 4 + } + len_26 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.RepeatedSint64 = make([]int64, len_26) + for i := range x.RepeatedSint64 { + x.RepeatedSint64[i] = int64(binary.LittleEndian.Uint64(buf[n:])) + n += 8 + } + len_27 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.RepeatedFixed32 = make([]uint32, len_27) + for i := range x.RepeatedFixed32 { + x.RepeatedFixed32[i] = binary.LittleEndian.Uint32(buf[n:]) + n += 4 + } + len_28 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.RepeatedFixed64 = make([]uint64, len_28) + for i := range x.RepeatedFixed64 { + x.RepeatedFixed64[i] = binary.LittleEndian.Uint64(buf[n:]) + n += 8 + } + len_29 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.RepeatedSfixed32 = make([]int32, len_29) + for i := range x.RepeatedSfixed32 { + x.RepeatedSfixed32[i] = int32(binary.LittleEndian.Uint32(buf[n:])) + n += 4 + } + len_30 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.RepeatedSfixed64 = make([]int64, len_30) + for i := range x.RepeatedSfixed64 { + x.RepeatedSfixed64[i] = int64(binary.LittleEndian.Uint64(buf[n:])) + n += 8 + } + len_31 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.RepeatedFloat = make([]float32, len_31) + for i := range x.RepeatedFloat { + x.RepeatedFloat[i] = float32(math.Float32frombits(binary.LittleEndian.Uint32(buf[n:]))) + n += 4 + } + len_32 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.RepeatedDouble = make([]float64, len_32) + for i := range x.RepeatedDouble { + x.RepeatedDouble[i] = float64(math.Float64frombits(binary.LittleEndian.Uint64(buf[n:]))) + n += 8 + } + len_33 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.RepeatedBool = make([]bool, len_33) + for i := range x.RepeatedBool { + bool_33 := binary.LittleEndian.Uint32(buf[n:]) + x.RepeatedBool[i] = false + if bool_33 != 0 { + x.RepeatedBool[i] = true + } + n += 4 + } + len_34 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.RepeatedString = make([]string, len_34) + for i := range x.RepeatedString { + len_34 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.RepeatedString[i] = string(buf[n : n+len_34]) + n += len_34 + } + len_35 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.RepeatedBytes = make([][]byte, len_35) + for i := range x.RepeatedBytes { + len_35 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.RepeatedBytes[i] = append([]byte{}, buf[n:n+len_35]...) + n += len_35 + } + len_36 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.RepeatedNestedMessage = make([]*TestAllTypes_NestedMessage, len_36) + for i := range x.RepeatedNestedMessage { + x.RepeatedNestedMessage[i] = new(goproto.proto.test3.TestAllTypes.NestedMessage) + n_36, err := x.RepeatedNestedMessage[i].UnmarshalZeroPB(buf[n:]) + n += n_36 + if err != nil { + return n, err + } + } + len_37 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.RepeatedForeignMessage = make([]*ForeignMessage, len_37) + for i := range x.RepeatedForeignMessage { + x.RepeatedForeignMessage[i] = new(goproto.proto.test3.ForeignMessage) + n_37, err := x.RepeatedForeignMessage[i].UnmarshalZeroPB(buf[n:]) + n += n_37 + if err != nil { + return n, err + } + } + len_38 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.RepeatedImportmessage = make([]*ImportMessage, len_38) + for i := range x.RepeatedImportmessage { + x.RepeatedImportmessage[i] = new(goproto.proto.test3.ImportMessage) + n_38, err := x.RepeatedImportmessage[i].UnmarshalZeroPB(buf[n:]) + n += n_38 + if err != nil { + return n, err + } + } + len_39 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.RepeatedNestedEnum = make([]TestAllTypes_NestedEnum, len_39) + for i := range x.RepeatedNestedEnum { + x.RepeatedNestedEnum[i] = goproto.proto.test3.TestAllTypes.NestedEnum(binary.LittleEndian.Uint32(buf[n:])) + n += 4 + } + len_40 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.RepeatedForeignEnum = make([]ForeignEnum, len_40) + for i := range x.RepeatedForeignEnum { + x.RepeatedForeignEnum[i] = goproto.proto.test3.ForeignEnum(binary.LittleEndian.Uint32(buf[n:])) + n += 4 + } + len_41 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.RepeatedImportenum = make([]ImportEnum, len_41) + for i := range x.RepeatedImportenum { + x.RepeatedImportenum[i] = goproto.proto.test3.ImportEnum(binary.LittleEndian.Uint32(buf[n:])) + n += 4 + } + len_42 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.MapInt32Int32 = make(map[int32]int32, len_42) + for i := 0; i < len_42; i++ { + var k int32 + var v int32 + k = int32(binary.LittleEndian.Uint32(buf[n:])) + n += 4 + v = int32(binary.LittleEndian.Uint32(buf[n:])) + n += 4 + x.MapInt32Int32[k] = v + } + len_43 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.MapInt64Int64 = make(map[int64]int64, len_43) + for i := 0; i < len_43; i++ { + var k int64 + var v int64 + k = int64(binary.LittleEndian.Uint64(buf[n:])) + n += 8 + v = int64(binary.LittleEndian.Uint64(buf[n:])) + n += 8 + x.MapInt64Int64[k] = v + } + len_44 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.MapUint32Uint32 = make(map[uint32]uint32, len_44) + for i := 0; i < len_44; i++ { + var k uint32 + var v uint32 + k = binary.LittleEndian.Uint32(buf[n:]) + n += 4 + v = binary.LittleEndian.Uint32(buf[n:]) + n += 4 + x.MapUint32Uint32[k] = v + } + len_45 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.MapUint64Uint64 = make(map[uint64]uint64, len_45) + for i := 0; i < len_45; i++ { + var k uint64 + var v uint64 + k = binary.LittleEndian.Uint64(buf[n:]) + n += 8 + v = binary.LittleEndian.Uint64(buf[n:]) + n += 8 + x.MapUint64Uint64[k] = v + } + len_46 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.MapSint32Sint32 = make(map[int32]int32, len_46) + for i := 0; i < len_46; i++ { + var k int32 + var v int32 + k = int32(binary.LittleEndian.Uint32(buf[n:])) + n += 4 + v = int32(binary.LittleEndian.Uint32(buf[n:])) + n += 4 + x.MapSint32Sint32[k] = v + } + len_47 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.MapSint64Sint64 = make(map[int64]int64, len_47) + for i := 0; i < len_47; i++ { + var k int64 + var v int64 + k = int64(binary.LittleEndian.Uint64(buf[n:])) + n += 8 + v = int64(binary.LittleEndian.Uint64(buf[n:])) + n += 8 + x.MapSint64Sint64[k] = v + } + len_48 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.MapFixed32Fixed32 = make(map[uint32]uint32, len_48) + for i := 0; i < len_48; i++ { + var k uint32 + var v uint32 + k = binary.LittleEndian.Uint32(buf[n:]) + n += 4 + v = binary.LittleEndian.Uint32(buf[n:]) + n += 4 + x.MapFixed32Fixed32[k] = v + } + len_49 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.MapFixed64Fixed64 = make(map[uint64]uint64, len_49) + for i := 0; i < len_49; i++ { + var k uint64 + var v uint64 + k = binary.LittleEndian.Uint64(buf[n:]) + n += 8 + v = binary.LittleEndian.Uint64(buf[n:]) + n += 8 + x.MapFixed64Fixed64[k] = v + } + len_50 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.MapSfixed32Sfixed32 = make(map[int32]int32, len_50) + for i := 0; i < len_50; i++ { + var k int32 + var v int32 + k = int32(binary.LittleEndian.Uint32(buf[n:])) + n += 4 + v = int32(binary.LittleEndian.Uint32(buf[n:])) + n += 4 + x.MapSfixed32Sfixed32[k] = v + } + len_51 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.MapSfixed64Sfixed64 = make(map[int64]int64, len_51) + for i := 0; i < len_51; i++ { + var k int64 + var v int64 + k = int64(binary.LittleEndian.Uint64(buf[n:])) + n += 8 + v = int64(binary.LittleEndian.Uint64(buf[n:])) + n += 8 + x.MapSfixed64Sfixed64[k] = v + } + len_52 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.MapInt32Float = make(map[int32]float32, len_52) + for i := 0; i < len_52; i++ { + var k int32 + var v float32 + k = int32(binary.LittleEndian.Uint32(buf[n:])) + n += 4 + v = float32(math.Float32frombits(binary.LittleEndian.Uint32(buf[n:]))) + n += 4 + x.MapInt32Float[k] = v + } + len_53 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.MapInt32Double = make(map[int32]float64, len_53) + for i := 0; i < len_53; i++ { + var k int32 + var v float64 + k = int32(binary.LittleEndian.Uint32(buf[n:])) + n += 4 + v = float64(math.Float64frombits(binary.LittleEndian.Uint64(buf[n:]))) + n += 8 + x.MapInt32Double[k] = v + } + len_54 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.MapBoolBool = make(map[bool]bool, len_54) + for i := 0; i < len_54; i++ { + var k bool + var v bool + bool_0 := binary.LittleEndian.Uint32(buf[n:]) + k = false + if bool_0 != 0 { + k = true + } + n += 4 + bool_1 := binary.LittleEndian.Uint32(buf[n:]) + v = false + if bool_1 != 0 { + v = true + } + n += 4 + x.MapBoolBool[k] = v + } + len_55 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.MapStringString = make(map[string]string, len_55) + for i := 0; i < len_55; i++ { + var k string + var v string + len_0 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + k = string(buf[n : n+len_0]) + n += len_0 + len_1 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + v = string(buf[n : n+len_1]) + n += len_1 + x.MapStringString[k] = v + } + len_56 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.MapStringBytes = make(map[string][]byte, len_56) + for i := 0; i < len_56; i++ { + var k string + var v []byte + len_0 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + k = string(buf[n : n+len_0]) + n += len_0 + len_1 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + v = append([]byte{}, buf[n:n+len_1]...) + n += len_1 + x.MapStringBytes[k] = v + } + len_57 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.MapStringNestedMessage = make(map[string]*TestAllTypes_NestedMessage, len_57) + for i := 0; i < len_57; i++ { + var k string + var v *TestAllTypes_NestedMessage + len_0 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + k = string(buf[n : n+len_0]) + n += len_0 + v = new(goproto.proto.test3.TestAllTypes.NestedMessage) + n_1, err := v.UnmarshalZeroPB(buf[n:]) + n += n_1 + if err != nil { + return n, err + } + x.MapStringNestedMessage[k] = v + } + len_58 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + x.MapStringNestedEnum = make(map[string]TestAllTypes_NestedEnum, len_58) + for i := 0; i < len_58; i++ { + var k string + var v TestAllTypes_NestedEnum + len_0 := int(binary.LittleEndian.Uint16(buf[n:])) + n += 2 + k = string(buf[n : n+len_0]) + n += len_0 + v = goproto.proto.test3.TestAllTypes.NestedEnum(binary.LittleEndian.Uint32(buf[n:])) + n += 4 + x.MapStringNestedEnum[k] = v + } + // TODO: field OneofUint32 + // TODO: field OneofNestedMessage + // TODO: field OneofString + // TODO: field OneofBytes + // TODO: field OneofBool + // TODO: field OneofUint64 + // TODO: field OneofFloat + // TODO: field OneofDouble + // TODO: field OneofEnum + return n, nil +} +func (x *ForeignMessage) MarshalZeroPB(buf []byte) (n int, err error) { + defer func() { + if e := recover(); e != nil { + err = errors.New("buffer overflow") + } + }() + binary.LittleEndian.PutUint32(buf[n:], uint32(x.C)) + n += 4 + binary.LittleEndian.PutUint32(buf[n:], uint32(x.D)) + n += 4 + return n, nil +} +func (x *ForeignMessage) UnmarshalZeroPB(buf []byte) (n int, err error) { + defer func() { + if e := recover(); e != nil { + err = errors.New("buffer underflow") + } + }() + x.C = int32(binary.LittleEndian.Uint32(buf[n:])) + n += 4 + x.D = int32(binary.LittleEndian.Uint32(buf[n:])) + n += 4 + return n, nil +} diff --git a/internal/testprotos/test3/test_import.pulsar.go b/internal/testprotos/test3/test_import.pulsar.go index 06ba752..ea25b01 100644 --- a/internal/testprotos/test3/test_import.pulsar.go +++ b/internal/testprotos/test3/test_import.pulsar.go @@ -2,6 +2,7 @@ package test3 import ( + errors "errors" fmt "fmt" runtime "github.com/cosmos/cosmos-proto/runtime" protoreflect "google.golang.org/protobuf/reflect/protoreflect" @@ -375,7 +376,7 @@ func (x *fastReflection_ImportMessage) ProtoMethods() *protoiface.Methods { // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.0 -// protoc v3.18.1 +// protoc v4.24.4 // source: internal/testprotos/test3/test_import.proto const ( @@ -536,3 +537,19 @@ func file_internal_testprotos_test3_test_import_proto_init() { file_internal_testprotos_test3_test_import_proto_goTypes = nil file_internal_testprotos_test3_test_import_proto_depIdxs = nil } +func (x *ImportMessage) MarshalZeroPB(buf []byte) (n int, err error) { + defer func() { + if e := recover(); e != nil { + err = errors.New("buffer overflow") + } + }() + return n, nil +} +func (x *ImportMessage) UnmarshalZeroPB(buf []byte) (n int, err error) { + defer func() { + if e := recover(); e != nil { + err = errors.New("buffer underflow") + } + }() + return n, nil +} diff --git a/internal/testprotos/test3/test_nesting.pulsar.go b/internal/testprotos/test3/test_nesting.pulsar.go index 4547c29..82a3d7e 100644 --- a/internal/testprotos/test3/test_nesting.pulsar.go +++ b/internal/testprotos/test3/test_nesting.pulsar.go @@ -2,6 +2,7 @@ package test3 import ( + errors "errors" fmt "fmt" runtime "github.com/cosmos/cosmos-proto/runtime" protoreflect "google.golang.org/protobuf/reflect/protoreflect" @@ -1754,7 +1755,7 @@ func (x *fastReflection_MultiLayeredNesting_Nested1_Nested2_Nested3) ProtoMethod // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.0 -// protoc v3.18.1 +// protoc v4.24.4 // source: internal/testprotos/test3/test_nesting.proto const ( @@ -1866,6 +1867,7 @@ type MultiLayeredNesting_Nested1_Nested2_Nested3 struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Nested3Oneof: + // // *MultiLayeredNesting_Nested1_Nested2_Nested3_Nested_3String // *MultiLayeredNesting_Nested1_Nested2_Nested3_Nested_3Int32 Nested3Oneof isMultiLayeredNesting_Nested1_Nested2_Nested3_Nested3Oneof `protobuf_oneof:"nested3_oneof"` @@ -2071,3 +2073,30 @@ func file_internal_testprotos_test3_test_nesting_proto_init() { file_internal_testprotos_test3_test_nesting_proto_goTypes = nil file_internal_testprotos_test3_test_nesting_proto_depIdxs = nil } +func (x *MultiLayeredNesting) MarshalZeroPB(buf []byte) (n int, err error) { + defer func() { + if e := recover(); e != nil { + err = errors.New("buffer overflow") + } + }() + n_0, err := x.Nested1.MarshalZeroPB(buf[n:]) + n += n_0 + if err != nil { + return n, err + } + return n, nil +} +func (x *MultiLayeredNesting) UnmarshalZeroPB(buf []byte) (n int, err error) { + defer func() { + if e := recover(); e != nil { + err = errors.New("buffer underflow") + } + }() + x.Nested1 = new(goproto.proto.test3.MultiLayeredNesting.Nested1) + n_0, err := x.Nested1.UnmarshalZeroPB(buf[n:]) + n += n_0 + if err != nil { + return n, err + } + return n, nil +} diff --git a/runtime/zeropb/zeropb.go b/runtime/zeropb/zeropb.go new file mode 100644 index 0000000..e7384dd --- /dev/null +++ b/runtime/zeropb/zeropb.go @@ -0,0 +1,70 @@ +package zeropb + +import ( + "encoding/binary" + "math" +) + +type Buffer struct { + buf []byte + allocated uint16 +} + +type Allocation struct { + Buf []byte + Offset uint16 +} + +func NewBuffer(b []byte) *Buffer { + if len(b) > math.MaxUint16 { + b = b[:math.MaxUint16] + } + return &Buffer{ + buf: b, + } +} + +func (b *Buffer) Alloc(n int) Allocation { + a := Allocation{ + Buf: b.buf[:n], + Offset: b.allocated, + } + // The slice above would have paniced if n would not fit a uint16. + n16 := uint16(n) + b.buf = b.buf[n16:] + b.allocated += n16 + return a +} + +func (b *Buffer) AllocRel(n int, dst Allocation, offset, len uint16) Allocation { + a := b.Alloc(n) + bo := binary.LittleEndian + // Write relative offset and len. + bo.PutUint16(dst.Buf[offset:], a.Offset-dst.Offset-offset) + bo.PutUint16(dst.Buf[offset+2:], len) + return a +} + +func (b *Buffer) Allocated() uint16 { + return b.allocated +} + +func (a Allocation) Slice(offset uint16) Allocation { + return Allocation{ + Buf: a.Buf[offset:], + Offset: a.Offset + offset, + } +} + +func ReadSlice(buf []byte, offset uint16) (off, len uint16) { + bo := binary.LittleEndian + off = ReadOffset(buf, offset) + len = bo.Uint16(buf[offset+2:]) + return +} + +func ReadOffset(buf []byte, offset uint16) (off uint16) { + bo := binary.LittleEndian + off = offset + bo.Uint16(buf[offset:]) + return +} diff --git a/scripts/fastreflect.sh b/scripts/fastreflect.sh index 135c1e3..7a3edbe 100755 --- a/scripts/fastreflect.sh +++ b/scripts/fastreflect.sh @@ -2,12 +2,14 @@ set -e +PULSAR_EXE=$(which protoc-gen-go-pulsar) + build() { echo finding protobuf files in "$1" proto_files=$(find "$1" -name "*.proto") for file in $proto_files; do echo "building proto file $file" - protoc -I=. --plugin /usr/bin/protoc-gen-go-pulsar --go-pulsar_out=. --go-pulsar_opt=features=protoc+fast "$file" + protoc -I=. --plugin "$PULSAR_EXE" --go-pulsar_out=. --go-pulsar_opt=features=protoc+fast+zeropb "$file" done } @@ -17,4 +19,4 @@ do done cp -r github.com/cosmos/cosmos-proto/* ./ -rm -rf github.com \ No newline at end of file +rm -rf github.com diff --git a/testpb/1.pulsar.go b/testpb/1.pulsar.go index 1397f0f..a532d29 100644 --- a/testpb/1.pulsar.go +++ b/testpb/1.pulsar.go @@ -3,8 +3,10 @@ package testpb import ( binary "encoding/binary" + errors "errors" fmt "fmt" runtime "github.com/cosmos/cosmos-proto/runtime" + zeropb "github.com/cosmos/cosmos-proto/runtime/zeropb" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoiface "google.golang.org/protobuf/runtime/protoiface" protoimpl "google.golang.org/protobuf/runtime/protoimpl" @@ -13,6 +15,7 @@ import ( reflect "reflect" sort "sort" sync "sync" + unsafe "unsafe" ) var _ protoreflect.Map = (*_A_18_map)(nil) @@ -2635,7 +2638,7 @@ func (x *fastReflection_B) ProtoMethods() *protoiface.Methods { // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.0 -// protoc v3.18.1 +// protoc v4.24.4 // source: testpb/1.proto const ( @@ -2716,6 +2719,7 @@ type A struct { MAP map[string]*B `protobuf:"bytes,18,rep,name=MAP,proto3" json:"MAP,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` LIST []*B `protobuf:"bytes,19,rep,name=LIST,proto3" json:"LIST,omitempty"` // Types that are assignable to ONEOF: + // // *A_ONEOF_B // *A_ONEOF_STRING ONEOF isA_ONEOF `protobuf_oneof:"ONEOF"` @@ -3123,3 +3127,326 @@ func file_testpb_1_proto_init() { file_testpb_1_proto_goTypes = nil file_testpb_1_proto_depIdxs = nil } +func (x *A) MarshalZeroPB(buf []byte) (n int, err error) { + defer func() { + if e := recover(); e != nil { + err = errors.New("buffer overflow") + } + }() + b := zeropb.NewBuffer(buf) + x.marshalZeroPB(b, b.Alloc(116)) + return int(b.Allocated()), nil +} + +func (x *A) marshalZeroPB(b *zeropb.Buffer, buf zeropb.Allocation) { + if x == nil { + return + } + binary.LittleEndian.PutUint32(buf.Buf[0:], uint32(x.Enum)) + bool_1 := uint32(0) + if x.SomeBoolean { + bool_1 = 1 + } + binary.LittleEndian.PutUint32(buf.Buf[4:], bool_1) + binary.LittleEndian.PutUint32(buf.Buf[8:], uint32(x.INT32)) + binary.LittleEndian.PutUint32(buf.Buf[12:], uint32(x.SINT32)) + binary.LittleEndian.PutUint32(buf.Buf[16:], uint32(x.UINT32)) + binary.LittleEndian.PutUint64(buf.Buf[20:], uint64(x.INT64)) + binary.LittleEndian.PutUint64(buf.Buf[28:], uint64(x.SING64)) + binary.LittleEndian.PutUint64(buf.Buf[36:], uint64(x.UINT64)) + binary.LittleEndian.PutUint32(buf.Buf[44:], uint32(x.SFIXED32)) + binary.LittleEndian.PutUint32(buf.Buf[48:], uint32(x.FIXED32)) + binary.LittleEndian.PutUint32(buf.Buf[52:], math.Float32bits(x.FLOAT)) + binary.LittleEndian.PutUint64(buf.Buf[56:], uint64(x.SFIXED64)) + binary.LittleEndian.PutUint64(buf.Buf[64:], uint64(x.FIXED64)) + binary.LittleEndian.PutUint64(buf.Buf[72:], math.Float64bits(x.DOUBLE)) + buf_14 := b.AllocRel(len(x.STRING), buf, 80, uint16(len(x.STRING))) + copy(buf_14.Buf, x.STRING) + buf_15 := b.AllocRel(len(x.BYTES), buf, 84, uint16(len(x.BYTES))) + copy(buf_15.Buf, x.BYTES) + x.MESSAGE.marshalZeroPB(b, buf.Slice(88)) + buf_17 := b.AllocRel(len(x.MAP)*8, buf, 92, uint16(len(x.MAP))) + { + var n uint16 + buf := buf_17 + for k, v := range x.MAP { + buf_0 := b.AllocRel(len(k), buf, n, uint16(len(k))) + copy(buf_0.Buf, k) + n += 4 + v.marshalZeroPB(b, buf.Slice(n)) + n += 4 + } + } + rem_18 := x.LIST + var link_18 zeropb.Allocation + for len(rem_18) > 0 { + seg := rem_18 + if len(seg) > 255 { + seg = seg[:255] + } + rem_18 = rem_18[len(seg):] + buf_18 := b.Alloc(len(seg)*4 + 4) + if link_18.Buf == nil { + binary.LittleEndian.PutUint16(buf.Buf[96:], buf_18.Offset-buf.Offset-96) + binary.LittleEndian.PutUint16(buf.Buf[96+2:], uint16(len(x.LIST))) + } else { + binary.LittleEndian.PutUint16(link_18.Buf[2:], buf_18.Offset-link_18.Offset-2) + } + { + buf := buf_18 + buf.Buf[0] = byte(len(seg)) + buf.Buf[1] = byte(len(seg)) + link_18 = buf + for i, e := range seg { + e.marshalZeroPB(b, buf.Slice(uint16(i)*4+4)) + } + } + } + // TODO: field ONEOF_B + // TODO: field ONEOF_STRING + rem_21 := x.LIST_ENUM + var link_21 zeropb.Allocation + for len(rem_21) > 0 { + seg := rem_21 + if len(seg) > 255 { + seg = seg[:255] + } + rem_21 = rem_21[len(seg):] + buf_21 := b.Alloc(len(seg)*4 + 4) + if link_21.Buf == nil { + binary.LittleEndian.PutUint16(buf.Buf[108:], buf_21.Offset-buf.Offset-108) + binary.LittleEndian.PutUint16(buf.Buf[108+2:], uint16(len(x.LIST_ENUM))) + } else { + binary.LittleEndian.PutUint16(link_21.Buf[2:], buf_21.Offset-link_21.Offset-2) + } + { + buf := buf_21 + buf.Buf[0] = byte(len(seg)) + buf.Buf[1] = byte(len(seg)) + link_21 = buf + for i, e := range seg { + binary.LittleEndian.PutUint32(buf.Buf[uint16(i)*4+4:], uint32(e)) + } + } + } + x.Imported.marshalZeroPB(b, buf.Slice(112)) + buf_23 := b.AllocRel(len(x.Type_), buf, 112, uint16(len(x.Type_))) + copy(buf_23.Buf, x.Type_) +} +func (x *A) UnmarshalZeroPB(buf []byte) (err error) { + defer func() { + if e := recover(); e != nil { + err = errors.New("buffer underflow") + } + }() + var mem []byte + memSize := _AUnmarshalZeroPBSize(buf, 0) + mem = make([]byte, memSize) + x.unmarshalZeroPB(buf, 0, zeropb.NewBuffer(mem)) + return nil +} + +func _AUnmarshalZeroPBSize(buf []byte, n uint16) (size uint16) { + _, len_14 := zeropb.ReadSlice(buf, n+80) + size += len_14 * uint16(unsafe.Sizeof(byte(0))) + _, len_15 := zeropb.ReadSlice(buf, n+84) + size += len_15 * uint16(unsafe.Sizeof(byte(0))) + size += uint16(unsafe.Sizeof(B{})) + size += _BUnmarshalZeroPBSize(buf, n+88) + n_17, len_17 := zeropb.ReadSlice(buf, n+92) + { + n := n_17 + _ = n + for i := uint16(0); i < len_17; i++ { + _, len_0 := zeropb.ReadSlice(buf, n) + size += len_0 * uint16(unsafe.Sizeof(byte(0))) + n += 4 + size += uint16(unsafe.Sizeof(B{})) + size += _BUnmarshalZeroPBSize(buf, n) + n += 4 + } + } + n_18, len_18 := zeropb.ReadSlice(buf, n+96) + { + n, len := n_18, len_18 + size += len * uint16(unsafe.Sizeof((A{}).LIST[0])) + i8 := byte(0) + segLen := buf[n] + for i := uint16(0); i < len; i++ { + if i8 == segLen { + i8 = 0 + n = zeropb.ReadOffset(buf, n+2) + segLen = buf[n] + } + size += uint16(unsafe.Sizeof(B{})) + size += _BUnmarshalZeroPBSize(buf, n+4+uint16(i8)*4) + i8++ + } + } + // TODO: field ONEOF_B + // TODO: field ONEOF_STRING + n_21, len_21 := zeropb.ReadSlice(buf, n+108) + { + n, len := n_21, len_21 + size += len * uint16(unsafe.Sizeof((A{}).LIST_ENUM[0])) + i8 := byte(0) + segLen := buf[n] + for i := uint16(0); i < len; i++ { + if i8 == segLen { + i8 = 0 + n = zeropb.ReadOffset(buf, n+2) + segLen = buf[n] + } + i8++ + } + } + size += uint16(unsafe.Sizeof(ImportedMessage{})) + size += _ImportedMessageUnmarshalZeroPBSize(buf, n+112) + _, len_23 := zeropb.ReadSlice(buf, n+112) + size += len_23 * uint16(unsafe.Sizeof(byte(0))) + return +} +func (x *A) unmarshalZeroPB(buf []byte, n uint16, mem *zeropb.Buffer) { + x.Enum = Enumeration(binary.LittleEndian.Uint32(buf[n+0:])) + bool_1 := binary.LittleEndian.Uint32(buf[n+4:]) + x.SomeBoolean = false + if bool_1 != 0 { + x.SomeBoolean = true + } + x.INT32 = int32(binary.LittleEndian.Uint32(buf[n+8:])) + x.SINT32 = int32(binary.LittleEndian.Uint32(buf[n+12:])) + x.UINT32 = binary.LittleEndian.Uint32(buf[n+16:]) + x.INT64 = int64(binary.LittleEndian.Uint64(buf[n+20:])) + x.SING64 = int64(binary.LittleEndian.Uint64(buf[n+28:])) + x.UINT64 = binary.LittleEndian.Uint64(buf[n+36:]) + x.SFIXED32 = int32(binary.LittleEndian.Uint32(buf[n+44:])) + x.FIXED32 = binary.LittleEndian.Uint32(buf[n+48:]) + x.FLOAT = float32(math.Float32frombits(binary.LittleEndian.Uint32(buf[n+52:]))) + x.SFIXED64 = int64(binary.LittleEndian.Uint64(buf[n+56:])) + x.FIXED64 = binary.LittleEndian.Uint64(buf[n+64:]) + x.DOUBLE = float64(math.Float64frombits(binary.LittleEndian.Uint64(buf[n+72:]))) + n_14, len_14 := zeropb.ReadSlice(buf, n+80) + buf_14 := buf[n_14 : n_14+len_14] + mem_14 := mem.Alloc(int(len_14) * int(unsafe.Sizeof(x.STRING[0]))) + copy(mem_14.Buf, buf_14) + x.STRING = unsafe.String(unsafe.SliceData(mem_14.Buf), len(mem_14.Buf)) + n_15, len_15 := zeropb.ReadSlice(buf, n+84) + buf_15 := buf[n_15 : n_15+len_15] + mem_15 := mem.Alloc(int(len_15) * int(unsafe.Sizeof(x.BYTES[0]))) + copy(mem_15.Buf, buf_15) + x.BYTES = mem_15.Buf + mem_16 := mem.Alloc(int(unsafe.Sizeof(*x.MESSAGE))) + x.MESSAGE = (*B)(unsafe.Pointer(unsafe.SliceData(mem_16.Buf))) + x.MESSAGE.unmarshalZeroPB(buf, n+88, mem) + n_17, len_17 := zeropb.ReadSlice(buf, n+92) + x.MAP = make(map[string]*B, len_17) + { + n := n_17 + for i := uint16(0); i < len_17; i++ { + var k string + var v *B + n_0, len_0 := zeropb.ReadSlice(buf, n) + buf_0 := buf[n_0 : n_0+len_0] + mem_0 := mem.Alloc(int(len_0) * int(unsafe.Sizeof(k[0]))) + copy(mem_0.Buf, buf_0) + k = unsafe.String(unsafe.SliceData(mem_0.Buf), len(mem_0.Buf)) + n += 4 + mem_1 := mem.Alloc(int(unsafe.Sizeof(*v))) + v = (*B)(unsafe.Pointer(unsafe.SliceData(mem_1.Buf))) + v.unmarshalZeroPB(buf, n, mem) + n += 4 + x.MAP[k] = v + } + } + n_18, len_18 := zeropb.ReadSlice(buf, n+96) + mem_18 := mem.Alloc(int(len_18) * int(unsafe.Sizeof(x.LIST[0]))) + x.LIST = unsafe.Slice((**B)(unsafe.Pointer(unsafe.SliceData(mem_18.Buf))), len_18) + { + n, len := n_18, len_18 + _ = len + i8 := byte(0) + segLen := buf[n] + for i := range x.LIST { + if i8 == segLen { + i8 = 0 + n = zeropb.ReadOffset(buf, n+2) + segLen = buf[n] + } + mem_18 := mem.Alloc(int(unsafe.Sizeof(*x.LIST[i]))) + x.LIST[i] = (*B)(unsafe.Pointer(unsafe.SliceData(mem_18.Buf))) + x.LIST[i].unmarshalZeroPB(buf, n+4+uint16(i8)*4, mem) + i8++ + } + } + // TODO: field ONEOF_B + // TODO: field ONEOF_STRING + n_21, len_21 := zeropb.ReadSlice(buf, n+108) + mem_21 := mem.Alloc(int(len_21) * int(unsafe.Sizeof(x.LIST_ENUM[0]))) + x.LIST_ENUM = unsafe.Slice((*Enumeration)(unsafe.Pointer(unsafe.SliceData(mem_21.Buf))), len_21) + { + n, len := n_21, len_21 + _ = len + i8 := byte(0) + segLen := buf[n] + for i := range x.LIST_ENUM { + if i8 == segLen { + i8 = 0 + n = zeropb.ReadOffset(buf, n+2) + segLen = buf[n] + } + x.LIST_ENUM[i] = Enumeration(binary.LittleEndian.Uint32(buf[n+4+uint16(i8)*4:])) + i8++ + } + } + mem_22 := mem.Alloc(int(unsafe.Sizeof(*x.Imported))) + x.Imported = (*ImportedMessage)(unsafe.Pointer(unsafe.SliceData(mem_22.Buf))) + x.Imported.unmarshalZeroPB(buf, n+112, mem) + n_23, len_23 := zeropb.ReadSlice(buf, n+112) + buf_23 := buf[n_23 : n_23+len_23] + mem_23 := mem.Alloc(int(len_23) * int(unsafe.Sizeof(x.Type_[0]))) + copy(mem_23.Buf, buf_23) + x.Type_ = unsafe.String(unsafe.SliceData(mem_23.Buf), len(mem_23.Buf)) +} +func (x *B) MarshalZeroPB(buf []byte) (n int, err error) { + defer func() { + if e := recover(); e != nil { + err = errors.New("buffer overflow") + } + }() + b := zeropb.NewBuffer(buf) + x.marshalZeroPB(b, b.Alloc(4)) + return int(b.Allocated()), nil +} + +func (x *B) marshalZeroPB(b *zeropb.Buffer, buf zeropb.Allocation) { + if x == nil { + return + } + buf_0 := b.AllocRel(len(x.X), buf, 0, uint16(len(x.X))) + copy(buf_0.Buf, x.X) +} +func (x *B) UnmarshalZeroPB(buf []byte) (err error) { + defer func() { + if e := recover(); e != nil { + err = errors.New("buffer underflow") + } + }() + var mem []byte + memSize := _BUnmarshalZeroPBSize(buf, 0) + mem = make([]byte, memSize) + x.unmarshalZeroPB(buf, 0, zeropb.NewBuffer(mem)) + return nil +} + +func _BUnmarshalZeroPBSize(buf []byte, n uint16) (size uint16) { + _, len_0 := zeropb.ReadSlice(buf, n+0) + size += len_0 * uint16(unsafe.Sizeof(byte(0))) + return +} +func (x *B) unmarshalZeroPB(buf []byte, n uint16, mem *zeropb.Buffer) { + n_0, len_0 := zeropb.ReadSlice(buf, n+0) + buf_0 := buf[n_0 : n_0+len_0] + mem_0 := mem.Alloc(int(len_0) * int(unsafe.Sizeof(x.X[0]))) + copy(mem_0.Buf, buf_0) + x.X = unsafe.String(unsafe.SliceData(mem_0.Buf), len(mem_0.Buf)) +} diff --git a/testpb/2.pulsar.go b/testpb/2.pulsar.go index cb2aac9..cbc03cc 100644 --- a/testpb/2.pulsar.go +++ b/testpb/2.pulsar.go @@ -2,8 +2,10 @@ package testpb import ( + errors "errors" fmt "fmt" runtime "github.com/cosmos/cosmos-proto/runtime" + zeropb "github.com/cosmos/cosmos-proto/runtime/zeropb" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoiface "google.golang.org/protobuf/runtime/protoiface" protoimpl "google.golang.org/protobuf/runtime/protoimpl" @@ -371,7 +373,7 @@ func (x *fastReflection_ImportedMessage) ProtoMethods() *protoiface.Methods { // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.0 -// protoc v3.18.1 +// protoc v4.24.4 // source: testpb/2.proto const ( @@ -480,3 +482,37 @@ func file_testpb_2_proto_init() { file_testpb_2_proto_goTypes = nil file_testpb_2_proto_depIdxs = nil } +func (x *ImportedMessage) MarshalZeroPB(buf []byte) (n int, err error) { + defer func() { + if e := recover(); e != nil { + err = errors.New("buffer overflow") + } + }() + b := zeropb.NewBuffer(buf) + x.marshalZeroPB(b, b.Alloc(0)) + return int(b.Allocated()), nil +} + +func (x *ImportedMessage) marshalZeroPB(b *zeropb.Buffer, buf zeropb.Allocation) { + if x == nil { + return + } +} +func (x *ImportedMessage) UnmarshalZeroPB(buf []byte) (err error) { + defer func() { + if e := recover(); e != nil { + err = errors.New("buffer underflow") + } + }() + var mem []byte + memSize := _ImportedMessageUnmarshalZeroPBSize(buf, 0) + mem = make([]byte, memSize) + x.unmarshalZeroPB(buf, 0, zeropb.NewBuffer(mem)) + return nil +} + +func _ImportedMessageUnmarshalZeroPBSize(buf []byte, n uint16) (size uint16) { + return +} +func (x *ImportedMessage) unmarshalZeroPB(buf []byte, n uint16, mem *zeropb.Buffer) { +} diff --git a/testpb/codec_test.go b/testpb/codec_test.go index fc8014e..cca0304 100644 --- a/testpb/codec_test.go +++ b/testpb/codec_test.go @@ -1,6 +1,7 @@ package testpb import ( + fmt "fmt" "testing" "github.com/stretchr/testify/require" @@ -9,62 +10,133 @@ import ( "google.golang.org/protobuf/types/dynamicpb" ) -func TestMarshal(t *testing.T) { - msg := &A{ - Enum: Enumeration_Two, - SomeBoolean: true, - INT32: 2, - SINT32: 3, - UINT32: 4, - INT64: 5, - SING64: 6, - UINT64: 7, - SFIXED32: 8, - FIXED32: 9, - FLOAT: 10.1, - SFIXED64: 11, - FIXED64: 12, - DOUBLE: 13, - STRING: "fourteen", - BYTES: []byte("fifteen"), - MESSAGE: &B{X: "something"}, - MAP: map[string]*B{"a": &B{X: "aa"}}, - LIST: []*B{{X: "list"}}, - ONEOF: &A_ONEOF_B{ONEOF_B: &B{X: "ONEOF"}}, - LIST_ENUM: []Enumeration{Enumeration_One}, - } +var testA = &A{ + Enum: Enumeration_Two, + SomeBoolean: true, + INT32: 2, + SINT32: 3, + UINT32: 4, + INT64: 5, + SING64: 6, + UINT64: 7, + SFIXED32: 8, + FIXED32: 9, + FLOAT: 10.1, + SFIXED64: 11, + FIXED64: 12, + DOUBLE: 13, + STRING: "fourteen", + BYTES: []byte("fifteen"), + MESSAGE: &B{X: "something"}, + MAP: map[string]*B{"a": &B{X: "aa"}}, + LIST: []*B{{X: "list"}}, + ONEOF: &A_ONEOF_B{ONEOF_B: &B{X: "ONEOF"}}, + LIST_ENUM: []Enumeration{Enumeration_One}, +} +func TestMarshal(t *testing.T) { dynA := dynamicpb.NewMessage(md_A) // dynB := dynamicpb.NewMessage(md_B) - dynA.Set(fd_A_enum, protoreflect.ValueOfEnum(protoreflect.EnumNumber(msg.Enum))) - dynA.Set(fd_A_some_boolean, protoreflect.ValueOfBool(msg.SomeBoolean)) - dynA.Set(fd_A_INT32, protoreflect.ValueOfInt32(msg.INT32)) - dynA.Set(fd_A_SINT32, protoreflect.ValueOfInt32(msg.SINT32)) - dynA.Set(fd_A_UINT32, protoreflect.ValueOfUint32(msg.UINT32)) - dynA.Set(fd_A_INT64, protoreflect.ValueOfInt64(msg.INT64)) - dynA.Set(fd_A_SING64, protoreflect.ValueOfInt64(msg.SING64)) - dynA.Set(fd_A_UINT64, protoreflect.ValueOfUint64(msg.UINT64)) - dynA.Set(fd_A_SFIXED32, protoreflect.ValueOfInt32(msg.SFIXED32)) - dynA.Set(fd_A_FIXED32, protoreflect.ValueOfUint32(msg.FIXED32)) - dynA.Set(fd_A_FLOAT, protoreflect.ValueOfFloat32(msg.FLOAT)) - dynA.Set(fd_A_SFIXED64, protoreflect.ValueOfInt64(msg.SFIXED64)) - dynA.Set(fd_A_FIXED64, protoreflect.ValueOfUint64(msg.FIXED64)) - dynA.Set(fd_A_DOUBLE, protoreflect.ValueOfFloat64(msg.DOUBLE)) - dynA.Set(fd_A_STRING, protoreflect.ValueOfString(msg.STRING)) - dynA.Set(fd_A_BYTES, protoreflect.ValueOfBytes(msg.BYTES)) - dynA.Set(fd_A_MESSAGE, protoreflect.ValueOfMessage(msg.MESSAGE.ProtoReflect())) + dynA.Set(fd_A_enum, protoreflect.ValueOfEnum(protoreflect.EnumNumber(testA.Enum))) + dynA.Set(fd_A_some_boolean, protoreflect.ValueOfBool(testA.SomeBoolean)) + dynA.Set(fd_A_INT32, protoreflect.ValueOfInt32(testA.INT32)) + dynA.Set(fd_A_SINT32, protoreflect.ValueOfInt32(testA.SINT32)) + dynA.Set(fd_A_UINT32, protoreflect.ValueOfUint32(testA.UINT32)) + dynA.Set(fd_A_INT64, protoreflect.ValueOfInt64(testA.INT64)) + dynA.Set(fd_A_SING64, protoreflect.ValueOfInt64(testA.SING64)) + dynA.Set(fd_A_UINT64, protoreflect.ValueOfUint64(testA.UINT64)) + dynA.Set(fd_A_SFIXED32, protoreflect.ValueOfInt32(testA.SFIXED32)) + dynA.Set(fd_A_FIXED32, protoreflect.ValueOfUint32(testA.FIXED32)) + dynA.Set(fd_A_FLOAT, protoreflect.ValueOfFloat32(testA.FLOAT)) + dynA.Set(fd_A_SFIXED64, protoreflect.ValueOfInt64(testA.SFIXED64)) + dynA.Set(fd_A_FIXED64, protoreflect.ValueOfUint64(testA.FIXED64)) + dynA.Set(fd_A_DOUBLE, protoreflect.ValueOfFloat64(testA.DOUBLE)) + dynA.Set(fd_A_STRING, protoreflect.ValueOfString(testA.STRING)) + dynA.Set(fd_A_BYTES, protoreflect.ValueOfBytes(testA.BYTES)) + dynA.Set(fd_A_MESSAGE, protoreflect.ValueOfMessage(testA.MESSAGE.ProtoReflect())) dynMap := dynA.Mutable(fd_A_MAP).Map() - dynMap.Set(protoreflect.MapKey(protoreflect.ValueOfString("a")), protoreflect.ValueOfMessage(msg.MAP["a"].ProtoReflect())) - dynA.Mutable(fd_A_LIST).List().AppendMutable().Message().Set(fd_B_x, protoreflect.ValueOfString(msg.LIST[0].X)) - dynA.Set(fd_A_ONEOF_B, protoreflect.ValueOfMessage(msg.ONEOF.(*A_ONEOF_B).ONEOF_B.ProtoReflect())) + dynMap.Set(protoreflect.MapKey(protoreflect.ValueOfString("a")), protoreflect.ValueOfMessage(testA.MAP["a"].ProtoReflect())) + dynA.Mutable(fd_A_LIST).List().AppendMutable().Message().Set(fd_B_x, protoreflect.ValueOfString(testA.LIST[0].X)) + dynA.Set(fd_A_ONEOF_B, protoreflect.ValueOfMessage(testA.ONEOF.(*A_ONEOF_B).ONEOF_B.ProtoReflect())) dynA.Mutable(fd_A_LIST_ENUM).List().Append(protoreflect.ValueOfEnum((protoreflect.EnumNumber)(Enumeration_One))) - got, err := proto.MarshalOptions{Deterministic: true}.Marshal(msg) + got, err := proto.MarshalOptions{Deterministic: true}.Marshal(testA) require.NoError(t, err) expected, err := proto.MarshalOptions{Deterministic: true}.Marshal(dynA) require.NoError(t, err) require.Equal(t, expected, got) + + zpbBuf := make([]byte, 64*1024) + n, err := testA.MarshalZeroPB(zpbBuf) + require.NoError(t, err) + var msg2 A + err = msg2.UnmarshalZeroPB(zpbBuf[:n]) + require.NoError(t, err) + zpbGot, err := proto.MarshalOptions{Deterministic: true}.Marshal(&msg2) + require.NoError(t, err) + require.Equal(t, expected, zpbGot) +} + +func TestZeroPBSegments(t *testing.T) { + var longList A + for i := 0; i < 256; i++ { + longList.LIST = append(longList.LIST, &B{ + X: fmt.Sprintf("list%d", i), + }) + } + buf := make([]byte, 64*1024) + n, err := longList.MarshalZeroPB(buf) + require.NoError(t, err) + var got A + err = got.UnmarshalZeroPB(buf[:n]) + require.NoError(t, err) + require.Equal(t, longList.LIST, got.LIST) +} + +func BenchmarkMarshalA(b *testing.B) { + protoOpts := proto.MarshalOptions{} + b.Run("proto", func(b *testing.B) { + for i := 0; i < b.N; i++ { + protoOpts.Marshal(testA) + } + }) + zpbBuf := make([]byte, 64*1024) + b.Run("zeropb", func(b *testing.B) { + for i := 0; i < b.N; i++ { + testA.MarshalZeroPB(zpbBuf) + } + }) + n, err := testA.MarshalZeroPB(zpbBuf) + require.NoError(b, err) + data := make([]byte, n) + testA.MarshalZeroPB(data) + b.Run("copy", func(b *testing.B) { + for i := 0; i < b.N; i++ { + copy(zpbBuf, data) + testA.MarshalZeroPB(zpbBuf) + } + }) +} + +func BenchmarkUnmarshalA(b *testing.B) { + protoA, err := proto.MarshalOptions{}.Marshal(testA) + require.NoError(b, err) + b.Run("proto", func(b *testing.B) { + var a A + for i := 0; i < b.N; i++ { + proto.Unmarshal(protoA, &a) + } + }) + zpbBuf := make([]byte, 64*1024) + n, err := testA.MarshalZeroPB(zpbBuf) + require.NoError(b, err) + b.Run("zeropb", func(b *testing.B) { + var testA A + for i := 0; i < b.N; i++ { + testA.UnmarshalZeroPB(zpbBuf[:n]) + } + }) }