Skip to content

Allow ByteTree deserialisation functions to throw #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 31 additions & 18 deletions Sources/SwiftSyntax/ByteTreeDeserialization.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,17 @@ struct ByteTreeUserInfoKey: Hashable {
}
}

public enum ByteTreeDecodingError: Error, CustomStringConvertible {
case invalidEnumRawValue(type: String, value: Int)

public var description: String {
switch self {
case .invalidEnumRawValue(let type, let value):
return "Invalid raw value \"\(value)\" for \(type)"
}
}
}

/// A type that can be deserialized from ByteTree into a scalar value that
/// doesn't have any child nodes
protocol ByteTreeScalarDecodable {
Expand All @@ -32,7 +43,8 @@ protocol ByteTreeScalarDecodable {
/// - size: The length of the serialized data in bytes
/// - Returns: The deserialized value
static func read(from pointer: UnsafeRawPointer, size: Int,
userInfo: UnsafePointer<[ByteTreeUserInfoKey: Any]>) -> Self
userInfo: UnsafePointer<[ByteTreeUserInfoKey: Any]>
) throws -> Self
}

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

// MARK: - Reader objects
Expand Down Expand Up @@ -92,9 +105,9 @@ struct ByteTreeObjectReader {
/// - Returns: The decoded field
mutating func readField<FieldType: ByteTreeScalarDecodable>(
_ objectType: FieldType.Type, index: Int
) -> FieldType {
) throws -> FieldType {
advanceAndValidateIndex(index)
return reader.pointee.read(objectType)
return try reader.pointee.read(objectType)
}

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

/// Read and immediately discard the field at the specified index. This
Expand Down Expand Up @@ -178,7 +191,7 @@ struct ByteTreeReader {
) throws -> T {
var reader = ByteTreeReader(pointer: pointer, userInfo: userInfo)
try reader.readAndValidateProtocolVersion(protocolVersionValidation)
return reader.read(rootObjectType)
return try reader.read(rootObjectType)
}

/// Deserialize an object tree from the ByteTree data at the given memory
Expand Down Expand Up @@ -266,15 +279,15 @@ struct ByteTreeReader {
/// - Returns: The deserialized object
fileprivate mutating func read<T: ByteTreeObjectDecodable>(
_ objectType: T.Type
) -> T {
) throws -> T {
let numFields = readObjectLength()
var objectReader = ByteTreeObjectReader(reader: &self,
numFields: numFields)
defer {
objectReader.finalize()
}
return T.read(from: &objectReader, numFields: numFields,
userInfo: userInfo)
return try T.read(from: &objectReader, numFields: numFields,
userInfo: userInfo)
}

/// Read the next field in the tree as a scalar of the specified type.
Expand All @@ -283,12 +296,12 @@ struct ByteTreeReader {
/// - Returns: The deserialized scalar
fileprivate mutating func read<T: ByteTreeScalarDecodable>(
_ scalarType: T.Type
) -> T {
) throws -> T {
let fieldSize = readScalarLength()
defer {
pointer = pointer.advanced(by: fieldSize)
}
return T.read(from: pointer, size: fieldSize, userInfo: userInfo)
return try T.read(from: pointer, size: fieldSize, userInfo: userInfo)
}

/// Discard the next scalar field, advancing the pointer to the next field
Expand Down Expand Up @@ -338,12 +351,12 @@ extension Optional: ByteTreeObjectDecodable
static func read(from reader: UnsafeMutablePointer<ByteTreeObjectReader>,
numFields: Int,
userInfo: UnsafePointer<[ByteTreeUserInfoKey: Any]>
) -> Optional<Wrapped> {
) throws -> Optional<Wrapped> {
if numFields == 0 {
return nil
} else {
return Wrapped.read(from: reader, numFields: numFields,
userInfo: userInfo)
return try Wrapped.read(from: reader, numFields: numFields,
userInfo: userInfo)
}
}
}
Expand All @@ -354,9 +367,9 @@ extension Array: ByteTreeObjectDecodable
static func read(from reader: UnsafeMutablePointer<ByteTreeObjectReader>,
numFields: Int,
userInfo: UnsafePointer<[ByteTreeUserInfoKey: Any]>
) -> Array<Element> {
return (0..<numFields).map {
return reader.pointee.readField(Element.self, index: $0)
) throws -> Array<Element> {
return try (0..<numFields).map {
return try reader.pointee.readField(Element.self, index: $0)
}
}
}
25 changes: 12 additions & 13 deletions Sources/SwiftSyntax/RawSyntax.swift
Original file line number Diff line number Diff line change
Expand Up @@ -409,33 +409,32 @@ extension RawSyntax: ByteTreeObjectDecodable {
static func read(from reader: UnsafeMutablePointer<ByteTreeObjectReader>,
numFields: Int,
userInfo: UnsafePointer<[ByteTreeUserInfoKey: Any]>
) -> RawSyntax {
) throws -> RawSyntax {
let syntaxNode: RawSyntax
let type = reader.pointee.readField(SyntaxType.self, index: 0)
let id = reader.pointee.readField(SyntaxNodeId.self, index: 1)
let type = try reader.pointee.readField(SyntaxType.self, index: 0)
let id = try reader.pointee.readField(SyntaxNodeId.self, index: 1)
switch type {
case .token:
let presence = reader.pointee.readField(SourcePresence.self, index: 2)
let kind = reader.pointee.readField(TokenKind.self, index: 3)
let leadingTrivia = reader.pointee.readField(Trivia.self, index: 4)
let trailingTrivia = reader.pointee.readField(Trivia.self, index: 5)
let presence = try reader.pointee.readField(SourcePresence.self, index: 2)
let kind = try reader.pointee.readField(TokenKind.self, index: 3)
let leadingTrivia = try reader.pointee.readField(Trivia.self, index: 4)
let trailingTrivia = try reader.pointee.readField(Trivia.self, index: 5)
syntaxNode = RawSyntax(kind: kind, leadingTrivia: leadingTrivia,
trailingTrivia: trailingTrivia,
presence: presence, id: id)
case .layout:
let presence = reader.pointee.readField(SourcePresence.self, index: 2)
let kind = reader.pointee.readField(SyntaxKind.self, index: 3)
let layout = reader.pointee.readField([RawSyntax?].self, index: 4)
let presence = try reader.pointee.readField(SourcePresence.self, index: 2)
let kind = try reader.pointee.readField(SyntaxKind.self, index: 3)
let layout = try reader.pointee.readField([RawSyntax?].self, index: 4)
syntaxNode = RawSyntax(kind: kind, layout: layout, presence: presence,
id: id)
case .omitted:
guard let lookupFunc = userInfo.pointee[.omittedNodeLookupFunction] as?
(SyntaxNodeId) -> RawSyntax? else {
fatalError("omittedNodeLookupFunction is required when decoding an " +
"incrementally transferred syntax tree")
throw IncrementalDecodingError.noLookupFunctionPassed
}
guard let lookupNode = lookupFunc(id) else {
fatalError("Node lookup for id \(id) failed")
throw IncrementalDecodingError.nodeLookupFailed(id)
}
syntaxNode = lookupNode
}
Expand Down
11 changes: 6 additions & 5 deletions Sources/SwiftSyntax/TokenKind.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -114,31 +114,32 @@ extension TokenKind: ByteTreeObjectDecodable {
static func read(from reader: UnsafeMutablePointer<ByteTreeObjectReader>,
numFields: Int,
userInfo: UnsafePointer<[ByteTreeUserInfoKey: Any]>
) -> TokenKind {
) throws -> TokenKind {
// Explicitly spell out all TokenKinds to keep the serialized value stable
// even if its members get reordered or members get removed
let kind = reader.pointee.readField(UInt8.self, index: 0)
let kind = try reader.pointee.readField(UInt8.self, index: 0)
switch kind {
case 0: return .eof
% for token in SYNTAX_TOKENS:
case ${token.serialization_code}:
% if token.text: # The token does not have text associated with it
return .${token.swift_kind()}
% else:
let text = reader.pointee.readField(String.self, index: 1)
let text = try reader.pointee.readField(String.self, index: 1)
return .${token.swift_kind()}(text)
% end
% end
default:
if numFields > 1 {
// Default to an unknown token with the passed text if we don't know
// its kind.
let text = reader.pointee.readField(String.self, index: 1)
let text = try reader.pointee.readField(String.self, index: 1)
return .unknown(text)
} else {
// If we were not passed the token's text, we cannot recover since we
// would lose roundtripness.
fatalError("Unknown TokenKind \(kind)")
throw ByteTreeDecodingError.invalidEnumRawValue(type: "\(self)",
value: Int(kind))
}
}
}
Expand Down
17 changes: 9 additions & 8 deletions Sources/SwiftSyntax/Trivia.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -224,9 +224,9 @@ extension Trivia: ByteTreeObjectDecodable {
static func read(from reader: UnsafeMutablePointer<ByteTreeObjectReader>,
numFields: Int,
userInfo: UnsafePointer<[ByteTreeUserInfoKey: Any]>
) -> Trivia {
let pieces = [TriviaPiece].read(from: reader, numFields: numFields,
userInfo: userInfo)
) throws -> Trivia {
let pieces = try [TriviaPiece].read(from: reader, numFields: numFields,
userInfo: userInfo)
return Trivia(pieces: pieces)
}
}
Expand All @@ -235,21 +235,22 @@ extension TriviaPiece: ByteTreeObjectDecodable {
static func read(from reader: UnsafeMutablePointer<ByteTreeObjectReader>,
numFields: Int,
userInfo: UnsafePointer<[ByteTreeUserInfoKey: Any]>
) -> TriviaPiece {
let kind = reader.pointee.readField(UInt8.self, index: 0)
) throws -> TriviaPiece {
let kind = try reader.pointee.readField(UInt8.self, index: 0)
switch kind {
% for trivia in TRIVIAS:
case ${trivia.serialization_code}:
% if trivia.is_collection():
let count = Int(reader.pointee.readField(UInt32.self, index: 1))
let count = Int(try reader.pointee.readField(UInt32.self, index: 1))
return .${trivia.lower_name}s(count)
% else:
let text = reader.pointee.readField(String.self, index: 1)
let text = try reader.pointee.readField(String.self, index: 1)
return .${trivia.lower_name}(text)
% end
% end
default:
fatalError("Unknown trivia piece kind \(kind)")
throw ByteTreeDecodingError.invalidEnumRawValue(type: "\(self)",
value: Int(kind))
}
}
}