Skip to content

Commit

Permalink
[C++] Refactor util::Status
Browse files Browse the repository at this point in the history
This change refactors util::Status to have a similar shape as the
recently open-sourced absl::Status. This will allow Protobuf to
eventually use absl::Status and reduce the codesize.

Note that there is more work required before absl::Status can be used.
  • Loading branch information
Yannic committed Feb 28, 2021
1 parent 8080beb commit a5cc5b7
Show file tree
Hide file tree
Showing 12 changed files with 180 additions and 133 deletions.
2 changes: 1 addition & 1 deletion BUILD
Expand Up @@ -183,7 +183,7 @@ cc_library(
"src/google/protobuf/stubs/bytestream.cc",
"src/google/protobuf/stubs/common.cc",
"src/google/protobuf/stubs/int128.cc",
"src/google/protobuf/stubs/status.cc",
"src/google/protobuf/stubs/internal/status.cc",
"src/google/protobuf/stubs/statusor.cc",
"src/google/protobuf/stubs/stringpiece.cc",
"src/google/protobuf/stubs/stringprintf.cc",
Expand Down
2 changes: 1 addition & 1 deletion cmake/libprotobuf-lite.cmake
Expand Up @@ -20,7 +20,7 @@ set(libprotobuf_lite_files
${protobuf_source_dir}/src/google/protobuf/stubs/bytestream.cc
${protobuf_source_dir}/src/google/protobuf/stubs/common.cc
${protobuf_source_dir}/src/google/protobuf/stubs/int128.cc
${protobuf_source_dir}/src/google/protobuf/stubs/status.cc
${protobuf_source_dir}/src/google/protobuf/stubs/internal/status.cc
${protobuf_source_dir}/src/google/protobuf/stubs/statusor.cc
${protobuf_source_dir}/src/google/protobuf/stubs/stringpiece.cc
${protobuf_source_dir}/src/google/protobuf/stubs/stringprintf.cc
Expand Down
2 changes: 1 addition & 1 deletion src/Makefile.am
Expand Up @@ -185,7 +185,7 @@ libprotobuf_lite_la_SOURCES = \
google/protobuf/io/io_win32.cc \
google/protobuf/stubs/map_util.h \
google/protobuf/stubs/mathutil.h \
google/protobuf/stubs/status.cc \
google/protobuf/stubs/internal/status.cc \
google/protobuf/stubs/status.h \
google/protobuf/stubs/status_macros.h \
google/protobuf/stubs/statusor.cc \
Expand Down
Expand Up @@ -37,61 +37,64 @@
namespace google {
namespace protobuf {
namespace util {
namespace error {
inline std::string CodeEnumToString(error::Code code) {
namespace status_internal {
namespace {

inline std::string StatusCodeToString(StatusCode code) {
switch (code) {
case OK:
case StatusCode::kOk:
return "OK";
case CANCELLED:
case StatusCode::kCancelled:
return "CANCELLED";
case UNKNOWN:
case StatusCode::kUnknown:
return "UNKNOWN";
case INVALID_ARGUMENT:
case StatusCode::kInvalidArgument:
return "INVALID_ARGUMENT";
case DEADLINE_EXCEEDED:
case StatusCode::kDeadlineExceeded:
return "DEADLINE_EXCEEDED";
case NOT_FOUND:
case StatusCode::kNotFound:
return "NOT_FOUND";
case ALREADY_EXISTS:
case StatusCode::kAlreadyExists:
return "ALREADY_EXISTS";
case PERMISSION_DENIED:
case StatusCode::kPermissionDenied:
return "PERMISSION_DENIED";
case UNAUTHENTICATED:
case StatusCode::kUnauthenticated:
return "UNAUTHENTICATED";
case RESOURCE_EXHAUSTED:
case StatusCode::kResourceExhausted:
return "RESOURCE_EXHAUSTED";
case FAILED_PRECONDITION:
case StatusCode::kFailedPrecondition:
return "FAILED_PRECONDITION";
case ABORTED:
case StatusCode::kAborted:
return "ABORTED";
case OUT_OF_RANGE:
case StatusCode::kOutOfRange:
return "OUT_OF_RANGE";
case UNIMPLEMENTED:
case StatusCode::kUnimplemented:
return "UNIMPLEMENTED";
case INTERNAL:
case StatusCode::kInternal:
return "INTERNAL";
case UNAVAILABLE:
case StatusCode::kUnavailable:
return "UNAVAILABLE";
case DATA_LOSS:
case StatusCode::kDataLoss:
return "DATA_LOSS";
}

// No default clause, clang will abort if a code is missing from
// above switch.
return "UNKNOWN";
}
} // namespace error.

} // namespace

const Status Status::OK = Status();
const Status Status::CANCELLED = Status(error::CANCELLED, "");
const Status Status::UNKNOWN = Status(error::UNKNOWN, "");
const Status Status::CANCELLED = Status(StatusCode::kCancelled, "");
const Status Status::UNKNOWN = Status(StatusCode::kUnknown, "");

Status::Status() : error_code_(error::OK) {
Status::Status() : error_code_(StatusCode::kOk) {
}

Status::Status(error::Code error_code, StringPiece error_message)
Status::Status(StatusCode error_code, StringPiece error_message)
: error_code_(error_code) {
if (error_code != error::OK) {
if (error_code != StatusCode::kOk) {
error_message_ = error_message.ToString();
}
}
Expand All @@ -112,13 +115,13 @@ bool Status::operator==(const Status& x) const {
}

std::string Status::ToString() const {
if (error_code_ == error::OK) {
if (error_code_ == StatusCode::kOk) {
return "OK";
} else {
if (error_message_.empty()) {
return error::CodeEnumToString(error_code_);
return StatusCodeToString(error_code_);
} else {
return error::CodeEnumToString(error_code_) + ":" +
return StatusCodeToString(error_code_) + ":" +
error_message_;
}
}
Expand All @@ -129,6 +132,7 @@ std::ostream& operator<<(std::ostream& os, const Status& x) {
return os;
}

} // namespace status_internal
} // namespace util
} // namespace protobuf
} // namespace google
119 changes: 119 additions & 0 deletions src/google/protobuf/stubs/internal/status.h
@@ -0,0 +1,119 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef GOOGLE_PROTOBUF_STUBS_INTERNAL_STATUS_H_
#define GOOGLE_PROTOBUF_STUBS_INTERNAL_STATUS_H_

#include <string>

#include <google/protobuf/stubs/stringpiece.h>

#include <google/protobuf/port_def.inc>

namespace google {
namespace protobuf {
namespace util {
namespace status_internal {

// These values must match error codes defined in google/rpc/code.proto.
enum class StatusCode : int {
kOk = 0,
kCancelled = 1,
kUnknown = 2,
kInvalidArgument = 3,
kDeadlineExceeded = 4,
kNotFound = 5,
kAlreadyExists = 6,
kPermissionDenied = 7,
kUnauthenticated = 16,
kResourceExhausted = 8,
kFailedPrecondition = 9,
kAborted = 10,
kOutOfRange = 11,
kUnimplemented = 12,
kInternal = 13,
kUnavailable = 14,
kDataLoss = 15,
};

class PROTOBUF_EXPORT Status {
public:
// Creates a "successful" status.
Status();

// Create a status in the canonical error space with the specified
// code, and error message. If "code == 0", error_message is
// ignored and a Status object identical to Status::kOk is
// constructed.
Status(StatusCode error_code, StringPiece error_message);
Status(const Status&);
Status& operator=(const Status& x);
~Status() {}

// Some pre-defined Status objects
static const Status OK; // Identical to 0-arg constructor
static const Status CANCELLED;
static const Status UNKNOWN;

// Accessor
bool ok() const {
return error_code_ == StatusCode::kOk;
}
StatusCode code() const {
return error_code_;
}
StringPiece message() const {
return error_message_;
}

bool operator==(const Status& x) const;
bool operator!=(const Status& x) const {
return !operator==(x);
}

// Return a combination of the error code name and message.
std::string ToString() const;

private:
StatusCode error_code_;
std::string error_message_;
};

// Prints a human-readable representation of 'x' to 'os'.
PROTOBUF_EXPORT std::ostream& operator<<(std::ostream& os, const Status& x);

} // namespace status_internal
} // namespace util
} // namespace protobuf
} // namespace google

#include <google/protobuf/port_undef.inc>

#endif // GOOGLE_PROTOBUF_STUBS_INTERNAL_STATUS_H_
4 changes: 1 addition & 3 deletions src/google/protobuf/stubs/logging.h
Expand Up @@ -33,6 +33,7 @@

#include <google/protobuf/stubs/macros.h>
#include <google/protobuf/stubs/port.h>
#include <google/protobuf/stubs/status.h>

#include <google/protobuf/port_def.inc>

Expand Down Expand Up @@ -64,9 +65,6 @@ enum LogLevel {
};

class StringPiece;
namespace util {
class Status;
}
class uint128;
namespace internal {

Expand Down
93 changes: 13 additions & 80 deletions src/google/protobuf/stubs/status.h
Expand Up @@ -27,99 +27,32 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef GOOGLE_PROTOBUF_STUBS_STATUS_H_
#define GOOGLE_PROTOBUF_STUBS_STATUS_H_

#include <iosfwd>
#include <string>

#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/stringpiece.h>

#include <google/protobuf/port_def.inc>
#include <google/protobuf/stubs/internal/status.h>

namespace google {
namespace protobuf {
namespace util {
namespace error {
// These values must match error codes defined in google/rpc/code.proto.
enum Code {
OK = 0,
CANCELLED = 1,
UNKNOWN = 2,
INVALID_ARGUMENT = 3,
DEADLINE_EXCEEDED = 4,
NOT_FOUND = 5,
ALREADY_EXISTS = 6,
PERMISSION_DENIED = 7,
UNAUTHENTICATED = 16,
RESOURCE_EXHAUSTED = 8,
FAILED_PRECONDITION = 9,
ABORTED = 10,
OUT_OF_RANGE = 11,
UNIMPLEMENTED = 12,
INTERNAL = 13,
UNAVAILABLE = 14,
DATA_LOSS = 15,
};
} // namespace error

class PROTOBUF_EXPORT Status {
public:
// Creates a "successful" status.
Status();

// Create a status in the canonical error space with the specified
// code, and error message. If "code == 0", error_message is
// ignored and a Status object identical to Status::OK is
// constructed.
Status(error::Code error_code, StringPiece error_message);
Status(const Status&);
Status& operator=(const Status& x);
~Status() {}

// Some pre-defined Status objects
static const Status OK; // Identical to 0-arg constructor
static const Status CANCELLED;
static const Status UNKNOWN;
using ::google::protobuf::util::status_internal::Status;
using ::google::protobuf::util::status_internal::StatusCode;

// Accessor
bool ok() const {
return error_code_ == error::OK;
}
int error_code() const {
return error_code_;
}
error::Code code() const {
return error_code_;
}
StringPiece error_message() const {
return error_message_;
}
StringPiece message() const {
return error_message_;
}

bool operator==(const Status& x) const;
bool operator!=(const Status& x) const {
return !operator==(x);
}

// Return a combination of the error code name and message.
std::string ToString() const;

private:
error::Code error_code_;
std::string error_message_;
};
namespace error {

// Prints a human-readable representation of 'x' to 'os'.
PROTOBUF_EXPORT std::ostream& operator<<(std::ostream& os, const Status& x);
// TODO(yannic): Remove these.
constexpr StatusCode OK = StatusCode::kOk;
constexpr StatusCode CANCELLED = StatusCode::kCancelled;
constexpr StatusCode UNKNOWN = StatusCode::kUnknown;
constexpr StatusCode INVALID_ARGUMENT = StatusCode::kInvalidArgument;
constexpr StatusCode NOT_FOUND = StatusCode::kNotFound;
constexpr StatusCode INTERNAL = StatusCode::kInternal;

} // namespace error
} // namespace util
} // namespace protobuf
} // namespace google

#include <google/protobuf/port_undef.inc>

#endif // GOOGLE_PROTOBUF_STUBS_STATUS_H_

0 comments on commit a5cc5b7

Please sign in to comment.