util/proto: Optimize int32 marshaling

This is the approach used in easyproto
52d3ac4744/writer.go (L203)

It allows to occupy slightly less space for negative numbers.
The format is still protobuf, although, technically, this is a breaking
change for our stable marshaling format.
However, we don't use int32 at all and all enums have positive values,
so nothing is broken.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
This commit is contained in:
Evgenii Stratonikov 2024-08-09 17:20:07 +03:00
parent 47a48969b0
commit c0565085c1

View file

@ -136,19 +136,19 @@ func UInt32Size(field int, v uint32) int {
} }
func Int32Marshal(field int, buf []byte, v int32) int { func Int32Marshal(field int, buf []byte, v int32) int {
return UInt64Marshal(field, buf, uint64(v)) return UInt64Marshal(field, buf, uint64(uint32(v)))
} }
func Int32Size(field int, v int32) int { func Int32Size(field int, v int32) int {
return UInt64Size(field, uint64(v)) return UInt64Size(field, uint64(uint32(v)))
} }
func EnumMarshal(field int, buf []byte, v int32) int { func EnumMarshal(field int, buf []byte, v int32) int {
return UInt64Marshal(field, buf, uint64(v)) return UInt64Marshal(field, buf, uint64(uint32(v)))
} }
func EnumSize(field int, v int32) int { func EnumSize(field int, v int32) int {
return UInt64Size(field, uint64(v)) return UInt64Size(field, uint64(uint32(v)))
} }
func RepeatedBytesMarshal(field int, buf []byte, v [][]byte) int { func RepeatedBytesMarshal(field int, buf []byte, v [][]byte) int {
@ -243,11 +243,28 @@ func RepeatedUInt32Size(field int, v []uint32) (size, arraySize int) {
} }
func RepeatedInt32Marshal(field int, buf []byte, v []int32) int { func RepeatedInt32Marshal(field int, buf []byte, v []int32) int {
return repeatedUIntMarshal(field, buf, v) if len(v) == 0 {
return 0
}
prefix := protowire.EncodeTag(protowire.Number(field), protowire.BytesType)
offset := binary.PutUvarint(buf, uint64(prefix))
_, arrSize := RepeatedInt32Size(field, v)
offset += binary.PutUvarint(buf[offset:], uint64(arrSize))
for i := range v {
offset += binary.PutUvarint(buf[offset:], uint64(uint32(v[i])))
}
return offset
} }
func RepeatedInt32Size(field int, v []int32) (size, arraySize int) { func RepeatedInt32Size(field int, v []int32) (size, arraySize int) {
return repeatedUIntSize(field, v) if len(v) == 0 {
return 0, 0
}
for i := range v {
arraySize += protowire.SizeVarint(uint64(uint32(v[i])))
}
return protowire.SizeGroup(protowire.Number(field), protowire.SizeBytes(arraySize)), arraySize
} }
// VarUIntSize returns length of varint byte sequence for uint64 value 'x'. // VarUIntSize returns length of varint byte sequence for uint64 value 'x'.