Add ChannelCore.tryUnwrapAs (#1919)
Motivation: For Channel implementations, we implemented ChannelCore.unwrapData to allow them to unwrap a NIOAny into their expected data type. This remains our recommended flow, as Channels are supposed to know what data type they can send. However, in a few cases the Channel has a runtime type: in particular, EmbeddedChannel is capable of tolerating nearly anything. As we're coming to split the code apart, we'll likely want EmbeddedChannel to live in a different module than NIOCore. To that end, we need to add new API to ChannelCore to allow the specific EmbeddedChannel use-case. Modifications: - Implement ChannelCore.tryUnwrapData. - Use this within EmbeddedChannel. Result: EmbeddedChannel can attempt to unwrap things.
This commit is contained in:
parent
8b06e8f996
commit
2a65f2b4be
|
@ -301,6 +301,28 @@ extension ChannelCore {
|
|||
return data.forceAs()
|
||||
}
|
||||
|
||||
/// Attempts to unwrap the given `NIOAny` as a specific concrete type.
|
||||
///
|
||||
/// This method is intended for use when writing custom `ChannelCore` implementations.
|
||||
/// This can safely be called in methods like `write0` to extract data from the `NIOAny`
|
||||
/// provided in those cases.
|
||||
///
|
||||
/// If the unwrap fails, this will return `nil`. `ChannelCore` implementations should almost
|
||||
/// always support only one runtime type, so in general they should avoid using this and prefer
|
||||
/// using `unwrapData` instead. This method exists for rare use-cases where tolerating type
|
||||
/// mismatches is acceptable.
|
||||
///
|
||||
/// - parameters:
|
||||
/// - data: The `NIOAny` to unwrap.
|
||||
/// - as: The type to extract from the `NIOAny`.
|
||||
/// - returns: The content of the `NIOAny`, or `nil` if the type is incorrect.
|
||||
/// - warning: If you are implementing a `ChannelCore`, you should use `unwrapData` unless you
|
||||
/// are doing something _extremely_ unusual.
|
||||
@inlinable
|
||||
public func tryUnwrapData<T>(_ data: NIOAny, as: T.Type = T.self) -> T? {
|
||||
return data.tryAs()
|
||||
}
|
||||
|
||||
/// Removes the `ChannelHandler`s from the `ChannelPipeline` belonging to `channel`, and
|
||||
/// closes that `ChannelPipeline`.
|
||||
///
|
||||
|
|
|
@ -630,7 +630,7 @@ public final class EmbeddedChannel: Channel {
|
|||
return nil
|
||||
}
|
||||
let elem = buffer.removeFirst()
|
||||
guard let t = elem.tryAs(type: T.self) else {
|
||||
guard let t = self._channelCore.tryUnwrapData(elem, as: T.self) else {
|
||||
throw WrongTypeError(expected: T.self, actual: type(of: elem.forceAs(type: Any.self)))
|
||||
}
|
||||
return t
|
||||
|
|
Loading…
Reference in New Issue