From 4567986682df932bbd7d134e17d0fc1657102aff Mon Sep 17 00:00:00 2001
From: Leonard Lyubich <leonard@nspcc.ru>
Date: Thu, 10 Dec 2020 12:15:17 +0300
Subject: [PATCH] [#226] v2/object: Add tombstone field to DeleteResponseBody

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
---
 v2/object/convert.go      |  6 ++++++
 v2/object/grpc/service.go |  7 +++++++
 v2/object/marshal.go      | 25 +++++++++++++++++++++++--
 v2/object/marshal_test.go |  9 ++++++---
 v2/object/types.go        | 20 +++++++++++++++++++-
 5 files changed, 61 insertions(+), 6 deletions(-)

diff --git a/v2/object/convert.go b/v2/object/convert.go
index 24d4f47a..f9d5a064 100644
--- a/v2/object/convert.go
+++ b/v2/object/convert.go
@@ -909,6 +909,9 @@ func DeleteResponseBodyToGRPCMessage(r *DeleteResponseBody) *object.DeleteRespon
 	}
 
 	m := new(object.DeleteResponse_Body)
+	m.SetTombstone(
+		refs.AddressToGRPCMessage(r.GetTombstone()),
+	)
 
 	return m
 }
@@ -919,6 +922,9 @@ func DeleteResponseBodyFromGRPCMessage(m *object.DeleteResponse_Body) *DeleteRes
 	}
 
 	r := new(DeleteResponseBody)
+	r.SetTombstone(
+		refs.AddressFromGRPCMessage(m.GetTombstone()),
+	)
 
 	return r
 }
diff --git a/v2/object/grpc/service.go b/v2/object/grpc/service.go
index 323522b5..e9b7659d 100644
--- a/v2/object/grpc/service.go
+++ b/v2/object/grpc/service.go
@@ -260,6 +260,13 @@ func (m *DeleteRequest) SetVerifyHeader(v *session.RequestVerificationHeader) {
 	}
 }
 
+// SetTombstone sets tombstone address.
+func (x *DeleteResponse_Body) SetTombstone(v *refs.Address) {
+	if x != nil {
+		x.Tombstone = v
+	}
+}
+
 // SetBody sets body of the response.
 func (m *DeleteResponse) SetBody(v *DeleteResponse_Body) {
 	if m != nil {
diff --git a/v2/object/marshal.go b/v2/object/marshal.go
index 04737b60..f08c71df 100644
--- a/v2/object/marshal.go
+++ b/v2/object/marshal.go
@@ -70,6 +70,8 @@ const (
 
 	deleteReqBodyAddressField = 1
 
+	deleteRespBodyTombstoneFNum = 1
+
 	headReqBodyAddressField  = 1
 	headReqBodyMainFlagField = 2
 	headReqBodyRawFlagField  = 3
@@ -953,11 +955,30 @@ func (r *DeleteRequestBody) StableSize() (size int) {
 }
 
 func (r *DeleteResponseBody) StableMarshal(buf []byte) ([]byte, error) {
-	return nil, nil
+	if r == nil {
+		return []byte{}, nil
+	}
+
+	if buf == nil {
+		buf = make([]byte, r.StableSize())
+	}
+
+	_, err := proto.NestedStructureMarshal(deleteRespBodyTombstoneFNum, buf, r.tombstone)
+	if err != nil {
+		return nil, err
+	}
+
+	return buf, nil
 }
 
 func (r *DeleteResponseBody) StableSize() (size int) {
-	return 0
+	if r == nil {
+		return 0
+	}
+
+	size += proto.NestedStructureSize(deleteRespBodyTombstoneFNum, r.tombstone)
+
+	return size
 }
 
 func (r *HeadRequestBody) StableMarshal(buf []byte) ([]byte, error) {
diff --git a/v2/object/marshal_test.go b/v2/object/marshal_test.go
index cc702afc..cafe0990 100644
--- a/v2/object/marshal_test.go
+++ b/v2/object/marshal_test.go
@@ -207,7 +207,7 @@ func TestDeleteRequestBody_StableMarshal(t *testing.T) {
 }
 
 func TestDeleteResponseBody_StableMarshal(t *testing.T) {
-	from := generateDeleteResponseBody()
+	from := generateDeleteResponseBody("CID", "OID")
 	transport := new(grpc.DeleteResponse_Body)
 
 	t.Run("non empty", func(t *testing.T) {
@@ -613,8 +613,11 @@ func generateDeleteRequestBody(cid, oid string) *object.DeleteRequestBody {
 	return req
 }
 
-func generateDeleteResponseBody() *object.DeleteResponseBody {
-	return new(object.DeleteResponseBody)
+func generateDeleteResponseBody(cid, oid string) *object.DeleteResponseBody {
+	resp := new(object.DeleteResponseBody)
+	resp.SetTombstone(generateAddress(cid, oid))
+
+	return resp
 }
 
 func generateHeadRequestBody(cid, oid string) *object.HeadRequestBody {
diff --git a/v2/object/types.go b/v2/object/types.go
index 2ab3ff5f..34419582 100644
--- a/v2/object/types.go
+++ b/v2/object/types.go
@@ -139,7 +139,9 @@ type DeleteRequestBody struct {
 	addr *refs.Address
 }
 
-type DeleteResponseBody struct{}
+type DeleteResponseBody struct {
+	tombstone *refs.Address
+}
 
 type HeadRequestBody struct {
 	addr *refs.Address
@@ -1124,6 +1126,22 @@ func (r *DeleteRequest) SetVerificationHeader(v *session.RequestVerificationHead
 	}
 }
 
+// GetTombstone returns tombstone address.
+func (r *DeleteResponseBody) GetTombstone() *refs.Address {
+	if r != nil {
+		return r.tombstone
+	}
+
+	return nil
+}
+
+// SetTombstone sets tombstone address.
+func (r *DeleteResponseBody) SetTombstone(v *refs.Address) {
+	if r != nil {
+		r.tombstone = v
+	}
+}
+
 func (r *DeleteResponse) GetBody() *DeleteResponseBody {
 	if r != nil {
 		return r.body