1 // Copyright 2015 The Weave Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef LIBWEAVE_INCLUDE_WEAVE_ERROR_H_
6 #define LIBWEAVE_INCLUDE_WEAVE_ERROR_H_
7 
8 #include <memory>
9 #include <string>
10 
11 #include <base/callback.h>
12 #include <base/compiler_specific.h>
13 #include <base/location.h>
14 #include <base/macros.h>
15 #include <weave/export.h>
16 
17 namespace weave {
18 
19 class Error;  // Forward declaration.
20 
21 using ErrorPtr = std::unique_ptr<Error>;
22 
23 class LIBWEAVE_EXPORT Error final {
24  public:
25   ~Error() = default;
26 
27   class AddToTypeProxy {
28    public:
29     operator bool() const { return false; }
30 
31     template <class T>
32     operator std::unique_ptr<T>() const {
33       return nullptr;
34     }
35 
36     template <class T>
37     operator T*() const {
38       return nullptr;
39     }
40   };
41 
42   // Creates an instance of Error class.
43   static ErrorPtr Create(const tracked_objects::Location& location,
44                          const std::string& code,
45                          const std::string& message);
46   static ErrorPtr Create(const tracked_objects::Location& location,
47                          const std::string& code,
48                          const std::string& message,
49                          ErrorPtr inner_error);
50   // If |error| is not nullptr, creates another instance of Error class,
51   // initializes it with specified arguments and adds it to the head of
52   // the error chain pointed to by |error|.
53   static AddToTypeProxy AddTo(ErrorPtr* error,
54                               const tracked_objects::Location& location,
55                               const std::string& code,
56                               const std::string& message);
57   // Same as the Error::AddTo above, but allows to pass in a printf-like
58   // format string and optional parameters to format the error message.
59   static AddToTypeProxy AddToPrintf(ErrorPtr* error,
60                                     const tracked_objects::Location& location,
61                                     const std::string& code,
62                                     const char* format,
63                                     ...) PRINTF_FORMAT(4, 5);
64 
65   // Clones error with all inner errors.
66   ErrorPtr Clone() const;
67 
68   // Returns the error code and message
GetCode()69   const std::string& GetCode() const { return code_; }
GetMessage()70   const std::string& GetMessage() const { return message_; }
71 
72   // Returns the location of the error in the source code.
GetLocation()73   const tracked_objects::LocationSnapshot& GetLocation() const {
74     return location_;
75   }
76 
77   // Checks if this or any of the inner errors in the chain matches the
78   // specified error code.
79   bool HasError(const std::string& code) const;
80 
81   // Gets a pointer to the inner error, if present. Returns nullptr otherwise.
GetInnerError()82   const Error* GetInnerError() const { return inner_error_.get(); }
83 
84   // Gets a pointer to the first error occurred.
85   // Returns itself if no inner error are available.
86   const Error* GetFirstError() const;
87 
88   // Finds an error with the given code in the error chain stating at
89   // |error_chain_start|. Returns the pointer to the first matching error
90   // object.
91   // Returns nullptr if no match is found or if |error_chain_start| is nullptr.
92   static const Error* FindError(const Error* error_chain_start,
93                                 const std::string& code);
94 
95  protected:
96   // Constructor is protected since this object is supposed to be
97   // created via the Create factory methods.
98   Error(const tracked_objects::Location& location,
99         const std::string& code,
100         const std::string& message,
101         ErrorPtr inner_error);
102 
103   Error(const tracked_objects::LocationSnapshot& location,
104         const std::string& code,
105         const std::string& message,
106         ErrorPtr inner_error);
107 
108   // Error code. A unique error code identifier.
109   std::string code_;
110   // Human-readable error message.
111   std::string message_;
112   // Error origin in the source code.
113   tracked_objects::LocationSnapshot location_;
114   // Pointer to inner error, if any. This forms a chain of errors.
115   ErrorPtr inner_error_;
116 
117  private:
118   DISALLOW_COPY_AND_ASSIGN(Error);
119 };
120 
121 // Default callback type for async operations.
122 // Function having this callback as argument should call the callback exactly
123 // one time.
124 // Successfully completed operation should run callback with |error| set to
125 // null. Failed operation should run callback with |error| containing error
126 // details.
127 using DoneCallback = base::Callback<void(ErrorPtr error)>;
128 
129 }  // namespace weave
130 
131 #endif  // LIBWEAVE_INCLUDE_WEAVE_ERROR_H_
132