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:
Cory Benfield 2021-07-26 18:18:46 +01:00 committed by GitHub
parent 8b06e8f996
commit 2a65f2b4be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 23 additions and 1 deletions

View File

@ -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`.
///

View File

@ -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