PHP WebShell
Текущая директория: /usr/lib/node_modules/bitgo/node_modules/react-native/ReactCommon/react/renderer/core
Просмотр файла: RawValue.h
/*
* 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 <unordered_map>
#include <variant>
#include <folly/dynamic.h>
#include <jsi/JSIDynamic.h>
#include <jsi/jsi.h>
#include <react/renderer/core/RawPropsPrimitives.h>
#include <react/debug/react_native_assert.h>
namespace facebook::react {
class RawPropsParser;
/*
* `RawValue` abstracts some arbitrary complex data structure similar to JSON.
* `RawValue` supports explicit conversion to: `bool`, `int`, `int64_t`,
* `float`, `double`, `string`, and `vector` & `map` of those types and itself.
*
* The main intention of the class is to abstract React props parsing infra from
* JSI, to enable support for any non-JSI-based data sources. The particular
* implementation of the interface is a very slim abstraction around
* `folly::dynamic` though.
* In the near future, this class will hold a `jsi::Runtime` and `jsi::Value`
* pair instead of `folly::dynamic`.
*
* How `RawValue` is different from `JSI::Value`:
* * `RawValue` provides much more scoped API without any references to
* JavaScript specifics.
* * The API is much more C++-idiomatic and easy to use from C++ code.
* * The API prevents access to JSI/JavaScript internals from prop-parsing
* code.
* * The `RawValue` is not copyable nor thread-safe, which prevent
* misuse and accidental performance problems.
*
* How `RawValue` is different from `folly::dynamic`:
* * `RawValue` is a lazy data structure, it does not copy all content inside,
* it provides efficient SAX-like access to the data.
* * `RawValue` has more static and C++-idiomatic API.
* * The `RawValue` is not copyable nor thread-safe, which prevent
* misuse and accidental performance problems.
*/
class RawValue {
public:
/*
* Constructors.
*/
RawValue() noexcept : value_(folly::dynamic(nullptr)) {}
RawValue(RawValue&& other) noexcept : value_(std::move(other.value_)) {}
RawValue& operator=(RawValue&& other) noexcept {
if (this != &other) {
value_ = std::move(other.value_);
}
return *this;
}
explicit RawValue(jsi::Runtime& runtime, const jsi::Value& value) noexcept
: value_(std::make_pair(&runtime, jsi::Value(runtime, value))) {}
explicit RawValue(jsi::Runtime& runtime, jsi::Value&& value) noexcept
: value_(std::make_pair(&runtime, std::move(value))) {}
explicit RawValue(const folly::dynamic& dynamic) noexcept : value_(dynamic) {}
explicit RawValue(folly::dynamic&& dynamic) noexcept
: value_(std::move(dynamic)) {}
private:
friend class RawProps;
friend class RawPropsParser;
friend class UIManagerBinding;
RawValue(const RawValue& other) {
if (std::holds_alternative<folly::dynamic>(other.value_)) {
auto& dynamic = std::get<folly::dynamic>(other.value_);
value_ = dynamic;
} else {
const auto& [runtime, value] = std::get<JsiValuePair>(other.value_);
value_ = std::make_pair(runtime, jsi::Value(*runtime, value));
}
}
RawValue& operator=(const RawValue& other) {
if (this != &other) {
if (std::holds_alternative<folly::dynamic>(other.value_)) {
auto& dynamic = std::get<folly::dynamic>(other.value_);
value_ = dynamic;
} else {
const auto& [runtime, value] = std::get<JsiValuePair>(other.value_);
value_ = std::make_pair(runtime, jsi::Value(*runtime, value));
}
}
return *this;
}
public:
/*
* Casts the value to a specified type.
*/
template <typename T>
explicit operator T() const {
if (std::holds_alternative<folly::dynamic>(value_)) {
auto& dynamic = std::get<folly::dynamic>(value_);
return castValue(dynamic, (T*)nullptr);
} else {
const auto& [runtime, value] = std::get<JsiValuePair>(value_);
return castValue(runtime, value, (T*)nullptr);
}
}
inline explicit operator folly::dynamic() const {
if (std::holds_alternative<folly::dynamic>(value_)) {
return std::get<folly::dynamic>(value_);
} else {
const auto& [runtime, value] = std::get<JsiValuePair>(value_);
return jsi::dynamicFromValue(*runtime, value);
}
}
/*
* Checks if the stored value has specified type.
*/
template <typename T>
bool hasType() const {
if (std::holds_alternative<folly::dynamic>(value_)) {
auto& dynamic = std::get<folly::dynamic>(value_);
return checkValueType(dynamic, (T*)nullptr);
} else {
const auto& [runtime, value] = std::get<JsiValuePair>(value_);
return checkValueType(runtime, value, (T*)nullptr);
}
}
/*
* Checks if the stored value is *not* `null`.
*/
bool hasValue() const {
if (std::holds_alternative<folly::dynamic>(value_)) {
auto& dynamic = std::get<folly::dynamic>(value_);
return !dynamic.isNull();
} else {
const auto& [runtime, value] = std::get<JsiValuePair>(value_);
return !value.isNull() && !value.isUndefined();
}
}
private:
using JsiValuePair = std::pair<jsi::Runtime*, jsi::Value>;
std::variant<folly::dynamic, JsiValuePair> value_;
static bool checkValueType(
const folly::dynamic& /*dynamic*/,
RawValue* /*type*/) noexcept {
return true;
}
static bool checkValueType(
jsi::Runtime* /*runtime*/,
const jsi::Value& /*value*/,
RawValue* /*type*/) noexcept {
return true;
}
static bool checkValueType(
const folly::dynamic& dynamic,
bool* /*type*/) noexcept {
return dynamic.isBool();
}
static bool checkValueType(
jsi::Runtime* /*runtime*/,
const jsi::Value& value,
bool* /*type*/) noexcept {
return value.isBool();
}
static bool checkValueType(
const folly::dynamic& dynamic,
int* /*type*/) noexcept {
return dynamic.isNumber();
}
static bool checkValueType(
jsi::Runtime* /*runtime*/,
const jsi::Value& value,
int* /*type*/) noexcept {
return value.isNumber();
}
static bool checkValueType(
const folly::dynamic& dynamic,
int64_t* /*type*/) noexcept {
return dynamic.isNumber();
}
static bool checkValueType(
jsi::Runtime* /*runtime*/,
const jsi::Value& value,
int64_t* /*type*/) noexcept {
return value.isNumber();
}
static bool checkValueType(
const folly::dynamic& dynamic,
float* /*type*/) noexcept {
return dynamic.isNumber();
}
static bool checkValueType(
jsi::Runtime* /*runtime*/,
const jsi::Value& value,
float* /*type*/) noexcept {
return value.isNumber();
}
static bool checkValueType(
const folly::dynamic& dynamic,
double* /*type*/) noexcept {
return dynamic.isNumber();
}
static bool checkValueType(
jsi::Runtime* /*runtime*/,
const jsi::Value& value,
double* /*type*/) noexcept {
return value.isNumber();
}
static bool checkValueType(
const folly::dynamic& dynamic,
std::string* /*type*/) noexcept {
return dynamic.isString();
}
static bool checkValueType(
jsi::Runtime* /*runtime*/,
const jsi::Value& value,
std::string* /*type*/) noexcept {
return value.isString();
}
static bool checkValueType(
const folly::dynamic& /*dynamic*/,
JsiValuePair* /*type*/) noexcept {
return false;
}
static bool checkValueType(
jsi::Runtime* /*runtime*/,
const jsi::Value& /*value*/,
JsiValuePair* /*type*/) noexcept {
return true;
}
template <typename T>
static bool checkValueType(
const folly::dynamic& dynamic,
std::vector<T>* /*type*/) noexcept {
if (!dynamic.isArray()) {
return false;
}
for (const auto& item : dynamic) {
if (!checkValueType(item, (T*)nullptr)) {
return false;
}
// Note: We test only one element.
break;
}
return true;
}
template <typename T>
static bool checkValueType(
jsi::Runtime* runtime,
const jsi::Value& value,
std::vector<T>* /*type*/) noexcept {
if (!value.isObject()) {
return false;
}
jsi::Object asObject = value.getObject(*runtime);
if (!asObject.isArray(*runtime)) {
return false;
}
jsi::Array array = asObject.getArray(*runtime);
size_t size = array.size(*runtime);
for (size_t i = 0; i < size; i++) {
jsi::Value itemValue = array.getValueAtIndex(*runtime, i);
if (!checkValueType(runtime, itemValue, (T*)nullptr)) {
return false;
}
// Note: We test only one element.
break;
}
return true;
}
template <typename T>
static bool checkValueType(
const folly::dynamic& dynamic,
std::unordered_map<std::string, T>* /*type*/) noexcept {
if (!dynamic.isObject()) {
return false;
}
for (const auto& item : dynamic.items()) {
react_native_assert(item.first.isString());
if (!checkValueType(item.second, (T*)nullptr)) {
return false;
}
// Note: We test only one element.
break;
}
return true;
}
template <typename T>
static bool checkValueType(
jsi::Runtime* runtime,
const jsi::Value& value,
std::unordered_map<std::string, T>* /*type*/) {
if (!value.isObject()) {
return false;
}
jsi::Object asObject = value.getObject(*runtime);
auto propertyNames = asObject.getPropertyNames(*runtime);
size_t size = propertyNames.size(*runtime);
for (size_t i = 0; i < size; i++) {
jsi::String propertyName =
propertyNames.getValueAtIndex(*runtime, i).getString(*runtime);
jsi::Value propertyValue = asObject.getProperty(*runtime, propertyName);
if (!checkValueType(runtime, propertyValue, (T*)nullptr)) {
return false;
}
// Note: We test only one element.
break;
}
return true;
}
// Casts
static RawValue castValue(
const folly::dynamic& dynamic,
RawValue* /*type*/) noexcept {
return RawValue(dynamic);
}
static RawValue castValue(
jsi::Runtime* runtime,
const jsi::Value& value,
RawValue* /*type*/) noexcept {
return RawValue(*runtime, value);
}
static bool castValue(const folly::dynamic& dynamic, bool* /*type*/) {
return dynamic.getBool();
}
static bool castValue(
jsi::Runtime* /*runtime*/,
const jsi::Value& value,
bool* /*type*/) {
return value.asBool();
}
static int castValue(const folly::dynamic& dynamic, int* /*type*/) {
return static_cast<int>(dynamic.asInt());
}
static int
castValue(jsi::Runtime* /*runtime*/, const jsi::Value& value, int* /*type*/) {
double number = value.asNumber();
return static_cast<int>(number);
}
static int64_t castValue(const folly::dynamic& dynamic, int64_t* /*type*/) {
return dynamic.asInt();
}
static int64_t castValue(
jsi::Runtime* /*runtime*/,
const jsi::Value& value,
int64_t* /*type*/) {
double number = value.asNumber();
return static_cast<int64_t>(number);
}
static float castValue(const folly::dynamic& dynamic, float* /*type*/) {
return static_cast<float>(dynamic.asDouble());
}
static float castValue(
jsi::Runtime* /*runtime*/,
const jsi::Value& value,
float* /*type*/) {
double number = value.asNumber();
return static_cast<float>(number);
}
static double castValue(const folly::dynamic& dynamic, double* /*type*/) {
return dynamic.asDouble();
}
static double castValue(
jsi::Runtime* /*runtime*/,
const jsi::Value& value,
double* /*type*/) {
return value.asNumber();
}
static std::string castValue(
const folly::dynamic& dynamic,
std::string* /*type*/) {
return dynamic.getString();
}
static std::string castValue(
jsi::Runtime* runtime,
const jsi::Value& value,
std::string* /*type*/) {
jsi::String stringValue = value.asString(*runtime);
return stringValue.utf8(*runtime);
}
static JsiValuePair castValue(
const folly::dynamic& /*dynamic*/,
JsiValuePair* /*type*/) {
react_native_assert(false);
throw std::runtime_error(
"Cannot cast dynamic to a jsi::Value type. Please use the 'useRawPropsJsiValue' feature flag to enable jsi::Value support for RawValues.");
}
static JsiValuePair castValue(
jsi::Runtime* runtime,
const jsi::Value& value,
JsiValuePair* /*type*/) {
return {runtime, jsi::Value(*runtime, value)};
}
template <typename T>
static std::vector<T> castValue(
const folly::dynamic& dynamic,
std::vector<T>* /*type*/) {
react_native_assert(dynamic.isArray());
auto result = std::vector<T>{};
result.reserve(dynamic.size());
for (const auto& item : dynamic) {
result.push_back(castValue(item, (T*)nullptr));
}
return result;
}
template <typename T>
static std::vector<T> castValue(
jsi::Runtime* runtime,
const jsi::Value& value,
std::vector<T>* /*type*/) {
react_native_assert(value.isObject());
jsi::Object object = value.getObject(*runtime);
react_native_assert(object.isArray(*runtime));
jsi::Array array = object.getArray(*runtime);
size_t size = array.size(*runtime);
std::vector<T> result;
result.reserve(size);
for (size_t i = 0; i < size; i++) {
jsi::Value itemValue = array.getValueAtIndex(*runtime, i);
T item = castValue(runtime, itemValue, (T*)nullptr);
result.push_back(std::move(item));
}
return result;
}
template <typename T>
static std::vector<std::vector<T>> castValue(
const folly::dynamic& dynamic,
std::vector<std::vector<T>>* /*type*/) {
react_native_assert(dynamic.isArray());
auto result = std::vector<std::vector<T>>{};
result.reserve(dynamic.size());
for (const auto& item : dynamic) {
result.push_back(castValue(item, (std::vector<T>*)nullptr));
}
return result;
}
template <typename T>
static std::vector<std::vector<T>> castValue(
jsi::Runtime* runtime,
const jsi::Value& value,
std::vector<std::vector<T>>* /*type*/) {
react_native_assert(value.isObject());
jsi::Object object = value.getObject(*runtime);
react_native_assert(object.isArray(*runtime));
jsi::Array array = std::move(object).getArray(*runtime);
size_t size = array.size(*runtime);
std::vector<std::vector<T>> result;
result.reserve(size);
for (size_t i = 0; i < size; i++) {
jsi::Value itemValue = array.getValueAtIndex(*runtime, i);
std::vector<T> item =
castValue(runtime, itemValue, (std::vector<T>*)nullptr);
result.push_back(std::move(item));
}
return result;
}
template <typename T>
static std::unordered_map<std::string, T> castValue(
const folly::dynamic& dynamic,
std::unordered_map<std::string, T>* /*type*/) {
react_native_assert(dynamic.isObject());
auto result = std::unordered_map<std::string, T>{};
for (const auto& item : dynamic.items()) {
react_native_assert(item.first.isString());
result[item.first.getString()] = castValue(item.second, (T*)nullptr);
}
return result;
}
template <typename T>
static std::unordered_map<std::string, T> castValue(
jsi::Runtime* runtime,
const jsi::Value& value,
std::unordered_map<std::string, T>* /*type*/) {
react_native_assert(value.isObject());
jsi::Object object = value.getObject(*runtime);
jsi::Array propertyNames = object.getPropertyNames(*runtime);
size_t size = propertyNames.size(*runtime);
std::unordered_map<std::string, T> result;
for (size_t i = 0; i < size; i++) {
jsi::Value propertyNameValue = propertyNames.getValueAtIndex(*runtime, i);
jsi::String propertyName = propertyNameValue.getString(*runtime);
jsi::Value propertyValue = object.getProperty(*runtime, propertyName);
if (propertyValue.isUndefined()) {
// Skip undefined values to mimic JSIDynamic::dynamicFromValue behavior.
// Null values are allowed in the map.
continue;
}
std::string propertyNameString = propertyName.utf8(*runtime);
T property = castValue(runtime, propertyValue, (T*)nullptr);
result.emplace(propertyNameString, std::move(property));
}
return result;
}
};
} // namespace facebook::react
Выполнить команду
Для локальной разработки. Не используйте в интернете!