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