Skip to content

Commit

Permalink
enumerate superclass property keyPaths
Browse files Browse the repository at this point in the history
  • Loading branch information
lhoward committed Jul 31, 2023
1 parent c23866d commit 572692d
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 16 deletions.
34 changes: 34 additions & 0 deletions Sources/SwiftOCA/OCA/OCF/MirrorWrapper.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//
// Copyright (c) 2023 PADL Software Pty Ltd
//
// Licensed under the Apache License, Version 2.0 (the License);
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an 'AS IS' BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import Foundation

// we don't want to add public Equatable / Hashable conformances to Mirror, so wrap it.
public struct _MirrorWrapper: Equatable, Hashable {
public let wrappedValue: Mirror

public init(_ wrappedValue: Mirror) {
self.wrappedValue = wrappedValue
}

public static func == (lhs: _MirrorWrapper, rhs: _MirrorWrapper) -> Bool {
lhs.wrappedValue.description == rhs.wrappedValue.description
}

public func hash(into hasher: inout Hasher) {
wrappedValue.description.hash(into: &hasher)
}
}
23 changes: 15 additions & 8 deletions Sources/SwiftOCA/OCC/ControlClasses/Root.swift
Original file line number Diff line number Diff line change
Expand Up @@ -131,19 +131,26 @@ private extension String {
}

public extension OcaRoot {
private subscript(checkedMirrorDescendant key: String) -> Any {
Mirror(reflecting: self).descendant(key)!
private subscript(_ wrapper: _MirrorWrapper, checkedMirrorDescendant key: String) -> Any {
wrapper.wrappedValue.descendant(key)!
}

private var allKeyPaths: [String: PartialKeyPath<OcaRoot>] {
// TODO: Mirror is inefficient
var membersToKeyPaths = [String: PartialKeyPath<OcaRoot>]()
let mirror = Mirror(reflecting: self)
for case let (key?, _) in mirror.children {
guard let dictionaryKey = key.deletingPrefix("_") else { continue }
membersToKeyPaths[dictionaryKey] = \Self
.[checkedMirrorDescendant: key] as PartialKeyPath
}
var mirror: Mirror? = Mirror(reflecting: self)

repeat {
if let mirror {
for case let (key?, _) in mirror.children {
guard let dictionaryKey = key.deletingPrefix("_") else { continue }
membersToKeyPaths[dictionaryKey] = \Self
.[_MirrorWrapper(mirror), checkedMirrorDescendant: key] as PartialKeyPath
}
}
mirror = mirror?.superclassMirror
} while mirror != nil

return membersToKeyPaths
}

Expand Down
22 changes: 14 additions & 8 deletions Sources/SwiftOCADevice/OCC/ControlClasses/Root.swift
Original file line number Diff line number Diff line change
Expand Up @@ -235,20 +235,26 @@ extension OcaRoot: Hashable {
}

extension OcaRoot {
private subscript(checkedMirrorDescendant key: String) -> Any {
Mirror(reflecting: self).descendant(key)!
private subscript(_ wrapper: _MirrorWrapper, checkedMirrorDescendant key: String) -> Any {
wrapper.wrappedValue.descendant(key)!
}

private var allKeyPaths: [String: PartialKeyPath<OcaRoot>] {
// TODO: Mirror is inefficient
var membersToKeyPaths = [String: PartialKeyPath<OcaRoot>]()
let mirror = Mirror(reflecting: self)
var mirror: Mirror? = Mirror(reflecting: self)

repeat {
if let mirror {
for case let (key?, _) in mirror.children {
guard let dictionaryKey = key.deletingPrefix("_") else { continue }
membersToKeyPaths[dictionaryKey] = \Self
.[_MirrorWrapper(mirror), checkedMirrorDescendant: key] as PartialKeyPath
}
}
mirror = mirror?.superclassMirror
} while mirror != nil

for case let (key?, _) in mirror.children {
guard let dictionaryKey = key.deletingPrefix("_") else { continue }
membersToKeyPaths[dictionaryKey] = \Self
.[checkedMirrorDescendant: key] as PartialKeyPath
}
return membersToKeyPaths
}

Expand Down
4 changes: 4 additions & 0 deletions SwiftOCA.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
D30644042A76CE790063DA65 /* IdentificationSensor.swift in Sources */ = {isa = PBXBuildFile; fileRef = D30644022A76CE310063DA65 /* IdentificationSensor.swift */; };
D30644062A770B640063DA65 /* Notification2.swift in Sources */ = {isa = PBXBuildFile; fileRef = D30644052A770B640063DA65 /* Notification2.swift */; };
D30644092A77EB160063DA65 /* BasicSensor.swift in Sources */ = {isa = PBXBuildFile; fileRef = D30644072A77EAEA0063DA65 /* BasicSensor.swift */; };
D306440B2A78039B0063DA65 /* MirrorWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D306440A2A78039B0063DA65 /* MirrorWrapper.swift */; };
D306556D2A524D720083F093 /* PhysicalPosition.swift in Sources */ = {isa = PBXBuildFile; fileRef = D306556C2A524D720083F093 /* PhysicalPosition.swift */; };
D306556F2A5254D70083F093 /* TimeSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = D306556E2A5254D70083F093 /* TimeSource.swift */; };
D31528802A526E24004B9BAD /* WorkerDataTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = D315287F2A526E24004B9BAD /* WorkerDataTypes.swift */; };
Expand Down Expand Up @@ -184,6 +185,7 @@
D30644022A76CE310063DA65 /* IdentificationSensor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentificationSensor.swift; sourceTree = "<group>"; };
D30644052A770B640063DA65 /* Notification2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notification2.swift; sourceTree = "<group>"; };
D30644072A77EAEA0063DA65 /* BasicSensor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BasicSensor.swift; sourceTree = "<group>"; };
D306440A2A78039B0063DA65 /* MirrorWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MirrorWrapper.swift; sourceTree = "<group>"; };
D306556C2A524D720083F093 /* PhysicalPosition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhysicalPosition.swift; sourceTree = "<group>"; };
D306556E2A5254D70083F093 /* TimeSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeSource.swift; sourceTree = "<group>"; };
D315287F2A526E24004B9BAD /* WorkerDataTypes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorkerDataTypes.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -822,6 +824,7 @@
D3E6E16F2A3ACA6C00BF7095 /* Data+IntegerCodable.swift */,
D3E6E1712A3ACA6C00BF7095 /* LengthTaggedData.swift */,
D37F7E1A2A6D2602005F035F /* DeviceAddressToString.swift */,
D306440A2A78039B0063DA65 /* MirrorWrapper.swift */,
);
path = OCF;
sourceTree = "<group>";
Expand Down Expand Up @@ -1166,6 +1169,7 @@
D3E6E1E32A3ACAA900BF7095 /* BaseDataTypes.swift in Sources */,
D3E6E1D12A3ACA9A00BF7095 /* EventHandler.swift in Sources */,
D30644042A76CE790063DA65 /* IdentificationSensor.swift in Sources */,
D306440B2A78039B0063DA65 /* MirrorWrapper.swift in Sources */,
D3E6E1C82A3ACA9000BF7095 /* Gain.swift in Sources */,
D3E6E1B62A3ACA7B00BF7095 /* AES70ClassRegistry.swift in Sources */,
D3E6E1C62A3ACA9000BF7095 /* BasicActuators.swift in Sources */,
Expand Down

0 comments on commit 572692d

Please sign in to comment.