/* * 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 namespace facebook { namespace xplat { namespace detail { inline std::string toStringHelper() { return ""; } template inline std::string toStringHelper(const T& value, const Rest&... rest) { return std::to_string(value) + toStringHelper(rest...); } template inline std::string toStringHelper(const char* value, const Rest&... rest) { return std::string(value) + toStringHelper(rest...); } template R jsArg1(const folly::dynamic& arg, M asFoo, const T&... desc) { try { return (arg.*asFoo)(); } catch (const folly::TypeError& ex) { throw JsArgumentException( "Error converting JavaScript arg " + toStringHelper(desc...) + " to C++: " + ex.what()); } catch (const std::range_error& ex) { throw JsArgumentException( "Could not convert argument " + toStringHelper(desc...) + " to required type: " + ex.what()); } } } // namespace detail template R jsArg( const folly::dynamic& arg, R (folly::dynamic::*asFoo)() const, const T&... desc) { return detail::jsArg1(arg, asFoo, desc...); } template R jsArg( const folly::dynamic& arg, R (folly::dynamic::*asFoo)() const&, const T&... desc) { return detail::jsArg1(arg, asFoo, desc...); } template // NOLINTNEXTLINE (T62192316) typename detail::is_dynamic::type& jsArgAsDynamic(T&& args, size_t n) { try { return args[n]; } catch (const std::out_of_range& ex) { // Use 1-base counting for argument description. throw JsArgumentException( "JavaScript provided " + std::to_string(args.size()) + " arguments for C++ method which references at least " + std::to_string(n + 1) + " arguments: " + ex.what()); } } template R jsArgN( const folly::dynamic& args, size_t n, R (folly::dynamic::*asFoo)() const) { return jsArg(jsArgAsDynamic(args, n), asFoo, n); } template R jsArgN( const folly::dynamic& args, size_t n, R (folly::dynamic::*asFoo)() const&) { return jsArg(jsArgAsDynamic(args, n), asFoo, n); } namespace detail { // This is a helper for jsArgAsArray and jsArgAsObject. template typename detail::is_dynamic::type& jsArgAsType( T&& args, size_t n, const char* required, bool (folly::dynamic::*isFoo)() const) { T& ret = jsArgAsDynamic(args, n); if ((ret.*isFoo)()) { return ret; } // Use 1-base counting for argument description. throw JsArgumentException( "Argument " + std::to_string(n + 1) + " of type " + ret.typeName() + " is not required type " + required); } } // end namespace detail template typename detail::is_dynamic::type& jsArgAsArray(T&& args, size_t n) { return detail::jsArgAsType(args, n, "Array", &folly::dynamic::isArray); } template typename detail::is_dynamic::type& jsArgAsObject(T&& args, size_t n) { return detail::jsArgAsType(args, n, "Object", &folly::dynamic::isObject); } } // namespace xplat } // namespace facebook