Skip to content

Commit 54315c4

Browse files
committed
Update UnaryElements
1 parent 76262dd commit 54315c4

File tree

4 files changed

+164
-41
lines changed

4 files changed

+164
-41
lines changed

Sources/OpenSwiftUICore/Graph/GraphReuse.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ package import OpenGraphShims
1212
package typealias Subgraph = OGSubgraph
1313
package typealias Graph = OGGraph
1414

15-
package final class IndirectAttributeMap {
15+
public final class IndirectAttributeMap {
1616
#if canImport(Darwin)
1717
package final let subgraph: Subgraph
1818
package final var map: [AnyAttribute: AnyAttribute]

Sources/OpenSwiftUICore/Graph/ReuseTrace.swift

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,23 @@ package struct ReuseTrace {
3434
package static func traceReuseViewInputsDifferentFailure() {
3535
traceReuseFailure("reuse_inputsDifferent")
3636
}
37-
37+
38+
@inline(__always)
39+
package static func traceReuseUnaryElementExpectedFailure(_ elementType: any Any.Type) {
40+
traceReuseFailure("reuse_unaryElement")
41+
}
42+
3843
@inline(__always)
3944
package static func traceReuseInvalidSubgraphFailure(_ typeFoundInvalid: any Any.Type) {
4045
// FIXME: ReuseTraceInternal.InvalidSubgraphFailure
4146
traceReuseFailure("reuse_invalidSubgraph")
4247
}
43-
48+
49+
@inline(__always)
50+
package static func traceReuseBodyMismatchedFailure() {
51+
traceReuseFailure("reuse_bodyMismatched")
52+
}
53+
4454
// TODO
4555

4656
final package class Recorder {

Sources/OpenSwiftUICore/Modifier/ViewModifier/CustomViewModifier.swift

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,56 @@ extension _ViewModifier_Content {
139139
}
140140
}
141141
}
142+
143+
// MARK: - BodyInput
144+
145+
// FIXME
146+
private struct BodyInput<Input> {}
147+
148+
private enum BodyInputElement: GraphReusable, Equatable {
149+
typealias MakeViewBody = (_Graph, _ViewInputs) -> _ViewOutputs
150+
typealias MakeViewListBody = (_Graph, _ViewListInputs) -> _ViewListOutputs
151+
152+
case view(MakeViewBody)
153+
case list(MakeViewListBody)
154+
155+
static func == (lhs: BodyInputElement, rhs: BodyInputElement) -> Bool {
156+
if case let .view(lhsBody) = lhs, case let .view(rhsBody) = rhs {
157+
compareValues(lhsBody, rhsBody, options: .init(rawValue: 0x103))
158+
} else if case let .list(lhsBody) = lhs, case let .list(rhsBody) = rhs{
159+
compareValues(lhsBody, rhsBody, options: .init(rawValue: 0x103))
160+
} else {
161+
false
162+
}
163+
}
164+
165+
static var isTriviallyReusable: Bool {
166+
_SemanticFeature_v5.isEnabled
167+
}
168+
169+
func makeReusable(indirectMap: IndirectAttributeMap) {
170+
return
171+
}
172+
173+
func tryToReuse(by other: BodyInputElement, indirectMap: IndirectAttributeMap, testOnly: Bool) -> Bool {
174+
switch self {
175+
case let .view(makeViewBody):
176+
guard case let .view(otherMakeViewBody) = other else {
177+
ReuseTrace.traceReuseInternalFailure()
178+
return false
179+
}
180+
return Self.isTriviallyReusable || compareValues(makeViewBody, otherMakeViewBody, options: .init(rawValue: 0x103))
181+
case let .list(makeViewListBody):
182+
guard case let .list(otherMakeViewListBody) = other else {
183+
ReuseTrace.traceReuseInternalFailure()
184+
return false
185+
}
186+
return Self.isTriviallyReusable || compareValues(makeViewListBody, otherMakeViewListBody, options: .init(rawValue: 0x103))
187+
}
188+
}
189+
}
190+
191+
192+
private struct BodyCountInput<V>: ViewInput {
193+
static var defaultValue: Stack<_ViewListCountInputs> { .init() }
194+
}

Sources/OpenSwiftUICore/View/Input/ViewList.swift

Lines changed: 98 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,60 +1044,62 @@ open class _ViewList_ID_Views: RandomAccessCollection, Equatable {
10441044
@available(*, unavailable)
10451045
extension ViewList.ID.Views: Sendable {}
10461046

1047-
// MARK: - ViewListOutputs + Extension [TODO]
1047+
// MARK: - UnaryViewGenerator
10481048

1049-
extension _ViewListOutputs {
1050-
private static func staticList(_ elements: any ViewList.Elements, inputs: _ViewListInputs, staticCount: Int) -> _ViewListOutputs {
1051-
preconditionFailure("TODO")
1052-
}
1049+
public protocol UnaryViewGenerator {
1050+
func makeView(inputs: _ViewInputs, indirectMap: IndirectAttributeMap?) -> _ViewOutputs
1051+
func tryToReuse(by other: Self, indirectMap: IndirectAttributeMap, testOnly: Bool) -> Bool
1052+
}
10531053

1054-
package static func unaryViewList<V>(view: _GraphValue<V>, inputs: _ViewListInputs) -> _ViewListOutputs where V: View {
1055-
preconditionFailure("TODO")
1056-
}
1054+
public struct BodyUnaryViewGenerator<V>: UnaryViewGenerator {
1055+
let body: ViewList.Elements.MakeElement
10571056

1058-
package static func unaryViewList<T>(viewType: T.Type = T.self, inputs: _ViewListInputs, body: @escaping (_ViewInputs) -> _ViewOutputs) -> _ViewListOutputs {
1059-
preconditionFailure("TODO")
1057+
public func makeView(inputs: _ViewInputs, indirectMap: IndirectAttributeMap?) -> _ViewOutputs {
1058+
body(inputs)
10601059
}
10611060

1062-
package static func emptyViewList(inputs: _ViewListInputs) -> _ViewListOutputs {
1063-
if inputs.options.contains(.isNonEmptyParent) {
1064-
nonEmptyParentViewList(inputs: inputs)
1065-
} else {
1066-
staticList(EmptyViewListElements(), inputs: inputs, staticCount: 0)
1061+
public func tryToReuse(by other: BodyUnaryViewGenerator<V>, indirectMap: IndirectAttributeMap, testOnly: Bool) -> Bool {
1062+
// FIXME
1063+
// 1. pass body to OGCompareValues directly instaed of withUnsafePointer
1064+
// 2. Add 0x103 case instead of rawValue
1065+
guard compareValues(body, other.body, mode: .init(rawValue: 0x103)) else {
1066+
ReuseTrace.traceReuseBodyMismatchedFailure()
1067+
Log.graphReuse("Reuse failed: \(Self.self) failed comparison")
1068+
return false
10671069
}
1070+
return true
10681071
}
1072+
}
10691073

1070-
static func nonEmptyParentViewList(inputs: _ViewListInputs) -> _ViewListOutputs {
1071-
preconditionFailure("TODO")
1072-
}
1073-
1074-
package func makeAttribute(inputs: _ViewListInputs) -> Attribute<any ViewList> {
1075-
preconditionFailure("TODO")
1076-
}
1077-
1078-
package func makeAttribute(viewInputs: _ViewInputs) -> Attribute<any ViewList> {
1079-
preconditionFailure("TODO")
1080-
}
1081-
1082-
package static func makeModifiedList(list: Attribute<any ViewList>, modifier: ListModifier?) -> Attribute<any ViewList> {
1083-
preconditionFailure("TODO")
1084-
}
1074+
public struct TypedUnaryViewGenerator<V>: UnaryViewGenerator where V: View {
1075+
let view: WeakAttribute<V>
10851076

1086-
package mutating func multiModifier<T>(_ modifier: _GraphValue<T>, inputs: _ViewListInputs) where T: ViewModifier {
1087-
preconditionFailure("TODO")
1077+
public func makeView(inputs: _ViewInputs, indirectMap: IndirectAttributeMap?) -> _ViewOutputs {
1078+
guard var view = view.attribute else {
1079+
return .init()
1080+
}
1081+
if let indirectMap {
1082+
view.makeReusable(indirectMap: indirectMap)
1083+
}
1084+
return V.makeDebuggableView(view: _GraphValue(view), inputs: inputs)
10881085
}
10891086

1090-
package static func concat(_ outputs: [_ViewListOutputs], inputs: _ViewListInputs) -> _ViewListOutputs {
1091-
preconditionFailure("TODO")
1087+
public func tryToReuse(by other: TypedUnaryViewGenerator<V>, indirectMap: IndirectAttributeMap, testOnly: Bool) -> Bool {
1088+
guard let view = view.attribute, let otherView = other.view.attribute else {
1089+
Log.graphReuse("Reuse failed: missing attribute for \(V.self)")
1090+
return false
1091+
}
1092+
return view.tryToReuse(by: otherView, indirectMap: indirectMap, testOnly: testOnly)
10921093
}
10931094
}
10941095

1095-
// TODO:
1096-
private struct UnaryElements<Value>: ViewList.Elements {
1097-
var body: Value
1096+
// MARK: - UnaryElements
1097+
1098+
private struct UnaryElements<Generator>: ViewList.Elements where Generator: UnaryViewGenerator {
1099+
var body: Generator
10981100
var baseInputs: _GraphInputs
10991101

1100-
init(body: Value, baseInputs: _GraphInputs) {
1102+
init(body: Generator, baseInputs: _GraphInputs) {
11011103
self.body = body
11021104
self.baseInputs = baseInputs
11031105
}
@@ -1120,6 +1122,64 @@ private struct UnaryElements<Value>: ViewList.Elements {
11201122
indirectMap: IndirectAttributeMap,
11211123
testOnly: Bool
11221124
) -> Bool {
1125+
guard let other = other as? UnaryElements else {
1126+
Log.graphReuse("Reuse failed: other is not Unary")
1127+
ReuseTrace.traceReuseUnaryElementExpectedFailure(type(of: other))
1128+
return false
1129+
}
1130+
// BodyInput
1131+
preconditionFailure("TODO")
1132+
}
1133+
}
1134+
1135+
// MARK: - ViewListOutputs + Extension [TODO]
1136+
1137+
extension _ViewListOutputs {
1138+
private static func staticList(_ elements: any ViewList.Elements, inputs: _ViewListInputs, staticCount: Int) -> _ViewListOutputs {
1139+
preconditionFailure("TODO")
1140+
}
1141+
1142+
static func nonEmptyParentViewList(inputs: _ViewListInputs) -> _ViewListOutputs {
1143+
preconditionFailure("TODO")
1144+
}
1145+
1146+
package static func unaryViewList<V>(view: _GraphValue<V>, inputs: _ViewListInputs) -> _ViewListOutputs where V: View {
1147+
let generator = TypedUnaryViewGenerator(view: .init(view.value))
1148+
let elements = UnaryElements(body: generator, baseInputs: inputs.base)
1149+
return staticList(elements, inputs: inputs, staticCount: 1)
1150+
}
1151+
1152+
package static func unaryViewList<T>(viewType: T.Type = T.self, inputs: _ViewListInputs, body: @escaping ViewList.Elements.MakeElement) -> _ViewListOutputs {
1153+
let generator = BodyUnaryViewGenerator<T>(body: body)
1154+
let elements = UnaryElements(body: generator, baseInputs: inputs.base)
1155+
return staticList(elements, inputs: inputs, staticCount: 1)
1156+
}
1157+
1158+
package static func emptyViewList(inputs: _ViewListInputs) -> _ViewListOutputs {
1159+
if inputs.options.contains(.isNonEmptyParent) {
1160+
nonEmptyParentViewList(inputs: inputs)
1161+
} else {
1162+
staticList(EmptyViewListElements(), inputs: inputs, staticCount: 0)
1163+
}
1164+
}
1165+
1166+
package func makeAttribute(inputs: _ViewListInputs) -> Attribute<any ViewList> {
1167+
preconditionFailure("TODO")
1168+
}
1169+
1170+
package func makeAttribute(viewInputs: _ViewInputs) -> Attribute<any ViewList> {
1171+
preconditionFailure("TODO")
1172+
}
1173+
1174+
package static func makeModifiedList(list: Attribute<any ViewList>, modifier: ListModifier?) -> Attribute<any ViewList> {
1175+
preconditionFailure("TODO")
1176+
}
1177+
1178+
package mutating func multiModifier<T>(_ modifier: _GraphValue<T>, inputs: _ViewListInputs) where T: ViewModifier {
1179+
preconditionFailure("TODO")
1180+
}
1181+
1182+
package static func concat(_ outputs: [_ViewListOutputs], inputs: _ViewListInputs) -> _ViewListOutputs {
11231183
preconditionFailure("TODO")
11241184
}
11251185
}

0 commit comments

Comments
 (0)