/src/swift-protobuf/Sources/SwiftProtobuf/ExtensionFieldValueSet.swift
Line | Count | Source |
1 | | // Sources/SwiftProtobuf/ExtensionFieldValueSet.swift - Extension support |
2 | | // |
3 | | // Copyright (c) 2014 - 2016 Apple Inc. and the project authors |
4 | | // Licensed under Apache License v2.0 with Runtime Library Exception |
5 | | // |
6 | | // See LICENSE.txt for license information: |
7 | | // https://github.com/apple/swift-protobuf/blob/main/LICENSE.txt |
8 | | // |
9 | | // ----------------------------------------------------------------------------- |
10 | | /// |
11 | | /// A collection of extension field values on a particular object. |
12 | | /// This is only used within messages to manage the values of extension fields; |
13 | | /// it does not need to be very sophisticated. |
14 | | /// |
15 | | // ----------------------------------------------------------------------------- |
16 | | |
17 | | public struct ExtensionFieldValueSet: Hashable, Sendable { |
18 | 43.4M | fileprivate var values = [Int: any AnyExtensionField]() |
19 | | |
20 | | public static func == ( |
21 | | lhs: ExtensionFieldValueSet, |
22 | | rhs: ExtensionFieldValueSet |
23 | 0 | ) -> Bool { |
24 | 0 | guard lhs.values.count == rhs.values.count else { |
25 | 0 | return false |
26 | 0 | } |
27 | 0 | for (index, l) in lhs.values { |
28 | 0 | if let r = rhs.values[index] { |
29 | 0 | if type(of: l) != type(of: r) { |
30 | 0 | return false |
31 | 0 | } |
32 | 0 | if !l.isEqual(other: r) { |
33 | 0 | return false |
34 | 0 | } |
35 | 0 | } else { |
36 | 0 | return false |
37 | 0 | } |
38 | 0 | } |
39 | 0 | return true |
40 | 0 | } |
41 | | |
42 | 43.4M | public init() {} |
43 | | |
44 | 0 | public func hash(into hasher: inout Hasher) { |
45 | 0 | // AnyExtensionField is not Hashable, and the Self constraint that would |
46 | 0 | // add breaks some of the uses of it; so the only choice is to manually |
47 | 0 | // mix things in. However, one must remember to do things in an order |
48 | 0 | // independent manner. |
49 | 0 | var hash = 16_777_619 |
50 | 0 | for (fieldNumber, v) in values { |
51 | 0 | var localHasher = hasher |
52 | 0 | localHasher.combine(fieldNumber) |
53 | 0 | v.hash(into: &localHasher) |
54 | 0 | hash = hash &+ localHasher.finalize() |
55 | 0 | } |
56 | 0 | hasher.combine(hash) |
57 | 0 | } |
58 | | |
59 | 90.9M | public func traverse<V: Visitor>(visitor: inout V, start: Int, end: Int) throws { |
60 | 90.9M | let validIndexes = values.keys.filter { $0 >= start && $0 < end } |
61 | 90.9M | for i in validIndexes.sorted() { |
62 | 31.7M | let value = values[i]! |
63 | 31.7M | try value.traverse(visitor: &visitor) |
64 | 90.9M | } |
65 | 90.9M | } |
66 | | |
67 | | public subscript(index: Int) -> (any AnyExtensionField)? { |
68 | 2.05M | get { values[index] } |
69 | 0 | set { values[index] = newValue } |
70 | | } |
71 | | |
72 | | mutating func modify<ReturnType>( |
73 | | index: Int, |
74 | | _ modifier: (inout (any AnyExtensionField)?) throws -> ReturnType |
75 | 83.3M | ) rethrows -> ReturnType { |
76 | 83.3M | // This internal helper exists to invoke the _modify accessor on Dictionary for the given operation, which can avoid CoWs |
77 | 83.3M | // during the modification operation. |
78 | 83.3M | try modifier(&values[index]) |
79 | 83.2M | } |
80 | | |
81 | 5.85M | public var isInitialized: Bool { |
82 | 5.85M | for (_, v) in values { |
83 | 2.28M | if !v.isInitialized { |
84 | 0 | return false |
85 | 2.28M | } |
86 | 5.85M | } |
87 | 5.85M | return true |
88 | 5.85M | } |
89 | | } |