Internal change

PiperOrigin-RevId: 486547910
This commit is contained in:
MediaPipe Team 2022-11-06 19:32:48 -08:00 committed by Copybara-Service
parent 9504c5e6a1
commit 4b0423e3a2
3 changed files with 175 additions and 90 deletions

View File

@ -14,45 +14,43 @@
#include "mediapipe/framework/deps/status_builder.h"
#include <memory>
#include <sstream>
#include "absl/memory/memory.h"
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
namespace mediapipe {
StatusBuilder::StatusBuilder(const StatusBuilder& sb) {
status_ = sb.status_;
file_ = sb.file_;
line_ = sb.line_;
no_logging_ = sb.no_logging_;
stream_ = sb.stream_
? absl::make_unique<std::ostringstream>(sb.stream_->str())
: nullptr;
join_style_ = sb.join_style_;
}
StatusBuilder::StatusBuilder(const StatusBuilder& sb)
: impl_(sb.impl_ ? std::make_unique<Impl>(*sb.impl_) : nullptr) {}
StatusBuilder& StatusBuilder::operator=(const StatusBuilder& sb) {
status_ = sb.status_;
file_ = sb.file_;
line_ = sb.line_;
no_logging_ = sb.no_logging_;
stream_ = sb.stream_
? absl::make_unique<std::ostringstream>(sb.stream_->str())
: nullptr;
join_style_ = sb.join_style_;
if (!sb.impl_) {
impl_ = nullptr;
return *this;
}
if (impl_) {
*impl_ = *sb.impl_;
return *this;
}
impl_ = std::make_unique<Impl>(*sb.impl_);
return *this;
}
StatusBuilder& StatusBuilder::SetAppend() & {
if (status_.ok()) return *this;
join_style_ = MessageJoinStyle::kAppend;
if (!impl_) return *this;
impl_->join_style = Impl::MessageJoinStyle::kAppend;
return *this;
}
StatusBuilder&& StatusBuilder::SetAppend() && { return std::move(SetAppend()); }
StatusBuilder& StatusBuilder::SetPrepend() & {
if (status_.ok()) return *this;
join_style_ = MessageJoinStyle::kPrepend;
if (!impl_) return *this;
impl_->join_style = Impl::MessageJoinStyle::kPrepend;
return *this;
}
@ -61,7 +59,8 @@ StatusBuilder&& StatusBuilder::SetPrepend() && {
}
StatusBuilder& StatusBuilder::SetNoLogging() & {
no_logging_ = true;
if (!impl_) return *this;
impl_->no_logging = true;
return *this;
}
@ -70,34 +69,72 @@ StatusBuilder&& StatusBuilder::SetNoLogging() && {
}
StatusBuilder::operator Status() const& {
if (!stream_ || stream_->str().empty() || no_logging_) {
return status_;
}
return StatusBuilder(*this).JoinMessageToStatus();
}
StatusBuilder::operator Status() && {
if (!stream_ || stream_->str().empty() || no_logging_) {
return status_;
}
return JoinMessageToStatus();
}
StatusBuilder::operator Status() && { return JoinMessageToStatus(); }
absl::Status StatusBuilder::JoinMessageToStatus() {
if (!stream_) {
if (!impl_) {
return absl::OkStatus();
}
std::string message;
if (join_style_ == MessageJoinStyle::kAnnotate) {
if (!status_.ok()) {
message = absl::StrCat(status_.message(), "; ", stream_->str());
}
} else {
message = join_style_ == MessageJoinStyle::kPrepend
? absl::StrCat(stream_->str(), status_.message())
: absl::StrCat(status_.message(), stream_->str());
return impl_->JoinMessageToStatus();
}
absl::Status StatusBuilder::Impl::JoinMessageToStatus() {
if (stream.str().empty() || no_logging) {
return status;
}
return Status(status_.code(), message);
return absl::Status(status.code(), [this]() {
switch (join_style) {
case MessageJoinStyle::kAnnotate:
return absl::StrCat(status.message(), "; ", stream.str());
case MessageJoinStyle::kAppend:
return absl::StrCat(status.message(), stream.str());
case MessageJoinStyle::kPrepend:
return absl::StrCat(stream.str(), status.message());
}
}());
}
StatusBuilder::Impl::Impl(const absl::Status& status, const char* file,
int line)
: status(status), line(line), file(file), stream() {}
StatusBuilder::Impl::Impl(absl::Status&& status, const char* file, int line)
: status(std::move(status)), line(line), file(file), stream() {}
StatusBuilder::Impl::Impl(const absl::Status& status,
mediapipe::source_location location)
: status(status),
line(location.line()),
file(location.file_name()),
stream() {}
StatusBuilder::Impl::Impl(absl::Status&& status,
mediapipe::source_location location)
: status(std::move(status)),
line(location.line()),
file(location.file_name()),
stream() {}
StatusBuilder::Impl::Impl(const Impl& other)
: status(other.status),
line(other.line),
file(other.file),
no_logging(other.no_logging),
stream(other.stream.str()),
join_style(other.join_style) {}
StatusBuilder::Impl& StatusBuilder::Impl::operator=(const Impl& other) {
status = other.status;
line = other.line;
file = other.file;
no_logging = other.no_logging;
stream = std::ostringstream(other.stream.str());
join_style = other.join_style;
return *this;
}
} // namespace mediapipe

View File

@ -22,7 +22,6 @@
#include "absl/base/attributes.h"
#include "absl/memory/memory.h"
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "mediapipe/framework/deps/source_location.h"
#include "mediapipe/framework/deps/status.h"
@ -42,34 +41,37 @@ class ABSL_MUST_USE_RESULT StatusBuilder {
// occurs. A typical user will call this with `MEDIAPIPE_LOC`.
StatusBuilder(const absl::Status& original_status,
mediapipe::source_location location)
: status_(original_status),
line_(location.line()),
file_(location.file_name()),
stream_(InitStream(status_)) {}
: impl_(original_status.ok()
? nullptr
: std::make_unique<Impl>(original_status, location)) {}
StatusBuilder(absl::Status&& original_status,
mediapipe::source_location location)
: status_(std::move(original_status)),
line_(location.line()),
file_(location.file_name()),
stream_(InitStream(status_)) {}
: impl_(original_status.ok()
? nullptr
: std::make_unique<Impl>(std::move(original_status),
location)) {}
// Creates a `StatusBuilder` from a mediapipe status code. If logging is
// enabled, it will use `location` as the location from which the log message
// occurs. A typical user will call this with `MEDIAPIPE_LOC`.
StatusBuilder(absl::StatusCode code, mediapipe::source_location location)
: status_(code, ""),
line_(location.line()),
file_(location.file_name()),
stream_(InitStream(status_)) {}
: impl_(code == absl::StatusCode::kOk
? nullptr
: std::make_unique<Impl>(absl::Status(code, ""), location)) {}
StatusBuilder(const absl::Status& original_status, const char* file, int line)
: status_(original_status),
line_(line),
file_(file),
stream_(InitStream(status_)) {}
: impl_(original_status.ok()
? nullptr
: std::make_unique<Impl>(original_status, file, line)) {}
bool ok() const { return status_.ok(); }
StatusBuilder(absl::Status&& original_status, const char* file, int line)
: impl_(original_status.ok()
? nullptr
: std::make_unique<Impl>(std::move(original_status), file,
line)) {}
bool ok() const { return !impl_; }
StatusBuilder& SetAppend() &;
StatusBuilder&& SetAppend() &&;
@ -82,8 +84,8 @@ class ABSL_MUST_USE_RESULT StatusBuilder {
template <typename T>
StatusBuilder& operator<<(const T& msg) & {
if (!stream_) return *this;
*stream_ << msg;
if (!impl_) return *this;
impl_->stream << msg;
return *this;
}
@ -98,35 +100,42 @@ class ABSL_MUST_USE_RESULT StatusBuilder {
absl::Status JoinMessageToStatus();
private:
// Specifies how to join the error message in the original status and any
// additional message that has been streamed into the builder.
enum class MessageJoinStyle {
kAnnotate,
kAppend,
kPrepend,
struct Impl {
// Specifies how to join the error message in the original status and any
// additional message that has been streamed into the builder.
enum class MessageJoinStyle {
kAnnotate,
kAppend,
kPrepend,
};
Impl(const absl::Status& status, const char* file, int line);
Impl(absl::Status&& status, const char* file, int line);
Impl(const absl::Status& status, mediapipe::source_location location);
Impl(absl::Status&& status, mediapipe::source_location location);
Impl(const Impl&);
Impl& operator=(const Impl&);
absl::Status JoinMessageToStatus();
// The status that the result will be based on.
absl::Status status;
// The line to record if this file is logged.
int line;
// Not-owned: The file to record if this status is logged.
const char* file;
// Logging disabled if true.
bool no_logging = false;
// The additional messages added with `<<`. This is nullptr when status_ is
// ok.
std::ostringstream stream;
// Specifies how to join the message in `status_` and `stream_`.
MessageJoinStyle join_style = MessageJoinStyle::kAnnotate;
};
// Conditionally creates an ostringstream if the status is not ok.
static std::unique_ptr<std::ostringstream> InitStream(
const absl::Status status) {
if (status.ok()) {
return nullptr;
}
return absl::make_unique<std::ostringstream>();
}
// The status that the result will be based on.
absl::Status status_;
// The line to record if this file is logged.
int line_;
// Not-owned: The file to record if this status is logged.
const char* file_;
bool no_logging_ = false;
// The additional messages added with `<<`. This is nullptr when status_ is
// ok.
std::unique_ptr<std::ostringstream> stream_;
// Specifies how to join the message in `status_` and `stream_`.
MessageJoinStyle join_style_ = MessageJoinStyle::kAnnotate;
// Internal store of data for the class. An invariant of the class is that
// this is null when the original status is okay, and not-null otherwise.
std::unique_ptr<Impl> impl_;
};
inline StatusBuilder AlreadyExistsErrorBuilder(

View File

@ -33,6 +33,21 @@ TEST(StatusBuilder, OkStatusRvalue) {
ASSERT_EQ(status, absl::OkStatus());
}
TEST(StatusBuilder, OkStatusFileAndLineRvalueStatus) {
absl::Status status = StatusBuilder(absl::OkStatus(), "hello.cc", 1234)
<< "annotated message1 "
<< "annotated message2";
ASSERT_EQ(status, absl::OkStatus());
}
TEST(StatusBuilder, OkStatusFileAndLineLvalueStatus) {
const auto original_status = absl::OkStatus();
absl::Status status = StatusBuilder(original_status, "hello.cc", 1234)
<< "annotated message1 "
<< "annotated message2";
ASSERT_EQ(status, absl::OkStatus());
}
TEST(StatusBuilder, AnnotateMode) {
absl::Status status = StatusBuilder(absl::Status(absl::StatusCode::kNotFound,
"original message"),
@ -45,6 +60,30 @@ TEST(StatusBuilder, AnnotateMode) {
"original message; annotated message1 annotated message2");
}
TEST(StatusBuilder, AnnotateModeFileAndLineRvalueStatus) {
absl::Status status = StatusBuilder(absl::Status(absl::StatusCode::kNotFound,
"original message"),
"hello.cc", 1234)
<< "annotated message1 "
<< "annotated message2";
ASSERT_FALSE(status.ok());
EXPECT_EQ(status.code(), absl::StatusCode::kNotFound);
EXPECT_EQ(status.message(),
"original message; annotated message1 annotated message2");
}
TEST(StatusBuilder, AnnotateModeFileAndLineLvalueStatus) {
const auto original_status =
absl::Status(absl::StatusCode::kNotFound, "original message");
absl::Status status = StatusBuilder(original_status, "hello.cc", 1234)
<< "annotated message1 "
<< "annotated message2";
ASSERT_FALSE(status.ok());
EXPECT_EQ(status.code(), absl::StatusCode::kNotFound);
EXPECT_EQ(status.message(),
"original message; annotated message1 annotated message2");
}
TEST(StatusBuilder, PrependModeLvalue) {
StatusBuilder builder(
absl::Status(absl::StatusCode::kInvalidArgument, "original message"),