Closed jakaplan closed 2 years ago
@amomchilov for your review when you have the time
Heyo
I'm a little busy this week. I'll try to review it this weekend. I like the idea.
I'm a little busy this week. I'll try to review it this weekend. I like the idea.
No worries, I appreciate all of the time you've spent contributing to this project.
@amomchilov would you have a chance to review this weekend? If not I completely understand, but I'll probably go back to committing without review. However, I'll keep using pull requests to make it easier for later feedback.
Hey Josh, sorry for the delay. I've just sat down to take look through this.
One high level design question:
Does it make sense to limit thrown types to only 1 type, and expect users to make their own union of all thrown types they want? That could simplify the framework, but adds a bit more burden on the user.
No, that's not the expectation. Any number of types can be registered, but each registration needs to be done with its own function call. However, these function calls can be chained so it should be relatively convenient. For example:
let route = XPCRoute.named("process")
.throwsType(AllowedCommandError.self)
.throwsType(SharedConstantsError.self)
The reason this needs to be done is that a variadic parameter of a generic type doesn't work here because Swift will try to resolve the error to its actual type, not a common protocol each argument conforms to. As a result, passing in two different types is not accepted by the compiler. This is at least is my empirical experience combined with my less than comprehensive knowledge of Swift's generics.
As an example let's say there was a function:
public func throwsTypes<E: Error & Codable>(_ errorTypes: E.Type...) -> XPCRouteWithoutMessageWithoutReply {
XPCRouteWithoutMessageWithoutReply(self.route.pathComponents,
errorTypes: self.route.errorTypes + errorTypes)
}
And then at the call site we attempted to do:
let route = XPCRoute.named("process")
.throwsTypes(AllowedCommandError.self, SharedConstantsError.self)
Where AllowedCommandError
and SharedConstantsError
both conform to Error
and Codable
. The compiler will provide the error:
Cannot convert value of type 'SharedConstants.SharedConstantsError.Type' to expected argument type 'AllowedCommandError.Type'
Overview of changes:
HandlerError
always represents the error thrown by a server's handler closureHandlerError
will unconditionally try to encode any thrown errorsHandlerError
will always encode a localized description of the erroruserInfo
dictionaryResponse
knows whichXPCRoute
it was for and adds this route to theuserInfo
when decoding an errorXPCClient
'sasync
send functions is called if an error was thrown and could be decoded by the client then it will be directly rethrown (that is,HandlerError
will not be thrown)