/* * 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 #include #include #include #include #include #include namespace facebook::react { /** * CSSDeclaredStyle represents the set of style declarations on an element set * by the user. Users should generally not read from CSSDeclaredStyle directly, * and should instead use the computed style calculated on ShadowTree commit. */ class CSSDeclaredStyle { public: template void set(const CSSDeclaredValue& value) { using DeclaredValueT = std::remove_cvref_t>; static_assert(sizeof(value) <= sizeof(PropMapping::value)); static_assert(std::is_trivially_destructible_v); if (specifiedProperties_.test(to_underlying(Prop))) { auto it = std::lower_bound( properties_.begin(), properties_.end(), PropMapping{Prop, {}}); react_native_assert(it->prop == Prop); std::construct_at( reinterpret_cast(it->value.data()), value); } else { auto it = std::upper_bound( properties_.begin(), properties_.end(), PropMapping{Prop, {}}); it = properties_.insert(it, {Prop, {}}); std::construct_at( reinterpret_cast(it->value.data()), value); specifiedProperties_.set(to_underlying(Prop)); } } template void set(std::string_view value) { set(parseCSSProp(value)); } /** * Returns the declared value, represented as the "unset" keyword if never * specified. Additional shorthands can be provided in order * of precedence if Prop is unset. */ template CSSDeclaredValue get() const { if (specifiedProperties_.test(to_underlying(Prop))) { auto it = std::lower_bound( properties_.begin(), properties_.end(), PropMapping{Prop, {}}); react_native_assert(it->prop == Prop); CSSDeclaredValue value{*std::launder( reinterpret_cast*>(it->value.data()))}; if (value) { return value; } } if constexpr (sizeof...(ShorthandsT) == 0) { return {}; } else { return get(); } } bool operator==(const CSSDeclaredStyle& rhs) const = default; private: struct PropMapping { CSSProp prop; std::array< std::byte, sizeof(CSSValueVariant< CSSWideKeyword, CSSKeyword, CSSLength, CSSNumber, CSSPercentage, CSSRatio>)> value; constexpr bool operator<(const PropMapping& rhs) const { return to_underlying(prop) < to_underlying(rhs.prop); } }; std::vector properties_; std::bitset specifiedProperties_; }; } // namespace facebook::react