/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #pragma once #include #include namespace facebook::react::bridging { // std::remove_cvref_t is not available until C++20. template using remove_cvref_t = std::remove_cv_t>; template inline constexpr bool is_jsi_v = std::is_same_v> || std::is_same_v> || std::is_base_of_v>; template struct ConverterBase { ConverterBase(jsi::Runtime &rt, T &&value) : rt_(rt), value_(std::forward(value)) {} operator T() && { return std::forward(this->value_); } protected: jsi::Runtime &rt_; T value_; }; template struct Converter : public ConverterBase { using ConverterBase::ConverterBase; }; template <> struct Converter : public ConverterBase { using ConverterBase::ConverterBase; operator jsi::String() && { return std::move(value_).asString(rt_); } operator jsi::Object() && { return std::move(value_).asObject(rt_); } operator jsi::Array() && { return std::move(value_).asObject(rt_).asArray(rt_); } operator jsi::Function() && { return std::move(value_).asObject(rt_).asFunction(rt_); } }; template <> struct Converter : public ConverterBase { using ConverterBase::ConverterBase; operator jsi::Array() && { return std::move(value_).asArray(rt_); } operator jsi::Function() && { return std::move(value_).asFunction(rt_); } }; template struct Converter { Converter(jsi::Runtime &rt, T &value) : rt_(rt), value_(value) {} operator T() && { // Copy the reference into a Value that then can be moved from. return Converter(rt_, jsi::Value(rt_, value_)); } template < typename U, // Ensure the non-reference type can be converted to the desired type. std::enable_if_t< std::is_convertible_v>, U>, int> = 0> operator U() && { return Converter(rt_, jsi::Value(rt_, value_)); } private: jsi::Runtime &rt_; const T &value_; }; template , int> = 0> auto convert(jsi::Runtime &rt, T &&value) { return Converter(rt, std::forward(value)); } template , int> = 0> auto convert(jsi::Runtime &rt, T &&value) { return value; } template auto convert(jsi::Runtime &rt, Converter &&converter) { return std::move(converter); } } // namespace facebook::react::bridging