Skip to content

Commit bcba8d1

Browse files
committed
Fix a bunch of follow-on errors from PotentCodable refactor
1 parent cc3d27a commit bcba8d1

File tree

6 files changed

+60
-91
lines changed

6 files changed

+60
-91
lines changed

Sources/allonet2/Place.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ public struct ComponentSet: CustomStringConvertible
136136
{
137137
public subscript<T>(componentType: T.Type) -> T? where T : Component
138138
{
139-
return state.current.components[componentType.componentTypeId]?[id] as! T?
139+
return state.current.components[componentType.componentTypeId]?[id]?.decoded() as! T?
140140
}
141141
public func set<T>(_ newValue: T) async throws(AlloverseError) where T: Component
142142
{
@@ -145,7 +145,7 @@ public struct ComponentSet: CustomStringConvertible
145145
}
146146
public subscript(componentTypeID: ComponentTypeID) -> (any Component)?
147147
{
148-
return state.current.components[componentTypeID]?[id]
148+
return state.current.components[componentTypeID]?[id]?.decoded()
149149
}
150150

151151
private let state: PlaceState

Sources/allonet2/PlaceContents+Changes.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ extension PlaceContents
7878
{
7979
added.append(.componentAdded(entityId, component))
8080
}
81-
else if !component.isEqualTo(prev!)
81+
else if component != prev!
8282
{
8383
updated.append(.componentUpdated(entityId, component))
8484
}
@@ -135,15 +135,15 @@ extension PlaceContents
135135
case .entityRemoved(let e):
136136
entities[e.id] = nil
137137
case .componentAdded(let eid, let component):
138-
let key = type(of:component).componentTypeId
138+
let key = component.componentTypeId
139139
lists[key, default: [:]][eid] = component
140140
case .componentUpdated(let eid, let component):
141-
let key = type(of:component).componentTypeId
141+
let key = component.componentTypeId
142142
guard let _ = lists[key]?[eid] else { return nil }
143143
lists[key]![eid]! = component
144144
case .componentRemoved(let edata, let component):
145-
guard let _ = lists[type(of:component).componentTypeId] else { return nil }
146-
lists[type(of:component).componentTypeId]![edata.id] = nil
145+
guard let _ = lists[component.componentTypeId] else { return nil }
146+
lists[component.componentTypeId]![edata.id] = nil
147147
}
148148
}
149149
return PlaceContents(revision: changeSet.toRevision, entities: entities, components: ComponentLists(lists: lists), logger: self.logger)

Sources/allonet2/PlaceContents+Codable.swift

Lines changed: 36 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
import Logging
99
import PotentCodables
10-
import PotentCBOR
1110

1211
extension PlaceContents: Equatable
1312
{
@@ -27,7 +26,7 @@ extension PlaceContents: Equatable
2726

2827
// Compare each component using the helper method.
2928
for (l, r) in zip(lhsComponents, rhsComponents) {
30-
if !l.value.isEqualTo(r.value) {
29+
if l.value != r.value {
3130
return false
3231
}
3332
}
@@ -63,9 +62,11 @@ public final class ComponentRegistry
6362

6463
/// `AnyComponent` lets AlloPlace only store and forward type-erased value trees of Components, while client code can use `decoded()` to receive the real concrete Component type.
6564
@MainActor
66-
public struct AnyComponent: Component {
67-
public static func == (lhs: AnyComponent, rhs: AnyComponent) -> Bool {
68-
return lhs.treeValue == rhs.treeValue
65+
public struct AnyComponent: Codable, Equatable
66+
{
67+
public static func == (lhs: AnyComponent, rhs: AnyComponent) -> Bool
68+
{
69+
return lhs.anyValue == rhs.anyValue
6970
}
7071

7172
// The concrete Component type we use
@@ -76,47 +77,47 @@ public struct AnyComponent: Component {
7677
// ... or nil, if the type is not compiled into this binary and registered with the ComponentRegistry.
7778
public func decodedIfAvailable() -> (any Component)?
7879
{
79-
guard
80-
let type = ComponentRegistry.shared.component(for: componentTypeId),
81-
let base = try? CBORDecoder().decodeTree(type.self, from: treeValue)
80+
guard let type = ComponentRegistry.shared.component(for: componentTypeId)
8281
else { return nil }
83-
return base
82+
return try! AnyValueDecoder.default.decode(type, from: anyValue) // if the type is registered, it should decode
8483
}
85-
/*public func decodeCustom() -> CustomComponent
84+
public func decodeCustom() -> CustomComponent
8685
{
87-
return CustomComponent(typeId: componentTypeId, fields: treeValue.anyValue)
88-
}*/
86+
return CustomComponent(typeId: componentTypeId, fields: anyValue)
87+
}
8988

9089
// The type-erased content, available whether the concrete type is available or not
91-
public var treeValue: CBOR
90+
public var anyValue: AnyValue
9291
public var componentTypeId: String
9392

94-
public init(_ base: some Component)
93+
func indentedDescription(_ prefix: String) -> String
9594
{
96-
componentTypeId = type(of: base).componentTypeId
97-
treeValue = try! CBOREncoder().encodeTree(base)
95+
return decodedIfAvailable()?.indentedDescription(prefix) ?? "\(prefix)AnyComponent<\(componentTypeId)>: \(anyValue.description)"
9896
}
9997

100-
public init(from decoder: Decoder) throws
98+
// MARK: Codable
99+
public init(_ base: some Component)
101100
{
102-
let treeContainer = try decoder.singleValueContainer() as! TreeValueDecodingContainer
103-
guard
104-
let cbor = treeContainer.decodeTreeValue() as? CBOR,
105-
let map = cbor.mapValue,
106-
let ctypeId = cbor.componentTypeId?.utf8StringValue
107-
else
108-
{
109-
throw DecodingError.dataCorruptedError(in: treeContainer,
110-
debugDescription: "Invalid Component CBOR")
111-
}
112-
treeValue = cbor
113-
componentTypeId = ctypeId
101+
componentTypeId = type(of: base).componentTypeId
102+
anyValue = try! AnyValueEncoder().encode(base)
114103
}
115104

116-
public func encode(to encoder: Encoder) throws
105+
// optimization idea: store CBOR treeValue instead of AnyValue to avoid two tree walks
106+
private enum CodingKeys: String, CodingKey
117107
{
118-
var treeContainer = try encoder.singleValueContainer()
119-
try treeContainer.encode(treeValue)
108+
case componentTypeId
109+
case value
110+
}
111+
public init(from decoder: Decoder) throws {
112+
let container = try decoder.container(keyedBy: CodingKeys.self)
113+
componentTypeId = try container.decode(String.self, forKey: .componentTypeId)
114+
anyValue = try container.decode(AnyValue.self, forKey: .value)
115+
}
116+
117+
public func encode(to encoder: Encoder) throws {
118+
var container = encoder.container(keyedBy: CodingKeys.self)
119+
try container.encode(componentTypeId, forKey: .componentTypeId)
120+
try container.encode(anyValue, forKey: .value)
120121
}
121122
}
122123

@@ -148,15 +149,15 @@ extension PlaceChange: Codable
148149
try container.encode(ChangeKind.componentAdded, forKey: .kind)
149150
try container.encode(eid, forKey: .entityID)
150151
// Wrap the component so we can encode it generically.
151-
try container.encode(AnyComponent(component), forKey: .component)
152+
try container.encode(component, forKey: .component)
152153
case .componentUpdated(let eid, let component):
153154
try container.encode(ChangeKind.componentUpdated, forKey: .kind)
154155
try container.encode(eid, forKey: .entityID)
155-
try container.encode(AnyComponent(component), forKey: .component)
156+
try container.encode(component, forKey: .component)
156157
case .componentRemoved(let edata, let component):
157158
try container.encode(ChangeKind.componentRemoved, forKey: .kind)
158159
try container.encode(edata, forKey: .entity)
159-
try container.encode(AnyComponent(component), forKey: .component)
160+
try container.encode(component, forKey: .component)
160161
}
161162
}
162163

Sources/allonet2/PlaceContents.swift

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,12 @@ public class PlaceState
6363
case .entityRemoved(let entity):
6464
observers.entityRemovedSubject.send(entity)
6565
case .componentAdded(let entityID, let comp):
66-
observers[type(of: comp).componentTypeId].sendAdded(entityID: entityID, component: comp)
67-
observers[type(of: comp).componentTypeId].sendUpdated(entityID: entityID, component: comp)
66+
observers[comp.componentTypeId]?.sendAdded(entityID: entityID, component: comp)
67+
observers[comp.componentTypeId]?.sendUpdated(entityID: entityID, component: comp)
6868
case .componentUpdated(let entityID, let comp):
69-
observers[type(of: comp).componentTypeId].sendUpdated(entityID: entityID, component: comp)
69+
observers[comp.componentTypeId]?.sendUpdated(entityID: entityID, component: comp)
7070
case .componentRemoved(let entityData, let comp):
71-
observers[type(of: comp).componentTypeId].sendRemoved(entityData: entityData, component: comp)
71+
observers[comp.componentTypeId]?.sendRemoved(entityData: entityData, component: comp)
7272
}
7373
}
7474
}
@@ -248,11 +248,10 @@ public struct PlaceObservers
248248
return lists[componentType.componentTypeId, setDefault: ComponentCallbacks<T>(state)] as! ComponentCallbacks<T>
249249
}
250250
}
251-
internal subscript(componentTypeID: ComponentTypeID) -> AnyComponentCallbacksProtocol
251+
// Get the same set of callbacks, but type-erased, and only if it already exists (which means someone has a registered listener from calling the above API)
252+
internal subscript(componentTypeID: ComponentTypeID) -> AnyComponentCallbacksProtocol?
252253
{
253-
mutating get {
254-
return lists[componentTypeID, setDefault: ComponentRegistry.shared.createCallbacks(for: componentTypeID, state: state)!]
255-
}
254+
return lists[componentTypeID]
256255
}
257256

258257
private var lists: Dictionary<ComponentTypeID, AnyComponentCallbacksProtocol> = [:]
@@ -277,9 +276,9 @@ public struct ComponentCallbacks<T: Component> : AnyComponentCallbacksProtocol
277276
/// A component has been removed from an entity.
278277
public var removed: AnyPublisher<(EntityData, T), Never> { removedSubject.eraseToAnyPublisher() }
279278

280-
internal func sendAdded (entityID: String, component: any Component) { addedSubject.send((entityID, component as! T)) }
281-
internal func sendUpdated(entityID: String, component: any Component) { updatedSubject.send((entityID, component as! T)) }
282-
internal func sendRemoved(entityData: EntityData, component: any Component) { removedSubject.send((entityData, component as! T)) }
279+
internal func sendAdded (entityID: String, component: AnyComponent) { addedSubject.send((entityID, component.decoded() as! T)) }
280+
internal func sendUpdated(entityID: String, component: AnyComponent) { updatedSubject.send((entityID, component.decoded() as! T)) }
281+
internal func sendRemoved(entityData: EntityData, component: AnyComponent) { removedSubject.send((entityData, component.decoded() as! T)) }
283282
private let addedSubject = PassthroughSubject<(EntityID, T), Never>()
284283
private let updatedSubject = PassthroughSubject<(EntityID, T), Never>()
285284
private let removedSubject = PassthroughSubject<(EntityData, T), Never>()
@@ -295,9 +294,9 @@ public struct ComponentCallbacks<T: Component> : AnyComponentCallbacksProtocol
295294
// MARK: Internals
296295
@MainActor
297296
protocol AnyComponentCallbacksProtocol {
298-
func sendAdded(entityID: EntityID, component: any Component)
299-
func sendUpdated(entityID: EntityID, component: any Component)
300-
func sendRemoved(entityData: EntityData, component: any Component)
297+
func sendAdded(entityID: EntityID, component: AnyComponent)
298+
func sendUpdated(entityID: EntityID, component: AnyComponent)
299+
func sendRemoved(entityData: EntityData, component: AnyComponent)
301300
}
302301

303302
extension Component
@@ -341,11 +340,11 @@ extension PlaceChange: Equatable {
341340
case (.entityRemoved(let e1), .entityRemoved(let e2)):
342341
return e1 == e2
343342
case (.componentAdded(let id1, let comp1), .componentAdded(let id2, let comp2)):
344-
return id1 == id2 && comp1.isEqualTo(comp2)
343+
return id1 == id2 && comp1 == comp2
345344
case (.componentUpdated(let id1, let comp1), .componentUpdated(let id2, let comp2)):
346-
return id1 == id2 && comp1.isEqualTo(comp2)
345+
return id1 == id2 && comp1 == comp2
347346
case (.componentRemoved(let id1, let comp1), .componentRemoved(let id2, let comp2)):
348-
return id1 == id2 && comp1.isEqualTo(comp2)
347+
return id1 == id2 && comp1 == comp2
349348
default:
350349
return false
351350
}

Sources/allonet2/SIMDExtensions.swift

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -15,38 +15,6 @@ public extension simd_float3x3 {
1515
}
1616
}
1717

18-
extension simd_float4x4 : Codable
19-
{
20-
public func encode(to encoder: Encoder) throws
21-
{
22-
var container = encoder.unkeyedContainer()
23-
// Encode in row-major order: for each row, encode all columns.
24-
for row in 0..<4
25-
{
26-
for col in 0..<4
27-
{
28-
try container.encode(self[col][row])
29-
}
30-
}
31-
}
32-
33-
public init(from decoder: Decoder) throws
34-
{
35-
var container = try decoder.unkeyedContainer()
36-
var matrix = simd_float4x4()
37-
// Decode in row-major order.
38-
for row in 0..<4
39-
{
40-
for col in 0..<4
41-
{
42-
let value = try container.decode(Float.self)
43-
matrix[col][row] = value
44-
}
45-
}
46-
self = matrix
47-
}
48-
}
49-
5018
extension simd_float4x4 {
5119
public static var identity: simd_float4x4 {
5220
return matrix_identity_float4x4

Sources/allonet2/StandardComponents.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
//
77

88
import simd
9+
import SIMDTools // for float4x4 codable
910
import PotentCodables
1011

1112
// MARK: Rendering/RealityKit related components

0 commit comments

Comments
 (0)