// Copyright 2017 Parity Technologies (UK) Ltd.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
use crate::{muxing::{Shutdown, StreamMuxer}, Multiaddr};
use futures::prelude::*;
use std::{fmt, io::{Error as IoError, Read, Write}};
use tokio_io::{AsyncRead, AsyncWrite};
#[derive(Debug, Copy, Clone)]
pub enum EitherError {
A(A),
B(B)
}
impl fmt::Display for EitherError
where
A: fmt::Display,
B: fmt::Display
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
EitherError::A(a) => a.fmt(f),
EitherError::B(b) => b.fmt(f)
}
}
}
impl std::error::Error for EitherError
where
A: fmt::Debug + std::error::Error,
B: fmt::Debug + std::error::Error
{
fn cause(&self) -> Option<&dyn std::error::Error> {
match self {
EitherError::A(a) => a.cause(),
EitherError::B(b) => b.cause()
}
}
}
/// Implements `AsyncRead` and `AsyncWrite` and dispatches all method calls to
/// either `First` or `Second`.
#[derive(Debug, Copy, Clone)]
pub enum EitherOutput {
First(A),
Second(B),
}
impl AsyncRead for EitherOutput
where
A: AsyncRead,
B: AsyncRead,
{
#[inline]
unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
match self {
EitherOutput::First(a) => a.prepare_uninitialized_buffer(buf),
EitherOutput::Second(b) => b.prepare_uninitialized_buffer(buf),
}
}
}
impl Read for EitherOutput
where
A: Read,
B: Read,
{
#[inline]
fn read(&mut self, buf: &mut [u8]) -> Result {
match self {
EitherOutput::First(a) => a.read(buf),
EitherOutput::Second(b) => b.read(buf),
}
}
}
impl AsyncWrite for EitherOutput
where
A: AsyncWrite,
B: AsyncWrite,
{
#[inline]
fn shutdown(&mut self) -> Poll<(), IoError> {
match self {
EitherOutput::First(a) => a.shutdown(),
EitherOutput::Second(b) => b.shutdown(),
}
}
}
impl Write for EitherOutput
where
A: Write,
B: Write,
{
#[inline]
fn write(&mut self, buf: &[u8]) -> Result {
match self {
EitherOutput::First(a) => a.write(buf),
EitherOutput::Second(b) => b.write(buf),
}
}
#[inline]
fn flush(&mut self) -> Result<(), IoError> {
match self {
EitherOutput::First(a) => a.flush(),
EitherOutput::Second(b) => b.flush(),
}
}
}
impl StreamMuxer for EitherOutput
where
A: StreamMuxer,
B: StreamMuxer,
{
type Substream = EitherOutput;
type OutboundSubstream = EitherOutbound;
fn poll_inbound(&self) -> Poll