diff --git a/.github/actions/setup-apple/action.yml b/.github/actions/setup-apple/action.yml index 6ef41f5806..4087ecbb74 100644 --- a/.github/actions/setup-apple/action.yml +++ b/.github/actions/setup-apple/action.yml @@ -7,3 +7,7 @@ runs: - name: Install Cocoapods shell: bash run: sudo gem install cocoapods + + - uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: 14.3.1 diff --git a/.github/workflows/validate-apple.yml b/.github/workflows/validate-apple.yml index 598ca2e830..3097cfe23d 100644 --- a/.github/workflows/validate-apple.yml +++ b/.github/workflows/validate-apple.yml @@ -11,7 +11,7 @@ on: jobs: lint-pods: name: Build [CocoaPods] - runs-on: macos-latest + runs-on: macos-13 steps: - uses: actions/checkout@v3 @@ -24,11 +24,14 @@ jobs: test: name: Build [SwiftPM] - runs-on: macos-latest + runs-on: macos-13 steps: - uses: actions/checkout@v3 + - name: Setup + uses: ./.github/actions/setup-apple + - name: Build Debug run: swift build -c debug diff --git a/enums.py b/enums.py index c7c3b29b0e..58b2f500fc 100755 --- a/enums.py +++ b/enums.py @@ -175,11 +175,6 @@ def to_hyphenated_lower(symbol): f.write(f" return {len(values)};\n") f.write("} \n\n") - f.write("template <>\n") - f.write(f"constexpr inline int32_t bitCount<{name}>() {{\n") - f.write(f" return {math.ceil(math.log(len(values), 2))};\n") - f.write("} \n\n") - f.write(f"constexpr inline {name} scopedEnum(YG{name} unscoped) {{\n") f.write(f" return static_cast<{name}>(unscoped);\n") f.write("}\n\n") diff --git a/yoga/bits/BitCast.h b/yoga/bits/BitCast.h deleted file mode 100644 index 13fb0e41f2..0000000000 --- a/yoga/bits/BitCast.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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::yoga { - -// Polyfill for std::bit_cast() from C++20, to allow safe type punning -// https://en.cppreference.com/w/cpp/numeric/bit_cast -// TODO: Remove when we upgrade to NDK 26+ -template -std::enable_if_t< - sizeof(To) == sizeof(From) && std::is_trivially_copyable_v && - std::is_trivially_copyable_v && - std::is_trivially_constructible_v, - To> -bit_cast(const From& src) noexcept { - To dst; - std::memcpy(&dst, &src, sizeof(To)); - return dst; -} - -} // namespace facebook::yoga diff --git a/yoga/enums/Align.h b/yoga/enums/Align.h index 67777fc31b..9a881b0fc1 100644 --- a/yoga/enums/Align.h +++ b/yoga/enums/Align.h @@ -32,11 +32,6 @@ constexpr inline int32_t ordinalCount() { return 9; } -template <> -constexpr inline int32_t bitCount() { - return 4; -} - constexpr inline Align scopedEnum(YGAlign unscoped) { return static_cast(unscoped); } diff --git a/yoga/enums/Dimension.h b/yoga/enums/Dimension.h index 2274a980a5..3ca2eace7a 100644 --- a/yoga/enums/Dimension.h +++ b/yoga/enums/Dimension.h @@ -25,11 +25,6 @@ constexpr inline int32_t ordinalCount() { return 2; } -template <> -constexpr inline int32_t bitCount() { - return 1; -} - constexpr inline Dimension scopedEnum(YGDimension unscoped) { return static_cast(unscoped); } diff --git a/yoga/enums/Direction.h b/yoga/enums/Direction.h index 1b5e19c93c..23b3bdfae9 100644 --- a/yoga/enums/Direction.h +++ b/yoga/enums/Direction.h @@ -26,11 +26,6 @@ constexpr inline int32_t ordinalCount() { return 3; } -template <> -constexpr inline int32_t bitCount() { - return 2; -} - constexpr inline Direction scopedEnum(YGDirection unscoped) { return static_cast(unscoped); } diff --git a/yoga/enums/Display.h b/yoga/enums/Display.h index c1d8c7a82e..c6559760af 100644 --- a/yoga/enums/Display.h +++ b/yoga/enums/Display.h @@ -25,11 +25,6 @@ constexpr inline int32_t ordinalCount() { return 2; } -template <> -constexpr inline int32_t bitCount() { - return 1; -} - constexpr inline Display scopedEnum(YGDisplay unscoped) { return static_cast(unscoped); } diff --git a/yoga/enums/Edge.h b/yoga/enums/Edge.h index d6d2b0ee66..0e72cc4258 100644 --- a/yoga/enums/Edge.h +++ b/yoga/enums/Edge.h @@ -32,11 +32,6 @@ constexpr inline int32_t ordinalCount() { return 9; } -template <> -constexpr inline int32_t bitCount() { - return 4; -} - constexpr inline Edge scopedEnum(YGEdge unscoped) { return static_cast(unscoped); } diff --git a/yoga/enums/ExperimentalFeature.h b/yoga/enums/ExperimentalFeature.h index 6ed358155b..447352240a 100644 --- a/yoga/enums/ExperimentalFeature.h +++ b/yoga/enums/ExperimentalFeature.h @@ -25,11 +25,6 @@ constexpr inline int32_t ordinalCount() { return 2; } -template <> -constexpr inline int32_t bitCount() { - return 1; -} - constexpr inline ExperimentalFeature scopedEnum(YGExperimentalFeature unscoped) { return static_cast(unscoped); } diff --git a/yoga/enums/FlexDirection.h b/yoga/enums/FlexDirection.h index 45f6497ca4..d5ca99ab5b 100644 --- a/yoga/enums/FlexDirection.h +++ b/yoga/enums/FlexDirection.h @@ -27,11 +27,6 @@ constexpr inline int32_t ordinalCount() { return 4; } -template <> -constexpr inline int32_t bitCount() { - return 2; -} - constexpr inline FlexDirection scopedEnum(YGFlexDirection unscoped) { return static_cast(unscoped); } diff --git a/yoga/enums/Gutter.h b/yoga/enums/Gutter.h index 5c0f4a254e..81f2125da7 100644 --- a/yoga/enums/Gutter.h +++ b/yoga/enums/Gutter.h @@ -26,11 +26,6 @@ constexpr inline int32_t ordinalCount() { return 3; } -template <> -constexpr inline int32_t bitCount() { - return 2; -} - constexpr inline Gutter scopedEnum(YGGutter unscoped) { return static_cast(unscoped); } diff --git a/yoga/enums/Justify.h b/yoga/enums/Justify.h index 870a3cb2a7..1c9fd461c5 100644 --- a/yoga/enums/Justify.h +++ b/yoga/enums/Justify.h @@ -29,11 +29,6 @@ constexpr inline int32_t ordinalCount() { return 6; } -template <> -constexpr inline int32_t bitCount() { - return 3; -} - constexpr inline Justify scopedEnum(YGJustify unscoped) { return static_cast(unscoped); } diff --git a/yoga/enums/LogLevel.h b/yoga/enums/LogLevel.h index 45cac9fe39..150593d367 100644 --- a/yoga/enums/LogLevel.h +++ b/yoga/enums/LogLevel.h @@ -29,11 +29,6 @@ constexpr inline int32_t ordinalCount() { return 6; } -template <> -constexpr inline int32_t bitCount() { - return 3; -} - constexpr inline LogLevel scopedEnum(YGLogLevel unscoped) { return static_cast(unscoped); } diff --git a/yoga/enums/MeasureMode.h b/yoga/enums/MeasureMode.h index 80fbcc599f..62edc6a575 100644 --- a/yoga/enums/MeasureMode.h +++ b/yoga/enums/MeasureMode.h @@ -26,11 +26,6 @@ constexpr inline int32_t ordinalCount() { return 3; } -template <> -constexpr inline int32_t bitCount() { - return 2; -} - constexpr inline MeasureMode scopedEnum(YGMeasureMode unscoped) { return static_cast(unscoped); } diff --git a/yoga/enums/NodeType.h b/yoga/enums/NodeType.h index 782b163c2e..cf42785792 100644 --- a/yoga/enums/NodeType.h +++ b/yoga/enums/NodeType.h @@ -25,11 +25,6 @@ constexpr inline int32_t ordinalCount() { return 2; } -template <> -constexpr inline int32_t bitCount() { - return 1; -} - constexpr inline NodeType scopedEnum(YGNodeType unscoped) { return static_cast(unscoped); } diff --git a/yoga/enums/Overflow.h b/yoga/enums/Overflow.h index 1d29103e62..a676b960a9 100644 --- a/yoga/enums/Overflow.h +++ b/yoga/enums/Overflow.h @@ -26,11 +26,6 @@ constexpr inline int32_t ordinalCount() { return 3; } -template <> -constexpr inline int32_t bitCount() { - return 2; -} - constexpr inline Overflow scopedEnum(YGOverflow unscoped) { return static_cast(unscoped); } diff --git a/yoga/enums/PositionType.h b/yoga/enums/PositionType.h index bde2b1896f..90005fa2eb 100644 --- a/yoga/enums/PositionType.h +++ b/yoga/enums/PositionType.h @@ -26,11 +26,6 @@ constexpr inline int32_t ordinalCount() { return 3; } -template <> -constexpr inline int32_t bitCount() { - return 2; -} - constexpr inline PositionType scopedEnum(YGPositionType unscoped) { return static_cast(unscoped); } diff --git a/yoga/enums/Unit.h b/yoga/enums/Unit.h index 36efe95aaf..c5e5e39bdd 100644 --- a/yoga/enums/Unit.h +++ b/yoga/enums/Unit.h @@ -27,11 +27,6 @@ constexpr inline int32_t ordinalCount() { return 4; } -template <> -constexpr inline int32_t bitCount() { - return 2; -} - constexpr inline Unit scopedEnum(YGUnit unscoped) { return static_cast(unscoped); } diff --git a/yoga/enums/Wrap.h b/yoga/enums/Wrap.h index ae380a4448..7dc3e3b056 100644 --- a/yoga/enums/Wrap.h +++ b/yoga/enums/Wrap.h @@ -26,11 +26,6 @@ constexpr inline int32_t ordinalCount() { return 3; } -template <> -constexpr inline int32_t bitCount() { - return 2; -} - constexpr inline Wrap scopedEnum(YGWrap unscoped) { return static_cast(unscoped); } diff --git a/yoga/enums/YogaEnums.h b/yoga/enums/YogaEnums.h index a3e1191de1..4c2a2f2349 100644 --- a/yoga/enums/YogaEnums.h +++ b/yoga/enums/YogaEnums.h @@ -7,25 +7,44 @@ #pragma once +#include #include #include namespace facebook::yoga { +/** + * Concept for any enum/enum class + */ template +concept Enumeration = std::is_enum_v; + +/** + * Count of ordinals in a Yoga enum which is sequential + */ +template constexpr inline int32_t ordinalCount(); /** - * Count of bits needed to represent every ordinal + * Concept for a yoga enum which is sequential */ template -constexpr inline int32_t bitCount(); +concept HasOrdinality = (ordinalCount() > 0); + +/** + * Count of bits needed to represent every ordinal + */ +template +constexpr inline int32_t bitCount() { + return std::bit_width( + static_cast>(ordinalCount() - 1)); +} /** * Polyfill of C++ 23 to_underlying() * https://en.cppreference.com/w/cpp/utility/to_underlying */ -constexpr auto to_underlying(auto e) noexcept { +constexpr auto to_underlying(Enumeration auto e) noexcept { return static_cast>(e); } @@ -33,7 +52,7 @@ constexpr auto to_underlying(auto e) noexcept { * Convenience function to iterate through every value in a Yoga enum as part of * a range-based for loop. */ -template +template auto ordinals() { struct Iterator { EnumT e{}; diff --git a/yoga/numeric/Comparison.h b/yoga/numeric/Comparison.h index 3bf1037b9c..729589b934 100644 --- a/yoga/numeric/Comparison.h +++ b/yoga/numeric/Comparison.h @@ -10,27 +10,32 @@ #include #include #include +#include #include namespace facebook::yoga { -constexpr bool isUndefined(auto value) { +constexpr bool isUndefined(std::floating_point auto value) { return value != value; } -constexpr bool isDefined(auto value) { +constexpr bool isDefined(std::floating_point auto value) { return !isUndefined(value); } -constexpr auto maxOrDefined(auto a, auto b) { +constexpr auto maxOrDefined( + std::floating_point auto a, + std::floating_point auto b) { if (yoga::isDefined(a) && yoga::isDefined(b)) { return std::max(a, b); } return yoga::isUndefined(a) ? b : a; } -constexpr auto minOrDefined(auto a, auto b) { +constexpr auto minOrDefined( + std::floating_point auto a, + std::floating_point auto b) { if (yoga::isDefined(a) && yoga::isDefined(b)) { return std::min(a, b); } diff --git a/yoga/style/CompactValue.h b/yoga/style/CompactValue.h index c32dd9276f..d7884e1d6f 100644 --- a/yoga/style/CompactValue.h +++ b/yoga/style/CompactValue.h @@ -7,6 +7,7 @@ #pragma once +#include #include #include #include @@ -14,7 +15,6 @@ #include #include -#include #include static_assert( @@ -69,7 +69,7 @@ class YG_EXPORT CompactValue { } uint32_t unitBit = Unit == YGUnitPercent ? PERCENT_BIT : 0; - auto data = yoga::bit_cast(value); + auto data = std::bit_cast(value); data -= BIAS; data |= unitBit; return {data}; @@ -112,7 +112,7 @@ class YG_EXPORT CompactValue { return YGValue{0.0f, YGUnitPercent}; } - if (std::isnan(yoga::bit_cast(repr_))) { + if (std::isnan(std::bit_cast(repr_))) { return YGValueUndefined; } @@ -121,14 +121,14 @@ class YG_EXPORT CompactValue { data += BIAS; return YGValue{ - yoga::bit_cast(data), + std::bit_cast(data), repr_ & 0x40000000 ? YGUnitPercent : YGUnitPoint}; } bool isUndefined() const noexcept { return ( repr_ != AUTO_BITS && repr_ != ZERO_BITS_POINT && - repr_ != ZERO_BITS_PERCENT && std::isnan(yoga::bit_cast(repr_))); + repr_ != ZERO_BITS_PERCENT && std::isnan(std::bit_cast(repr_))); } bool isDefined() const noexcept {