Export of internal Abseil changes
-- bffb14058bb46137d42c7a113a36b6b582997cda by Xiaoyi Zhang <zhangxy@google.com>: Add ABSL_MUST_USE_RESULT to Status. PiperOrigin-RevId: 296272498 -- b426fdd3b3f687d7a8aeb644925923bbab503778 by CJ Johnson <johnsoncj@google.com>: Optimizes absl::InlinedVector::clear() by not deallocating the data, if allocated. This allows allocations to be reused. This matches the behavior of std::vector::clear() PiperOrigin-RevId: 296197235 -- 8cb9fbfe20e749816065c1a042e84f72dac9bfc0 by CJ Johnson <johnsoncj@google.com>: Optimizes absl::InlinedVector::clear() by not deallocating the data, if allocated. This allows allocations to be reused. This matches the behavior of std::vector::clear() PiperOrigin-RevId: 296058092 -- 2558d3369a482879919155b6f46317ccafe0ca13 by Matthew Brown <matthewbr@google.com>: Internal cleanup PiperOrigin-RevId: 296025806 -- cf7ee57228534021c15ed7421df92acf6c27c9c7 by Gennadiy Rozental <rogeeff@google.com>: Make FlagOps enum class. We also add comments to all the functions used to invoke flag ops. PiperOrigin-RevId: 295975809 -- 74bbdbd12fbc54e9c4ebcb3005e727becf0e509d by Xiaoyi Zhang <zhangxy@google.com>: Release `absl::Status`. PiperOrigin-RevId: 295777662 -- 3dbc622b4e2227863525da2f7de7ecbeb3ede21f by Xiaoyi Zhang <zhangxy@google.com>: Internal change. PiperOrigin-RevId: 295733658 -- 48d74aa0ab01d611da6012b377f038d8b26c712e by Abseil Team <absl-team@google.com>: Fix typo in container/CMakeLists.txt for container_common PiperOrigin-RevId: 295491438 GitOrigin-RevId: bffb14058bb46137d42c7a113a36b6b582997cda Change-Id: Ia966857b07fa7412cd6489ac37b5fa26640e4141
This commit is contained in:
		
							parent
							
								
									3c81410510
								
							
						
					
					
						commit
						914ff44510
					
				
					 13 changed files with 1557 additions and 44 deletions
				
			
		| 
						 | 
					@ -633,7 +633,7 @@ absl_cc_library(
 | 
				
			||||||
  NAME
 | 
					  NAME
 | 
				
			||||||
    container_common
 | 
					    container_common
 | 
				
			||||||
  HDRS
 | 
					  HDRS
 | 
				
			||||||
    "internal/commom.h"
 | 
					    "internal/common.h"
 | 
				
			||||||
  COPTS
 | 
					  COPTS
 | 
				
			||||||
    ${ABSL_DEFAULT_COPTS}
 | 
					    ${ABSL_DEFAULT_COPTS}
 | 
				
			||||||
  DEPS
 | 
					  DEPS
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,10 +43,10 @@ template <typename T>
 | 
				
			||||||
class Flag;
 | 
					class Flag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
///////////////////////////////////////////////////////////////////////////////
 | 
					///////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
// Type-specific operations, eg., parsing, copying, etc. are provided
 | 
					// Flag value type operations, eg., parsing, copying, etc. are provided
 | 
				
			||||||
// by function specific to that type with a signature matching FlagOpFn.
 | 
					// by function specific to that type with a signature matching FlagOpFn.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum FlagOp {
 | 
					enum class FlagOp {
 | 
				
			||||||
  kDelete,
 | 
					  kDelete,
 | 
				
			||||||
  kClone,
 | 
					  kClone,
 | 
				
			||||||
  kCopy,
 | 
					  kCopy,
 | 
				
			||||||
| 
						 | 
					@ -58,26 +58,26 @@ enum FlagOp {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
using FlagOpFn = void* (*)(FlagOp, const void*, void*, void*);
 | 
					using FlagOpFn = void* (*)(FlagOp, const void*, void*, void*);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// The per-type function
 | 
					// Flag value specific operations routine.
 | 
				
			||||||
template <typename T>
 | 
					template <typename T>
 | 
				
			||||||
void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3) {
 | 
					void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3) {
 | 
				
			||||||
  switch (op) {
 | 
					  switch (op) {
 | 
				
			||||||
    case flags_internal::kDelete:
 | 
					    case FlagOp::kDelete:
 | 
				
			||||||
      delete static_cast<const T*>(v1);
 | 
					      delete static_cast<const T*>(v1);
 | 
				
			||||||
      return nullptr;
 | 
					      return nullptr;
 | 
				
			||||||
    case flags_internal::kClone:
 | 
					    case FlagOp::kClone:
 | 
				
			||||||
      return new T(*static_cast<const T*>(v1));
 | 
					      return new T(*static_cast<const T*>(v1));
 | 
				
			||||||
    case flags_internal::kCopy:
 | 
					    case FlagOp::kCopy:
 | 
				
			||||||
      *static_cast<T*>(v2) = *static_cast<const T*>(v1);
 | 
					      *static_cast<T*>(v2) = *static_cast<const T*>(v1);
 | 
				
			||||||
      return nullptr;
 | 
					      return nullptr;
 | 
				
			||||||
    case flags_internal::kCopyConstruct:
 | 
					    case FlagOp::kCopyConstruct:
 | 
				
			||||||
      new (v2) T(*static_cast<const T*>(v1));
 | 
					      new (v2) T(*static_cast<const T*>(v1));
 | 
				
			||||||
      return nullptr;
 | 
					      return nullptr;
 | 
				
			||||||
    case flags_internal::kSizeof:
 | 
					    case FlagOp::kSizeof:
 | 
				
			||||||
      return reinterpret_cast<void*>(sizeof(T));
 | 
					      return reinterpret_cast<void*>(sizeof(T));
 | 
				
			||||||
    case flags_internal::kStaticTypeId:
 | 
					    case FlagOp::kStaticTypeId:
 | 
				
			||||||
      return reinterpret_cast<void*>(&FlagStaticTypeIdGen<T>);
 | 
					      return reinterpret_cast<void*>(&FlagStaticTypeIdGen<T>);
 | 
				
			||||||
    case flags_internal::kParse: {
 | 
					    case FlagOp::kParse: {
 | 
				
			||||||
      // Initialize the temporary instance of type T based on current value in
 | 
					      // Initialize the temporary instance of type T based on current value in
 | 
				
			||||||
      // destination (which is going to be flag's default value).
 | 
					      // destination (which is going to be flag's default value).
 | 
				
			||||||
      T temp(*static_cast<T*>(v2));
 | 
					      T temp(*static_cast<T*>(v2));
 | 
				
			||||||
| 
						 | 
					@ -88,7 +88,7 @@ void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3) {
 | 
				
			||||||
      *static_cast<T*>(v2) = std::move(temp);
 | 
					      *static_cast<T*>(v2) = std::move(temp);
 | 
				
			||||||
      return v2;
 | 
					      return v2;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case flags_internal::kUnparse:
 | 
					    case FlagOp::kUnparse:
 | 
				
			||||||
      *static_cast<std::string*>(v2) =
 | 
					      *static_cast<std::string*>(v2) =
 | 
				
			||||||
          absl::UnparseFlag<T>(*static_cast<const T*>(v1));
 | 
					          absl::UnparseFlag<T>(*static_cast<const T*>(v1));
 | 
				
			||||||
      return nullptr;
 | 
					      return nullptr;
 | 
				
			||||||
| 
						 | 
					@ -97,37 +97,45 @@ void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3) {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Functions that invoke flag-type-specific operations.
 | 
					// Deletes memory interpreting obj as flag value type pointer.
 | 
				
			||||||
inline void Delete(FlagOpFn op, const void* obj) {
 | 
					inline void Delete(FlagOpFn op, const void* obj) {
 | 
				
			||||||
  op(flags_internal::kDelete, obj, nullptr, nullptr);
 | 
					  op(FlagOp::kDelete, obj, nullptr, nullptr);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					// Makes a copy of flag value pointed by obj.
 | 
				
			||||||
inline void* Clone(FlagOpFn op, const void* obj) {
 | 
					inline void* Clone(FlagOpFn op, const void* obj) {
 | 
				
			||||||
  return op(flags_internal::kClone, obj, nullptr, nullptr);
 | 
					  return op(FlagOp::kClone, obj, nullptr, nullptr);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					// Copies src to dst interpreting as flag value type pointers.
 | 
				
			||||||
inline void Copy(FlagOpFn op, const void* src, void* dst) {
 | 
					inline void Copy(FlagOpFn op, const void* src, void* dst) {
 | 
				
			||||||
  op(flags_internal::kCopy, src, dst, nullptr);
 | 
					  op(FlagOp::kCopy, src, dst, nullptr);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					// Construct a copy of flag value in a location pointed by dst
 | 
				
			||||||
 | 
					// based on src - pointer to the flag's value.
 | 
				
			||||||
inline void CopyConstruct(FlagOpFn op, const void* src, void* dst) {
 | 
					inline void CopyConstruct(FlagOpFn op, const void* src, void* dst) {
 | 
				
			||||||
  op(flags_internal::kCopyConstruct, src, dst, nullptr);
 | 
					  op(FlagOp::kCopyConstruct, src, dst, nullptr);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					// Returns true if parsing of input text is successfull.
 | 
				
			||||||
inline bool Parse(FlagOpFn op, absl::string_view text, void* dst,
 | 
					inline bool Parse(FlagOpFn op, absl::string_view text, void* dst,
 | 
				
			||||||
                  std::string* error) {
 | 
					                  std::string* error) {
 | 
				
			||||||
  return op(flags_internal::kParse, &text, dst, error) != nullptr;
 | 
					  return op(FlagOp::kParse, &text, dst, error) != nullptr;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					// Returns string representing supplied value.
 | 
				
			||||||
inline std::string Unparse(FlagOpFn op, const void* val) {
 | 
					inline std::string Unparse(FlagOpFn op, const void* val) {
 | 
				
			||||||
  std::string result;
 | 
					  std::string result;
 | 
				
			||||||
  op(flags_internal::kUnparse, val, &result, nullptr);
 | 
					  op(FlagOp::kUnparse, val, &result, nullptr);
 | 
				
			||||||
  return result;
 | 
					  return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					// Returns size of flag value type.
 | 
				
			||||||
inline size_t Sizeof(FlagOpFn op) {
 | 
					inline size_t Sizeof(FlagOpFn op) {
 | 
				
			||||||
  // This sequence of casts reverses the sequence from
 | 
					  // This sequence of casts reverses the sequence from
 | 
				
			||||||
  // `flags_internal::FlagOps()`
 | 
					  // `flags_internal::FlagOps()`
 | 
				
			||||||
  return static_cast<size_t>(reinterpret_cast<intptr_t>(
 | 
					  return static_cast<size_t>(reinterpret_cast<intptr_t>(
 | 
				
			||||||
      op(flags_internal::kSizeof, nullptr, nullptr, nullptr)));
 | 
					      op(FlagOp::kSizeof, nullptr, nullptr, nullptr)));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					// Returns static type id coresponding to the value type.
 | 
				
			||||||
inline FlagStaticTypeId StaticTypeId(FlagOpFn op) {
 | 
					inline FlagStaticTypeId StaticTypeId(FlagOpFn op) {
 | 
				
			||||||
  return reinterpret_cast<FlagStaticTypeId>(
 | 
					  return reinterpret_cast<FlagStaticTypeId>(
 | 
				
			||||||
      op(flags_internal::kStaticTypeId, nullptr, nullptr, nullptr));
 | 
					      op(FlagOp::kStaticTypeId, nullptr, nullptr, nullptr));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
///////////////////////////////////////////////////////////////////////////////
 | 
					///////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										65
									
								
								absl/status/BUILD.bazel
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								absl/status/BUILD.bazel
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,65 @@
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright 2017 The Abseil Authors.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					# you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					# You may obtain a copy of the License at
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#      https://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					# distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					# See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					# limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# This package contains `absl::Status`.
 | 
				
			||||||
 | 
					# It will expand later to have utilities around `Status` like `StatusOr`,
 | 
				
			||||||
 | 
					# `StatusBuilder` and macros.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
 | 
				
			||||||
 | 
					load(
 | 
				
			||||||
 | 
					    "//absl:copts/configure_copts.bzl",
 | 
				
			||||||
 | 
					    "ABSL_DEFAULT_COPTS",
 | 
				
			||||||
 | 
					    "ABSL_TEST_COPTS",
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package(default_visibility = ["//visibility:public"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					licenses(["notice"])  # Apache 2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cc_library(
 | 
				
			||||||
 | 
					    name = "status",
 | 
				
			||||||
 | 
					    srcs = [
 | 
				
			||||||
 | 
					        "status.cc",
 | 
				
			||||||
 | 
					        "status_payload_printer.cc",
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    hdrs = [
 | 
				
			||||||
 | 
					        "status.h",
 | 
				
			||||||
 | 
					        "status_payload_printer.h",
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    copts = ABSL_DEFAULT_COPTS,
 | 
				
			||||||
 | 
					    deps = [
 | 
				
			||||||
 | 
					        "//absl/base:config",
 | 
				
			||||||
 | 
					        "//absl/base:core_headers",
 | 
				
			||||||
 | 
					        "//absl/base:raw_logging_internal",
 | 
				
			||||||
 | 
					        "//absl/container:inlined_vector",
 | 
				
			||||||
 | 
					        "//absl/debugging:stacktrace",
 | 
				
			||||||
 | 
					        "//absl/debugging:symbolize",
 | 
				
			||||||
 | 
					        "//absl/strings",
 | 
				
			||||||
 | 
					        "//absl/strings:cord",
 | 
				
			||||||
 | 
					        "//absl/strings:str_format",
 | 
				
			||||||
 | 
					        "//absl/types:optional",
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cc_test(
 | 
				
			||||||
 | 
					    name = "status_test",
 | 
				
			||||||
 | 
					    srcs = ["status_test.cc"],
 | 
				
			||||||
 | 
					    copts = ABSL_TEST_COPTS,
 | 
				
			||||||
 | 
					    deps = [
 | 
				
			||||||
 | 
					        ":status",
 | 
				
			||||||
 | 
					        "//absl/strings",
 | 
				
			||||||
 | 
					        "@com_google_googletest//:gtest_main",
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										52
									
								
								absl/status/CMakeLists.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								absl/status/CMakeLists.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,52 @@
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright 2020 The Abseil Authors.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					# you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					# You may obtain a copy of the License at
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#      https://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					# distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					# See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					# limitations under the License.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					absl_cc_library(
 | 
				
			||||||
 | 
					  NAME
 | 
				
			||||||
 | 
					    status
 | 
				
			||||||
 | 
					  HDRS
 | 
				
			||||||
 | 
					    "status.h"
 | 
				
			||||||
 | 
					  SRCS
 | 
				
			||||||
 | 
					    "status.cc"
 | 
				
			||||||
 | 
					    "status_payload_printer.h"
 | 
				
			||||||
 | 
					    "status_payload_printer.cc"
 | 
				
			||||||
 | 
					  COPTS
 | 
				
			||||||
 | 
					    ${ABSL_DEFAULT_COPTS}
 | 
				
			||||||
 | 
					  DEPS
 | 
				
			||||||
 | 
					    absl::config
 | 
				
			||||||
 | 
					    absl::core_headers
 | 
				
			||||||
 | 
					    absl::raw_logging_internal
 | 
				
			||||||
 | 
					    absl::inlined_vector
 | 
				
			||||||
 | 
					    absl::stacktrace
 | 
				
			||||||
 | 
					    absl::symbolize
 | 
				
			||||||
 | 
					    absl::strings
 | 
				
			||||||
 | 
					    absl::cord
 | 
				
			||||||
 | 
					    absl::str_format
 | 
				
			||||||
 | 
					    absl::optional
 | 
				
			||||||
 | 
					  PUBLIC
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					absl_cc_test(
 | 
				
			||||||
 | 
					  NAME
 | 
				
			||||||
 | 
					    status_test
 | 
				
			||||||
 | 
					  HDRS
 | 
				
			||||||
 | 
					   "status_test.cc"
 | 
				
			||||||
 | 
					  COPTS
 | 
				
			||||||
 | 
					    ${ABSL_TEST_COPTS}
 | 
				
			||||||
 | 
					  DEPS
 | 
				
			||||||
 | 
					    absl::status
 | 
				
			||||||
 | 
					    absl::strings
 | 
				
			||||||
 | 
					    gmock_main
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										439
									
								
								absl/status/status.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										439
									
								
								absl/status/status.cc
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,439 @@
 | 
				
			||||||
 | 
					// Copyright 2019 The Abseil Authors.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//      https://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					#include "absl/status/status.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cassert>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "absl/base/internal/raw_logging.h"
 | 
				
			||||||
 | 
					#include "absl/debugging/stacktrace.h"
 | 
				
			||||||
 | 
					#include "absl/debugging/symbolize.h"
 | 
				
			||||||
 | 
					#include "absl/status/status_payload_printer.h"
 | 
				
			||||||
 | 
					#include "absl/strings/escaping.h"
 | 
				
			||||||
 | 
					#include "absl/strings/str_cat.h"
 | 
				
			||||||
 | 
					#include "absl/strings/str_format.h"
 | 
				
			||||||
 | 
					#include "absl/strings/str_split.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace absl {
 | 
				
			||||||
 | 
					ABSL_NAMESPACE_BEGIN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// The implementation was intentionally kept same as util::error::Code_Name()
 | 
				
			||||||
 | 
					// to ease the migration.
 | 
				
			||||||
 | 
					std::string StatusCodeToString(StatusCode code) {
 | 
				
			||||||
 | 
					  switch (code) {
 | 
				
			||||||
 | 
					    case StatusCode::kOk:
 | 
				
			||||||
 | 
					      return "OK";
 | 
				
			||||||
 | 
					    case StatusCode::kCancelled:
 | 
				
			||||||
 | 
					      return "CANCELLED";
 | 
				
			||||||
 | 
					    case StatusCode::kUnknown:
 | 
				
			||||||
 | 
					      return "UNKNOWN";
 | 
				
			||||||
 | 
					    case StatusCode::kInvalidArgument:
 | 
				
			||||||
 | 
					      return "INVALID_ARGUMENT";
 | 
				
			||||||
 | 
					    case StatusCode::kDeadlineExceeded:
 | 
				
			||||||
 | 
					      return "DEADLINE_EXCEEDED";
 | 
				
			||||||
 | 
					    case StatusCode::kNotFound:
 | 
				
			||||||
 | 
					      return "NOT_FOUND";
 | 
				
			||||||
 | 
					    case StatusCode::kAlreadyExists:
 | 
				
			||||||
 | 
					      return "ALREADY_EXISTS";
 | 
				
			||||||
 | 
					    case StatusCode::kPermissionDenied:
 | 
				
			||||||
 | 
					      return "PERMISSION_DENIED";
 | 
				
			||||||
 | 
					    case StatusCode::kUnauthenticated:
 | 
				
			||||||
 | 
					      return "UNAUTHENTICATED";
 | 
				
			||||||
 | 
					    case StatusCode::kResourceExhausted:
 | 
				
			||||||
 | 
					      return "RESOURCE_EXHAUSTED";
 | 
				
			||||||
 | 
					    case StatusCode::kFailedPrecondition:
 | 
				
			||||||
 | 
					      return "FAILED_PRECONDITION";
 | 
				
			||||||
 | 
					    case StatusCode::kAborted:
 | 
				
			||||||
 | 
					      return "ABORTED";
 | 
				
			||||||
 | 
					    case StatusCode::kOutOfRange:
 | 
				
			||||||
 | 
					      return "OUT_OF_RANGE";
 | 
				
			||||||
 | 
					    case StatusCode::kUnimplemented:
 | 
				
			||||||
 | 
					      return "UNIMPLEMENTED";
 | 
				
			||||||
 | 
					    case StatusCode::kInternal:
 | 
				
			||||||
 | 
					      return "INTERNAL";
 | 
				
			||||||
 | 
					    case StatusCode::kUnavailable:
 | 
				
			||||||
 | 
					      return "UNAVAILABLE";
 | 
				
			||||||
 | 
					    case StatusCode::kDataLoss:
 | 
				
			||||||
 | 
					      return "DATA_LOSS";
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					      return "";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::ostream& operator<<(std::ostream& os, StatusCode code) {
 | 
				
			||||||
 | 
					  return os << StatusCodeToString(code);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace status_internal {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int FindPayloadIndexByUrl(const Payloads* payloads,
 | 
				
			||||||
 | 
					                                 absl::string_view type_url) {
 | 
				
			||||||
 | 
					  if (payloads == nullptr) return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (int i = 0; i < payloads->size(); ++i) {
 | 
				
			||||||
 | 
					    if ((*payloads)[i].type_url == type_url) return i;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return -1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Convert canonical code to a value known to this binary.
 | 
				
			||||||
 | 
					absl::StatusCode MapToLocalCode(int value) {
 | 
				
			||||||
 | 
					  absl::StatusCode code = static_cast<absl::StatusCode>(value);
 | 
				
			||||||
 | 
					  switch (code) {
 | 
				
			||||||
 | 
					    case absl::StatusCode::kOk:
 | 
				
			||||||
 | 
					    case absl::StatusCode::kCancelled:
 | 
				
			||||||
 | 
					    case absl::StatusCode::kUnknown:
 | 
				
			||||||
 | 
					    case absl::StatusCode::kInvalidArgument:
 | 
				
			||||||
 | 
					    case absl::StatusCode::kDeadlineExceeded:
 | 
				
			||||||
 | 
					    case absl::StatusCode::kNotFound:
 | 
				
			||||||
 | 
					    case absl::StatusCode::kAlreadyExists:
 | 
				
			||||||
 | 
					    case absl::StatusCode::kPermissionDenied:
 | 
				
			||||||
 | 
					    case absl::StatusCode::kResourceExhausted:
 | 
				
			||||||
 | 
					    case absl::StatusCode::kFailedPrecondition:
 | 
				
			||||||
 | 
					    case absl::StatusCode::kAborted:
 | 
				
			||||||
 | 
					    case absl::StatusCode::kOutOfRange:
 | 
				
			||||||
 | 
					    case absl::StatusCode::kUnimplemented:
 | 
				
			||||||
 | 
					    case absl::StatusCode::kInternal:
 | 
				
			||||||
 | 
					    case absl::StatusCode::kUnavailable:
 | 
				
			||||||
 | 
					    case absl::StatusCode::kDataLoss:
 | 
				
			||||||
 | 
					    case absl::StatusCode::kUnauthenticated:
 | 
				
			||||||
 | 
					      return code;
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					      return absl::StatusCode::kUnknown;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}  // namespace status_internal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					absl::optional<absl::Cord> Status::GetPayload(
 | 
				
			||||||
 | 
					    absl::string_view type_url) const {
 | 
				
			||||||
 | 
					  const auto* payloads = GetPayloads();
 | 
				
			||||||
 | 
					  int index = status_internal::FindPayloadIndexByUrl(payloads, type_url);
 | 
				
			||||||
 | 
					  if (index != -1) return (*payloads)[index].payload;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return absl::nullopt;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Status::SetPayload(absl::string_view type_url, absl::Cord payload) {
 | 
				
			||||||
 | 
					  if (ok()) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  PrepareToModify();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  status_internal::StatusRep* rep = RepToPointer(rep_);
 | 
				
			||||||
 | 
					  if (!rep->payloads) {
 | 
				
			||||||
 | 
					    rep->payloads = absl::make_unique<status_internal::Payloads>();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int index =
 | 
				
			||||||
 | 
					      status_internal::FindPayloadIndexByUrl(rep->payloads.get(), type_url);
 | 
				
			||||||
 | 
					  if (index != -1) {
 | 
				
			||||||
 | 
					    (*rep->payloads)[index].payload = std::move(payload);
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  rep->payloads->push_back({std::string(type_url), std::move(payload)});
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool Status::ErasePayload(absl::string_view type_url) {
 | 
				
			||||||
 | 
					  int index = status_internal::FindPayloadIndexByUrl(GetPayloads(), type_url);
 | 
				
			||||||
 | 
					  if (index != -1) {
 | 
				
			||||||
 | 
					    GetPayloads()->erase(GetPayloads()->begin() + index);
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Status::ForEachPayload(
 | 
				
			||||||
 | 
					    const std::function<void(absl::string_view, const absl::Cord&)>& visitor)
 | 
				
			||||||
 | 
					    const {
 | 
				
			||||||
 | 
					  if (auto* payloads = GetPayloads()) {
 | 
				
			||||||
 | 
					    bool in_reverse =
 | 
				
			||||||
 | 
					        payloads->size() > 1 && reinterpret_cast<uintptr_t>(payloads) % 13 > 6;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (int index = 0; index < payloads->size(); ++index) {
 | 
				
			||||||
 | 
					      const auto& elem =
 | 
				
			||||||
 | 
					          (*payloads)[in_reverse ? payloads->size() - 1 - index : index];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef NDEBUG
 | 
				
			||||||
 | 
					      visitor(elem.type_url, elem.payload);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					      // In debug mode invaldiate the type url to prevent users from relying on
 | 
				
			||||||
 | 
					      // this std::string lifetime.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // NOLINTNEXTLINE intentional extra conversion to force temporary.
 | 
				
			||||||
 | 
					      visitor(std::string(elem.type_url), elem.payload);
 | 
				
			||||||
 | 
					#endif  // NDEBUG
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const std::string* Status::EmptyString() {
 | 
				
			||||||
 | 
					  static std::string* empty_string = new std::string();
 | 
				
			||||||
 | 
					  return empty_string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					constexpr const char Status::kMovedFromString[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const std::string* Status::MovedFromString() {
 | 
				
			||||||
 | 
					  static std::string* moved_from_string = new std::string(kMovedFromString);
 | 
				
			||||||
 | 
					  return moved_from_string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Status::UnrefNonInlined(uintptr_t rep) {
 | 
				
			||||||
 | 
					  status_internal::StatusRep* r = RepToPointer(rep);
 | 
				
			||||||
 | 
					  // Fast path: if ref==1, there is no need for a RefCountDec (since
 | 
				
			||||||
 | 
					  // this is the only reference and therefore no other thread is
 | 
				
			||||||
 | 
					  // allowed to be mucking with r).
 | 
				
			||||||
 | 
					  if (r->ref.load(std::memory_order_acquire) == 1 ||
 | 
				
			||||||
 | 
					      r->ref.fetch_sub(1, std::memory_order_acq_rel) - 1 == 0) {
 | 
				
			||||||
 | 
					    delete r;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uintptr_t Status::NewRep(absl::StatusCode code, absl::string_view msg,
 | 
				
			||||||
 | 
					                         std::unique_ptr<status_internal::Payloads> payloads) {
 | 
				
			||||||
 | 
					  status_internal::StatusRep* rep = new status_internal::StatusRep;
 | 
				
			||||||
 | 
					  rep->ref.store(1, std::memory_order_relaxed);
 | 
				
			||||||
 | 
					  rep->code = code;
 | 
				
			||||||
 | 
					  rep->message.assign(msg.data(), msg.size());
 | 
				
			||||||
 | 
					  rep->payloads = std::move(payloads);
 | 
				
			||||||
 | 
					  return PointerToRep(rep);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Status::Status(absl::StatusCode code, absl::string_view msg)
 | 
				
			||||||
 | 
					    : rep_(CodeToInlinedRep(code)) {
 | 
				
			||||||
 | 
					  if (code != absl::StatusCode::kOk && !msg.empty()) {
 | 
				
			||||||
 | 
					    rep_ = NewRep(code, msg, nullptr);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int Status::raw_code() const {
 | 
				
			||||||
 | 
					  if (IsInlined(rep_)) {
 | 
				
			||||||
 | 
					    return static_cast<int>(InlinedRepToCode(rep_));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  status_internal::StatusRep* rep = RepToPointer(rep_);
 | 
				
			||||||
 | 
					  return static_cast<int>(rep->code);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					absl::StatusCode Status::code() const {
 | 
				
			||||||
 | 
					  return status_internal::MapToLocalCode(raw_code());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Status::PrepareToModify() {
 | 
				
			||||||
 | 
					  ABSL_RAW_CHECK(!ok(), "PrepareToModify shouldn't be called on OK status.");
 | 
				
			||||||
 | 
					  if (IsInlined(rep_)) {
 | 
				
			||||||
 | 
					    rep_ = NewRep(static_cast<absl::StatusCode>(raw_code()),
 | 
				
			||||||
 | 
					                  absl::string_view(), nullptr);
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uintptr_t rep_i = rep_;
 | 
				
			||||||
 | 
					  status_internal::StatusRep* rep = RepToPointer(rep_);
 | 
				
			||||||
 | 
					  if (rep->ref.load(std::memory_order_acquire) != 1) {
 | 
				
			||||||
 | 
					    std::unique_ptr<status_internal::Payloads> payloads;
 | 
				
			||||||
 | 
					    if (rep->payloads) {
 | 
				
			||||||
 | 
					      payloads = absl::make_unique<status_internal::Payloads>(*rep->payloads);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    rep_ = NewRep(rep->code, message(), std::move(payloads));
 | 
				
			||||||
 | 
					    UnrefNonInlined(rep_i);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool Status::EqualsSlow(const absl::Status& a, const absl::Status& b) {
 | 
				
			||||||
 | 
					  if (IsInlined(a.rep_) != IsInlined(b.rep_)) return false;
 | 
				
			||||||
 | 
					  if (a.message() != b.message()) return false;
 | 
				
			||||||
 | 
					  if (a.raw_code() != b.raw_code()) return false;
 | 
				
			||||||
 | 
					  if (a.GetPayloads() == b.GetPayloads()) return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const status_internal::Payloads no_payloads;
 | 
				
			||||||
 | 
					  const status_internal::Payloads* larger_payloads =
 | 
				
			||||||
 | 
					      a.GetPayloads() ? a.GetPayloads() : &no_payloads;
 | 
				
			||||||
 | 
					  const status_internal::Payloads* smaller_payloads =
 | 
				
			||||||
 | 
					      b.GetPayloads() ? b.GetPayloads() : &no_payloads;
 | 
				
			||||||
 | 
					  if (larger_payloads->size() < smaller_payloads->size()) {
 | 
				
			||||||
 | 
					    std::swap(larger_payloads, smaller_payloads);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if ((larger_payloads->size() - smaller_payloads->size()) > 1) return false;
 | 
				
			||||||
 | 
					  // Payloads can be ordered differently, so we can't just compare payload
 | 
				
			||||||
 | 
					  // vectors.
 | 
				
			||||||
 | 
					  for (const auto& payload : *larger_payloads) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool found = false;
 | 
				
			||||||
 | 
					    for (const auto& other_payload : *smaller_payloads) {
 | 
				
			||||||
 | 
					      if (payload.type_url == other_payload.type_url) {
 | 
				
			||||||
 | 
					        if (payload.payload != other_payload.payload) {
 | 
				
			||||||
 | 
					          return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        found = true;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (!found) return false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::string Status::ToStringSlow() const {
 | 
				
			||||||
 | 
					  std::string text;
 | 
				
			||||||
 | 
					  absl::StrAppend(&text, absl::StatusCodeToString(code()), ": ", message());
 | 
				
			||||||
 | 
					  status_internal::StatusPayloadPrinter printer =
 | 
				
			||||||
 | 
					      status_internal::GetStatusPayloadPrinter();
 | 
				
			||||||
 | 
					  this->ForEachPayload([&](absl::string_view type_url,
 | 
				
			||||||
 | 
					                           const absl::Cord& payload) {
 | 
				
			||||||
 | 
					    absl::optional<std::string> result;
 | 
				
			||||||
 | 
					    if (printer) result = printer(type_url, payload);
 | 
				
			||||||
 | 
					    absl::StrAppend(
 | 
				
			||||||
 | 
					        &text, " [", type_url, "='",
 | 
				
			||||||
 | 
					        result.has_value() ? *result : absl::CHexEscape(std::string(payload)),
 | 
				
			||||||
 | 
					        "']");
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return text;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::ostream& operator<<(std::ostream& os, const Status& x) {
 | 
				
			||||||
 | 
					  os << x.ToString();
 | 
				
			||||||
 | 
					  return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Status AbortedError(absl::string_view message) {
 | 
				
			||||||
 | 
					  return Status(absl::StatusCode::kAborted, message);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Status AlreadyExistsError(absl::string_view message) {
 | 
				
			||||||
 | 
					  return Status(absl::StatusCode::kAlreadyExists, message);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Status CancelledError(absl::string_view message) {
 | 
				
			||||||
 | 
					  return Status(absl::StatusCode::kCancelled, message);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Status DataLossError(absl::string_view message) {
 | 
				
			||||||
 | 
					  return Status(absl::StatusCode::kDataLoss, message);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Status DeadlineExceededError(absl::string_view message) {
 | 
				
			||||||
 | 
					  return Status(absl::StatusCode::kDeadlineExceeded, message);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Status FailedPreconditionError(absl::string_view message) {
 | 
				
			||||||
 | 
					  return Status(absl::StatusCode::kFailedPrecondition, message);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Status InternalError(absl::string_view message) {
 | 
				
			||||||
 | 
					  return Status(absl::StatusCode::kInternal, message);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Status InvalidArgumentError(absl::string_view message) {
 | 
				
			||||||
 | 
					  return Status(absl::StatusCode::kInvalidArgument, message);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Status NotFoundError(absl::string_view message) {
 | 
				
			||||||
 | 
					  return Status(absl::StatusCode::kNotFound, message);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Status OutOfRangeError(absl::string_view message) {
 | 
				
			||||||
 | 
					  return Status(absl::StatusCode::kOutOfRange, message);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Status PermissionDeniedError(absl::string_view message) {
 | 
				
			||||||
 | 
					  return Status(absl::StatusCode::kPermissionDenied, message);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Status ResourceExhaustedError(absl::string_view message) {
 | 
				
			||||||
 | 
					  return Status(absl::StatusCode::kResourceExhausted, message);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Status UnauthenticatedError(absl::string_view message) {
 | 
				
			||||||
 | 
					  return Status(absl::StatusCode::kUnauthenticated, message);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Status UnavailableError(absl::string_view message) {
 | 
				
			||||||
 | 
					  return Status(absl::StatusCode::kUnavailable, message);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Status UnimplementedError(absl::string_view message) {
 | 
				
			||||||
 | 
					  return Status(absl::StatusCode::kUnimplemented, message);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Status UnknownError(absl::string_view message) {
 | 
				
			||||||
 | 
					  return Status(absl::StatusCode::kUnknown, message);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool IsAborted(const Status& status) {
 | 
				
			||||||
 | 
					  return status.code() == absl::StatusCode::kAborted;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool IsAlreadyExists(const Status& status) {
 | 
				
			||||||
 | 
					  return status.code() == absl::StatusCode::kAlreadyExists;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool IsCancelled(const Status& status) {
 | 
				
			||||||
 | 
					  return status.code() == absl::StatusCode::kCancelled;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool IsDataLoss(const Status& status) {
 | 
				
			||||||
 | 
					  return status.code() == absl::StatusCode::kDataLoss;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool IsDeadlineExceeded(const Status& status) {
 | 
				
			||||||
 | 
					  return status.code() == absl::StatusCode::kDeadlineExceeded;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool IsFailedPrecondition(const Status& status) {
 | 
				
			||||||
 | 
					  return status.code() == absl::StatusCode::kFailedPrecondition;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool IsInternal(const Status& status) {
 | 
				
			||||||
 | 
					  return status.code() == absl::StatusCode::kInternal;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool IsInvalidArgument(const Status& status) {
 | 
				
			||||||
 | 
					  return status.code() == absl::StatusCode::kInvalidArgument;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool IsNotFound(const Status& status) {
 | 
				
			||||||
 | 
					  return status.code() == absl::StatusCode::kNotFound;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool IsOutOfRange(const Status& status) {
 | 
				
			||||||
 | 
					  return status.code() == absl::StatusCode::kOutOfRange;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool IsPermissionDenied(const Status& status) {
 | 
				
			||||||
 | 
					  return status.code() == absl::StatusCode::kPermissionDenied;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool IsResourceExhausted(const Status& status) {
 | 
				
			||||||
 | 
					  return status.code() == absl::StatusCode::kResourceExhausted;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool IsUnauthenticated(const Status& status) {
 | 
				
			||||||
 | 
					  return status.code() == absl::StatusCode::kUnauthenticated;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool IsUnavailable(const Status& status) {
 | 
				
			||||||
 | 
					  return status.code() == absl::StatusCode::kUnavailable;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool IsUnimplemented(const Status& status) {
 | 
				
			||||||
 | 
					  return status.code() == absl::StatusCode::kUnimplemented;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool IsUnknown(const Status& status) {
 | 
				
			||||||
 | 
					  return status.code() == absl::StatusCode::kUnknown;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ABSL_NAMESPACE_END
 | 
				
			||||||
 | 
					}  // namespace absl
 | 
				
			||||||
							
								
								
									
										428
									
								
								absl/status/status.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										428
									
								
								absl/status/status.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,428 @@
 | 
				
			||||||
 | 
					// Copyright 2019 The Abseil Authors.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//      https://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					#ifndef ABSL_STATUS_STATUS_H_
 | 
				
			||||||
 | 
					#define ABSL_STATUS_STATUS_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "absl/container/inlined_vector.h"
 | 
				
			||||||
 | 
					#include "absl/strings/cord.h"
 | 
				
			||||||
 | 
					#include "absl/types/optional.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace absl {
 | 
				
			||||||
 | 
					ABSL_NAMESPACE_BEGIN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum class StatusCode : int {
 | 
				
			||||||
 | 
					  kOk = 0,
 | 
				
			||||||
 | 
					  kCancelled = 1,
 | 
				
			||||||
 | 
					  kUnknown = 2,
 | 
				
			||||||
 | 
					  kInvalidArgument = 3,
 | 
				
			||||||
 | 
					  kDeadlineExceeded = 4,
 | 
				
			||||||
 | 
					  kNotFound = 5,
 | 
				
			||||||
 | 
					  kAlreadyExists = 6,
 | 
				
			||||||
 | 
					  kPermissionDenied = 7,
 | 
				
			||||||
 | 
					  kResourceExhausted = 8,
 | 
				
			||||||
 | 
					  kFailedPrecondition = 9,
 | 
				
			||||||
 | 
					  kAborted = 10,
 | 
				
			||||||
 | 
					  kOutOfRange = 11,
 | 
				
			||||||
 | 
					  kUnimplemented = 12,
 | 
				
			||||||
 | 
					  kInternal = 13,
 | 
				
			||||||
 | 
					  kUnavailable = 14,
 | 
				
			||||||
 | 
					  kDataLoss = 15,
 | 
				
			||||||
 | 
					  kUnauthenticated = 16,
 | 
				
			||||||
 | 
					  kDoNotUseReservedForFutureExpansionUseDefaultInSwitchInstead_ = 20
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Returns the name for the status code, or "" if it is an unknown value.
 | 
				
			||||||
 | 
					std::string StatusCodeToString(StatusCode code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Streams StatusCodeToString(code) to `os`.
 | 
				
			||||||
 | 
					std::ostream& operator<<(std::ostream& os, StatusCode code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace status_internal {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Container for status payloads.
 | 
				
			||||||
 | 
					struct Payload {
 | 
				
			||||||
 | 
					  std::string type_url;
 | 
				
			||||||
 | 
					  absl::Cord payload;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Payloads = absl::InlinedVector<Payload, 1>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Reference-counted representation of Status data.
 | 
				
			||||||
 | 
					struct StatusRep {
 | 
				
			||||||
 | 
					  std::atomic<int32_t> ref;
 | 
				
			||||||
 | 
					  absl::StatusCode code;
 | 
				
			||||||
 | 
					  std::string message;
 | 
				
			||||||
 | 
					  std::unique_ptr<status_internal::Payloads> payloads;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					absl::StatusCode MapToLocalCode(int value);
 | 
				
			||||||
 | 
					}  // namespace status_internal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ABSL_MUST_USE_RESULT Status final {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  // Creates an OK status with no message or payload.
 | 
				
			||||||
 | 
					  Status();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Create a status in the canonical error space with the specified code and
 | 
				
			||||||
 | 
					  // error message.  If `code == util::error::OK`, `msg` is ignored and an
 | 
				
			||||||
 | 
					  // object identical to an OK status is constructed.
 | 
				
			||||||
 | 
					  //
 | 
				
			||||||
 | 
					  // `msg` must be in UTF-8. The implementation may complain (e.g.,
 | 
				
			||||||
 | 
					  // by printing a warning) if it is not.
 | 
				
			||||||
 | 
					  Status(absl::StatusCode code, absl::string_view msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Status(const Status&);
 | 
				
			||||||
 | 
					  Status& operator=(const Status& x);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Move operations.
 | 
				
			||||||
 | 
					  // The moved-from state is valid but unspecified.
 | 
				
			||||||
 | 
					  Status(Status&&) noexcept;
 | 
				
			||||||
 | 
					  Status& operator=(Status&&);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ~Status();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // If `this->ok()`, stores `new_status` into *this. If `!this->ok()`,
 | 
				
			||||||
 | 
					  // preserves the current data. May, in the future, augment the current status
 | 
				
			||||||
 | 
					  // with additional information about `new_status`.
 | 
				
			||||||
 | 
					  //
 | 
				
			||||||
 | 
					  // Convenient way of keeping track of the first error encountered.
 | 
				
			||||||
 | 
					  // Instead of:
 | 
				
			||||||
 | 
					  //   if (overall_status.ok()) overall_status = new_status
 | 
				
			||||||
 | 
					  // Use:
 | 
				
			||||||
 | 
					  //   overall_status.Update(new_status);
 | 
				
			||||||
 | 
					  //
 | 
				
			||||||
 | 
					  // Style guide exception for rvalue reference granted in CL 153567220.
 | 
				
			||||||
 | 
					  void Update(const Status& new_status);
 | 
				
			||||||
 | 
					  void Update(Status&& new_status);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Returns true if the Status is OK.
 | 
				
			||||||
 | 
					  ABSL_MUST_USE_RESULT bool ok() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Returns the (canonical) error code.
 | 
				
			||||||
 | 
					  absl::StatusCode code() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Returns the raw (canonical) error code which could be out of the range of
 | 
				
			||||||
 | 
					  // the local `absl::StatusCode` enum. NOTE: This should only be called when
 | 
				
			||||||
 | 
					  // converting to wire format. Use `code` for error handling.
 | 
				
			||||||
 | 
					  int raw_code() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Returns the error message.  Note: prefer ToString() for debug logging.
 | 
				
			||||||
 | 
					  // This message rarely describes the error code.  It is not unusual for the
 | 
				
			||||||
 | 
					  // error message to be the empty std::string.
 | 
				
			||||||
 | 
					  absl::string_view message() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  friend bool operator==(const Status&, const Status&);
 | 
				
			||||||
 | 
					  friend bool operator!=(const Status&, const Status&);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Returns a combination of the error code name, the message and the payloads.
 | 
				
			||||||
 | 
					  // You can expect the code name and the message to be substrings of the
 | 
				
			||||||
 | 
					  // result, and the payloads to be printed by the registered printer extensions
 | 
				
			||||||
 | 
					  // if they are recognized.
 | 
				
			||||||
 | 
					  // WARNING: Do not depend on the exact format of the result of `ToString()`
 | 
				
			||||||
 | 
					  // which is subject to change.
 | 
				
			||||||
 | 
					  std::string ToString() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Ignores any errors. This method does nothing except potentially suppress
 | 
				
			||||||
 | 
					  // complaints from any tools that are checking that errors are not dropped on
 | 
				
			||||||
 | 
					  // the floor.
 | 
				
			||||||
 | 
					  void IgnoreError() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Swap the contents of `a` with `b`
 | 
				
			||||||
 | 
					  friend void swap(Status& a, Status& b);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Payload management APIs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Type URL should be unique and follow the naming convention below:
 | 
				
			||||||
 | 
					  // The idea of type URL comes from `google.protobuf.Any`
 | 
				
			||||||
 | 
					  // (https://developers.google.com/protocol-buffers/docs/proto3#any). The
 | 
				
			||||||
 | 
					  // type URL should be globally unique and follow the format of URL
 | 
				
			||||||
 | 
					  // (https://en.wikipedia.org/wiki/URL). The default type URL for a given
 | 
				
			||||||
 | 
					  // protobuf message type is "type.googleapis.com/packagename.messagename". For
 | 
				
			||||||
 | 
					  // other custom wire formats, users should define the format of type URL in a
 | 
				
			||||||
 | 
					  // similar practice so as to minimize the chance of conflict between type
 | 
				
			||||||
 | 
					  // URLs. Users should make sure that the type URL can be mapped to a concrete
 | 
				
			||||||
 | 
					  // C++ type if they want to deserialize the payload and read it effectively.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Gets the payload based for `type_url` key, if it is present.
 | 
				
			||||||
 | 
					  absl::optional<absl::Cord> GetPayload(absl::string_view type_url) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Sets the payload for `type_url` key for a non-ok status, overwriting any
 | 
				
			||||||
 | 
					  // existing payload for `type_url`.
 | 
				
			||||||
 | 
					  //
 | 
				
			||||||
 | 
					  // NOTE: Does nothing if the Status is ok.
 | 
				
			||||||
 | 
					  void SetPayload(absl::string_view type_url, absl::Cord payload);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Erases the payload corresponding to the `type_url` key.  Returns true if
 | 
				
			||||||
 | 
					  // the payload was present.
 | 
				
			||||||
 | 
					  bool ErasePayload(absl::string_view type_url);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Iterates over the stored payloads and calls `visitor(type_key, payload)`
 | 
				
			||||||
 | 
					  // for each one.
 | 
				
			||||||
 | 
					  //
 | 
				
			||||||
 | 
					  // NOTE: The order of calls to `visitor` is not specified and may change at
 | 
				
			||||||
 | 
					  // any time.
 | 
				
			||||||
 | 
					  //
 | 
				
			||||||
 | 
					  // NOTE: Any mutation on the same 'Status' object during visitation is
 | 
				
			||||||
 | 
					  // forbidden and could result in undefined behavior.
 | 
				
			||||||
 | 
					  void ForEachPayload(
 | 
				
			||||||
 | 
					      const std::function<void(absl::string_view, const absl::Cord&)>& visitor)
 | 
				
			||||||
 | 
					      const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 private:
 | 
				
			||||||
 | 
					  friend Status CancelledError();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Creates a status in the canonical error space with the specified
 | 
				
			||||||
 | 
					  // code, and an empty error message.
 | 
				
			||||||
 | 
					  explicit Status(absl::StatusCode code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static void UnrefNonInlined(uintptr_t rep);
 | 
				
			||||||
 | 
					  static void Ref(uintptr_t rep);
 | 
				
			||||||
 | 
					  static void Unref(uintptr_t rep);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // REQUIRES: !ok()
 | 
				
			||||||
 | 
					  // Ensures rep_ is not shared with any other Status.
 | 
				
			||||||
 | 
					  void PrepareToModify();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const status_internal::Payloads* GetPayloads() const;
 | 
				
			||||||
 | 
					  status_internal::Payloads* GetPayloads();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Takes ownership of payload.
 | 
				
			||||||
 | 
					  static uintptr_t NewRep(absl::StatusCode code, absl::string_view msg,
 | 
				
			||||||
 | 
					                          std::unique_ptr<status_internal::Payloads> payload);
 | 
				
			||||||
 | 
					  static bool EqualsSlow(const absl::Status& a, const absl::Status& b);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // MSVC 14.0 limitation requires the const.
 | 
				
			||||||
 | 
					  static constexpr const char kMovedFromString[] =
 | 
				
			||||||
 | 
					      "Status accessed after move.";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static const std::string* EmptyString();
 | 
				
			||||||
 | 
					  static const std::string* MovedFromString();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Returns whether rep contains an inlined representation.
 | 
				
			||||||
 | 
					  // See rep_ for details.
 | 
				
			||||||
 | 
					  static bool IsInlined(uintptr_t rep);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Indicates whether this Status was the rhs of a move operation. See rep_
 | 
				
			||||||
 | 
					  // for details.
 | 
				
			||||||
 | 
					  static bool IsMovedFrom(uintptr_t rep);
 | 
				
			||||||
 | 
					  static uintptr_t MovedFromRep();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Convert between error::Code and the inlined uintptr_t representation used
 | 
				
			||||||
 | 
					  // by rep_. See rep_ for details.
 | 
				
			||||||
 | 
					  static uintptr_t CodeToInlinedRep(absl::StatusCode code);
 | 
				
			||||||
 | 
					  static absl::StatusCode InlinedRepToCode(uintptr_t rep);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Converts between StatusRep* and the external uintptr_t representation used
 | 
				
			||||||
 | 
					  // by rep_. See rep_ for details.
 | 
				
			||||||
 | 
					  static uintptr_t PointerToRep(status_internal::StatusRep* r);
 | 
				
			||||||
 | 
					  static status_internal::StatusRep* RepToPointer(uintptr_t r);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Returns std::string for non-ok Status.
 | 
				
			||||||
 | 
					  std::string ToStringSlow() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Status supports two different representations.
 | 
				
			||||||
 | 
					  //  - When the low bit is off it is an inlined representation.
 | 
				
			||||||
 | 
					  //    It uses the canonical error space, no message or payload.
 | 
				
			||||||
 | 
					  //    The error code is (rep_ >> 2).
 | 
				
			||||||
 | 
					  //    The (rep_ & 2) bit is the "moved from" indicator, used in IsMovedFrom().
 | 
				
			||||||
 | 
					  //  - When the low bit is on it is an external representation.
 | 
				
			||||||
 | 
					  //    In this case all the data comes from a heap allocated Rep object.
 | 
				
			||||||
 | 
					  //    (rep_ - 1) is a status_internal::StatusRep* pointer to that structure.
 | 
				
			||||||
 | 
					  uintptr_t rep_;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Returns an OK status, equivalent to a default constructed instance.
 | 
				
			||||||
 | 
					Status OkStatus();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Prints a human-readable representation of `x` to `os`.
 | 
				
			||||||
 | 
					std::ostream& operator<<(std::ostream& os, const Status& x);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// -----------------------------------------------------------------
 | 
				
			||||||
 | 
					// Implementation details follow
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline Status::Status() : rep_(CodeToInlinedRep(absl::StatusCode::kOk)) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline Status::Status(absl::StatusCode code) : rep_(CodeToInlinedRep(code)) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline Status::Status(const Status& x) : rep_(x.rep_) { Ref(rep_); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline Status& Status::operator=(const Status& x) {
 | 
				
			||||||
 | 
					  uintptr_t old_rep = rep_;
 | 
				
			||||||
 | 
					  if (x.rep_ != old_rep) {
 | 
				
			||||||
 | 
					    Ref(x.rep_);
 | 
				
			||||||
 | 
					    rep_ = x.rep_;
 | 
				
			||||||
 | 
					    Unref(old_rep);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return *this;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline Status::Status(Status&& x) noexcept : rep_(x.rep_) {
 | 
				
			||||||
 | 
					  x.rep_ = MovedFromRep();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline Status& Status::operator=(Status&& x) {
 | 
				
			||||||
 | 
					  uintptr_t old_rep = rep_;
 | 
				
			||||||
 | 
					  rep_ = x.rep_;
 | 
				
			||||||
 | 
					  x.rep_ = MovedFromRep();
 | 
				
			||||||
 | 
					  Unref(old_rep);
 | 
				
			||||||
 | 
					  return *this;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline void Status::Update(const Status& new_status) {
 | 
				
			||||||
 | 
					  if (ok()) {
 | 
				
			||||||
 | 
					    *this = new_status;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline void Status::Update(Status&& new_status) {
 | 
				
			||||||
 | 
					  if (ok()) {
 | 
				
			||||||
 | 
					    *this = std::move(new_status);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline Status::~Status() { Unref(rep_); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline bool Status::ok() const {
 | 
				
			||||||
 | 
					  return rep_ == CodeToInlinedRep(absl::StatusCode::kOk);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline absl::string_view Status::message() const {
 | 
				
			||||||
 | 
					  return !IsInlined(rep_)
 | 
				
			||||||
 | 
					             ? RepToPointer(rep_)->message
 | 
				
			||||||
 | 
					             : (IsMovedFrom(rep_) ? absl::string_view(kMovedFromString)
 | 
				
			||||||
 | 
					                                  : absl::string_view());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline bool operator==(const Status& lhs, const Status& rhs) {
 | 
				
			||||||
 | 
					  return lhs.rep_ == rhs.rep_ || Status::EqualsSlow(lhs, rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline bool operator!=(const Status& lhs, const Status& rhs) {
 | 
				
			||||||
 | 
					  return !(lhs == rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline std::string Status::ToString() const {
 | 
				
			||||||
 | 
					  return ok() ? "OK" : ToStringSlow();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline void Status::IgnoreError() const {
 | 
				
			||||||
 | 
					  // no-op
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline void swap(absl::Status& a, absl::Status& b) {
 | 
				
			||||||
 | 
					  using std::swap;
 | 
				
			||||||
 | 
					  swap(a.rep_, b.rep_);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline const status_internal::Payloads* Status::GetPayloads() const {
 | 
				
			||||||
 | 
					  return IsInlined(rep_) ? nullptr : RepToPointer(rep_)->payloads.get();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline status_internal::Payloads* Status::GetPayloads() {
 | 
				
			||||||
 | 
					  return IsInlined(rep_) ? nullptr : RepToPointer(rep_)->payloads.get();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline bool Status::IsInlined(uintptr_t rep) { return (rep & 1) == 0; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline bool Status::IsMovedFrom(uintptr_t rep) {
 | 
				
			||||||
 | 
					  return IsInlined(rep) && (rep & 2) != 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline uintptr_t Status::MovedFromRep() {
 | 
				
			||||||
 | 
					  return CodeToInlinedRep(absl::StatusCode::kInternal) | 2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline uintptr_t Status::CodeToInlinedRep(absl::StatusCode code) {
 | 
				
			||||||
 | 
					  return static_cast<uintptr_t>(code) << 2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline absl::StatusCode Status::InlinedRepToCode(uintptr_t rep) {
 | 
				
			||||||
 | 
					  assert(IsInlined(rep));
 | 
				
			||||||
 | 
					  return static_cast<absl::StatusCode>(rep >> 2);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline status_internal::StatusRep* Status::RepToPointer(uintptr_t rep) {
 | 
				
			||||||
 | 
					  assert(!IsInlined(rep));
 | 
				
			||||||
 | 
					  return reinterpret_cast<status_internal::StatusRep*>(rep - 1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline uintptr_t Status::PointerToRep(status_internal::StatusRep* rep) {
 | 
				
			||||||
 | 
					  return reinterpret_cast<uintptr_t>(rep) + 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline void Status::Ref(uintptr_t rep) {
 | 
				
			||||||
 | 
					  if (!IsInlined(rep)) {
 | 
				
			||||||
 | 
					    RepToPointer(rep)->ref.fetch_add(1, std::memory_order_relaxed);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline void Status::Unref(uintptr_t rep) {
 | 
				
			||||||
 | 
					  if (!IsInlined(rep)) {
 | 
				
			||||||
 | 
					    UnrefNonInlined(rep);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline Status OkStatus() { return Status(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Each of the functions below creates a Status object with a particular error
 | 
				
			||||||
 | 
					// code and the given message. The error code of the returned status object
 | 
				
			||||||
 | 
					// matches the name of the function.
 | 
				
			||||||
 | 
					Status AbortedError(absl::string_view message);
 | 
				
			||||||
 | 
					Status AlreadyExistsError(absl::string_view message);
 | 
				
			||||||
 | 
					Status CancelledError(absl::string_view message);
 | 
				
			||||||
 | 
					Status DataLossError(absl::string_view message);
 | 
				
			||||||
 | 
					Status DeadlineExceededError(absl::string_view message);
 | 
				
			||||||
 | 
					Status FailedPreconditionError(absl::string_view message);
 | 
				
			||||||
 | 
					Status InternalError(absl::string_view message);
 | 
				
			||||||
 | 
					Status InvalidArgumentError(absl::string_view message);
 | 
				
			||||||
 | 
					Status NotFoundError(absl::string_view message);
 | 
				
			||||||
 | 
					Status OutOfRangeError(absl::string_view message);
 | 
				
			||||||
 | 
					Status PermissionDeniedError(absl::string_view message);
 | 
				
			||||||
 | 
					Status ResourceExhaustedError(absl::string_view message);
 | 
				
			||||||
 | 
					Status UnauthenticatedError(absl::string_view message);
 | 
				
			||||||
 | 
					Status UnavailableError(absl::string_view message);
 | 
				
			||||||
 | 
					Status UnimplementedError(absl::string_view message);
 | 
				
			||||||
 | 
					Status UnknownError(absl::string_view message);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Creates a `Status` object with the `absl::StatusCode::kCancelled` error code
 | 
				
			||||||
 | 
					// and an empty message. It is provided only for efficiency, given that
 | 
				
			||||||
 | 
					// message-less kCancelled errors are common in the infrastructure.
 | 
				
			||||||
 | 
					inline Status CancelledError() { return Status(absl::StatusCode::kCancelled); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Each of the functions below returns true if the given status matches the
 | 
				
			||||||
 | 
					// error code implied by the function's name.
 | 
				
			||||||
 | 
					ABSL_MUST_USE_RESULT bool IsAborted(const Status& status);
 | 
				
			||||||
 | 
					ABSL_MUST_USE_RESULT bool IsAlreadyExists(const Status& status);
 | 
				
			||||||
 | 
					ABSL_MUST_USE_RESULT bool IsCancelled(const Status& status);
 | 
				
			||||||
 | 
					ABSL_MUST_USE_RESULT bool IsDataLoss(const Status& status);
 | 
				
			||||||
 | 
					ABSL_MUST_USE_RESULT bool IsDeadlineExceeded(const Status& status);
 | 
				
			||||||
 | 
					ABSL_MUST_USE_RESULT bool IsFailedPrecondition(const Status& status);
 | 
				
			||||||
 | 
					ABSL_MUST_USE_RESULT bool IsInternal(const Status& status);
 | 
				
			||||||
 | 
					ABSL_MUST_USE_RESULT bool IsInvalidArgument(const Status& status);
 | 
				
			||||||
 | 
					ABSL_MUST_USE_RESULT bool IsNotFound(const Status& status);
 | 
				
			||||||
 | 
					ABSL_MUST_USE_RESULT bool IsOutOfRange(const Status& status);
 | 
				
			||||||
 | 
					ABSL_MUST_USE_RESULT bool IsPermissionDenied(const Status& status);
 | 
				
			||||||
 | 
					ABSL_MUST_USE_RESULT bool IsResourceExhausted(const Status& status);
 | 
				
			||||||
 | 
					ABSL_MUST_USE_RESULT bool IsUnauthenticated(const Status& status);
 | 
				
			||||||
 | 
					ABSL_MUST_USE_RESULT bool IsUnavailable(const Status& status);
 | 
				
			||||||
 | 
					ABSL_MUST_USE_RESULT bool IsUnimplemented(const Status& status);
 | 
				
			||||||
 | 
					ABSL_MUST_USE_RESULT bool IsUnknown(const Status& status);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ABSL_NAMESPACE_END
 | 
				
			||||||
 | 
					}  // namespace absl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif  // ABSL_STATUS_STATUS_H_
 | 
				
			||||||
							
								
								
									
										43
									
								
								absl/status/status_payload_printer.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								absl/status/status_payload_printer.cc
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,43 @@
 | 
				
			||||||
 | 
					// Copyright 2019 The Abseil Authors.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//      https://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					#include "absl/status/status_payload_printer.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <atomic>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "absl/base/attributes.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace absl {
 | 
				
			||||||
 | 
					ABSL_NAMESPACE_BEGIN
 | 
				
			||||||
 | 
					namespace status_internal {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace {
 | 
				
			||||||
 | 
					// Tried constant initialized global variable but it doesn't work with Lexan
 | 
				
			||||||
 | 
					// (MSVC's `std::atomic` has trouble constant initializing).
 | 
				
			||||||
 | 
					std::atomic<StatusPayloadPrinter>& GetStatusPayloadPrinterStorage() {
 | 
				
			||||||
 | 
					  ABSL_CONST_INIT static std::atomic<StatusPayloadPrinter> instance{nullptr};
 | 
				
			||||||
 | 
					  return instance;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}  // namespace
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void SetStatusPayloadPrinter(StatusPayloadPrinter printer) {
 | 
				
			||||||
 | 
					  GetStatusPayloadPrinterStorage().store(printer, std::memory_order_relaxed);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					StatusPayloadPrinter GetStatusPayloadPrinter() {
 | 
				
			||||||
 | 
					  return GetStatusPayloadPrinterStorage().load(std::memory_order_relaxed);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}  // namespace status_internal
 | 
				
			||||||
 | 
					ABSL_NAMESPACE_END
 | 
				
			||||||
 | 
					}  // namespace absl
 | 
				
			||||||
							
								
								
									
										51
									
								
								absl/status/status_payload_printer.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								absl/status/status_payload_printer.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,51 @@
 | 
				
			||||||
 | 
					// Copyright 2019 The Abseil Authors.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//      https://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					#ifndef ABSL_STATUS_STATUS_PAYLOAD_PRINTER_H_
 | 
				
			||||||
 | 
					#define ABSL_STATUS_STATUS_PAYLOAD_PRINTER_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "absl/strings/cord.h"
 | 
				
			||||||
 | 
					#include "absl/strings/string_view.h"
 | 
				
			||||||
 | 
					#include "absl/types/optional.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace absl {
 | 
				
			||||||
 | 
					ABSL_NAMESPACE_BEGIN
 | 
				
			||||||
 | 
					namespace status_internal {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// By default, `Status::ToString` and `operator<<(Status)` print a payload by
 | 
				
			||||||
 | 
					// dumping the type URL and the raw bytes. To help debugging, we provide an
 | 
				
			||||||
 | 
					// extension point, which is a global printer function that can be set by users
 | 
				
			||||||
 | 
					// to specify how to print payloads. The function takes the type URL and the
 | 
				
			||||||
 | 
					// payload as input, and should return a valid human-readable string on success
 | 
				
			||||||
 | 
					// or `absl::nullopt` on failure (in which case it falls back to the default
 | 
				
			||||||
 | 
					// approach of printing the raw bytes).
 | 
				
			||||||
 | 
					// NOTE: This is an internal API and the design is subject to change in the
 | 
				
			||||||
 | 
					// future in a non-backward-compatible way. Since it's only meant for debugging
 | 
				
			||||||
 | 
					// purpose, you should not rely on it in any critical logic.
 | 
				
			||||||
 | 
					using StatusPayloadPrinter = absl::optional<std::string> (*)(absl::string_view,
 | 
				
			||||||
 | 
					                                                             const absl::Cord&);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Sets the global payload printer. Only one printer should be set per process.
 | 
				
			||||||
 | 
					// If multiple printers are set, it's undefined which one will be used.
 | 
				
			||||||
 | 
					void SetStatusPayloadPrinter(StatusPayloadPrinter);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Returns the global payload printer if previously set, otherwise `nullptr`.
 | 
				
			||||||
 | 
					StatusPayloadPrinter GetStatusPayloadPrinter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}  // namespace status_internal
 | 
				
			||||||
 | 
					ABSL_NAMESPACE_END
 | 
				
			||||||
 | 
					}  // namespace absl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif  // ABSL_STATUS_STATUS_PAYLOAD_PRINTER_H_
 | 
				
			||||||
							
								
								
									
										401
									
								
								absl/status/status_test.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										401
									
								
								absl/status/status_test.cc
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,401 @@
 | 
				
			||||||
 | 
					// Copyright 2019 The Abseil Authors.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//      https://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "absl/status/status.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "gmock/gmock.h"
 | 
				
			||||||
 | 
					#include "gtest/gtest.h"
 | 
				
			||||||
 | 
					#include "absl/strings/str_cat.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using ::testing::Eq;
 | 
				
			||||||
 | 
					using ::testing::HasSubstr;
 | 
				
			||||||
 | 
					using ::testing::Optional;
 | 
				
			||||||
 | 
					using ::testing::UnorderedElementsAreArray;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(StatusCode, InsertionOperator) {
 | 
				
			||||||
 | 
					  const absl::StatusCode code = absl::StatusCode::kUnknown;
 | 
				
			||||||
 | 
					  std::ostringstream oss;
 | 
				
			||||||
 | 
					  oss << code;
 | 
				
			||||||
 | 
					  EXPECT_EQ(oss.str(), absl::StatusCodeToString(code));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This structure holds the details for testing a single error code,
 | 
				
			||||||
 | 
					// its creator, and its classifier.
 | 
				
			||||||
 | 
					struct ErrorTest {
 | 
				
			||||||
 | 
					  absl::StatusCode code;
 | 
				
			||||||
 | 
					  using Creator = absl::Status (*)(absl::string_view);
 | 
				
			||||||
 | 
					  using Classifier = bool (*)(const absl::Status&);
 | 
				
			||||||
 | 
					  Creator creator;
 | 
				
			||||||
 | 
					  Classifier classifier;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					constexpr ErrorTest kErrorTests[]{
 | 
				
			||||||
 | 
					    {absl::StatusCode::kCancelled, absl::CancelledError, absl::IsCancelled},
 | 
				
			||||||
 | 
					    {absl::StatusCode::kUnknown, absl::UnknownError, absl::IsUnknown},
 | 
				
			||||||
 | 
					    {absl::StatusCode::kInvalidArgument, absl::InvalidArgumentError,
 | 
				
			||||||
 | 
					     absl::IsInvalidArgument},
 | 
				
			||||||
 | 
					    {absl::StatusCode::kDeadlineExceeded, absl::DeadlineExceededError,
 | 
				
			||||||
 | 
					     absl::IsDeadlineExceeded},
 | 
				
			||||||
 | 
					    {absl::StatusCode::kNotFound, absl::NotFoundError, absl::IsNotFound},
 | 
				
			||||||
 | 
					    {absl::StatusCode::kAlreadyExists, absl::AlreadyExistsError,
 | 
				
			||||||
 | 
					     absl::IsAlreadyExists},
 | 
				
			||||||
 | 
					    {absl::StatusCode::kPermissionDenied, absl::PermissionDeniedError,
 | 
				
			||||||
 | 
					     absl::IsPermissionDenied},
 | 
				
			||||||
 | 
					    {absl::StatusCode::kResourceExhausted, absl::ResourceExhaustedError,
 | 
				
			||||||
 | 
					     absl::IsResourceExhausted},
 | 
				
			||||||
 | 
					    {absl::StatusCode::kFailedPrecondition, absl::FailedPreconditionError,
 | 
				
			||||||
 | 
					     absl::IsFailedPrecondition},
 | 
				
			||||||
 | 
					    {absl::StatusCode::kAborted, absl::AbortedError, absl::IsAborted},
 | 
				
			||||||
 | 
					    {absl::StatusCode::kOutOfRange, absl::OutOfRangeError, absl::IsOutOfRange},
 | 
				
			||||||
 | 
					    {absl::StatusCode::kUnimplemented, absl::UnimplementedError,
 | 
				
			||||||
 | 
					     absl::IsUnimplemented},
 | 
				
			||||||
 | 
					    {absl::StatusCode::kInternal, absl::InternalError, absl::IsInternal},
 | 
				
			||||||
 | 
					    {absl::StatusCode::kUnavailable, absl::UnavailableError,
 | 
				
			||||||
 | 
					     absl::IsUnavailable},
 | 
				
			||||||
 | 
					    {absl::StatusCode::kDataLoss, absl::DataLossError, absl::IsDataLoss},
 | 
				
			||||||
 | 
					    {absl::StatusCode::kUnauthenticated, absl::UnauthenticatedError,
 | 
				
			||||||
 | 
					     absl::IsUnauthenticated},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(Status, CreateAndClassify) {
 | 
				
			||||||
 | 
					  for (const auto& test : kErrorTests) {
 | 
				
			||||||
 | 
					    SCOPED_TRACE(absl::StatusCodeToString(test.code));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Ensure that the creator does, in fact, create status objects with the
 | 
				
			||||||
 | 
					    // expected error code and message.
 | 
				
			||||||
 | 
					    std::string message =
 | 
				
			||||||
 | 
					        absl::StrCat("error code ", test.code, " test message");
 | 
				
			||||||
 | 
					    absl::Status status = test.creator(message);
 | 
				
			||||||
 | 
					    EXPECT_EQ(test.code, status.code());
 | 
				
			||||||
 | 
					    EXPECT_EQ(message, status.message());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Ensure that the classifier returns true for a status produced by the
 | 
				
			||||||
 | 
					    // creator.
 | 
				
			||||||
 | 
					    EXPECT_TRUE(test.classifier(status));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Ensure that the classifier returns false for status with a different
 | 
				
			||||||
 | 
					    // code.
 | 
				
			||||||
 | 
					    for (const auto& other : kErrorTests) {
 | 
				
			||||||
 | 
					      if (other.code != test.code) {
 | 
				
			||||||
 | 
					        EXPECT_FALSE(test.classifier(absl::Status(other.code, "")))
 | 
				
			||||||
 | 
					            << " other.code = " << other.code;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(Status, DefaultConstructor) {
 | 
				
			||||||
 | 
					  absl::Status status;
 | 
				
			||||||
 | 
					  EXPECT_TRUE(status.ok());
 | 
				
			||||||
 | 
					  EXPECT_EQ(absl::StatusCode::kOk, status.code());
 | 
				
			||||||
 | 
					  EXPECT_EQ("", status.message());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(Status, OkStatus) {
 | 
				
			||||||
 | 
					  absl::Status status = absl::OkStatus();
 | 
				
			||||||
 | 
					  EXPECT_TRUE(status.ok());
 | 
				
			||||||
 | 
					  EXPECT_EQ(absl::StatusCode::kOk, status.code());
 | 
				
			||||||
 | 
					  EXPECT_EQ("", status.message());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(Status, ConstructorWithCodeMessage) {
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    absl::Status status(absl::StatusCode::kCancelled, "");
 | 
				
			||||||
 | 
					    EXPECT_FALSE(status.ok());
 | 
				
			||||||
 | 
					    EXPECT_EQ(absl::StatusCode::kCancelled, status.code());
 | 
				
			||||||
 | 
					    EXPECT_EQ("", status.message());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    absl::Status status(absl::StatusCode::kInternal, "message");
 | 
				
			||||||
 | 
					    EXPECT_FALSE(status.ok());
 | 
				
			||||||
 | 
					    EXPECT_EQ(absl::StatusCode::kInternal, status.code());
 | 
				
			||||||
 | 
					    EXPECT_EQ("message", status.message());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(Status, ConstructOutOfRangeCode) {
 | 
				
			||||||
 | 
					  const int kRawCode = 9999;
 | 
				
			||||||
 | 
					  absl::Status status(static_cast<absl::StatusCode>(kRawCode), "");
 | 
				
			||||||
 | 
					  EXPECT_EQ(absl::StatusCode::kUnknown, status.code());
 | 
				
			||||||
 | 
					  EXPECT_EQ(kRawCode, status.raw_code());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					constexpr char kUrl1[] = "url.payload.1";
 | 
				
			||||||
 | 
					constexpr char kUrl2[] = "url.payload.2";
 | 
				
			||||||
 | 
					constexpr char kUrl3[] = "url.payload.3";
 | 
				
			||||||
 | 
					constexpr char kUrl4[] = "url.payload.xx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					constexpr char kPayload1[] = "aaaaa";
 | 
				
			||||||
 | 
					constexpr char kPayload2[] = "bbbbb";
 | 
				
			||||||
 | 
					constexpr char kPayload3[] = "ccccc";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using PayloadsVec = std::vector<std::pair<std::string, absl::Cord>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(Status, TestGetSetPayload) {
 | 
				
			||||||
 | 
					  absl::Status ok_status = absl::OkStatus();
 | 
				
			||||||
 | 
					  ok_status.SetPayload(kUrl1, absl::Cord(kPayload1));
 | 
				
			||||||
 | 
					  ok_status.SetPayload(kUrl2, absl::Cord(kPayload2));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  EXPECT_FALSE(ok_status.GetPayload(kUrl1));
 | 
				
			||||||
 | 
					  EXPECT_FALSE(ok_status.GetPayload(kUrl2));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  absl::Status bad_status(absl::StatusCode::kInternal, "fail");
 | 
				
			||||||
 | 
					  bad_status.SetPayload(kUrl1, absl::Cord(kPayload1));
 | 
				
			||||||
 | 
					  bad_status.SetPayload(kUrl2, absl::Cord(kPayload2));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  EXPECT_THAT(bad_status.GetPayload(kUrl1), Optional(Eq(kPayload1)));
 | 
				
			||||||
 | 
					  EXPECT_THAT(bad_status.GetPayload(kUrl2), Optional(Eq(kPayload2)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  EXPECT_FALSE(bad_status.GetPayload(kUrl3));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bad_status.SetPayload(kUrl1, absl::Cord(kPayload3));
 | 
				
			||||||
 | 
					  EXPECT_THAT(bad_status.GetPayload(kUrl1), Optional(Eq(kPayload3)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Testing dynamically generated type_url
 | 
				
			||||||
 | 
					  bad_status.SetPayload(absl::StrCat(kUrl1, ".1"), absl::Cord(kPayload1));
 | 
				
			||||||
 | 
					  EXPECT_THAT(bad_status.GetPayload(absl::StrCat(kUrl1, ".1")),
 | 
				
			||||||
 | 
					              Optional(Eq(kPayload1)));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(Status, TestErasePayload) {
 | 
				
			||||||
 | 
					  absl::Status bad_status(absl::StatusCode::kInternal, "fail");
 | 
				
			||||||
 | 
					  bad_status.SetPayload(kUrl1, absl::Cord(kPayload1));
 | 
				
			||||||
 | 
					  bad_status.SetPayload(kUrl2, absl::Cord(kPayload2));
 | 
				
			||||||
 | 
					  bad_status.SetPayload(kUrl3, absl::Cord(kPayload3));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  EXPECT_FALSE(bad_status.ErasePayload(kUrl4));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  EXPECT_TRUE(bad_status.GetPayload(kUrl2));
 | 
				
			||||||
 | 
					  EXPECT_TRUE(bad_status.ErasePayload(kUrl2));
 | 
				
			||||||
 | 
					  EXPECT_FALSE(bad_status.GetPayload(kUrl2));
 | 
				
			||||||
 | 
					  EXPECT_FALSE(bad_status.ErasePayload(kUrl2));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  EXPECT_TRUE(bad_status.ErasePayload(kUrl1));
 | 
				
			||||||
 | 
					  EXPECT_TRUE(bad_status.ErasePayload(kUrl3));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bad_status.SetPayload(kUrl1, absl::Cord(kPayload1));
 | 
				
			||||||
 | 
					  EXPECT_TRUE(bad_status.ErasePayload(kUrl1));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(Status, TestComparePayloads) {
 | 
				
			||||||
 | 
					  absl::Status bad_status1(absl::StatusCode::kInternal, "fail");
 | 
				
			||||||
 | 
					  bad_status1.SetPayload(kUrl1, absl::Cord(kPayload1));
 | 
				
			||||||
 | 
					  bad_status1.SetPayload(kUrl2, absl::Cord(kPayload2));
 | 
				
			||||||
 | 
					  bad_status1.SetPayload(kUrl3, absl::Cord(kPayload3));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  absl::Status bad_status2(absl::StatusCode::kInternal, "fail");
 | 
				
			||||||
 | 
					  bad_status2.SetPayload(kUrl2, absl::Cord(kPayload2));
 | 
				
			||||||
 | 
					  bad_status2.SetPayload(kUrl3, absl::Cord(kPayload3));
 | 
				
			||||||
 | 
					  bad_status2.SetPayload(kUrl1, absl::Cord(kPayload1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  EXPECT_EQ(bad_status1, bad_status2);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PayloadsVec AllVisitedPayloads(const absl::Status& s) {
 | 
				
			||||||
 | 
					  PayloadsVec result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  s.ForEachPayload([&](absl::string_view type_url, const absl::Cord& payload) {
 | 
				
			||||||
 | 
					    result.push_back(std::make_pair(std::string(type_url), payload));
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(Status, TestForEachPayload) {
 | 
				
			||||||
 | 
					  absl::Status bad_status(absl::StatusCode::kInternal, "fail");
 | 
				
			||||||
 | 
					  bad_status.SetPayload(kUrl1, absl::Cord(kPayload1));
 | 
				
			||||||
 | 
					  bad_status.SetPayload(kUrl2, absl::Cord(kPayload2));
 | 
				
			||||||
 | 
					  bad_status.SetPayload(kUrl3, absl::Cord(kPayload3));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int count = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bad_status.ForEachPayload(
 | 
				
			||||||
 | 
					      [&count](absl::string_view, const absl::Cord&) { ++count; });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  EXPECT_EQ(count, 3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  PayloadsVec expected_payloads = {{kUrl1, absl::Cord(kPayload1)},
 | 
				
			||||||
 | 
					                                   {kUrl2, absl::Cord(kPayload2)},
 | 
				
			||||||
 | 
					                                   {kUrl3, absl::Cord(kPayload3)}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Test that we visit all the payloads in the status.
 | 
				
			||||||
 | 
					  PayloadsVec visited_payloads = AllVisitedPayloads(bad_status);
 | 
				
			||||||
 | 
					  EXPECT_THAT(visited_payloads, UnorderedElementsAreArray(expected_payloads));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Test that visitation order is not consistent between run.
 | 
				
			||||||
 | 
					  std::vector<absl::Status> scratch;
 | 
				
			||||||
 | 
					  while (true) {
 | 
				
			||||||
 | 
					    scratch.emplace_back(absl::StatusCode::kInternal, "fail");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    scratch.back().SetPayload(kUrl1, absl::Cord(kPayload1));
 | 
				
			||||||
 | 
					    scratch.back().SetPayload(kUrl2, absl::Cord(kPayload2));
 | 
				
			||||||
 | 
					    scratch.back().SetPayload(kUrl3, absl::Cord(kPayload3));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (AllVisitedPayloads(scratch.back()) != visited_payloads) {
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(Status, ToString) {
 | 
				
			||||||
 | 
					  absl::Status s(absl::StatusCode::kInternal, "fail");
 | 
				
			||||||
 | 
					  EXPECT_EQ("INTERNAL: fail", s.ToString());
 | 
				
			||||||
 | 
					  s.SetPayload("foo", absl::Cord("bar"));
 | 
				
			||||||
 | 
					  EXPECT_EQ("INTERNAL: fail [foo='bar']", s.ToString());
 | 
				
			||||||
 | 
					  s.SetPayload("bar", absl::Cord("\377"));
 | 
				
			||||||
 | 
					  EXPECT_THAT(s.ToString(),
 | 
				
			||||||
 | 
					              AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"),
 | 
				
			||||||
 | 
					                    HasSubstr("[bar='\\xff']")));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(Status, CopyConstructor) {
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    absl::Status status;
 | 
				
			||||||
 | 
					    absl::Status copy(status);
 | 
				
			||||||
 | 
					    EXPECT_EQ(copy, status);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    absl::Status status(absl::StatusCode::kInvalidArgument, "message");
 | 
				
			||||||
 | 
					    absl::Status copy(status);
 | 
				
			||||||
 | 
					    EXPECT_EQ(copy, status);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    absl::Status status(absl::StatusCode::kInvalidArgument, "message");
 | 
				
			||||||
 | 
					    status.SetPayload(kUrl1, absl::Cord(kPayload1));
 | 
				
			||||||
 | 
					    absl::Status copy(status);
 | 
				
			||||||
 | 
					    EXPECT_EQ(copy, status);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(Status, CopyAssignment) {
 | 
				
			||||||
 | 
					  absl::Status assignee;
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    absl::Status status;
 | 
				
			||||||
 | 
					    assignee = status;
 | 
				
			||||||
 | 
					    EXPECT_EQ(assignee, status);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    absl::Status status(absl::StatusCode::kInvalidArgument, "message");
 | 
				
			||||||
 | 
					    assignee = status;
 | 
				
			||||||
 | 
					    EXPECT_EQ(assignee, status);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    absl::Status status(absl::StatusCode::kInvalidArgument, "message");
 | 
				
			||||||
 | 
					    status.SetPayload(kUrl1, absl::Cord(kPayload1));
 | 
				
			||||||
 | 
					    assignee = status;
 | 
				
			||||||
 | 
					    EXPECT_EQ(assignee, status);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(Status, MoveConstructor) {
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    absl::Status status;
 | 
				
			||||||
 | 
					    absl::Status copy(absl::Status{});
 | 
				
			||||||
 | 
					    EXPECT_EQ(copy, status);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    absl::Status status(absl::StatusCode::kInvalidArgument, "message");
 | 
				
			||||||
 | 
					    absl::Status copy(
 | 
				
			||||||
 | 
					        absl::Status(absl::StatusCode::kInvalidArgument, "message"));
 | 
				
			||||||
 | 
					    EXPECT_EQ(copy, status);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    absl::Status status(absl::StatusCode::kInvalidArgument, "message");
 | 
				
			||||||
 | 
					    status.SetPayload(kUrl1, absl::Cord(kPayload1));
 | 
				
			||||||
 | 
					    absl::Status copy1(status);
 | 
				
			||||||
 | 
					    absl::Status copy2(std::move(status));
 | 
				
			||||||
 | 
					    EXPECT_EQ(copy1, copy2);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(Status, MoveAssignment) {
 | 
				
			||||||
 | 
					  absl::Status assignee;
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    absl::Status status;
 | 
				
			||||||
 | 
					    assignee = absl::Status();
 | 
				
			||||||
 | 
					    EXPECT_EQ(assignee, status);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    absl::Status status(absl::StatusCode::kInvalidArgument, "message");
 | 
				
			||||||
 | 
					    assignee = absl::Status(absl::StatusCode::kInvalidArgument, "message");
 | 
				
			||||||
 | 
					    EXPECT_EQ(assignee, status);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    absl::Status status(absl::StatusCode::kInvalidArgument, "message");
 | 
				
			||||||
 | 
					    status.SetPayload(kUrl1, absl::Cord(kPayload1));
 | 
				
			||||||
 | 
					    absl::Status copy(status);
 | 
				
			||||||
 | 
					    assignee = std::move(status);
 | 
				
			||||||
 | 
					    EXPECT_EQ(assignee, copy);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(Status, Update) {
 | 
				
			||||||
 | 
					  absl::Status s;
 | 
				
			||||||
 | 
					  s.Update(absl::OkStatus());
 | 
				
			||||||
 | 
					  EXPECT_TRUE(s.ok());
 | 
				
			||||||
 | 
					  const absl::Status a(absl::StatusCode::kCancelled, "message");
 | 
				
			||||||
 | 
					  s.Update(a);
 | 
				
			||||||
 | 
					  EXPECT_EQ(s, a);
 | 
				
			||||||
 | 
					  const absl::Status b(absl::StatusCode::kInternal, "other message");
 | 
				
			||||||
 | 
					  s.Update(b);
 | 
				
			||||||
 | 
					  EXPECT_EQ(s, a);
 | 
				
			||||||
 | 
					  s.Update(absl::OkStatus());
 | 
				
			||||||
 | 
					  EXPECT_EQ(s, a);
 | 
				
			||||||
 | 
					  EXPECT_FALSE(s.ok());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(Status, Equality) {
 | 
				
			||||||
 | 
					  absl::Status ok;
 | 
				
			||||||
 | 
					  absl::Status no_payload = absl::CancelledError("no payload");
 | 
				
			||||||
 | 
					  absl::Status one_payload = absl::InvalidArgumentError("one payload");
 | 
				
			||||||
 | 
					  one_payload.SetPayload(kUrl1, absl::Cord(kPayload1));
 | 
				
			||||||
 | 
					  absl::Status two_payloads = one_payload;
 | 
				
			||||||
 | 
					  two_payloads.SetPayload(kUrl2, absl::Cord(kPayload2));
 | 
				
			||||||
 | 
					  const std::array<absl::Status, 4> status_arr = {ok, no_payload, one_payload,
 | 
				
			||||||
 | 
					                                                  two_payloads};
 | 
				
			||||||
 | 
					  for (int i = 0; i < status_arr.size(); i++) {
 | 
				
			||||||
 | 
					    for (int j = 0; j < status_arr.size(); j++) {
 | 
				
			||||||
 | 
					      if (i == j) {
 | 
				
			||||||
 | 
					        EXPECT_TRUE(status_arr[i] == status_arr[j]);
 | 
				
			||||||
 | 
					        EXPECT_FALSE(status_arr[i] != status_arr[j]);
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        EXPECT_TRUE(status_arr[i] != status_arr[j]);
 | 
				
			||||||
 | 
					        EXPECT_FALSE(status_arr[i] == status_arr[j]);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(Status, Swap) {
 | 
				
			||||||
 | 
					  auto test_swap = [](const absl::Status& s1, const absl::Status& s2) {
 | 
				
			||||||
 | 
					    absl::Status copy1 = s1, copy2 = s2;
 | 
				
			||||||
 | 
					    swap(copy1, copy2);
 | 
				
			||||||
 | 
					    EXPECT_EQ(copy1, s2);
 | 
				
			||||||
 | 
					    EXPECT_EQ(copy2, s1);
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  const absl::Status ok;
 | 
				
			||||||
 | 
					  const absl::Status no_payload(absl::StatusCode::kAlreadyExists, "no payload");
 | 
				
			||||||
 | 
					  absl::Status with_payload(absl::StatusCode::kInternal, "with payload");
 | 
				
			||||||
 | 
					  with_payload.SetPayload(kUrl1, absl::Cord(kPayload1));
 | 
				
			||||||
 | 
					  test_swap(ok, no_payload);
 | 
				
			||||||
 | 
					  test_swap(no_payload, ok);
 | 
				
			||||||
 | 
					  test_swap(ok, with_payload);
 | 
				
			||||||
 | 
					  test_swap(with_payload, ok);
 | 
				
			||||||
 | 
					  test_swap(no_payload, with_payload);
 | 
				
			||||||
 | 
					  test_swap(with_payload, no_payload);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}  // namespace
 | 
				
			||||||
| 
						 | 
					@ -96,10 +96,10 @@ TEST_F(FormatArgImplTest, WorksWithCharArraysOfUnknownSize) {
 | 
				
			||||||
  std::string s;
 | 
					  std::string s;
 | 
				
			||||||
  FormatSinkImpl sink(&s);
 | 
					  FormatSinkImpl sink(&s);
 | 
				
			||||||
  ConversionSpec conv;
 | 
					  ConversionSpec conv;
 | 
				
			||||||
  conv.set_conv(ConversionChar::s);
 | 
					  FormatConversionSpecImplFriend::SetConversionChar(ConversionChar::s, &conv);
 | 
				
			||||||
  conv.set_flags(Flags());
 | 
					  FormatConversionSpecImplFriend::SetFlags(Flags(), &conv);
 | 
				
			||||||
  conv.set_width(-1);
 | 
					  FormatConversionSpecImplFriend::SetWidth(-1, &conv);
 | 
				
			||||||
  conv.set_precision(-1);
 | 
					  FormatConversionSpecImplFriend::SetPrecision(-1, &conv);
 | 
				
			||||||
  EXPECT_TRUE(
 | 
					  EXPECT_TRUE(
 | 
				
			||||||
      FormatArgImplFriend::Convert(FormatArgImpl(kMyArray), conv, &sink));
 | 
					      FormatArgImplFriend::Convert(FormatArgImpl(kMyArray), conv, &sink));
 | 
				
			||||||
  sink.Flush();
 | 
					  sink.Flush();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -66,18 +66,22 @@ inline bool ArgContext::Bind(const UnboundConversion* unbound,
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bound->set_width(width);
 | 
					    FormatConversionSpecImplFriend::SetWidth(width, bound);
 | 
				
			||||||
    bound->set_precision(precision);
 | 
					    FormatConversionSpecImplFriend::SetPrecision(precision, bound);
 | 
				
			||||||
    bound->set_flags(unbound->flags);
 | 
					 | 
				
			||||||
    if (force_left)
 | 
					 | 
				
			||||||
      bound->set_left(true);
 | 
					 | 
				
			||||||
  } else {
 | 
					 | 
				
			||||||
    bound->set_flags(unbound->flags);
 | 
					 | 
				
			||||||
    bound->set_width(-1);
 | 
					 | 
				
			||||||
    bound->set_precision(-1);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bound->set_conv(unbound->conv);
 | 
					    if (force_left) {
 | 
				
			||||||
 | 
					      Flags flags = unbound->flags;
 | 
				
			||||||
 | 
					      flags.left = true;
 | 
				
			||||||
 | 
					      FormatConversionSpecImplFriend::SetFlags(flags, bound);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      FormatConversionSpecImplFriend::SetFlags(unbound->flags, bound);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    FormatConversionSpecImplFriend::SetFlags(unbound->flags, bound);
 | 
				
			||||||
 | 
					    FormatConversionSpecImplFriend::SetWidth(-1, bound);
 | 
				
			||||||
 | 
					    FormatConversionSpecImplFriend::SetPrecision(-1, bound);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  FormatConversionSpecImplFriend::SetConversionChar(unbound->conv, bound);
 | 
				
			||||||
  bound->set_arg(arg);
 | 
					  bound->set_arg(arg);
 | 
				
			||||||
  return true;
 | 
					  return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -139,7 +143,8 @@ class SummarizingConverter {
 | 
				
			||||||
    UntypedFormatSpecImpl spec("%d");
 | 
					    UntypedFormatSpecImpl spec("%d");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::ostringstream ss;
 | 
					    std::ostringstream ss;
 | 
				
			||||||
    ss << "{" << Streamable(spec, {*bound.arg()}) << ":" << bound.flags();
 | 
					    ss << "{" << Streamable(spec, {*bound.arg()}) << ":"
 | 
				
			||||||
 | 
					       << FormatConversionSpecImplFriend::FlagsToString(bound);
 | 
				
			||||||
    if (bound.width() >= 0) ss << bound.width();
 | 
					    if (bound.width() >= 0) ss << bound.width();
 | 
				
			||||||
    if (bound.precision() >= 0) ss << "." << bound.precision();
 | 
					    if (bound.precision() >= 0) ss << "." << bound.precision();
 | 
				
			||||||
    ss << bound.conv() << "}";
 | 
					    ss << bound.conv() << "}";
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -260,9 +260,21 @@ inline std::ostream& operator<<(std::ostream& os, FormatConversionChar v) {
 | 
				
			||||||
  return os << c;
 | 
					  return os << c;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct FormatConversionSpecImplFriend;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ConversionSpec {
 | 
					class ConversionSpec {
 | 
				
			||||||
 public:
 | 
					 public:
 | 
				
			||||||
 | 
					  // Deprecated (use has_x_flag() instead).
 | 
				
			||||||
  Flags flags() const { return flags_; }
 | 
					  Flags flags() const { return flags_; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Width and precison are not specified, no flags are set.
 | 
				
			||||||
 | 
					  bool is_basic() const { return flags_.basic; }
 | 
				
			||||||
 | 
					  bool has_left_flag() const { return flags_.left; }
 | 
				
			||||||
 | 
					  bool has_show_pos_flag() const { return flags_.show_pos; }
 | 
				
			||||||
 | 
					  bool has_sign_col_flag() const { return flags_.sign_col; }
 | 
				
			||||||
 | 
					  bool has_alt_flag() const { return flags_.alt; }
 | 
				
			||||||
 | 
					  bool has_zero_flag() const { return flags_.zero; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  FormatConversionChar conv() const {
 | 
					  FormatConversionChar conv() const {
 | 
				
			||||||
    // Keep this field first in the struct . It generates better code when
 | 
					    // Keep this field first in the struct . It generates better code when
 | 
				
			||||||
    // accessing it when ConversionSpec is passed by value in registers.
 | 
					    // accessing it when ConversionSpec is passed by value in registers.
 | 
				
			||||||
| 
						 | 
					@ -277,19 +289,28 @@ class ConversionSpec {
 | 
				
			||||||
  // negative value.
 | 
					  // negative value.
 | 
				
			||||||
  int precision() const { return precision_; }
 | 
					  int precision() const { return precision_; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void set_flags(Flags f) { flags_ = f; }
 | 
					 | 
				
			||||||
  void set_conv(FormatConversionChar c) { conv_ = c; }
 | 
					 | 
				
			||||||
  void set_width(int w) { width_ = w; }
 | 
					 | 
				
			||||||
  void set_precision(int p) { precision_ = p; }
 | 
					 | 
				
			||||||
  void set_left(bool b) { flags_.left = b; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 private:
 | 
					 private:
 | 
				
			||||||
 | 
					  friend struct str_format_internal::FormatConversionSpecImplFriend;
 | 
				
			||||||
  FormatConversionChar conv_ = FormatConversionChar::kNone;
 | 
					  FormatConversionChar conv_ = FormatConversionChar::kNone;
 | 
				
			||||||
  Flags flags_;
 | 
					  Flags flags_;
 | 
				
			||||||
  int width_;
 | 
					  int width_;
 | 
				
			||||||
  int precision_;
 | 
					  int precision_;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct FormatConversionSpecImplFriend final {
 | 
				
			||||||
 | 
					  static void SetFlags(Flags f, ConversionSpec* conv) { conv->flags_ = f; }
 | 
				
			||||||
 | 
					  static void SetConversionChar(FormatConversionChar c, ConversionSpec* conv) {
 | 
				
			||||||
 | 
					    conv->conv_ = c;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  static void SetWidth(int w, ConversionSpec* conv) { conv->width_ = w; }
 | 
				
			||||||
 | 
					  static void SetPrecision(int p, ConversionSpec* conv) {
 | 
				
			||||||
 | 
					    conv->precision_ = p;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  static std::string FlagsToString(const ConversionSpec& spec) {
 | 
				
			||||||
 | 
					    return spec.flags_.ToString();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
constexpr uint64_t FormatConversionCharToConvValue(char conv) {
 | 
					constexpr uint64_t FormatConversionCharToConvValue(char conv) {
 | 
				
			||||||
  return
 | 
					  return
 | 
				
			||||||
#define CONV_SET_CASE(c)                                                     \
 | 
					#define CONV_SET_CASE(c)                                                     \
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,7 +28,7 @@ bool FallbackToSnprintf(const Float v, const ConversionSpec &conv,
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    char *fp = fmt;
 | 
					    char *fp = fmt;
 | 
				
			||||||
    *fp++ = '%';
 | 
					    *fp++ = '%';
 | 
				
			||||||
    fp = CopyStringTo(conv.flags().ToString(), fp);
 | 
					    fp = CopyStringTo(FormatConversionSpecImplFriend::FlagsToString(conv), fp);
 | 
				
			||||||
    fp = CopyStringTo("*.*", fp);
 | 
					    fp = CopyStringTo("*.*", fp);
 | 
				
			||||||
    if (std::is_same<long double, Float>()) {
 | 
					    if (std::is_same<long double, Float>()) {
 | 
				
			||||||
      *fp++ = 'L';
 | 
					      *fp++ = 'L';
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue