diff --git a/packages/react-native/ReactCommon/react/renderer/css/CSSKeywords.h b/packages/react-native/ReactCommon/react/renderer/css/CSSKeywords.h index a584ef023b2..7279c36c7fd 100644 --- a/packages/react-native/ReactCommon/react/renderer/css/CSSKeywords.h +++ b/packages/react-native/ReactCommon/react/renderer/css/CSSKeywords.h @@ -8,7 +8,6 @@ #pragma once #include -#include #include #include @@ -172,8 +171,11 @@ CSS_DEFINE_KEYWORD_CONEPTS(WrapReverse) template constexpr std::optional parseCSSKeyword(std::string_view ident) { struct LowerCaseTransform { - char operator()(char c) const { - return static_cast(tolower(c)); + constexpr char operator()(char c) const { + if (c >= 'A' && c <= 'Z') { + return c + static_cast('a' - 'A'); + } + return c; } }; diff --git a/packages/react-native/ReactCommon/react/renderer/css/CSSValue.h b/packages/react-native/ReactCommon/react/renderer/css/CSSValue.h index 4663dd9e818..5d7d9b1ee41 100644 --- a/packages/react-native/ReactCommon/react/renderer/css/CSSValue.h +++ b/packages/react-native/ReactCommon/react/renderer/css/CSSValue.h @@ -7,7 +7,6 @@ #pragma once -#include #include #include #include @@ -91,15 +90,6 @@ struct CSSRatio { #pragma pack(push, 1) template class CSSValueVariant { - template - constexpr ValueT getIf() const { - if (type_ == Type) { - return *std::launder(reinterpret_cast(data_.data())); - } else { - return ValueT{}; - } - } - template static constexpr bool canRepresent() { return traits::containsType(); @@ -201,20 +191,81 @@ class CSSValueVariant { } constexpr operator bool() const requires(canRepresent()) { - return *this != CSSValueVariant{}; + return type() != CSSValueType::CSSWideKeyword || + getCSSWideKeyword() != CSSWideKeyword::Unset; } - constexpr bool operator==(const CSSValueVariant& rhs) const = default; + constexpr bool operator==(const CSSValueVariant& other) const { + if (type() != other.type()) { + return false; + } + switch (type()) { + case CSSValueType::CSSWideKeyword: + return getCSSWideKeyword() == other.getCSSWideKeyword(); + case CSSValueType::Keyword: + return getKeyword() == other.getKeyword(); + case CSSValueType::Length: + return getLength() == other.getLength(); + case CSSValueType::Number: + return getNumber() == other.getNumber(); + case CSSValueType::Percentage: + return getPercentage() == other.getPercentage(); + case CSSValueType::Ratio: + return getRatio() == other.getRatio(); + } + + return false; + } private: - constexpr CSSValueVariant(CSSValueType type, CSSDataType auto&& value) - : type_(type) { - new (data_.data()) std::remove_cvref_t{ - std::forward(value)}; + template + constexpr ValueT getIf() const { + if (type_ == Type) { + return getFromUnion(data_); + } else { + return ValueT{}; + } + } + + template + union RecursiveUnion { + ValueT first; + RecursiveUnion rest; + }; + + template + union RecursiveUnion { + ValueT first; + }; + + template + constexpr const ValueT& getFromUnion(const UnionT& u) const { + if constexpr (std::is_same_v) { + return u.first; + } else { + return getFromUnion(u.rest); + } + } + + template + constexpr CSSValueVariant(CSSValueType type, DataTypeT&& value) + : type_{type}, + data_{constructIntoUnion( + std::forward(value))} {} + + template + constexpr UnionT constructIntoUnion(DataTypeT&& value) { + if constexpr (std::is_same_v) { + return UnionT{.first = std::forward(value)}; + } else { + return UnionT{ + .rest = constructIntoUnion( + std::forward(value))}; + } } CSSValueType type_; - std::array()> data_; + RecursiveUnion data_; }; #pragma pack(pop) diff --git a/packages/react-native/ReactCommon/react/renderer/css/tests/CSSParserTest.cpp b/packages/react-native/ReactCommon/react/renderer/css/tests/CSSParserTest.cpp index 7a16be05bc0..2ff8760e0dc 100644 --- a/packages/react-native/ReactCommon/react/renderer/css/tests/CSSParserTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/css/tests/CSSParserTest.cpp @@ -300,4 +300,18 @@ TEST(CSSParser, parse_prop) { EXPECT_EQ(keywordlessValue.getLength().unit, CSSLengthUnit::Px); } +TEST(CSSParser, parse_keyword_prop_constexpr) { + constexpr auto rowValue = parseCSSProp("row"); + EXPECT_EQ(rowValue.type(), CSSValueType::Keyword); + EXPECT_EQ( + rowValue.getKeyword(), CSSAllowedKeywords::Row); +} + +TEST(CSSParser, parse_length_prop_constexpr) { + constexpr auto pxValue = parseCSSProp("2px"); + EXPECT_EQ(pxValue.type(), CSSValueType::Length); + EXPECT_EQ(pxValue.getLength().value, 2.0f); + EXPECT_EQ(pxValue.getLength().unit, CSSLengthUnit::Px); +} + } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/utils/PackTraits.h b/packages/react-native/ReactCommon/react/utils/PackTraits.h index 0f14add9652..91d912f4a06 100644 --- a/packages/react-native/ReactCommon/react/utils/PackTraits.h +++ b/packages/react-native/ReactCommon/react/utils/PackTraits.h @@ -13,15 +13,6 @@ namespace facebook::react::traits { -template -static constexpr size_t maxSizeof() { - if constexpr (sizeof...(RestT) > 0) { - return std::max(sizeof(T), maxSizeof()); - } else { - return sizeof(T); - } -} - template static constexpr bool containsType() { return false;