diff --git a/Sources/OpenAttributeGraph/Attribute/Attribute/Attribute.swift b/Sources/OpenAttributeGraph/Attribute/Attribute/Attribute.swift index 716eb10b..688bc028 100644 --- a/Sources/OpenAttributeGraph/Attribute/Attribute/Attribute.swift +++ b/Sources/OpenAttributeGraph/Attribute/Attribute/Attribute.swift @@ -289,11 +289,27 @@ extension Attribute { } } + public init(_ rule: R, initialValue: Value) where R.Value == Value { + self = withUnsafePointer(to: rule) { pointer in + withUnsafePointer(to: initialValue) { initialValuePointer in + Attribute(body: pointer, value: initialValuePointer) { R._update } + } + } + } + public init(_ rule: R) where R.Value == Value { self = withUnsafePointer(to: rule) { pointer in Attribute(body: pointer, value: nil) { R._update } } } + + public init(_ rule: R, initialValue: Value) where R.Value == Value { + self = withUnsafePointer(to: rule) { pointer in + withUnsafePointer(to: initialValue) { initialValuePointer in + Attribute(body: pointer, value: initialValuePointer) { R._update } + } + } + } } @_silgen_name("OAGGraphCreateAttribute") diff --git a/Sources/OpenAttributeGraph/Attribute/Body/AttributeBodyVisitor.swift b/Sources/OpenAttributeGraph/Attribute/Body/AttributeBodyVisitor.swift index d85fbf42..e7b825dd 100644 --- a/Sources/OpenAttributeGraph/Attribute/Body/AttributeBodyVisitor.swift +++ b/Sources/OpenAttributeGraph/Attribute/Body/AttributeBodyVisitor.swift @@ -5,5 +5,5 @@ // Status: WIP public protocol AttributeBodyVisitor { - func visit(body: UnsafePointer) + mutating func visit(body: UnsafePointer) } diff --git a/Sources/OpenAttributeGraph/Attribute/Indirect/IndirectAttribute.swift b/Sources/OpenAttributeGraph/Attribute/Indirect/IndirectAttribute.swift index ceb3ba6d..81c5e419 100644 --- a/Sources/OpenAttributeGraph/Attribute/Indirect/IndirectAttribute.swift +++ b/Sources/OpenAttributeGraph/Attribute/Indirect/IndirectAttribute.swift @@ -15,11 +15,19 @@ public struct IndirectAttribute { identifier = source.identifier.createIndirect(size: UInt64(MemoryLayout.size)) } + public var attribute: Attribute { + Attribute(identifier: identifier) + } + public var source: Attribute { get { Attribute(identifier: identifier.source) } nonmutating set { identifier.source = newValue.identifier } } + public func resetSource() { + __OAGGraphResetIndirectAttribute(identifier, false) + } + public var dependency: AnyAttribute? { get { let dependency = identifier._indirectDependency diff --git a/Sources/OpenAttributeGraphCxx/Attribute/OAGAttribute.cpp b/Sources/OpenAttributeGraphCxx/Attribute/OAGAttribute.cpp index 5042935f..38fefd44 100644 --- a/Sources/OpenAttributeGraphCxx/Attribute/OAGAttribute.cpp +++ b/Sources/OpenAttributeGraphCxx/Attribute/OAGAttribute.cpp @@ -103,6 +103,10 @@ void OAGGraphSetIndirectAttribute(OAGAttribute attribute1, OAGAttribute attribut // TODO } +void OAGGraphResetIndirectAttribute(OAGAttribute attribute, bool non_nil) { + // TODO +} + OAGAttribute OAGGraphCreateAttribute(long index, const void *body, const void * value) { // TODO return OAGAttributeNil; diff --git a/Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGAttribute.h b/Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGAttribute.h index 44312958..9eb3ed4d 100644 --- a/Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGAttribute.h +++ b/Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGAttribute.h @@ -89,6 +89,10 @@ OAG_EXPORT OAG_REFINED_FOR_SWIFT void OAGGraphSetIndirectAttribute(OAGAttribute attribute1, OAGAttribute attribute2) OAG_SWIFT_NAME(setter:OAGAttribute.source(self:_:)); +OAG_EXPORT +OAG_REFINED_FOR_SWIFT +void OAGGraphResetIndirectAttribute(OAGAttribute attribute, bool non_nil); + OAG_EXPORT OAG_REFINED_FOR_SWIFT OAGAttribute OAGGraphCreateAttribute(long index, const void *body, const void * _Nullable value); diff --git a/Tests/OpenAttributeGraphCompatibilityTests/Attribute/Attribute/AttributeCompatibilityTests.swift b/Tests/OpenAttributeGraphCompatibilityTests/Attribute/Attribute/AttributeCompatibilityTests.swift index 9405c9e9..35945951 100644 --- a/Tests/OpenAttributeGraphCompatibilityTests/Attribute/Attribute/AttributeCompatibilityTests.swift +++ b/Tests/OpenAttributeGraphCompatibilityTests/Attribute/Attribute/AttributeCompatibilityTests.swift @@ -14,6 +14,37 @@ struct AttributeCompatibilityTests { #expect(intAttribute.value == 0) } + @Test + func initWithRule() { + struct TestRule: Rule { + var value: Int { + return 0 + } + } + let attribute1 = Attribute(TestRule()) + #expect(attribute1.value == 0) + + let attribute2 = Attribute(TestRule(), initialValue: 1) + #expect(attribute2.value == 1) + } + + @Test + func initWithStatefulRule() { + struct TestStatefuleRule: StatefulRule { + typealias Value = Int + func updateValue() { + withUnsafePointer(to: 0) { ptr in + Graph.setOutputValue(ptr) + } + } + } + let attribute1 = Attribute(TestStatefuleRule()) + #expect(attribute1.value == 0) + + let attribute2 = Attribute(TestStatefuleRule(), initialValue: 1) + #expect(attribute2.value == 1) + } + @Test func hashableAndEquatable() { let a = Attribute(identifier: .nil) diff --git a/Tests/OpenAttributeGraphCompatibilityTests/Attribute/Indirect/IndirectAttributeCompatibilityTests.swift b/Tests/OpenAttributeGraphCompatibilityTests/Attribute/Indirect/IndirectAttributeCompatibilityTests.swift index a9077464..21c6bd7f 100644 --- a/Tests/OpenAttributeGraphCompatibilityTests/Attribute/Indirect/IndirectAttributeCompatibilityTests.swift +++ b/Tests/OpenAttributeGraphCompatibilityTests/Attribute/Indirect/IndirectAttributeCompatibilityTests.swift @@ -12,9 +12,24 @@ struct IndirectAttributeCompatibilityTests { func basic() { let source = Attribute(value: 0) let indirect = IndirectAttribute(source: source) + #expect(indirect.attribute.identifier == indirect.identifier) #expect(indirect.identifier != source.identifier) #expect(indirect.source.identifier == source.identifier) #expect(indirect.dependency == .init(rawValue: 0)) } + + @Test + func resetSource() { + let source1 = Attribute(value: 0) + let indirect = IndirectAttribute(source: source1) + #expect(indirect.source.identifier == source1.identifier) + + let source2 = Attribute(value: 0) + indirect.source = source2 + #expect(indirect.source.identifier == source2.identifier) + + indirect.resetSource() + #expect(indirect.source.identifier == source1.identifier) + } } #endif