Skip to content

Commit b57ba6f

Browse files
Add new section on details of Codable conformance. (#2371)
* Add new section on details of Codable conformance. * Expand section on Codable errors. * Missed some. * Move discussion of Codable errors to Alternatives Considered.
1 parent c94d4e9 commit b57ba6f

File tree

1 file changed

+80
-13
lines changed

1 file changed

+80
-13
lines changed

proposals/0425-int128.md

Lines changed: 80 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,6 @@ Considered for sordid history).
5151
The `[U]Int128` types conform to `AtomicRepresentable` on targets with
5252
`_hasAtomicBitWidth(_128)` set (notably x86\_64, arm64, and arm64\_32).
5353

54-
The `[U]Int128` types conform to `Codable`; however, many existing encoders
55-
and decoders do not support such large integer types. Therefore they are
56-
encoded as a pair of 64b integers. This pair is always in little-endian
57-
order, regardless of the endianness of the architecture.
58-
5954
The actual API of the types is uninteresting; they are entirely constrained by
6055
their protocol conformances. Notably, these types conform to the following
6156
protocols, and hence to any protocol that they refine:
@@ -77,6 +72,78 @@ protocols, and hence to any protocol that they refine:
7772
¹ For the purposes of this discussion, arm64\_32 and similar architectures
7873
are "64b targets."
7974

75+
### Codable details
76+
77+
An earlier version of this proposal conformed `[U]Int128` to `Codable`
78+
with a representation as a pair of `[U]Int64` values. During the first review
79+
period several people made excellent points:
80+
81+
- Making it possible for encoders to customize how they represent these types
82+
is desirable. Some cannot represent all 64b values or might prefer to use a
83+
string representation, others might prefer to treat 128b integers as native
84+
values to encode.
85+
86+
- If we make it customizable but provide a default behavior, some decoders
87+
would have to support that default as well as their desired representation,
88+
for compatibility with any encodings created between when we added support
89+
and when they defined their preferred encoding.
90+
91+
For this reason, the proposal has been updated to add new protocol requirements
92+
for encoders and decoders to support `[U]Int128`, but with default
93+
implementations that throw an EncodingError or DecodingError unconditionally,
94+
allowing implementations to choose their preferred behavior when they add
95+
support without worrying about compatibility with a defaulted implementation.
96+
97+
Thus, the following requirements will be added:
98+
```swift
99+
protocol KeyedEncodingContainerProtocol {
100+
mutating func encode(_ value: Int128, forKey key: Key) throws
101+
mutating func encode(_ value: UInt128, forKey key: Key) throws
102+
mutating func encodeIfPresent(_ value: Int128?, forKey key: Key) throws
103+
mutating func encodeIfPresent(_ value: UInt128?, forKey key: Key) throws
104+
// And matching changes to KeyedEncodingContainer<Key>
105+
}
106+
107+
protocol KeyedDecodingContainerProtocol {
108+
func decode(_ type: Int128.Type, forKey key: Key) throws -> Int128
109+
func decode(_ type: UInt128.Type, forKey key: Key) throws -> UInt128
110+
func decodeIfPresent(_ type: Int128.Type, forKey key: Key) throws -> Int128?
111+
func decodeIfPresent(_ type: UInt128.Type, forKey key: Key) throws -> UInt128?
112+
// And matching changes to KeyedDecodingContainer<Key>
113+
}
114+
115+
protocol UnkeyedEncodingContainer {
116+
mutating func encode(_ value: Int128) throws
117+
mutating func encode(_ value: UInt128) throws
118+
mutating func encode<T: Sequence>(
119+
contentsOf sequence: T
120+
) throws where T.Element == Int128
121+
mutating func encode<T: Sequence>(
122+
contentsOf sequence: T
123+
) throws where T.Element == UInt128
124+
}
125+
126+
protocol UnkeyedDecodingContainer {
127+
mutating func decode(_ type: Int128.Type) throws -> Int128
128+
mutating func decode(_ type: UInt128.Type) throws -> UInt128
129+
mutating func decodeIfPresent(_ type: Int128.Type) throws -> Int128?
130+
mutating func decodeIfPresent(_ type: UInt128.Type) throws -> UInt128?
131+
}
132+
133+
protocol SingleValueEncodingContainer {
134+
mutating func encode(_ value: Int128) throws
135+
mutating func encode(_ value: UInt128) throws
136+
}
137+
138+
protocol SingleValueDecodingContainer {
139+
func decode(_ type: Int128.Type) throws -> Int128
140+
func decode(_ type: UInt128.Type) throws -> UInt128
141+
}
142+
```
143+
and given default implementations. The default encode implementations throw
144+
`EncodingError.invalidValue`, and the default decode implementations throw
145+
`DecodingError.typeMismatch`.
146+
80147
## Source compatibility
81148

82149
This proposal has no effect on source compatibility.
@@ -126,14 +193,6 @@ While other fixed-width integer types are interesting, 128 bits is a couple
126193
orders of magnitude more useful than all the others for general-purpose
127194
software at this point in time.
128195

129-
### Codable conformance
130-
Because many existing encoders and decoders do not already support 128b
131-
integers, we use a pair of 64b integers instead. To maximize compatibility,
132-
or to improve human-readability, we could instead encode these types as
133-
decimal or hexadecimal strings. However, this would be somewhat less
134-
efficient in some use cases, and it is possible for users to achieve the
135-
same effect by converting to a string before encoding.
136-
137196
### NSNumber bridging
138197
`[U]Int128` will not bridge to `NSNumber`. In the future, Swift will need
139198
a careful rethinking of how best to handle type-erased numbers, but we don't
@@ -142,3 +201,11 @@ that isn't supported on all platforms. In addition, the most common use for
142201
such bridging, unpacking type-erased fields from encoded dictionaries, is
143202
somewhat moot since most existing coders do not support 128b integers. We
144203
will likely revisit this more holistically in the future.
204+
205+
### Codable errors
206+
It would be nice to introduce new `unsupportedType` error cases for the
207+
default Codable conformances, but we cannot add new cases with associated
208+
values and constrained availability to existing enums, which prevents
209+
attaching context or a useful debug description. It's more useful for users
210+
if we use existing error cases `invalidValue` and `typeMismatch` but put an
211+
actionable message in that description field.

0 commit comments

Comments
 (0)