Skip to content

Commit 94c903b

Browse files
committed
feat(storage): Add ReadFromOffset and ReadLast convenience to object_… (#82)
feat(storage): Add ReadFromOffset and ReadLast convenience to object_descriptor
1 parent 36f5b29 commit 94c903b

File tree

3 files changed

+102
-0
lines changed

3 files changed

+102
-0
lines changed

google/cloud/storage/async/object_descriptor.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,20 @@ std::pair<AsyncReader, AsyncToken> ObjectDescriptor::Read(std::int64_t offset,
3131
return {AsyncReader(std::move(reader)), std::move(token)};
3232
}
3333

34+
std::pair<AsyncReader, AsyncToken> ObjectDescriptor::ReadFromOffset(
35+
std::int64_t offset) {
36+
auto reader = impl_->Read({offset, 0});
37+
auto token = storage_internal::MakeAsyncToken(reader.get());
38+
return {AsyncReader(std::move(reader)), std::move(token)};
39+
}
40+
41+
std::pair<AsyncReader, AsyncToken> ObjectDescriptor::ReadLast(
42+
std::int64_t limit) {
43+
auto reader = impl_->Read({-limit, 0});
44+
auto token = storage_internal::MakeAsyncToken(reader.get());
45+
return {AsyncReader(std::move(reader)), std::move(token)};
46+
}
47+
3448
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
3549
} // namespace storage_experimental
3650
} // namespace cloud

google/cloud/storage/async/object_descriptor.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,17 @@ class ObjectDescriptor {
6363
std::pair<AsyncReader, AsyncToken> Read(std::int64_t offset,
6464
std::int64_t limit);
6565

66+
/**
67+
* Starts a new read beginning at the supplied offset and continuing
68+
* until the end.
69+
*/
70+
std::pair<AsyncReader, AsyncToken> ReadFromOffset(std::int64_t offset);
71+
72+
/**
73+
* Reads the last number of bytes from the end.
74+
*/
75+
std::pair<AsyncReader, AsyncToken> ReadLast(std::int64_t limit);
76+
6677
private:
6778
std::shared_ptr<ObjectDescriptorConnection> impl_;
6879
};

google/cloud/storage/async/object_descriptor_test.cc

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,83 @@ TEST(ObjectDescriptor, Basic) {
6969
EXPECT_FALSE(token.valid());
7070
}
7171

72+
TEST(ObjectDescriptor, ReadFromOffset) {
73+
auto mock = std::make_shared<MockAsyncObjectDescriptorConnection>();
74+
EXPECT_CALL(*mock, metadata).WillOnce(Return(absl::nullopt));
75+
EXPECT_CALL(*mock, Read)
76+
.WillOnce([](ReadParams p) -> std::unique_ptr<AsyncReaderConnection> {
77+
EXPECT_EQ(p.start, 10);
78+
EXPECT_EQ(p.limit, 0);
79+
auto reader = std::make_unique<MockAsyncReaderConnection>();
80+
EXPECT_CALL(*reader, Read)
81+
.WillOnce([] {
82+
auto response =
83+
std::string("The quick brown fox jumps over the lazy dog")
84+
.substr(10);
85+
return make_ready_future(ReadResponse(ReadPayload(response)));
86+
})
87+
.WillOnce([] { return make_ready_future(ReadResponse(Status{})); });
88+
return reader;
89+
});
90+
91+
auto tested = ObjectDescriptor(mock);
92+
EXPECT_FALSE(tested.metadata().has_value());
93+
AsyncReader reader;
94+
AsyncToken token;
95+
std::tie(reader, token) = tested.ReadFromOffset(10);
96+
ASSERT_TRUE(token.valid());
97+
98+
auto r1 = reader.Read(std::move(token)).get();
99+
ASSERT_STATUS_OK(r1);
100+
ReadPayload payload;
101+
std::tie(payload, token) = *std::move(r1);
102+
EXPECT_THAT(payload.contents(),
103+
ElementsAre("brown fox jumps over the lazy dog"));
104+
105+
auto r2 = reader.Read(std::move(token)).get();
106+
ASSERT_STATUS_OK(r2);
107+
std::tie(payload, token) = *std::move(r2);
108+
EXPECT_FALSE(token.valid());
109+
}
110+
111+
TEST(ObjectDescriptor, ReadLast) {
112+
auto mock = std::make_shared<MockAsyncObjectDescriptorConnection>();
113+
EXPECT_CALL(*mock, metadata).WillOnce(Return(absl::nullopt));
114+
EXPECT_CALL(*mock, Read)
115+
.WillOnce([](ReadParams p) -> std::unique_ptr<AsyncReaderConnection> {
116+
EXPECT_EQ(p.start, -15);
117+
EXPECT_EQ(p.limit, 0);
118+
auto reader = std::make_unique<MockAsyncReaderConnection>();
119+
EXPECT_CALL(*reader, Read)
120+
.WillOnce([] {
121+
std::string full_response(
122+
"The quick brown fox jumps over the lazy dog");
123+
auto response = full_response.substr(full_response.size() - 15);
124+
return make_ready_future(ReadResponse(ReadPayload(response)));
125+
})
126+
.WillOnce([] { return make_ready_future(ReadResponse(Status{})); });
127+
return reader;
128+
});
129+
130+
auto tested = ObjectDescriptor(mock);
131+
EXPECT_FALSE(tested.metadata().has_value());
132+
AsyncReader reader;
133+
AsyncToken token;
134+
std::tie(reader, token) = tested.ReadLast(15);
135+
ASSERT_TRUE(token.valid());
136+
137+
auto r1 = reader.Read(std::move(token)).get();
138+
ASSERT_STATUS_OK(r1);
139+
ReadPayload payload;
140+
std::tie(payload, token) = *std::move(r1);
141+
EXPECT_THAT(payload.contents(), ElementsAre("er the lazy dog"));
142+
143+
auto r2 = reader.Read(std::move(token)).get();
144+
ASSERT_STATUS_OK(r2);
145+
std::tie(payload, token) = *std::move(r2);
146+
EXPECT_FALSE(token.valid());
147+
}
148+
72149
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
73150
} // namespace storage_experimental
74151
} // namespace cloud

0 commit comments

Comments
 (0)