v8-maybe.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // Copyright 2021 the V8 project 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. #ifndef INCLUDE_V8_MAYBE_H_
  5. #define INCLUDE_V8_MAYBE_H_
  6. #include "v8-internal.h" // NOLINT(build/include_directory)
  7. #include "v8config.h" // NOLINT(build/include_directory)
  8. namespace v8 {
  9. namespace api_internal {
  10. // Called when ToChecked is called on an empty Maybe.
  11. V8_EXPORT void FromJustIsNothing();
  12. } // namespace api_internal
  13. /**
  14. * A simple Maybe type, representing an object which may or may not have a
  15. * value, see https://hackage.haskell.org/package/base/docs/Data-Maybe.html.
  16. *
  17. * If an API method returns a Maybe<>, the API method can potentially fail
  18. * either because an exception is thrown, or because an exception is pending,
  19. * e.g. because a previous API call threw an exception that hasn't been caught
  20. * yet, or because a TerminateExecution exception was thrown. In that case, a
  21. * "Nothing" value is returned.
  22. */
  23. template <class T>
  24. class Maybe {
  25. public:
  26. V8_INLINE bool IsNothing() const { return !has_value_; }
  27. V8_INLINE bool IsJust() const { return has_value_; }
  28. /**
  29. * An alias for |FromJust|. Will crash if the Maybe<> is nothing.
  30. */
  31. V8_INLINE T ToChecked() const { return FromJust(); }
  32. /**
  33. * Short-hand for ToChecked(), which doesn't return a value. To be used, where
  34. * the actual value of the Maybe is not needed like Object::Set.
  35. */
  36. V8_INLINE void Check() const {
  37. if (V8_UNLIKELY(!IsJust())) api_internal::FromJustIsNothing();
  38. }
  39. /**
  40. * Converts this Maybe<> to a value of type T. If this Maybe<> is
  41. * nothing (empty), |false| is returned and |out| is left untouched.
  42. */
  43. V8_WARN_UNUSED_RESULT V8_INLINE bool To(T* out) const {
  44. if (V8_LIKELY(IsJust())) *out = value_;
  45. return IsJust();
  46. }
  47. /**
  48. * Converts this Maybe<> to a value of type T. If this Maybe<> is
  49. * nothing (empty), V8 will crash the process.
  50. */
  51. V8_INLINE T FromJust() const {
  52. if (V8_UNLIKELY(!IsJust())) api_internal::FromJustIsNothing();
  53. return value_;
  54. }
  55. /**
  56. * Converts this Maybe<> to a value of type T, using a default value if this
  57. * Maybe<> is nothing (empty).
  58. */
  59. V8_INLINE T FromMaybe(const T& default_value) const {
  60. return has_value_ ? value_ : default_value;
  61. }
  62. V8_INLINE bool operator==(const Maybe& other) const {
  63. return (IsJust() == other.IsJust()) &&
  64. (!IsJust() || FromJust() == other.FromJust());
  65. }
  66. V8_INLINE bool operator!=(const Maybe& other) const {
  67. return !operator==(other);
  68. }
  69. private:
  70. Maybe() : has_value_(false) {}
  71. explicit Maybe(const T& t) : has_value_(true), value_(t) {}
  72. bool has_value_;
  73. T value_;
  74. template <class U>
  75. friend Maybe<U> Nothing();
  76. template <class U>
  77. friend Maybe<U> Just(const U& u);
  78. };
  79. template <class T>
  80. inline Maybe<T> Nothing() {
  81. return Maybe<T>();
  82. }
  83. template <class T>
  84. inline Maybe<T> Just(const T& t) {
  85. return Maybe<T>(t);
  86. }
  87. // A template specialization of Maybe<T> for the case of T = void.
  88. template <>
  89. class Maybe<void> {
  90. public:
  91. V8_INLINE bool IsNothing() const { return !is_valid_; }
  92. V8_INLINE bool IsJust() const { return is_valid_; }
  93. V8_INLINE bool operator==(const Maybe& other) const {
  94. return IsJust() == other.IsJust();
  95. }
  96. V8_INLINE bool operator!=(const Maybe& other) const {
  97. return !operator==(other);
  98. }
  99. private:
  100. struct JustTag {};
  101. Maybe() : is_valid_(false) {}
  102. explicit Maybe(JustTag) : is_valid_(true) {}
  103. bool is_valid_;
  104. template <class U>
  105. friend Maybe<U> Nothing();
  106. friend Maybe<void> JustVoid();
  107. };
  108. inline Maybe<void> JustVoid() { return Maybe<void>(Maybe<void>::JustTag()); }
  109. } // namespace v8
  110. #endif // INCLUDE_V8_MAYBE_H_