public async Task <Object.Object> GetObject(GetRequest request, DateTime?deadline = null, CancellationToken context = default)
        {
            using var call = ObjectClient.Get(request, deadline: deadline, cancellationToken: context);
            var obj     = new Object.Object();
            var payload = Array.Empty <byte>();
            int offset  = 0;

            while (await call.ResponseStream.MoveNext())
            {
                var resp = call.ResponseStream.Current;
                if (!resp.Verify())
                {
                    throw new InvalidOperationException("invalid object get response");
                }
                CheckStatus(resp);
                switch (resp.Body.ObjectPartCase)
                {
                case GetResponse.Types.Body.ObjectPartOneofCase.Init:
                {
                    obj.ObjectId  = resp.Body.Init.ObjectId;
                    obj.Signature = resp.Body.Init.Signature;
                    obj.Header    = resp.Body.Init.Header;
                    payload       = new byte[obj.PayloadSize];
                    break;
                }

                case GetResponse.Types.Body.ObjectPartOneofCase.Chunk:
                {
                    if (payload.Length == 0)
                    {
                        throw new InvalidOperationException("missing init");
                    }
                    var chunk = resp.Body.Chunk;
                    if (obj.PayloadSize < (ulong)(offset + chunk.Length))
                    {
                        throw new InvalidOperationException("data exceeds PayloadSize");
                    }
                    resp.Body.Chunk.CopyTo(payload, offset);
                    offset += chunk.Length;
                    break;
                }

                case GetResponse.Types.Body.ObjectPartOneofCase.SplitInfo:
                {
                    throw new SplitInfoException(resp.Body.SplitInfo);
                }

                default:
                    throw new FormatException("malformed object get reponse");
                }
            }
            if ((ulong)offset < obj.PayloadSize)
            {
                throw new InvalidOperationException("data is less than PayloadSize");
            }
            obj.Payload = ByteString.CopyFrom(payload);
            return(obj);
        }
        public async Task <Object.Object> GetObject(Address address, Stream writer, bool raw = false, CallOptions options = null, CancellationToken context = default)
        {
            if (address is null)
            {
                throw new ArgumentNullException(nameof(address));
            }
            var opts = DefaultCallOptions.ApplyCustomOptions(options);

            CheckOptions(opts);
            var req = new GetRequest
            {
                Body = new GetRequest.Types.Body
                {
                    Raw     = raw,
                    Address = address,
                }
            };
            var meta = opts.GetRequestMetaHeader();

            AttachObjectSessionToken(opts, meta, address, ObjectSessionContext.Types.Verb.Get);
            req.MetaHeader = meta;
            opts.Key.Sign(req);
            using var call = ObjectClient.Get(req, cancellationToken: context);
            var obj    = new Object.Object();
            int offset = 0;

            while (await call.ResponseStream.MoveNext())
            {
                var resp = call.ResponseStream.Current;
                if (!resp.Verify())
                {
                    throw new InvalidOperationException("invalid object get response");
                }
                CheckStatus(resp);
                switch (resp.Body.ObjectPartCase)
                {
                case GetResponse.Types.Body.ObjectPartOneofCase.Init:
                {
                    obj.ObjectId  = resp.Body.Init.ObjectId;
                    obj.Signature = resp.Body.Init.Signature;
                    obj.Header    = resp.Body.Init.Header;
                    break;
                }

                case GetResponse.Types.Body.ObjectPartOneofCase.Chunk:
                {
                    if (obj.Header is null)
                    {
                        throw new InvalidOperationException("missing init");
                    }
                    var chunk = resp.Body.Chunk.ToByteArray();
                    if (obj.PayloadSize < (ulong)(offset + chunk.Length))
                    {
                        throw new InvalidOperationException("data exceeds PayloadSize");
                    }
                    writer.Write(chunk, 0, chunk.Length);
                    offset += chunk.Length;
                    break;
                }

                case GetResponse.Types.Body.ObjectPartOneofCase.SplitInfo:
                {
                    throw new SplitInfoException(resp.Body.SplitInfo);
                }

                default:
                    throw new FormatException("malformed object get reponse");
                }
            }
            if ((ulong)offset < obj.PayloadSize)
            {
                throw new InvalidOperationException("data is less than PayloadSize");
            }
            return(obj);
        }