error.h 7.14 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
#ifndef AIRMAP_ERROR_H_
#define AIRMAP_ERROR_H_

#include <airmap/do_not_copy_or_move.h>
#include <airmap/optional.h>

#include <cstdint>

#include <iosfwd>
#include <map>
#include <memory>
#include <string>
#include <vector>

namespace airmap {

/// Error models an error raised by an AirMap component.
struct Error {
  /// Value is a discriminated union type wrapping up multiple atomic types and
  /// their composition into a vector or a dictionary.
  class Value {
   public:
    /// Type enumerates all datatypes that can be wrapped in a Value.
    enum class Type {
      undefined,       ///< Marks the undefined type.
      boolean,         ///< Marks a boolean type.
      integer,         ///< Marks an integer type with 64 bits.
      floating_point,  ///< Marks a double-precision floating point number.
      string,          ///< Marks a string.
      blob,            ///< Marks a binary blob.
      dictionary,      ///< Marks a dictionary of values.
      vector           ///< Marks a vector of values.
    };

    /// Value initializes a new Value instance of type undefined.
    explicit Value();
    /// Value initializes a new Value instance of type boolean with 'value'.
    explicit Value(bool value);
    /// Value initializes a new Value instance of type integer with 'value'.
    explicit Value(std::int64_t value);
    /// Value initializes a new Value instance of type floating_point with 'value'.
    explicit Value(double value);
    /// Value initializes a new Value instance of type string with 'value'.
    explicit Value(const std::string& value);
    /// Value initializes a new Value instance of type blob with 'value'.
    explicit Value(const std::vector<std::uint8_t>& value);
    /// Value initializes a new Value instance of type dictionary with 'value'.
    explicit Value(const std::map<Value, Value>& value);
    /// Value initializes a new Value instance of type vector with 'value'.
    explicit Value(const std::vector<Value>& value);
    /// Value copy-constructs a value from 'other'.
    Value(const Value& other);
    /// Value move-constructs a value from 'other'.
    Value(Value&&);
    /// ~Value cleans up all resources by a Value instance.
    ~Value();

    /// operator= assigns type and value from rhs.
    Value& operator=(const Value& rhs);
    /// operator= moves type and value from rhs.
    Value& operator=(Value&& rhs);

    /// type returns the Type of this Value instance.
    Type type() const;

    /// boolean returns the boolean value of this Value instance.
    /// The behavior in case of type() != Type::boolean is undefined.
    bool boolean() const;
    /// integer returns the boolean value of this Value instance.
    /// The behavior in case of type() != Type::integer is undefined.
    std::int64_t integer() const;
    /// floating_point returns the floating point value of this Value instance.
    /// The behavior in case of type() != Type::floating_point is undefined.
    double floating_point() const;
    /// string returns the string value of this Value instance.
    /// The behavior in case of type() != Type::string is undefined.
    const std::string& string() const;
    /// blob returns the blob value of this Value instance.
    /// The behavior in case of type() != Type::blob is undefined.
    const std::vector<std::uint8_t> blob() const;
    /// dictionary returns the dictionary value of this Value instance.
    /// The behavior in case of type() != Type::dictionary is undefined.
    const std::map<Value, Value>& dictionary() const;
    /// vector returns the vector value of this Value instance.
    /// The behavior in case of type() != Type::vector is undefined.
    const std::vector<Value>& vector() const;

   private:
    union Details {
      Details();
      ~Details();

      bool boolean;
      std::int64_t integer;
      double floating_point;
      std::string string;
      std::vector<std::uint8_t> blob;
      std::map<Value, Value> dictionary;
      std::vector<Value> vector;
    };

    Value& construct(bool value);
    Value& construct(std::int64_t value);
    Value& construct(double value);
    Value& construct(const std::string& value);
    Value& construct(std::string&& value);
    Value& construct(const std::vector<std::uint8_t>& value);
    Value& construct(std::vector<std::uint8_t>&& value);
    Value& construct(const std::map<Value, Value>& value);
    Value& construct(std::map<Value, Value>&& value);
    Value& construct(const std::vector<Value>& value);
    Value& construct(std::vector<Value>&& value);
    Value& construct(const Value& value);
    Value& construct(Value&& value);
    Value& destruct();

    Type type_;
    Details details_;
  };

  /// Error initializes a new error instance with 'message'.
  explicit Error();

  /// Error initializes a new error instance with 'message'.
  explicit Error(const std::string& message);

  /// message returns the message describing an error condition.
  const std::string& message() const;
  /// message sets the message of the Error instance to 'message'.
  Error message(const std::string& message) const;
  /// message sets the message of the Error instance to 'message'.
  Error& message(const std::string& message);

  /// description returns the optional description of an error condition.
  const Optional<std::string>& description() const;
  /// clear_description resets the description of the Error instance.
  Error clear_description() const;
  /// clear_description resets the description of the Error instance.
  Error& clear_description();
  /// description sets the description of the Error instance to 'description'.
  Error description(const std::string& description) const;
  /// description sets the description of the Error instance to 'description'.
  Error& description(const std::string& description);

  /// values returns the additional values describing an error condition.
  const std::map<Value, Value>& values() const;
  /// clear_values resets the values of the Error instance.
  Error clear_values() const;
  /// clear_values resets the values of the Error instance.
  Error& clear_values();
  /// value adds the pair (key, value) to the additional values describing an error condition.
  Error value(const Value& key, const Value& value) const;
  /// value adds the pair (key, value) to the additional values describing an error condition.
  Error& value(const Value& key, const Value& value);

 private:
  std::string message_;                ///< Short, human-readable message.
  Optional<std::string> description_;  ///< Detailed description of the error, meant to be used for defect analysis.
  std::map<Value, Value> values_;      ///< Dictionary of additional data attached to the error.
};

/// operator== returns true if both type and value of lhs and rhs compare equal.
bool operator==(const Error::Value& lhs, const Error::Value& rhs);
/// operator< returns true if type and value of lhs compare < than type and value of rhs.
bool operator<(const Error::Value& lhs, const Error::Value& rhs);
/// operator<< inserts 'value' into 'out'.
std::ostream& operator<<(std::ostream& out, const Error::Value& value);
/// operator<< inserts 'error' into 'out'.
std::ostream& operator<<(std::ostream& out, const Error& error);

}  // namespace airmap

#endif  // AIRMAP_ERROR_H_