[#299] client: Do not use pointers to required response fields

In previous implementation `client` package provided access to nested
response fields as pointers to them. This caused clients to handle nil
cases even when the field presence in the response is required.

Avoid returning pointers to required fields in response getters. This
also reduces reference counter load and allows fields to be decoded
directly without additional assignment.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
Leonard Lyubich 2022-08-05 11:56:49 +04:00 committed by Pavel Karpy
parent 30bf79f075
commit 4e31b4f231
10 changed files with 150 additions and 160 deletions

View file

@ -54,22 +54,16 @@ func (x *PrmContainerPut) WithinSession(s session.Container) {
type ResContainerPut struct {
statusRes
id *cid.ID
id cid.ID
}
// ID returns identifier of the container declared to be stored in the system.
// Used as a link to information about the container (in particular, you can
// asynchronously check if the save was successful).
//
// Client doesn't retain value so modification is safe.
func (x ResContainerPut) ID() *cid.ID {
func (x ResContainerPut) ID() cid.ID {
return x.id
}
func (x *ResContainerPut) setID(id *cid.ID) {
x.id = id
}
// ContainerPut sends request to save container in NeoFS.
//
// Exactly one return value is non-nil. By default, server status is returned in res structure.
@ -150,17 +144,19 @@ func (c *Client) ContainerPut(ctx context.Context, prm PrmContainerPut) (*ResCon
}
cc.result = func(r responseV2) {
resp := r.(*v2container.PutResponse)
var cID *cid.ID
const fieldCnrID = "container ID"
cidV2 := resp.GetBody().GetContainerID()
if cidV2 != nil {
var c cid.ID
_ = c.ReadFromV2(*cidV2)
cID = &c
if cidV2 == nil {
cc.err = newErrMissingResponseField(fieldCnrID)
return
}
res.setID(cID)
cc.err = res.id.ReadFromV2(*cidV2)
if cc.err != nil {
cc.err = newErrInvalidResponseField(fieldCnrID, cc.err)
}
}
// process call
@ -200,10 +196,6 @@ func (x ResContainerGet) Container() container.Container {
return x.cnr
}
func (x *ResContainerGet) setContainer(cnr container.Container) {
x.cnr = cnr
}
// ContainerGet reads NeoFS container by ID.
//
// Exactly one return value is non-nil. By default, server status is returned in res structure.
@ -261,15 +253,10 @@ func (c *Client) ContainerGet(ctx context.Context, prm PrmContainerGet) (*ResCon
return
}
var cnr container.Container
err := cnr.ReadFromV2(*cnrV2)
if err != nil {
cc.err = fmt.Errorf("invalid container in response: %w", err)
return
cc.err = res.cnr.ReadFromV2(*cnrV2)
if cc.err != nil {
cc.err = fmt.Errorf("invalid container in response: %w", cc.err)
}
res.setContainer(cnr)
}
// process call
@ -309,10 +296,6 @@ func (x ResContainerList) Containers() []cid.ID {
return x.ids
}
func (x *ResContainerList) setContainers(ids []cid.ID) {
x.ids = ids
}
// ContainerList requests identifiers of the account-owned containers.
//
// Exactly one return value is non-nil. By default, server status is returned in res structure.
@ -364,13 +347,15 @@ func (c *Client) ContainerList(ctx context.Context, prm PrmContainerList) (*ResC
cc.result = func(r responseV2) {
resp := r.(*v2container.ListResponse)
ids := make([]cid.ID, len(resp.GetBody().GetContainerIDs()))
res.ids = make([]cid.ID, len(resp.GetBody().GetContainerIDs()))
for i, cidV2 := range resp.GetBody().GetContainerIDs() {
_ = ids[i].ReadFromV2(cidV2)
cc.err = res.ids[i].ReadFromV2(cidV2)
if cc.err != nil {
cc.err = fmt.Errorf("invalid ID in the response: %w", cc.err)
return
}
}
res.setContainers(ids)
}
// process call
@ -527,20 +512,14 @@ func (x *PrmContainerEACL) SetContainer(id cid.ID) {
type ResContainerEACL struct {
statusRes
table *eacl.Table
table eacl.Table
}
// Table returns eACL table of the requested container.
//
// Client doesn't retain value so modification is safe.
func (x ResContainerEACL) Table() *eacl.Table {
func (x ResContainerEACL) Table() eacl.Table {
return x.table
}
func (x *ResContainerEACL) setTable(table *eacl.Table) {
x.table = table
}
// ContainerEACL reads eACL table of the NeoFS container.
//
// Exactly one return value is non-nil. By default, server status is returned in res structure.
@ -594,11 +573,13 @@ func (c *Client) ContainerEACL(ctx context.Context, prm PrmContainerEACL) (*ResC
cc.result = func(r responseV2) {
resp := r.(*v2container.GetExtendedACLResponse)
body := resp.GetBody()
eACL := resp.GetBody().GetEACL()
if eACL == nil {
cc.err = newErrMissingResponseField("eACL")
return
}
table := eacl.NewTableFromV2(body.GetEACL())
res.setTable(table)
res.table = *eacl.NewTableFromV2(eACL)
}
// process call
@ -833,7 +814,7 @@ func SyncContainerWithNetwork(ctx context.Context, cnr *container.Container, c *
return fmt.Errorf("network info call: %w", err)
}
container.ApplyNetworkConfig(cnr, *res.Info())
container.ApplyNetworkConfig(cnr, res.Info())
return nil
}