From f21a835be92d5ff5a02ddbb88fc4750ba5a2a048 Mon Sep 17 00:00:00 2001 From: Chris O'Hara Date: Fri, 24 Nov 2023 11:17:21 +1000 Subject: [PATCH] Change how array regions are serialized --- gen/proto/go/coroutine/v1/coroutine.pb.go | 19 +++++++++---------- .../go/coroutine/v1/coroutine_vtproto.pb.go | 2 +- proto/coroutine/v1/coroutine.proto | 15 +++++++-------- types/inspect.go | 4 ++-- types/reflect.go | 14 ++++++++------ types/serde.go | 5 ++--- 6 files changed, 29 insertions(+), 30 deletions(-) diff --git a/gen/proto/go/coroutine/v1/coroutine.pb.go b/gen/proto/go/coroutine/v1/coroutine.pb.go index 3566782..063de0c 100644 --- a/gen/proto/go/coroutine/v1/coroutine.pb.go +++ b/gen/proto/go/coroutine/v1/coroutine.pb.go @@ -197,15 +197,14 @@ type Region struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // Type is the type of the region. + // Type is the type of the region, shifted left by one. + // + // The least significant bit indicates that this region represents + // an array, and that the type is the array element type rather + // than the object that's encoded in this region. Type uint32 `protobuf:"varint,1,opt,name=type,proto3" json:"type,omitempty"` - // Array length, when >= 0, indicates that this region is an - // array of the specified length (in terms of number of - // elements, not in terms of bytes) and that the region type - // is the type of the array element. If the array length is < 0 - // then this region does not represent an array, and the region - // type describes the object that is encoded. - ArrayLength int32 `protobuf:"varint,2,opt,name=array_length,json=arrayLength,proto3" json:"array_length,omitempty"` + // Array length, for regions that are arrays. + ArrayLength uint32 `protobuf:"varint,2,opt,name=array_length,json=arrayLength,proto3" json:"array_length,omitempty"` // Data is the encoded contents of the memory region. Data []byte `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"` } @@ -249,7 +248,7 @@ func (x *Region) GetType() uint32 { return 0 } -func (x *Region) GetArrayLength() int32 { +func (x *Region) GetArrayLength() uint32 { if x != nil { return x.ArrayLength } @@ -297,7 +296,7 @@ var file_coroutine_v1_coroutine_proto_rawDesc = []byte{ 0x0a, 0x06, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x72, 0x72, 0x61, 0x79, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x0b, 0x61, 0x72, 0x72, 0x61, 0x79, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, + 0x28, 0x0d, 0x52, 0x0b, 0x61, 0x72, 0x72, 0x61, 0x79, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x42, 0xbd, 0x01, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x42, 0x0e, 0x43, 0x6f, 0x72, 0x6f, 0x75, 0x74, diff --git a/gen/proto/go/coroutine/v1/coroutine_vtproto.pb.go b/gen/proto/go/coroutine/v1/coroutine_vtproto.pb.go index 7c613dd..e12fc18 100644 --- a/gen/proto/go/coroutine/v1/coroutine_vtproto.pb.go +++ b/gen/proto/go/coroutine/v1/coroutine_vtproto.pb.go @@ -814,7 +814,7 @@ func (m *Region) UnmarshalVT(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.ArrayLength |= int32(b&0x7F) << shift + m.ArrayLength |= uint32(b&0x7F) << shift if b < 0x80 { break } diff --git a/proto/coroutine/v1/coroutine.proto b/proto/coroutine/v1/coroutine.proto index c732341..c5acd64 100644 --- a/proto/coroutine/v1/coroutine.proto +++ b/proto/coroutine/v1/coroutine.proto @@ -42,16 +42,15 @@ message Build { // Region is an encoded region of memory. message Region { - // Type is the type of the region. + // Type is the type of the region, shifted left by one. + // + // The least significant bit indicates that this region represents + // an array, and that the type is the array element type rather + // than the object that's encoded in this region. uint32 type = 1; - // Array length, when >= 0, indicates that this region is an - // array of the specified length (in terms of number of - // elements, not in terms of bytes) and that the region type - // is the type of the array element. If the array length is < 0 - // then this region does not represent an array, and the region - // type describes the object that is encoded. - int32 array_length = 2; + // Array length, for regions that are arrays. + uint32 array_length = 2; // Data is the encoded contents of the memory region. bytes data = 3; diff --git a/types/inspect.go b/types/inspect.go index 7ade231..51b7c3a 100644 --- a/types/inspect.go +++ b/types/inspect.go @@ -598,8 +598,8 @@ func (t *Region) Index() int { // Type is the type of the region. func (r *Region) Type() *Type { - t := r.state.Type(int(r.region.Type - 1)) - if r.region.ArrayLength >= 0 { + t := r.state.Type(int((r.region.Type >> 1) - 1)) + if r.region.Type&1 == 1 { t = newArrayType(r.state, int64(r.region.ArrayLength), t) } return t diff --git a/types/reflect.go b/types/reflect.go index 52ef709..98b313a 100644 --- a/types/reflect.go +++ b/types/reflect.go @@ -415,8 +415,11 @@ func serializePointedAt(s *Serializer, et reflect.Type, length int, p unsafe.Poi } region := &coroutinev1.Region{ - Type: s.types.ToType(r.typ), - ArrayLength: int32(r.len), + Type: s.types.ToType(r.typ) << 1, + } + if r.len >= 0 { + region.Type |= 1 + region.ArrayLength = uint32(r.len) } s.regions = append(s.regions, region) @@ -473,9 +476,9 @@ func deserializePointedAt(d *Deserializer, t reflect.Type, length int) unsafe.Po } region := d.regions[id-1] - regionType := d.types.ToReflect(typeid(region.Type)) + regionType := d.types.ToReflect(typeid(region.Type >> 1)) - if region.ArrayLength >= 0 { + if region.Type&1 == 1 { elemSize := int(regionType.Size()) length := int(region.ArrayLength) data := make([]byte, elemSize*length) @@ -531,8 +534,7 @@ func serializeMapReflect(s *Serializer, t reflect.Type, r reflect.Value) { size := r.Len() region := &coroutinev1.Region{ - Type: s.types.ToType(t), - ArrayLength: -1, // not an array + Type: s.types.ToType(t) << 1, } s.regions = append(s.regions, region) diff --git a/types/serde.go b/types/serde.go index c7be6cd..73f87f8 100644 --- a/types/serde.go +++ b/types/serde.go @@ -58,9 +58,8 @@ func Serialize(x any) ([]byte, error) { Strings: s.strings.strings, Regions: s.regions, Root: &coroutinev1.Region{ - Type: s.types.ToType(t), - ArrayLength: -1, // not an array - Data: s.b, + Type: s.types.ToType(t) << 1, + Data: s.b, }, } return state.MarshalVT()