diff --git a/Package.resolved b/Package.resolved index fa4105d..4a23213 100644 --- a/Package.resolved +++ b/Package.resolved @@ -15,7 +15,7 @@ "location" : "https://github.com/OpenSwiftUIProject/OpenGraph", "state" : { "branch" : "main", - "revision" : "17b4ef3ead4c0c1bce51c965d6a1169f4e65c61d" + "revision" : "ca3f8991a8a9564d581a08d9ce43b216c9afe01b" } }, { diff --git a/Sources/OpenSwiftUI/DataAndStorage/EnvironmentValues/Internal/TODO/CachedEnvironment.swift b/Sources/OpenSwiftUI/DataAndStorage/EnvironmentValues/Internal/TODO/CachedEnvironment.swift new file mode 100644 index 0000000..302ebf6 --- /dev/null +++ b/Sources/OpenSwiftUI/DataAndStorage/EnvironmentValues/Internal/TODO/CachedEnvironment.swift @@ -0,0 +1 @@ +struct CachedEnvironment {} diff --git a/Sources/OpenSwiftUI/DataAndStorage/Internal/Property/PropertyList.swift b/Sources/OpenSwiftUI/DataAndStorage/Internal/Property/PropertyList.swift index ec594f8..3f89da4 100644 --- a/Sources/OpenSwiftUI/DataAndStorage/Internal/Property/PropertyList.swift +++ b/Sources/OpenSwiftUI/DataAndStorage/Internal/Property/PropertyList.swift @@ -63,8 +63,7 @@ struct PropertyList: CustomStringConvertible { if let result = find(elements.map { .passUnretained($0) }, key: keyType) { guard !compareValues( newValue, - result.takeUnretainedValue().value, - mode: ._3 + result.takeUnretainedValue().value ) else { return } @@ -270,7 +269,7 @@ private class TypedElement: PropertyList.Element { guard !ignoredTypes.contains(ObjectIdentifier(Key.self)) else { return true } - guard compareValues(value, typedElement.value, mode: ._3) else { + guard compareValues(value, typedElement.value) else { return false } ignoredTypes.insert(ObjectIdentifier(Key.self)) diff --git a/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/DynamicProperty.swift b/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/DynamicProperty.swift index e2435c9..8ded783 100644 --- a/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/DynamicProperty.swift +++ b/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/DynamicProperty.swift @@ -4,7 +4,7 @@ // // Created by Kyle on 2023/11/2. // Lastest Version: iOS 15.5 -// Status: WIP +// Status: Complete /// An interface for a stored variable that updates an external property of a /// view. @@ -12,8 +12,15 @@ /// The view gives values to these properties prior to recomputing the view's /// ``View/body-swift.property``. public protocol DynamicProperty { - static func _makeProperty(in buffer: inout _DynamicPropertyBuffer, container: _GraphValue, fieldOffset: Int, inputs: inout _GraphInputs) + static func _makeProperty( + in buffer: inout _DynamicPropertyBuffer, + container: _GraphValue, + fieldOffset: Int, + inputs: inout _GraphInputs + ) + static var _propertyBehaviors: UInt32 { get } + /// Updates the underlying value of the stored value. /// /// OpenSwiftUI calls this function before rendering a view's @@ -23,28 +30,7 @@ public protocol DynamicProperty { } extension DynamicProperty { - public static func _makeProperty(in buffer: inout _DynamicPropertyBuffer, container: _GraphValue, fieldOffset: Int, inputs: inout _GraphInputs) { - makeEmbeddedProperties(in: &buffer, container: container, fieldOffset: fieldOffset, inputs: &inputs) - // TODO - buffer.append(EmbeddedDynamicPropertyBox(), fieldOffset: fieldOffset) - } - - static func makeEmbeddedProperties(in buffer: inout _DynamicPropertyBuffer, container: _GraphValue, fieldOffset: Int, inputs: inout _GraphInputs) -> () { - let fields = DynamicPropertyCache.fields(of: self) - // TODO - buffer.addFields(fields, container: container, inputs: &inputs, baseOffset: fieldOffset) - } - - public mutating func update() {} public static var _propertyBehaviors: UInt32 { 0 } -} - -private struct EmbeddedDynamicPropertyBox: DynamicPropertyBox { - typealias Property = Value - func destroy() {} - func reset() {} - func update(property: inout Value, phase _: _GraphInputs.Phase) -> Bool { - property.update() - return false - } + + public mutating func update() {} } diff --git a/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/DynamicPropertyBehaviors.swift b/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/DynamicPropertyBehaviors.swift new file mode 100644 index 0000000..eb755ba --- /dev/null +++ b/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/DynamicPropertyBehaviors.swift @@ -0,0 +1,11 @@ +// +// DynamicPropertyBehaviors.swift +// OpenSwiftUI +// +// Created by Kyle on 2024/1/6. +// Lastest Version: iOS 15.5 +// Status: Complete + +struct DynamicPropertyBehaviors: OptionSet { + let rawValue: UInt32 +} diff --git a/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/Internal/DynamicPropertyBox.swift b/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/DynamicPropertyBox.swift similarity index 68% rename from Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/Internal/DynamicPropertyBox.swift rename to Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/DynamicPropertyBox.swift index 1813194..ae8a83c 100644 --- a/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/Internal/DynamicPropertyBox.swift +++ b/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/DynamicPropertyBox.swift @@ -11,9 +11,9 @@ protocol DynamicPropertyBox: DynamicProperty { func destroy() func reset() func update(property: inout Property, phase: _GraphInputs.Phase) -> Bool - func getState(type: S.Type) -> Binding? + func getState(type: Value.Type) -> Binding? } -extension DynamicProperty { - func getState(type: S.Type) -> Binding? { nil } +extension DynamicPropertyBox { + func getState(type _: Value.Type) -> Binding? { nil } } diff --git a/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/DynamicPropertyCache.swift b/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/DynamicPropertyCache.swift new file mode 100644 index 0000000..a151d03 --- /dev/null +++ b/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/DynamicPropertyCache.swift @@ -0,0 +1,163 @@ +// +// DynamicPropertyCache.swift +// OpenSwiftUI +// +// Created by Kyle on 2024/1/10. +// Lastest Version: iOS 15.5 +// Status: Complete +// ID: 49D2A32E637CD497C6DE29B8E060A506 + +internal import OpenGraphShims + +// MARK: - DynamicPropertyCache + +struct DynamicPropertyCache { + private static var cache = MutableBox([ObjectIdentifier: Fields]()) + + static func fields(of type: Any.Type) -> Fields { + if let fields = cache.value[ObjectIdentifier(type)] { + return fields + } + let fields: Fields + let typeID = OGTypeID(type) + switch typeID.kind { + case .enum, .optional: + var taggedFields: [TaggedFields] = [] + _ = typeID.forEachField(options: [._2, ._4]) { name, offset, fieldType in + var fields: [Field] = [] + let tupleType = OGTupleType(fieldType) + for index in tupleType.indices { + guard let dynamicPropertyType = tupleType.type(at: index) as? DynamicProperty.Type else { + break + } + let offset = tupleType.offset(at: index) + let field = Field(type: dynamicPropertyType, offset: offset, name: name) + fields.append(field) + } + if !fields.isEmpty { + let taggedField = TaggedFields(tag: offset, fields: fields) + taggedFields.append(taggedField) + } + return true + } + fields = Fields(layout: .sum(type, taggedFields)) + case .struct, .tuple: + var fieldArray: [Field] = [] + _ = typeID.forEachField(options: [._2]) { name, offset, fieldType in + guard let dynamicPropertyType = fieldType as? DynamicProperty.Type else { + return true + } + let field = Field(type: dynamicPropertyType, offset: offset, name: name) + fieldArray.append(field) + return true + } + fields = Fields(layout: .product(fieldArray)) + default: + fields = Fields(layout: .product([])) + break + } + if fields.behaviors.contains(.init(rawValue: 3)) { + Log.runtimeIssues("%s is marked async, but contains properties that require the main thread.", [_typeName(type)]) + } + cache.value[ObjectIdentifier(type)] = fields + return fields + } +} + +// MARK: - DynamicPropertyCache.Fields + +extension DynamicPropertyCache { + struct Fields { + var layout: Layout + var behaviors: DynamicPropertyBehaviors + + enum Layout { + case product([Field]) + case sum(Any.Type, [TaggedFields]) + } + + init(layout: Layout) { + var behaviors: UInt32 = 0 + switch layout { + case let .product(fields): + for field in fields { + behaviors |= field.type._propertyBehaviors + } + case let .sum(_, taggedFields): + for taggedField in taggedFields { + for field in taggedField.fields { + behaviors |= field.type._propertyBehaviors + } + } + } + self.layout = layout + self.behaviors = .init(rawValue: behaviors) + } + } +} + +// MARK: - DynamicPropertyCache.Field + +extension DynamicPropertyCache { + struct Field { + var type: DynamicProperty.Type + var offset: Int + var name: UnsafePointer? + } +} + +// MARK: - DynamicPropertyCache.TaggedFields + +extension DynamicPropertyCache { + struct TaggedFields { + var tag: Int + var fields: [Field] + } +} + +// MARK: - EmbeddedDynamicPropertyBox + +private struct EmbeddedDynamicPropertyBox: DynamicPropertyBox { + typealias Property = Value + func destroy() {} + func reset() {} + func update(property: inout Property, phase _: _GraphInputs.Phase) -> Bool { + property.update() + return false + } +} + +extension DynamicProperty { + public static func _makeProperty( + in buffer: inout _DynamicPropertyBuffer, + container: _GraphValue, + fieldOffset: Int, + inputs: inout _GraphInputs + ) { + makeEmbeddedProperties( + in: &buffer, + container: container, + fieldOffset: fieldOffset, + inputs: &inputs + ) + buffer.append( + EmbeddedDynamicPropertyBox(), + fieldOffset: fieldOffset + ) + } + + static func makeEmbeddedProperties( + in buffer: inout _DynamicPropertyBuffer, + container: _GraphValue, + fieldOffset: Int, + inputs: inout _GraphInputs + ) -> () { + let fields = DynamicPropertyCache.fields(of: self) + buffer.addFields( + fields, + container: container, + inputs: &inputs, + baseOffset: fieldOffset + ) + } +} diff --git a/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/Internal/TODO/DynamicPropertyCache.swift b/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/Internal/TODO/DynamicPropertyCache.swift deleted file mode 100644 index f7b2626..0000000 --- a/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/Internal/TODO/DynamicPropertyCache.swift +++ /dev/null @@ -1,38 +0,0 @@ - -struct DynamicPropertyCache { - // TODO - static func fields(of: Any.Type) -> Fields { - .init(layout: .product([]), behaviors: []) - } -} - -extension DynamicPropertyCache { - struct Field { - var type: DynamicProperty.Type - var offset: Int - var name: UnsafePointer? - } - - struct Fields { - var layout: Layout - var behaviors: DynamicPropertyBehaviors - - enum Layout { - case product([Field]) - case sum(Any.Type, [TaggedFields]) - } - } -} - -extension DynamicPropertyCache { - struct TaggedFields { - var tag: Int - var fields: [Field] - var name: UnsafePointer? - } -} - - -struct DynamicPropertyBehaviors: OptionSet { - let rawValue: UInt32 -} diff --git a/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/TODO/_DynamicPropertyBuffer.swift b/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/TODO/_DynamicPropertyBuffer.swift deleted file mode 100644 index bc5cde5..0000000 --- a/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/TODO/_DynamicPropertyBuffer.swift +++ /dev/null @@ -1,20 +0,0 @@ -// -// _DynamicPropertyBuffer.swift -// OpenSwiftUI -// -// Created by Kyle on 2023/9/24. -// Lastest Version: iOS 15.5 -// Status: Complete - -public struct _DynamicPropertyBuffer { - var buf: UnsafeMutableRawPointer - var size: Int32 - var _count: Int32 - - func append(_ box: Box, fieldOffset: Int) { - } - - func addFields(_ fields: DynamicPropertyCache.Fields, container: _GraphValue, inputs: inout _GraphInputs, baseOffset: Int) { - - } -} diff --git a/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/_DynamicPropertyBuffer.swift b/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/_DynamicPropertyBuffer.swift new file mode 100644 index 0000000..352cae4 --- /dev/null +++ b/Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/_DynamicPropertyBuffer.swift @@ -0,0 +1,103 @@ +// +// _DynamicPropertyBuffer.swift +// OpenSwiftUI +// +// Created by Kyle on 2023/9/24. +// Lastest Version: iOS 15.5 +// Status: WIP +// ID: 68550FF604D39F05971FE35A26EE75B0 + +private let nullPtr: UnsafeMutableRawPointer = Unmanaged.passUnretained(unsafeBitCast(0, to: AnyObject.self)).toOpaque() + +public struct _DynamicPropertyBuffer { + var buf: UnsafeMutableRawPointer + var size: Int32 + var _count: Int32 + + init() { + buf = nullPtr + size = 0 + _count = 0 + } + + init( + fields: DynamicPropertyCache.Fields, + container: _GraphValue, + inputs: inout _GraphInputs, + baseOffset: Int + ) { + self.init() + addFields(fields, container: container, inputs: &inputs, baseOffset: baseOffset) + } + + + mutating func addFields( + _ fields: DynamicPropertyCache.Fields, + container: _GraphValue, + inputs: inout _GraphInputs, + baseOffset: Int + ) { + switch fields.layout { + case let .product(fieldArray): + for field in fieldArray { + field.type._makeProperty( + in: &self, + container: container, + fieldOffset: field.offset + baseOffset, + inputs: &inputs + ) + } + case let .sum(_, taggedFields): + guard !taggedFields.isEmpty else { + return + } + // TODO + } + } + + func append(_: some DynamicPropertyBox, fieldOffset _: Int) { + // TODO + } +} + +extension _DynamicPropertyBuffer { + private struct Item { + var vtable: BoxVTableBase.Type + var size: Int32 + var _fieldOffsetAndLastChanged: UInt32 + + init(vtable: BoxVTableBase, size: Int, fieldOffset: Int) { + + fatalError("TODO") + +// self.vtable = vtable +// self.size = size +// self._fieldOffsetAndLastChanged = _fieldOffsetAndLastChanged +// if size < 0 { +// +// } else { +// +// } + } + } +} + +// MARK: - BoxVTableBase + +private class BoxVTableBase { + static func moveInitialize(ptr _: UnsafeMutableRawPointer, from _: UnsafeMutableRawPointer) { + fatalError() + } + + static func deinitialize(ptr _: UnsafeMutableRawPointer) {} + + static func reset(ptr _: UnsafeMutableRawPointer) {} + + static func update(ptr _: UnsafeMutableRawPointer, property _: UnsafeMutableRawPointer, phase _: _GraphInputs.Phase) -> Bool { + false + } + + static func getState(ptr _: UnsafeMutableRawPointer, type _: Value.Type) -> Binding? { + nil + } +} diff --git a/Sources/OpenSwiftUI/Internal/Graph/TODO/_GraphInputs.swift b/Sources/OpenSwiftUI/Internal/Graph/TODO/_GraphInputs.swift index 7e08ac8..e31cfbb 100644 --- a/Sources/OpenSwiftUI/Internal/Graph/TODO/_GraphInputs.swift +++ b/Sources/OpenSwiftUI/Internal/Graph/TODO/_GraphInputs.swift @@ -1,13 +1,13 @@ internal import OpenGraphShims public struct _GraphInputs { -// var customInputs: PropertyList + var customInputs: PropertyList var time: Attribute