diff --git a/client/status/object.go b/client/status/object.go new file mode 100644 index 00000000..43a6a8eb --- /dev/null +++ b/client/status/object.go @@ -0,0 +1,66 @@ +package apistatus + +import ( + "github.com/nspcc-dev/neofs-api-go/v2/object" + "github.com/nspcc-dev/neofs-api-go/v2/status" +) + +// ObjectLocked describes status of the failure because of the locked object. +// Instances provide Status and StatusV2 interfaces. +type ObjectLocked struct { + v2 status.Status +} + +func (x ObjectLocked) Error() string { + return errMessageStatusV2( + globalizeCodeV2(object.StatusLocked, object.GlobalizeFail), + x.v2.Message(), + ) +} + +// implements local interface defined in FromStatusV2 func. +func (x *ObjectLocked) fromStatusV2(st *status.Status) { + x.v2 = *st +} + +// ToStatusV2 implements StatusV2 interface method. +// If the value was returned by FromStatusV2, returns the source message. +// Otherwise, returns message with +// * code: LOCKED; +// * string message: "object is locked"; +// * details: empty. +func (x ObjectLocked) ToStatusV2() *status.Status { + x.v2.SetCode(globalizeCodeV2(object.StatusLocked, object.GlobalizeFail)) + x.v2.SetMessage("object is locked") + return &x.v2 +} + +// LockNonRegularObject describes status returned on locking the non-regular object. +// Instances provide Status and StatusV2 interfaces. +type LockNonRegularObject struct { + v2 status.Status +} + +func (x LockNonRegularObject) Error() string { + return errMessageStatusV2( + globalizeCodeV2(object.StatusLockNonRegularObject, object.GlobalizeFail), + x.v2.Message(), + ) +} + +// implements local interface defined in FromStatusV2 func. +func (x *LockNonRegularObject) fromStatusV2(st *status.Status) { + x.v2 = *st +} + +// ToStatusV2 implements StatusV2 interface method. +// If the value was returned by FromStatusV2, returns the source message. +// Otherwise, returns message with +// * code: LOCK_NON_REGULAR_OBJECT; +// * string message: "locking non-regular object is forbidden"; +// * details: empty. +func (x LockNonRegularObject) ToStatusV2() *status.Status { + x.v2.SetCode(globalizeCodeV2(object.StatusLockNonRegularObject, object.GlobalizeFail)) + x.v2.SetMessage("locking non-regular object is forbidden") + return &x.v2 +} diff --git a/client/status/v2.go b/client/status/v2.go index 42a97208..0fb5b672 100644 --- a/client/status/v2.go +++ b/client/status/v2.go @@ -3,6 +3,7 @@ package apistatus import ( "fmt" + "github.com/nspcc-dev/neofs-api-go/v2/object" "github.com/nspcc-dev/neofs-api-go/v2/status" ) @@ -29,6 +30,10 @@ type StatusV2 interface { // // Common failures: // * status.Internal: *ServerInternal. +// +// Object failures: +// * object.StatusLocked: *ObjectLocked; +// * object.StatusLockNonRegularObject: *LockNonRegularObject. func FromStatusV2(st *status.Status) Status { var decoder interface { fromStatusV2(*status.Status) @@ -48,6 +53,13 @@ func FromStatusV2(st *status.Status) Status { case status.WrongMagicNumber: decoder = new(WrongMagicNumber) } + case object.LocalizeFailStatus(&code): + switch code { + case object.StatusLocked: + decoder = new(ObjectLocked) + case object.StatusLockNonRegularObject: + decoder = new(LockNonRegularObject) + } } if decoder == nil { diff --git a/client/status/v2_test.go b/client/status/v2_test.go index ebcab1d2..6fe71972 100644 --- a/client/status/v2_test.go +++ b/client/status/v2_test.go @@ -59,6 +59,18 @@ func TestToStatusV2(t *testing.T) { }), codeV2: 1025, }, + { + status: (statusConstructor)(func() apistatus.Status { + return new(apistatus.ObjectLocked) + }), + codeV2: 2050, + }, + { + status: (statusConstructor)(func() apistatus.Status { + return new(apistatus.LockNonRegularObject) + }), + codeV2: 2051, + }, } { var st apistatus.Status @@ -137,6 +149,18 @@ func TestFromStatusV2(t *testing.T) { }), codeV2: 1025, }, + { + status: (statusConstructor)(func() apistatus.Status { + return new(apistatus.ObjectLocked) + }), + codeV2: 2050, + }, + { + status: (statusConstructor)(func() apistatus.Status { + return new(apistatus.LockNonRegularObject) + }), + codeV2: 2051, + }, } { var st apistatus.Status diff --git a/object/lock.go b/object/lock.go new file mode 100644 index 00000000..2ac632f6 --- /dev/null +++ b/object/lock.go @@ -0,0 +1,58 @@ +package object + +import ( + v2object "github.com/nspcc-dev/neofs-api-go/v2/object" + "github.com/nspcc-dev/neofs-api-go/v2/refs" + oid "github.com/nspcc-dev/neofs-sdk-go/object/id" +) + +// Lock represents record with locked objects. It is compatible with +// NeoFS API V2 protocol. +type Lock v2object.Lock + +// NumberOfMembers returns number of members in lock list. +func (x Lock) NumberOfMembers() int { + return (*v2object.Lock)(&x).NumberOfMembers() +} + +// ReadMembers reads list of locked members. +// +// Buffer length must not be less than NumberOfMembers. +func (x Lock) ReadMembers(buf []oid.ID) { + var i int + + (*v2object.Lock)(&x).IterateMembers(func(id refs.ObjectID) { + buf[i] = *oid.NewIDFromV2(&id) // need smth better + i++ + }) +} + +// WriteMembers writes list of locked members. +func (x *Lock) WriteMembers(ids []oid.ID) { + var members []refs.ObjectID + + if ids != nil { + members = make([]refs.ObjectID, len(ids)) + + for i := range ids { + members[i] = *ids[i].ToV2() // need smth better + } + } + + (*v2object.Lock)(x).SetMembers(members) +} + +// Marshal encodes the Lock into a NeoFS protocol binary format. +func (x Lock) Marshal() []byte { + data, err := (*v2object.Lock)(&x).StableMarshal(nil) + if err != nil { + panic(err) + } + + return data +} + +// Unmarshal decodes the Lock from its NeoFS protocol binary representation. +func (x *Lock) Unmarshal(data []byte) error { + return (*v2object.Lock)(x).Unmarshal(data) +} diff --git a/object/type.go b/object/type.go index 71c8032a..ba6dde43 100644 --- a/object/type.go +++ b/object/type.go @@ -4,34 +4,21 @@ import ( "github.com/nspcc-dev/neofs-api-go/v2/object" ) -type Type uint8 +type Type object.Type const ( TypeRegular Type = iota TypeTombstone TypeStorageGroup + TypeLock ) func (t Type) ToV2() object.Type { - switch t { - case TypeTombstone: - return object.TypeTombstone - case TypeStorageGroup: - return object.TypeStorageGroup - default: - return object.TypeRegular - } + return object.Type(t) } func TypeFromV2(t object.Type) Type { - switch t { - case object.TypeTombstone: - return TypeTombstone - case object.TypeStorageGroup: - return TypeStorageGroup - default: - return TypeRegular - } + return Type(t) } // String returns string representation of Type. @@ -39,6 +26,7 @@ func TypeFromV2(t object.Type) Type { // String mapping: // * TypeTombstone: TOMBSTONE; // * TypeStorageGroup: STORAGE_GROUP; +// * TypeLock: LOCK; // * TypeRegular, default: REGULAR. func (t Type) String() string { return t.ToV2().String() diff --git a/object/type_test.go b/object/type_test.go index f97c985b..d95a41e2 100644 --- a/object/type_test.go +++ b/object/type_test.go @@ -25,6 +25,10 @@ func TestType_ToV2(t *testing.T) { t: object.TypeStorageGroup, t2: v2object.TypeStorageGroup, }, + { + t: object.TypeLock, + t2: v2object.TypeLock, + }, } for _, item := range typs { @@ -45,6 +49,7 @@ func TestType_String(t *testing.T) { {val: toPtr(object.TypeTombstone), str: "TOMBSTONE"}, {val: toPtr(object.TypeStorageGroup), str: "STORAGE_GROUP"}, {val: toPtr(object.TypeRegular), str: "REGULAR"}, + {val: toPtr(object.TypeLock), str: "LOCK"}, }) }