diff --git a/Package.swift b/Package.swift index 61b6186..4c22b42 100644 --- a/Package.swift +++ b/Package.swift @@ -20,7 +20,7 @@ let openSwiftUITarget = Target.target( ], swiftSettings: [ .enableExperimentalFeature("AccessLevelOnImport"), - .define("OPENSWIFTUI_SUPPRESS_DEPRECATED_WARNINGS") + .define("OPENSWIFTUI_SUPPRESS_DEPRECATED_WARNINGS"), ], linkerSettings: [ .unsafeFlags( @@ -80,17 +80,42 @@ let package = Package( ] ) +// FIXME: The binary of AG for macOS is copied from dyld shared cache and it will cause a link error when running. Use iOS Simulator to run this target as a temporary workaround +let graphCompatibilityTest = ProcessInfo.processInfo.environment["OPENGRAPH_COMPATIBILITY_TEST"] != nil +let openGraphCompatibilityTestTarget = Target.testTarget( + name: "OpenGraphCompatibilityTests", + dependencies: [ + graphCompatibilityTest ? "AttributeGraph" : "OpenGraph", + ], + exclude: ["README.md"], + swiftSettings: graphCompatibilityTest ? [ + .define("OPENGRAPH_COMPATIBILITY_TEST") + ] : [] +) +package.targets.append(openGraphCompatibilityTestTarget) + let useAG = ProcessInfo.processInfo.environment["OPENSWIFTUI_USE_AG"] != nil if useAG { + if !graphCompatibilityTest { + let targets: [Target] = [ + // FIXME: Merge into one target + // OpenGraph is a C++ & Swift mix target. + // The SwiftPM support for such usage is still in progress. + .target( + name: "_OpenGraph", + dependencies: [.product(name: "OpenFoundation", package: "OpenFoundation")], + cSettings: [clangEnumFixSetting] + ), + .target( + name: "OpenGraph", + dependencies: ["_OpenGraph"], + cSettings: [clangEnumFixSetting] + ), + ] + package.targets.append(contentsOf: targets) + } let targets: [Target] = [ .binaryTarget(name: "AttributeGraph", path: "Sources/AttributeGraph.xcframework"), - // FIXME: The binary of AG for macOS is copied from dyld shared cache and it will cause a link error when running. Use iOS Simulator to run this target as a temporary workaround - .testTarget( - name: "AttributeGraphTests", - dependencies: [ - "AttributeGraph", - ] - ), ] package.targets.append(contentsOf: targets) openSwiftUITarget.dependencies.append( @@ -100,6 +125,12 @@ if useAG { swiftSettings.append(.define("OPENSWIFTUI_USE_AG")) openSwiftUITarget.swiftSettings = swiftSettings } else { + if graphCompatibilityTest { + let targets: [Target] = [ + .binaryTarget(name: "AttributeGraph", path: "Sources/AttributeGraph.xcframework"), + ] + package.targets.append(contentsOf: targets) + } package.products.append( .library(name: "OpenGraph", targets: ["OpenGraph", "_OpenGraph"]) ) diff --git a/Sources/AttributeGraph.xcframework/ios-arm64_x86_64-simulator/AttributeGraph.framework/Headers/AGCompareValues.h b/Sources/AttributeGraph.xcframework/ios-arm64_x86_64-simulator/AttributeGraph.framework/Headers/AGCompareValues.h new file mode 100644 index 0000000..fbc12fa --- /dev/null +++ b/Sources/AttributeGraph.xcframework/ios-arm64_x86_64-simulator/AttributeGraph.framework/Headers/AGCompareValues.h @@ -0,0 +1,20 @@ +// +// AGCompareValues.h +// +// +// Created by Kyle on 2023/10/9. +// + +#ifndef AGCompareValues_h +#define AGCompareValues_h + +#include +#include "AGComparisonMode.h" +#include + +CF_EXTERN_C_BEGIN +CF_EXPORT +bool AGCompareValues(const void *lhs, const void *rhs, const AGComparisonMode comparisonMode, const void *type); +CF_EXTERN_C_END + +#endif /* AGCompareValues_h */ diff --git a/Sources/AttributeGraph.xcframework/ios-arm64_x86_64-simulator/AttributeGraph.framework/Headers/AttributeGraph-umbrella.h b/Sources/AttributeGraph.xcframework/ios-arm64_x86_64-simulator/AttributeGraph.framework/Headers/AttributeGraph-umbrella.h index ab7dd44..749b3f6 100644 --- a/Sources/AttributeGraph.xcframework/ios-arm64_x86_64-simulator/AttributeGraph.framework/Headers/AttributeGraph-umbrella.h +++ b/Sources/AttributeGraph.xcframework/ios-arm64_x86_64-simulator/AttributeGraph.framework/Headers/AttributeGraph-umbrella.h @@ -13,6 +13,7 @@ #import "AGAttribute.h" #import "AGUniqueID.h" #import "AGComparisonMode.h" +#import "AGCompareValues.h" FOUNDATION_EXPORT double AGAttributeVersionNumber; FOUNDATION_EXPORT const unsigned char AGAttributeVersionString[]; diff --git a/Sources/AttributeGraph.xcframework/ios-arm64_x86_64-simulator/AttributeGraph.framework/Modules/AttributeGraph.swiftmodule/arm64-apple-ios-simulator.swiftinterface b/Sources/AttributeGraph.xcframework/ios-arm64_x86_64-simulator/AttributeGraph.framework/Modules/AttributeGraph.swiftmodule/arm64-apple-ios-simulator.swiftinterface index 7460aff..2a8a775 100644 --- a/Sources/AttributeGraph.xcframework/ios-arm64_x86_64-simulator/AttributeGraph.framework/Modules/AttributeGraph.swiftmodule/arm64-apple-ios-simulator.swiftinterface +++ b/Sources/AttributeGraph.xcframework/ios-arm64_x86_64-simulator/AttributeGraph.framework/Modules/AttributeGraph.swiftmodule/arm64-apple-ios-simulator.swiftinterface @@ -63,3 +63,4 @@ extension AttributeGraph.Rule { get } } +public func compareValues(_ lhs: A, _ rhs: A, mode: AGComparisonMode = ._3) -> Swift.Bool \ No newline at end of file diff --git a/Sources/AttributeGraph.xcframework/ios-arm64_x86_64-simulator/AttributeGraph.framework/Modules/AttributeGraph.swiftmodule/x86_64-apple-ios-simulator.swiftinterface b/Sources/AttributeGraph.xcframework/ios-arm64_x86_64-simulator/AttributeGraph.framework/Modules/AttributeGraph.swiftmodule/x86_64-apple-ios-simulator.swiftinterface index 11812ba..2ab7105 100644 --- a/Sources/AttributeGraph.xcframework/ios-arm64_x86_64-simulator/AttributeGraph.framework/Modules/AttributeGraph.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +++ b/Sources/AttributeGraph.xcframework/ios-arm64_x86_64-simulator/AttributeGraph.framework/Modules/AttributeGraph.swiftmodule/x86_64-apple-ios-simulator.swiftinterface @@ -63,3 +63,4 @@ extension AttributeGraph.Rule { get } } +public func compareValues(_ lhs: A, _ rhs: A, mode: AGComparisonMode = ._3) -> Swift.Bool \ No newline at end of file diff --git a/Sources/AttributeGraph.xcframework/ios-arm64e/AttributeGraph.framework/Headers/AGCompareValues.h b/Sources/AttributeGraph.xcframework/ios-arm64e/AttributeGraph.framework/Headers/AGCompareValues.h new file mode 100644 index 0000000..fbc12fa --- /dev/null +++ b/Sources/AttributeGraph.xcframework/ios-arm64e/AttributeGraph.framework/Headers/AGCompareValues.h @@ -0,0 +1,20 @@ +// +// AGCompareValues.h +// +// +// Created by Kyle on 2023/10/9. +// + +#ifndef AGCompareValues_h +#define AGCompareValues_h + +#include +#include "AGComparisonMode.h" +#include + +CF_EXTERN_C_BEGIN +CF_EXPORT +bool AGCompareValues(const void *lhs, const void *rhs, const AGComparisonMode comparisonMode, const void *type); +CF_EXTERN_C_END + +#endif /* AGCompareValues_h */ diff --git a/Sources/AttributeGraph.xcframework/ios-arm64e/AttributeGraph.framework/Headers/AttributeGraph-umbrella.h b/Sources/AttributeGraph.xcframework/ios-arm64e/AttributeGraph.framework/Headers/AttributeGraph-umbrella.h index ab7dd44..749b3f6 100644 --- a/Sources/AttributeGraph.xcframework/ios-arm64e/AttributeGraph.framework/Headers/AttributeGraph-umbrella.h +++ b/Sources/AttributeGraph.xcframework/ios-arm64e/AttributeGraph.framework/Headers/AttributeGraph-umbrella.h @@ -13,6 +13,7 @@ #import "AGAttribute.h" #import "AGUniqueID.h" #import "AGComparisonMode.h" +#import "AGCompareValues.h" FOUNDATION_EXPORT double AGAttributeVersionNumber; FOUNDATION_EXPORT const unsigned char AGAttributeVersionString[]; diff --git a/Sources/AttributeGraph.xcframework/ios-arm64e/AttributeGraph.framework/Modules/AttributeGraph.swiftmodule/arm64e-apple-ios.swiftinterface b/Sources/AttributeGraph.xcframework/ios-arm64e/AttributeGraph.framework/Modules/AttributeGraph.swiftmodule/arm64e-apple-ios.swiftinterface index 384238a..33c1ad0 100644 --- a/Sources/AttributeGraph.xcframework/ios-arm64e/AttributeGraph.framework/Modules/AttributeGraph.swiftmodule/arm64e-apple-ios.swiftinterface +++ b/Sources/AttributeGraph.xcframework/ios-arm64e/AttributeGraph.framework/Modules/AttributeGraph.swiftmodule/arm64e-apple-ios.swiftinterface @@ -63,3 +63,4 @@ extension AttributeGraph.Rule { get } } +public func compareValues(_ lhs: A, _ rhs: A, mode: AGComparisonMode = ._3) -> Swift.Bool \ No newline at end of file diff --git a/Sources/AttributeGraph.xcframework/macos-arm64e/AttributeGraph.framework/Headers/AGCompareValues.h b/Sources/AttributeGraph.xcframework/macos-arm64e/AttributeGraph.framework/Headers/AGCompareValues.h new file mode 100644 index 0000000..fbc12fa --- /dev/null +++ b/Sources/AttributeGraph.xcframework/macos-arm64e/AttributeGraph.framework/Headers/AGCompareValues.h @@ -0,0 +1,20 @@ +// +// AGCompareValues.h +// +// +// Created by Kyle on 2023/10/9. +// + +#ifndef AGCompareValues_h +#define AGCompareValues_h + +#include +#include "AGComparisonMode.h" +#include + +CF_EXTERN_C_BEGIN +CF_EXPORT +bool AGCompareValues(const void *lhs, const void *rhs, const AGComparisonMode comparisonMode, const void *type); +CF_EXTERN_C_END + +#endif /* AGCompareValues_h */ diff --git a/Sources/AttributeGraph.xcframework/macos-arm64e/AttributeGraph.framework/Headers/AttributeGraph-umbrella.h b/Sources/AttributeGraph.xcframework/macos-arm64e/AttributeGraph.framework/Headers/AttributeGraph-umbrella.h index e93ba61..5dbff92 100644 --- a/Sources/AttributeGraph.xcframework/macos-arm64e/AttributeGraph.framework/Headers/AttributeGraph-umbrella.h +++ b/Sources/AttributeGraph.xcframework/macos-arm64e/AttributeGraph.framework/Headers/AttributeGraph-umbrella.h @@ -13,6 +13,7 @@ #import "AGAttribute.h" #import "AGUniqueID.h" #import "AGComparisonMode.h" +#import "AGCompareValues.h" FOUNDATION_EXPORT double AGAttributeVersionNumber; FOUNDATION_EXPORT const unsigned char AGAttributeVersionString[]; diff --git a/Sources/AttributeGraph.xcframework/macos-arm64e/AttributeGraph.framework/Modules/AttributeGraph.swiftmodule/arm64e-apple-macos.swiftinterface b/Sources/AttributeGraph.xcframework/macos-arm64e/AttributeGraph.framework/Modules/AttributeGraph.swiftmodule/arm64e-apple-macos.swiftinterface index 1c3ccb1..c67fdd4 100644 --- a/Sources/AttributeGraph.xcframework/macos-arm64e/AttributeGraph.framework/Modules/AttributeGraph.swiftmodule/arm64e-apple-macos.swiftinterface +++ b/Sources/AttributeGraph.xcframework/macos-arm64e/AttributeGraph.framework/Modules/AttributeGraph.swiftmodule/arm64e-apple-macos.swiftinterface @@ -63,3 +63,4 @@ extension AttributeGraph.Rule { get } } +public func compareValues(_ lhs: A, _ rhs: A, mode: AGComparisonMode = ._3) -> Swift.Bool \ No newline at end of file diff --git a/Sources/OpenGraph/TODO/compareValues.swift b/Sources/OpenGraph/TODO/compareValues.swift new file mode 100644 index 0000000..c9526e9 --- /dev/null +++ b/Sources/OpenGraph/TODO/compareValues.swift @@ -0,0 +1,11 @@ +import _OpenGraph + +public func compareValues(_ lhs: Value, _ rhs: Value, mode: OGComparisonMode = ._3) -> Bool { + withUnsafePointer(to: lhs) { p1 in + withUnsafePointer(to: rhs) { p2 in + withUnsafePointer(to: Value.self) { metatype in + OGCompareValues(p1, p2, metatype, mode) + } + } + } +} diff --git a/Sources/OpenSwiftUI/DataAndStorage/Internal/Property/TODO/PropertyList.swift b/Sources/OpenSwiftUI/DataAndStorage/Internal/Property/TODO/PropertyList.swift index 57a4149..8195c4b 100644 --- a/Sources/OpenSwiftUI/DataAndStorage/Internal/Property/TODO/PropertyList.swift +++ b/Sources/OpenSwiftUI/DataAndStorage/Internal/Property/TODO/PropertyList.swift @@ -7,6 +7,12 @@ // Status: Empty // ID: 2B32D570B0B3D2A55DA9D4BFC1584D20 +#if OPENSWIFTUI_USE_AG +internal import AttributeGraph +#else +internal import OpenGraph +#endif + @usableFromInline @frozen struct PropertyList: CustomStringConvertible { @@ -16,17 +22,37 @@ struct PropertyList: CustomStringConvertible { @inlinable init() { elements = nil } + // TODO: See Element implementatation @usableFromInline var description: String { - "TODO" + var description = "[" + var elements = elements + while let element = elements { + description.append(element.description) + elements = element.after + if elements != nil { + description.append(", ") + } + } + description.append("]") + return description + } + + // TODO + subscript(_ key: Key.Type) -> Key.Value { + get { fatalError("TODO") } + set { fatalError("TODO") } } } extension PropertyList { @usableFromInline class Element: CustomStringConvertible { + // 0x10 let keyType: Any.Type + // 0x18 let before: Element? + // 0x20 let after: Element? let length: Int let keyFilter: BloomFilter @@ -59,6 +85,49 @@ extension PropertyList { // extension PropertyList { // class Tracker { // @UnsafeLockedPointer -// var data: TrackerData +// var data: TrackerData // 0x10 // } // } + + +private struct TrackerData { + var plistID: UniqueID + var values: [ObjectIdentifier : AnyTrackedValue] + var derivedValues: [ObjectIdentifier : AnyTrackedValue] + var invalidValues: [AnyTrackedValue] + var unrecordedDependencies: Bool +} + + +private protocol AnyTrackedValue { + func unwrap() -> Value + func hasMatchingValue(in: PropertyList) -> Bool +} + +private struct TrackedValue: AnyTrackedValue { + var value: Key.Value + + func unwrap() -> Value { + value as! Value + } + + func hasMatchingValue(in plist: PropertyList) -> Bool { + compareValues(value, plist[Key.self]) + } +} + +private struct DerivedValue: AnyTrackedValue { + var value: Key.Value + + func unwrap() -> Value { + value as! Value + } + + func hasMatchingValue(in plist: PropertyList) -> Bool { + value == Key.value(in: plist) + } +} + +private struct EmptyKey: PropertyKey { + static var defaultValue: Void { () } +} diff --git a/Sources/OpenSwiftUI/Internal/Graph/TODO/_GraphValue.swift b/Sources/OpenSwiftUI/Internal/Graph/TODO/_GraphValue.swift index 8b6b8ce..7f790f3 100644 --- a/Sources/OpenSwiftUI/Internal/Graph/TODO/_GraphValue.swift +++ b/Sources/OpenSwiftUI/Internal/Graph/TODO/_GraphValue.swift @@ -8,7 +8,8 @@ public struct _GraphValue: Equatable { var value: Attribute public subscript(keyPath: KeyPath) -> _GraphValue { - _GraphValue(value[keyPath]) +// _GraphValue(value[keyPath]) + fatalError() } public static func == (a: _GraphValue, b: _GraphValue) -> Bool { diff --git a/Sources/_OpenGraph/OGCompareValues.cpp b/Sources/_OpenGraph/OGCompareValues.cpp new file mode 100644 index 0000000..f2ab722 --- /dev/null +++ b/Sources/_OpenGraph/OGCompareValues.cpp @@ -0,0 +1,13 @@ +// +// OGCompareValues.cpp +// +// +// Created by Kyle on 2023/12/20. +// + +#include "OGCompareValues.hpp" + +bool OGCompareValues(const void *lhs, const void *rhs, const void *type, const OGComparisonMode comparisonMode) { + // FIXME: Implement this function + return false; +} diff --git a/Sources/_OpenGraph/include/OGCompareValues.hpp b/Sources/_OpenGraph/include/OGCompareValues.hpp new file mode 100644 index 0000000..782856a --- /dev/null +++ b/Sources/_OpenGraph/include/OGCompareValues.hpp @@ -0,0 +1,20 @@ +// +// OGCompareValues.hpp +// +// +// Created by Kyle on 2023/10/9. +// + +#ifndef OGCompareValues_hpp +#define OGCompareValues_hpp + +#include +#include "OGComparisonMode.hpp" +#include + +OF_EXTERN_C_BEGIN +OF_EXPORT +bool OGCompareValues(const void *lhs, const void *rhs, const void *type, const OGComparisonMode comparisonMode); +OF_EXTERN_C_END + +#endif /* OGCompareValues_hpp */ diff --git a/Tests/OpenGraphCompatibilityTests/AGCompareValuesTests.swift b/Tests/OpenGraphCompatibilityTests/AGCompareValuesTests.swift new file mode 100644 index 0000000..4654249 --- /dev/null +++ b/Tests/OpenGraphCompatibilityTests/AGCompareValuesTests.swift @@ -0,0 +1,72 @@ +// +// AGCompareValuesTests.swift +// +// +// Created by Kyle on 2023/12/20. +// + +import XCTest +#if OPENGRAPH_COMPATIBILITY_TEST +import AttributeGraph +#else +import OpenGraph +#endif + +final class AGCompareValuesTests: XCTestCase { + override func setUp() async throws { + #if !OPENGRAPH_COMPATIBILITY_TEST + throw XCTSkip("OG implementation for compareValues is not ready") + #endif + } + + func testIntCompare() throws { + XCTAssertTrue(compareValues(1, 1)) + XCTAssertFalse(compareValues(1, 2)) + } + + func testEnumCompare() throws { + enum A { case a, b } + XCTAssertTrue(compareValues(A.a, A.a)) + XCTAssertFalse(compareValues(A.a, A.b)) + + enum B { case a, b, c } + let b = B.b + withUnsafePointer(to: b) { p in + p.withMemoryRebound(to: A.self, capacity: MemoryLayout.size) { pointer in + XCTAssertTrue(compareValues(pointer.pointee, A.b)) + } + } + withUnsafePointer(to: b) { p in + p.withMemoryRebound(to: A.self, capacity: MemoryLayout.size) { pointer in + XCTAssertFalse(compareValues(pointer.pointee, A.a)) + } + } + } + + func testStructCompare() throws { + struct A1{ + var a: Int + var b: Bool + } + struct A2 { + var a: Int + var b: Bool + } + let a = A1(a: 1, b: true) + let b = A1(a: 1, b: true) + let c = A1(a: 1, b: false) + XCTAssertTrue(compareValues(b, a)) + XCTAssertFalse(compareValues(c, a)) + let d = A2(a: 1, b: true) + withUnsafePointer(to: d) { p in + p.withMemoryRebound(to: A1.self, capacity: MemoryLayout.size) { pointer in + XCTAssertTrue(compareValues(pointer.pointee, a)) + } + } + withUnsafePointer(to: d) { p in + p.withMemoryRebound(to: A1.self, capacity: MemoryLayout.size) { pointer in + XCTAssertFalse(compareValues(pointer.pointee, c)) + } + } + } +} diff --git a/Tests/OpenGraphCompatibilityTests/README.md b/Tests/OpenGraphCompatibilityTests/README.md new file mode 100644 index 0000000..bdca1ef --- /dev/null +++ b/Tests/OpenGraphCompatibilityTests/README.md @@ -0,0 +1,11 @@ +## OpenSwiftUICompatibilityTests + +Test public API of OpenGraph and run it against with AttributeGraph on Apple Platform. + +```swift +#if OPENGRAPH_COMPATIBILITY_TEST +import AttributeGraph +#else +import OpenGraph +#endif +``` diff --git a/Tests/AttributeGraphTests/RuleTests.swift b/Tests/OpenGraphCompatibilityTests/RuleTests.swift similarity index 84% rename from Tests/AttributeGraphTests/RuleTests.swift rename to Tests/OpenGraphCompatibilityTests/RuleTests.swift index 9edb94b..3d02261 100644 --- a/Tests/AttributeGraphTests/RuleTests.swift +++ b/Tests/OpenGraphCompatibilityTests/RuleTests.swift @@ -6,10 +6,13 @@ // import XCTest +#if OPENGRAPH_COMPATIBILITY_TEST import AttributeGraph +#else +import OpenGraph +#endif final class RuleTests: XCTestCase { - func testRuleInitialValue() throws { struct A: Rule { typealias Value = Int diff --git a/Tests/OpenGraphCompatibilityTests/UniqueIDTests.swift b/Tests/OpenGraphCompatibilityTests/UniqueIDTests.swift new file mode 100644 index 0000000..a7ef0b6 --- /dev/null +++ b/Tests/OpenGraphCompatibilityTests/UniqueIDTests.swift @@ -0,0 +1,30 @@ +// +// UniqueIDTests.swift +// +// +// Created by Kyle on 2023/10/9. +// + +import XCTest +#if OPENGRAPH_COMPATIBILITY_TEST +import AttributeGraph +#else +import OpenGraph +#endif + +final class UniqueIDTests: XCTestCase { + #if OPENGRAPH_COMPATIBILITY_TEST + private func makeUniqueID() -> AGUniqueID { + AGMakeUniqueID() + } + #else + private func makeUniqueID() -> OGUniqueID { + OGMakeUniqueID() + } + #endif + + func testUniqueID() throws { + XCTAssertEqual(makeUniqueID(), 1) + XCTAssertEqual(makeUniqueID(), 2) + } +} diff --git a/Tests/OpenGraphTests/DummyTests.swift b/Tests/OpenGraphTests/DummyTests.swift new file mode 100644 index 0000000..0b02a12 --- /dev/null +++ b/Tests/OpenGraphTests/DummyTests.swift @@ -0,0 +1,13 @@ +// +// DummyTests.swift +// +// +// Created by Kyle on 2023/12/20. +// + +import XCTest +@testable import OpenGraph + +final class DummyTests: XCTestCase { + func testExample() throws {} +} diff --git a/Tests/OpenGraphTests/UniqueIDTests.swift b/Tests/OpenGraphTests/UniqueIDTests.swift deleted file mode 100644 index b14b08f..0000000 --- a/Tests/OpenGraphTests/UniqueIDTests.swift +++ /dev/null @@ -1,16 +0,0 @@ -// -// UniqueIDTests.swift -// -// -// Created by Kyle on 2023/10/9. -// - -import XCTest -import OpenGraph - -final class UniqueIDTests: XCTestCase { - func testUniqueID() throws { - XCTAssertEqual(OGMakeUniqueID(), 1) - XCTAssertEqual(OGMakeUniqueID(), 2) - } -}