Skip to content

Commit 239c66a

Browse files
authored
Merge pull request #2 from ahoppen/throwing-decoding
Allow ByteTree deserialisation functions to throw
2 parents 88fcc8b + 02bf28b commit 239c66a

File tree

4 files changed

+58
-44
lines changed

4 files changed

+58
-44
lines changed

Sources/SwiftSyntax/ByteTreeDeserialization.swift

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,17 @@ struct ByteTreeUserInfoKey: Hashable {
2222
}
2323
}
2424

25+
public enum ByteTreeDecodingError: Error, CustomStringConvertible {
26+
case invalidEnumRawValue(type: String, value: Int)
27+
28+
public var description: String {
29+
switch self {
30+
case .invalidEnumRawValue(let type, let value):
31+
return "Invalid raw value \"\(value)\" for \(type)"
32+
}
33+
}
34+
}
35+
2536
/// A type that can be deserialized from ByteTree into a scalar value that
2637
/// doesn't have any child nodes
2738
protocol ByteTreeScalarDecodable {
@@ -32,7 +43,8 @@ protocol ByteTreeScalarDecodable {
3243
/// - size: The length of the serialized data in bytes
3344
/// - Returns: The deserialized value
3445
static func read(from pointer: UnsafeRawPointer, size: Int,
35-
userInfo: UnsafePointer<[ByteTreeUserInfoKey: Any]>) -> Self
46+
userInfo: UnsafePointer<[ByteTreeUserInfoKey: Any]>
47+
) throws -> Self
3648
}
3749

3850
/// A type that can be deserialized from ByteTree into an object with child
@@ -50,7 +62,8 @@ protocol ByteTreeObjectDecodable {
5062
/// - Returns: The deserialized object
5163
static func read(from reader: UnsafeMutablePointer<ByteTreeObjectReader>,
5264
numFields: Int,
53-
userInfo: UnsafePointer<[ByteTreeUserInfoKey: Any]>) -> Self
65+
userInfo: UnsafePointer<[ByteTreeUserInfoKey: Any]>
66+
) throws -> Self
5467
}
5568

5669
// MARK: - Reader objects
@@ -92,9 +105,9 @@ struct ByteTreeObjectReader {
92105
/// - Returns: The decoded field
93106
mutating func readField<FieldType: ByteTreeScalarDecodable>(
94107
_ objectType: FieldType.Type, index: Int
95-
) -> FieldType {
108+
) throws -> FieldType {
96109
advanceAndValidateIndex(index)
97-
return reader.pointee.read(objectType)
110+
return try reader.pointee.read(objectType)
98111
}
99112

100113
/// Read the field at the given index as the specified type. All indicies must
@@ -107,9 +120,9 @@ struct ByteTreeObjectReader {
107120
/// - Returns: The decoded field
108121
mutating func readField<FieldType: ByteTreeObjectDecodable>(
109122
_ objectType: FieldType.Type, index: Int
110-
) -> FieldType {
123+
) throws -> FieldType {
111124
advanceAndValidateIndex(index)
112-
return reader.pointee.read(objectType)
125+
return try reader.pointee.read(objectType)
113126
}
114127

115128
/// Read and immediately discard the field at the specified index. This
@@ -180,7 +193,7 @@ struct ByteTreeReader {
180193
) throws -> T {
181194
var reader = ByteTreeReader(pointer: pointer, userInfo: userInfo)
182195
try reader.readAndValidateProtocolVersion(protocolVersionValidation)
183-
return reader.read(rootObjectType)
196+
return try reader.read(rootObjectType)
184197
}
185198

186199
/// Deserialize an object tree from the ByteTree data at the given memory
@@ -275,15 +288,15 @@ struct ByteTreeReader {
275288
/// - Returns: The deserialized object
276289
fileprivate mutating func read<T: ByteTreeObjectDecodable>(
277290
_ objectType: T.Type
278-
) -> T {
291+
) throws -> T {
279292
let numFields = readObjectLength()
280293
var objectReader = ByteTreeObjectReader(reader: &self,
281294
numFields: numFields)
282295
defer {
283296
objectReader.finalize()
284297
}
285-
return T.read(from: &objectReader, numFields: numFields,
286-
userInfo: userInfo)
298+
return try T.read(from: &objectReader, numFields: numFields,
299+
userInfo: userInfo)
287300
}
288301

289302
/// Read the next field in the tree as a scalar of the specified type.
@@ -292,12 +305,12 @@ struct ByteTreeReader {
292305
/// - Returns: The deserialized scalar
293306
fileprivate mutating func read<T: ByteTreeScalarDecodable>(
294307
_ scalarType: T.Type
295-
) -> T {
308+
) throws -> T {
296309
let fieldSize = readScalarLength()
297310
defer {
298311
pointer = pointer.advanced(by: fieldSize)
299312
}
300-
return T.read(from: pointer, size: fieldSize, userInfo: userInfo)
313+
return try T.read(from: pointer, size: fieldSize, userInfo: userInfo)
301314
}
302315

303316
/// Discard the next scalar field, advancing the pointer to the next field
@@ -347,12 +360,12 @@ extension Optional: ByteTreeObjectDecodable
347360
static func read(from reader: UnsafeMutablePointer<ByteTreeObjectReader>,
348361
numFields: Int,
349362
userInfo: UnsafePointer<[ByteTreeUserInfoKey: Any]>
350-
) -> Optional<Wrapped> {
363+
) throws -> Optional<Wrapped> {
351364
if numFields == 0 {
352365
return nil
353366
} else {
354-
return Wrapped.read(from: reader, numFields: numFields,
355-
userInfo: userInfo)
367+
return try Wrapped.read(from: reader, numFields: numFields,
368+
userInfo: userInfo)
356369
}
357370
}
358371
}
@@ -363,9 +376,9 @@ extension Array: ByteTreeObjectDecodable
363376
static func read(from reader: UnsafeMutablePointer<ByteTreeObjectReader>,
364377
numFields: Int,
365378
userInfo: UnsafePointer<[ByteTreeUserInfoKey: Any]>
366-
) -> Array<Element> {
367-
return (0..<numFields).map {
368-
return reader.pointee.readField(Element.self, index: $0)
379+
) throws -> Array<Element> {
380+
return try (0..<numFields).map {
381+
return try reader.pointee.readField(Element.self, index: $0)
369382
}
370383
}
371384
}

Sources/SwiftSyntax/RawSyntax.swift

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -409,33 +409,32 @@ extension RawSyntax: ByteTreeObjectDecodable {
409409
static func read(from reader: UnsafeMutablePointer<ByteTreeObjectReader>,
410410
numFields: Int,
411411
userInfo: UnsafePointer<[ByteTreeUserInfoKey: Any]>
412-
) -> RawSyntax {
412+
) throws -> RawSyntax {
413413
let syntaxNode: RawSyntax
414-
let type = reader.pointee.readField(SyntaxType.self, index: 0)
415-
let id = reader.pointee.readField(SyntaxNodeId.self, index: 1)
414+
let type = try reader.pointee.readField(SyntaxType.self, index: 0)
415+
let id = try reader.pointee.readField(SyntaxNodeId.self, index: 1)
416416
switch type {
417417
case .token:
418-
let presence = reader.pointee.readField(SourcePresence.self, index: 2)
419-
let kind = reader.pointee.readField(TokenKind.self, index: 3)
420-
let leadingTrivia = reader.pointee.readField(Trivia.self, index: 4)
421-
let trailingTrivia = reader.pointee.readField(Trivia.self, index: 5)
418+
let presence = try reader.pointee.readField(SourcePresence.self, index: 2)
419+
let kind = try reader.pointee.readField(TokenKind.self, index: 3)
420+
let leadingTrivia = try reader.pointee.readField(Trivia.self, index: 4)
421+
let trailingTrivia = try reader.pointee.readField(Trivia.self, index: 5)
422422
syntaxNode = RawSyntax(kind: kind, leadingTrivia: leadingTrivia,
423423
trailingTrivia: trailingTrivia,
424424
presence: presence, id: id)
425425
case .layout:
426-
let presence = reader.pointee.readField(SourcePresence.self, index: 2)
427-
let kind = reader.pointee.readField(SyntaxKind.self, index: 3)
428-
let layout = reader.pointee.readField([RawSyntax?].self, index: 4)
426+
let presence = try reader.pointee.readField(SourcePresence.self, index: 2)
427+
let kind = try reader.pointee.readField(SyntaxKind.self, index: 3)
428+
let layout = try reader.pointee.readField([RawSyntax?].self, index: 4)
429429
syntaxNode = RawSyntax(kind: kind, layout: layout, presence: presence,
430430
id: id)
431431
case .omitted:
432432
guard let lookupFunc = userInfo.pointee[.omittedNodeLookupFunction] as?
433433
(SyntaxNodeId) -> RawSyntax? else {
434-
fatalError("omittedNodeLookupFunction is required when decoding an " +
435-
"incrementally transferred syntax tree")
434+
throw IncrementalDecodingError.noLookupFunctionPassed
436435
}
437436
guard let lookupNode = lookupFunc(id) else {
438-
fatalError("Node lookup for id \(id) failed")
437+
throw IncrementalDecodingError.nodeLookupFailed(id)
439438
}
440439
syntaxNode = lookupNode
441440
}

Sources/SwiftSyntax/TokenKind.swift.gyb

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,31 +114,32 @@ extension TokenKind: ByteTreeObjectDecodable {
114114
static func read(from reader: UnsafeMutablePointer<ByteTreeObjectReader>,
115115
numFields: Int,
116116
userInfo: UnsafePointer<[ByteTreeUserInfoKey: Any]>
117-
) -> TokenKind {
117+
) throws -> TokenKind {
118118
// Explicitly spell out all TokenKinds to keep the serialized value stable
119119
// even if its members get reordered or members get removed
120-
let kind = reader.pointee.readField(UInt8.self, index: 0)
120+
let kind = try reader.pointee.readField(UInt8.self, index: 0)
121121
switch kind {
122122
case 0: return .eof
123123
% for token in SYNTAX_TOKENS:
124124
case ${token.serialization_code}:
125125
% if token.text: # The token does not have text associated with it
126126
return .${token.swift_kind()}
127127
% else:
128-
let text = reader.pointee.readField(String.self, index: 1)
128+
let text = try reader.pointee.readField(String.self, index: 1)
129129
return .${token.swift_kind()}(text)
130130
% end
131131
% end
132132
default:
133133
if numFields > 1 {
134134
// Default to an unknown token with the passed text if we don't know
135135
// its kind.
136-
let text = reader.pointee.readField(String.self, index: 1)
136+
let text = try reader.pointee.readField(String.self, index: 1)
137137
return .unknown(text)
138138
} else {
139139
// If we were not passed the token's text, we cannot recover since we
140140
// would lose roundtripness.
141-
fatalError("Unknown TokenKind \(kind)")
141+
throw ByteTreeDecodingError.invalidEnumRawValue(type: "\(self)",
142+
value: Int(kind))
142143
}
143144
}
144145
}

Sources/SwiftSyntax/Trivia.swift.gyb

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -224,9 +224,9 @@ extension Trivia: ByteTreeObjectDecodable {
224224
static func read(from reader: UnsafeMutablePointer<ByteTreeObjectReader>,
225225
numFields: Int,
226226
userInfo: UnsafePointer<[ByteTreeUserInfoKey: Any]>
227-
) -> Trivia {
228-
let pieces = [TriviaPiece].read(from: reader, numFields: numFields,
229-
userInfo: userInfo)
227+
) throws -> Trivia {
228+
let pieces = try [TriviaPiece].read(from: reader, numFields: numFields,
229+
userInfo: userInfo)
230230
return Trivia(pieces: pieces)
231231
}
232232
}
@@ -235,21 +235,22 @@ extension TriviaPiece: ByteTreeObjectDecodable {
235235
static func read(from reader: UnsafeMutablePointer<ByteTreeObjectReader>,
236236
numFields: Int,
237237
userInfo: UnsafePointer<[ByteTreeUserInfoKey: Any]>
238-
) -> TriviaPiece {
239-
let kind = reader.pointee.readField(UInt8.self, index: 0)
238+
) throws -> TriviaPiece {
239+
let kind = try reader.pointee.readField(UInt8.self, index: 0)
240240
switch kind {
241241
% for trivia in TRIVIAS:
242242
case ${trivia.serialization_code}:
243243
% if trivia.is_collection():
244-
let count = Int(reader.pointee.readField(UInt32.self, index: 1))
244+
let count = Int(try reader.pointee.readField(UInt32.self, index: 1))
245245
return .${trivia.lower_name}s(count)
246246
% else:
247-
let text = reader.pointee.readField(String.self, index: 1)
247+
let text = try reader.pointee.readField(String.self, index: 1)
248248
return .${trivia.lower_name}(text)
249249
% end
250250
% end
251251
default:
252-
fatalError("Unknown trivia piece kind \(kind)")
252+
throw ByteTreeDecodingError.invalidEnumRawValue(type: "\(self)",
253+
value: Int(kind))
253254
}
254255
}
255256
}

0 commit comments

Comments
 (0)