Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-21 10:05:25

0001 // Copyright 2021 the V8 project authors. All rights reserved.
0002 // Use of this source code is governed by a BSD-style license that can be
0003 // found in the LICENSE file.
0004 
0005 #ifndef INCLUDE_V8_MAYBE_H_
0006 #define INCLUDE_V8_MAYBE_H_
0007 
0008 #include <type_traits>
0009 #include <utility>
0010 
0011 #include "v8-internal.h"  // NOLINT(build/include_directory)
0012 #include "v8config.h"     // NOLINT(build/include_directory)
0013 
0014 namespace v8 {
0015 
0016 namespace api_internal {
0017 // Called when ToChecked is called on an empty Maybe.
0018 V8_EXPORT void FromJustIsNothing();
0019 }  // namespace api_internal
0020 
0021 /**
0022  * A simple Maybe type, representing an object which may or may not have a
0023  * value, see https://hackage.haskell.org/package/base/docs/Data-Maybe.html.
0024  *
0025  * If an API method returns a Maybe<>, the API method can potentially fail
0026  * either because an exception is thrown, or because an exception is pending,
0027  * e.g. because a previous API call threw an exception that hasn't been caught
0028  * yet, or because a TerminateExecution exception was thrown. In that case, a
0029  * "Nothing" value is returned.
0030  */
0031 template <class T>
0032 class Maybe {
0033  public:
0034   V8_INLINE bool IsNothing() const { return !has_value_; }
0035   V8_INLINE bool IsJust() const { return has_value_; }
0036 
0037   /**
0038    * An alias for |FromJust|. Will crash if the Maybe<> is nothing.
0039    */
0040   V8_INLINE T ToChecked() const { return FromJust(); }
0041 
0042   /**
0043    * Short-hand for ToChecked(), which doesn't return a value. To be used, where
0044    * the actual value of the Maybe is not needed like Object::Set.
0045    */
0046   V8_INLINE void Check() const {
0047     if (V8_UNLIKELY(!IsJust())) api_internal::FromJustIsNothing();
0048   }
0049 
0050   /**
0051    * Converts this Maybe<> to a value of type T. If this Maybe<> is
0052    * nothing (empty), |false| is returned and |out| is left untouched.
0053    */
0054   V8_WARN_UNUSED_RESULT V8_INLINE bool To(T* out) const {
0055     if (V8_LIKELY(IsJust())) *out = value_;
0056     return IsJust();
0057   }
0058 
0059   /**
0060    * Converts this Maybe<> to a value of type T. If this Maybe<> is
0061    * nothing (empty), V8 will crash the process.
0062    */
0063   V8_INLINE T FromJust() const& {
0064     if (V8_UNLIKELY(!IsJust())) api_internal::FromJustIsNothing();
0065     return value_;
0066   }
0067 
0068   /**
0069    * Converts this Maybe<> to a value of type T. If this Maybe<> is
0070    * nothing (empty), V8 will crash the process.
0071    */
0072   V8_INLINE T FromJust() && {
0073     if (V8_UNLIKELY(!IsJust())) api_internal::FromJustIsNothing();
0074     return std::move(value_);
0075   }
0076 
0077   /**
0078    * Converts this Maybe<> to a value of type T, using a default value if this
0079    * Maybe<> is nothing (empty).
0080    */
0081   V8_INLINE T FromMaybe(const T& default_value) const {
0082     return has_value_ ? value_ : default_value;
0083   }
0084 
0085   V8_INLINE bool operator==(const Maybe& other) const {
0086     return (IsJust() == other.IsJust()) &&
0087            (!IsJust() || FromJust() == other.FromJust());
0088   }
0089 
0090   V8_INLINE bool operator!=(const Maybe& other) const {
0091     return !operator==(other);
0092   }
0093 
0094  private:
0095   Maybe() : has_value_(false) {}
0096   explicit Maybe(const T& t) : has_value_(true), value_(t) {}
0097   explicit Maybe(T&& t) : has_value_(true), value_(std::move(t)) {}
0098 
0099   bool has_value_;
0100   T value_;
0101 
0102   template <class U>
0103   friend Maybe<U> Nothing();
0104   template <class U>
0105   friend Maybe<U> Just(const U& u);
0106   template <class U, std::enable_if_t<!std::is_lvalue_reference_v<U>>*>
0107   friend Maybe<U> Just(U&& u);
0108 };
0109 
0110 template <class T>
0111 inline Maybe<T> Nothing() {
0112   return Maybe<T>();
0113 }
0114 
0115 template <class T>
0116 inline Maybe<T> Just(const T& t) {
0117   return Maybe<T>(t);
0118 }
0119 
0120 // Don't use forwarding references here but instead use two overloads.
0121 // Forwarding references only work when type deduction takes place, which is not
0122 // the case for callsites such as Just<Type>(t).
0123 template <class T, std::enable_if_t<!std::is_lvalue_reference_v<T>>* = nullptr>
0124 inline Maybe<T> Just(T&& t) {
0125   return Maybe<T>(std::move(t));
0126 }
0127 
0128 // A template specialization of Maybe<T> for the case of T = void.
0129 template <>
0130 class Maybe<void> {
0131  public:
0132   V8_INLINE bool IsNothing() const { return !is_valid_; }
0133   V8_INLINE bool IsJust() const { return is_valid_; }
0134 
0135   V8_INLINE bool operator==(const Maybe& other) const {
0136     return IsJust() == other.IsJust();
0137   }
0138 
0139   V8_INLINE bool operator!=(const Maybe& other) const {
0140     return !operator==(other);
0141   }
0142 
0143  private:
0144   struct JustTag {};
0145 
0146   Maybe() : is_valid_(false) {}
0147   explicit Maybe(JustTag) : is_valid_(true) {}
0148 
0149   bool is_valid_;
0150 
0151   template <class U>
0152   friend Maybe<U> Nothing();
0153   friend Maybe<void> JustVoid();
0154 };
0155 
0156 inline Maybe<void> JustVoid() { return Maybe<void>(Maybe<void>::JustTag()); }
0157 
0158 }  // namespace v8
0159 
0160 #endif  // INCLUDE_V8_MAYBE_H_