1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift open source project
//
// Copyright (c) 2025 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
public final class UniquingSerializationCoordinator {
private var data: [AnyHashable: Int] = [:]
public init() {
}
public func getOrInsert<T: Hashable>(_ x: T) -> Int? {
if let existingKey = data[x] {
return existingKey
}
data[x] = data.count
return nil
}
}
@available(*, unavailable)
extension UniquingSerializationCoordinator: Sendable { }
public final class UniquingDeserializationCoordinator {
private var data: [Any] = []
public init() {
}
public func addUnique<T>(_ x : T) {
data.append(x)
}
public func getUnique<T>(at index: Int) throws -> T {
// Should these errors be fatalErrors? Isn't it a programming error in deserialization logic if you use an out of bounds index or request the wrong type? No: correct code can trigger these conditions if the serialized data is malformed.
guard index < data.count else { throw DeserializerError.deserializationFailed("Index \(index) out of bounds for unique \(T.self) deserialization") }
let value = data[index]
guard let valueT = value as? T else { throw DeserializerError.deserializationFailed("Could not convert \(value) to \(T.self)") }
return valueT
}
}
@available(*, unavailable)
extension UniquingDeserializationCoordinator: Sendable { }
public protocol UniquingSerializerDelegate: SerializerDelegate {
var uniquingCoordinator: UniquingSerializationCoordinator { get }
}
public protocol UniquingDeserializerDelegate: DeserializerDelegate {
var uniquingCoordinator: UniquingDeserializationCoordinator { get }
}
fileprivate struct UniqueSerializableWrapper<T: Serializable & Hashable>: Serializable {
let value: T
init(_ value: T) {
self.value = value
}
func serialize<S: Serializer>(to serializer: S) {
let coordinator = (serializer.delegate as! (any UniquingSerializerDelegate)).uniquingCoordinator
serializer.serializeAggregate(2) {
if let index = coordinator.getOrInsert(value) {
serializer.serialize(1)
serializer.serialize(index)
}
else {
serializer.serialize(0)
value.serialize(to: serializer)
}
}
}
init(from deserializer: any Deserializer) throws {
let coordinator = (deserializer.delegate as! (any UniquingDeserializerDelegate)).uniquingCoordinator
try deserializer.beginAggregate(2)
let tag: Int = try deserializer.deserialize()
switch tag {
case 0:
self.value = try deserializer.deserialize()
coordinator.addUnique(self.value)
case 1:
let index: Int = try deserializer.deserialize()
self.value = try coordinator.getUnique(at: index)
default:
throw DeserializerError.deserializationFailed("Unknown tag \(tag) for Ref<\(T.self)> deserialization")
}
}
}
public extension Serializer {
func serializeUniquely<T: Serializable & Hashable>(_ x: T) {
serialize(UniqueSerializableWrapper(x))
}
func serializeUniquely<T: Serializable & Hashable>(_ xOpt: T?) {
if let x = xOpt {
serializeUniquely(x)
}
else {
serializeNil()
}
}
}
public extension Deserializer {
func deserializeUniquely<T: Serializable & Hashable>() throws -> T {
return try (deserialize() as UniqueSerializableWrapper<T>).value
}
func deserializeUniquely<T: Serializable & Hashable>() throws -> T? {
if deserializeNil() {
return nil
}
else {
return try .some(self.deserializeUniquely() as T)
}
}
}
|