From ca746f38002a6326bd166ded62b412f9ff5d1af1 Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Sat, 6 Nov 2021 13:38:52 +0300 Subject: [PATCH] [#350] v2: Define response status messages Create `status` package. Define `status.Status` message structure. Export getters, setters and encoding methods. Signed-off-by: Leonard Lyubich --- v2/status/convert.go | 103 +++++++++++++++++++++++++++++++++ v2/status/marshal.go | 115 +++++++++++++++++++++++++++++++++++++ v2/status/message_test.go | 16 ++++++ v2/status/status.go | 80 ++++++++++++++++++++++++++ v2/status/test/generate.go | 44 ++++++++++++++ v2/status/types.go | 114 ++++++++++++++++++++++++++++++++++++ 6 files changed, 472 insertions(+) create mode 100644 v2/status/convert.go create mode 100644 v2/status/marshal.go create mode 100644 v2/status/message_test.go create mode 100644 v2/status/status.go create mode 100644 v2/status/test/generate.go create mode 100644 v2/status/types.go diff --git a/v2/status/convert.go b/v2/status/convert.go new file mode 100644 index 0000000..5c05221 --- /dev/null +++ b/v2/status/convert.go @@ -0,0 +1,103 @@ +package status + +import ( + "github.com/nspcc-dev/neofs-api-go/rpc/grpc" + "github.com/nspcc-dev/neofs-api-go/rpc/message" + status "github.com/nspcc-dev/neofs-api-go/v2/status/grpc" +) + +func (x *Detail) ToGRPCMessage() grpc.Message { + var m *status.Status_Detail + + if x != nil { + m = new(status.Status_Detail) + + m.SetId(x.id) + m.SetValue(x.val) + } + + return m +} + +func (x *Detail) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*status.Status_Detail) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + x.id = v.GetId() + x.val = v.GetValue() + + return nil +} + +func CodeFromGRPC(v uint32) Code { + return Code(v) +} + +func CodeToGRPC(v Code) uint32 { + return uint32(v) +} + +func (x *Status) ToGRPCMessage() grpc.Message { + var m *status.Status + + if x != nil { + m = new(status.Status) + + m.SetCode(CodeToGRPC(x.code)) + m.SetMessage(x.msg) + + var ds []*status.Status_Detail + + if ln := len(x.details); ln > 0 { + ds = make([]*status.Status_Detail, 0, ln) + + for i := 0; i < ln; i++ { + ds = append(ds, x.details[i].ToGRPCMessage().(*status.Status_Detail)) + } + } + + m.SetDetails(ds) + } + + return m +} + +func (x *Status) FromGRPCMessage(m grpc.Message) error { + v, ok := m.(*status.Status) + if !ok { + return message.NewUnexpectedMessageType(m, v) + } + + var ( + ds []*Detail + dsV2 = v.GetDetails() + ) + + if dsV2 != nil { + ln := len(dsV2) + + ds = make([]*Detail, 0, ln) + + for i := 0; i < ln; i++ { + var p *Detail + + if dsV2[i] != nil { + p = new(Detail) + + if err := p.FromGRPCMessage(dsV2[i]); err != nil { + return err + } + } + + ds = append(ds, p) + } + } + + x.details = ds + x.msg = v.GetMessage() + x.code = CodeFromGRPC(v.GetCode()) + + return nil +} diff --git a/v2/status/marshal.go b/v2/status/marshal.go new file mode 100644 index 0000000..8170325 --- /dev/null +++ b/v2/status/marshal.go @@ -0,0 +1,115 @@ +package status + +import ( + "github.com/nspcc-dev/neofs-api-go/rpc/message" + protoutil "github.com/nspcc-dev/neofs-api-go/util/proto" + status "github.com/nspcc-dev/neofs-api-go/v2/status/grpc" +) + +const ( + _ = iota + detailIDFNum + detailValueFNum +) + +func (x *Detail) StableMarshal(buf []byte) ([]byte, error) { + if x == nil { + return []byte{}, nil + } + + if buf == nil { + buf = make([]byte, x.StableSize()) + } + + var ( + offset, n int + err error + ) + + n, err = protoutil.UInt32Marshal(detailIDFNum, buf[offset:], x.id) + if err != nil { + return nil, err + } + + offset += n + + _, err = protoutil.BytesMarshal(detailValueFNum, buf[offset:], x.val) + if err != nil { + return nil, err + } + + return buf, nil +} + +func (x *Detail) StableSize() (size int) { + size += protoutil.UInt32Size(detailIDFNum, x.id) + size += protoutil.BytesSize(detailValueFNum, x.val) + + return size +} + +func (x *Detail) Unmarshal(data []byte) error { + return message.Unmarshal(x, data, new(status.Status_Detail)) +} + +const ( + _ = iota + statusCodeFNum + statusMsgFNum + statusDetailsFNum +) + +func (x *Status) StableMarshal(buf []byte) ([]byte, error) { + if x == nil { + return []byte{}, nil + } + + if buf == nil { + buf = make([]byte, x.StableSize()) + } + + var ( + offset, n int + err error + ) + + n, err = protoutil.UInt32Marshal(statusCodeFNum, buf[offset:], CodeToGRPC(x.code)) + if err != nil { + return nil, err + } + + offset += n + + n, err = protoutil.StringMarshal(statusMsgFNum, buf[offset:], x.msg) + if err != nil { + return nil, err + } + + offset += n + + for i := range x.details { + n, err = protoutil.NestedStructureMarshal(statusDetailsFNum, buf[offset:], x.details[i]) + if err != nil { + return nil, err + } + + offset += n + } + + return buf, nil +} + +func (x *Status) StableSize() (size int) { + size += protoutil.UInt32Size(statusCodeFNum, CodeToGRPC(x.code)) + size += protoutil.StringSize(statusMsgFNum, x.msg) + + for i := range x.details { + size += protoutil.NestedStructureSize(statusDetailsFNum, x.details[i]) + } + + return size +} + +func (x *Status) Unmarshal(data []byte) error { + return message.Unmarshal(x, data, new(status.Status)) +} diff --git a/v2/status/message_test.go b/v2/status/message_test.go new file mode 100644 index 0000000..c301162 --- /dev/null +++ b/v2/status/message_test.go @@ -0,0 +1,16 @@ +package status_test + +import ( + "testing" + + "github.com/nspcc-dev/neofs-api-go/rpc/message" + messagetest "github.com/nspcc-dev/neofs-api-go/rpc/message/test" + statustest "github.com/nspcc-dev/neofs-api-go/v2/status/test" +) + +func TestMessageConvert(t *testing.T) { + messagetest.TestRPCMessage(t, + func(empty bool) message.Message { return statustest.Detail(empty) }, + func(empty bool) message.Message { return statustest.Status(empty) }, + ) +} diff --git a/v2/status/status.go b/v2/status/status.go new file mode 100644 index 0000000..d24ce57 --- /dev/null +++ b/v2/status/status.go @@ -0,0 +1,80 @@ +package status + +const sectionBitSize = 10 + +// InSections checks if the Code is in [i,j] section list. +func (x Code) InSections(i, j uint32) bool { + return uint32(x) >= i<