chromium/components/reporting/util/status.h

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_REPORTING_UTIL_STATUS_H_
#define COMPONENTS_REPORTING_UTIL_STATUS_H_

#include <cstdint>
#include <iosfwd>
#include <string>
#include <utility>

#include "base/check.h"
#include "base/functional/callback.h"
#include "base/functional/callback_forward.h"
#include "base/functional/callback_helpers.h"
#include "components/reporting/proto/synced/status.pb.h"

namespace reporting {
namespace error {
// These values must match error codes defined in google/rpc/code.proto
// This also must match the order EnterpriseCloudReportingStatusCode at
// tools/metrics/histograms/enums.xml and the integer of option shouldn't be
// changed.
// If two assumptions above conflict, please create a new enum for metrics
// purposes and keep the original order.
enum Code : int32_t {};
}  // namespace error

class [[nodiscard]] Status {};

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

// Auto runner wrapping a provided callback.
// When it goes out of scope and the callback has not been run, it is invoked
// with the `failed` value. Intended to be used in code like:
//
//   class Handler {
//    public:
//     using ResultCb = base::OnceCallback<void(Status)>;
//     Handler(...) {...}
//     void Method(..., Scoped<ResultCb> done) {
//       ...
//       std::move(done).Run(Status::StatusOK());
//     }
//   };
//   auto handler = std::make_unique<Handler>(...);
//   task_runner->PostTask(
//       FROM_HERE,
//       base::BindOnce(&Handler::Method, handler->GetWeakPtr(), ...,
//                      Scoped<ResultCb>(
//                          base::BindOnce(&Done, ...),
//                          Status(error::UNAVAILABLE,
//                                 "Handler has been destructed"))));
//
// If at run time `handler` is destructed before `Handler::Method` is executed,
// `Done` will still be called with:
//     Status(error::UNAVAILABLE, "Handler has been destructed")
//  as a result.
//
// If `Done` expects something else than `Status`, `Scoped` needs to be
// tagged with respective type - e.g.
//                      Scoped<ResultCb, StatusOr<Result>>(
//                          base::BindOnce(&Done, ...),
//                          base::unexpected(Status(error::UNAVAILABLE,
//                                           "Handler has been destructed")))
//

template <typename Failed = Status>
class Scoped : public base::OnceCallback<void(Failed)> {};
}  // namespace reporting

#endif  // COMPONENTS_REPORTING_UTIL_STATUS_H_