use super::*;
use ::core::error::Error;
use ::core::fmt::Display;
use ::core::ops::{Deref, DerefMut};
use ::core::pin::Pin;
use ::core::task::{Context, Poll};
use ::quither_proc_macros::quither;
#[cfg(feature = "use_std")]
use ::std::io::{BufRead, Read, Result as IoResult, Seek, SeekFrom};
#[cfg(feature = "use_std")]
#[quither]
impl<L, R> Read for Quither<L, R>
where
L: Read,
R: Read,
{
fn read(&mut self, #[allow(unused)] buf: &mut [u8]) -> IoResult<usize> {
match self {
#[either]
Self::Left(l) => l.read(buf),
#[either]
Self::Right(r) => r.read(buf),
#[neither]
Self::Neither => Ok(0),
#[both]
Self::Both(l, r) => {
if buf.is_empty() {
return Ok(0);
}
let left_len = l.read(buf)?;
if left_len == 0 {
r.read(buf)
} else {
Ok(left_len)
}
}
}
}
}
#[cfg(feature = "use_std")]
#[quither(!has_both)]
impl<L, R> BufRead for Quither<L, R>
where
L: BufRead,
R: BufRead,
{
fn fill_buf(&mut self) -> IoResult<&[u8]> {
match self {
#[either]
Self::Left(l) => l.fill_buf(),
#[either]
Self::Right(r) => r.fill_buf(),
#[neither]
Self::Neither => Ok(&[]),
}
}
fn consume(&mut self, #[allow(unused)] amt: usize) {
match self {
#[either]
Self::Left(l) => l.consume(amt),
#[either]
Self::Right(r) => r.consume(amt),
#[neither]
Self::Neither => {}
}
}
}
#[cfg(feature = "use_std")]
#[quither(!has_both)]
impl<L, R> Seek for Quither<L, R>
where
L: Seek,
R: Seek,
{
fn seek(&mut self, #[allow(unused)] pos: SeekFrom) -> IoResult<u64> {
match self {
#[either]
Self::Left(l) => l.seek(pos),
#[either]
Self::Right(r) => r.seek(pos),
#[neither]
Self::Neither => Ok(0),
}
}
}
impl<L, R> Deref for Either<L, R>
where
L: Deref,
R: Deref<Target = L::Target>,
{
type Target = L::Target;
fn deref(&self) -> &Self::Target {
match self {
Self::Left(l) => l,
Self::Right(r) => r,
}
}
}
impl<L, R> DerefMut for Either<L, R>
where
L: DerefMut,
R: DerefMut<Target = L::Target>,
{
fn deref_mut(&mut self) -> &mut Self::Target {
match self {
Self::Left(l) => l,
Self::Right(r) => r,
}
}
}
#[quither]
impl<L, R> Display for Quither<L, R>
where
L: Display,
R: Display,
{
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
match self {
#[either]
Self::Left(l) => write!(f, "Left({})", l),
#[either]
Self::Right(r) => write!(f, "Right({})", r),
#[neither]
Self::Neither => write!(f, "Neither"),
#[both]
Self::Both(l, r) => write!(f, "Both({}, {})", l, r),
}
}
}
impl<L, R> Error for Either<L, R>
where
L: Error,
R: Error,
{
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::Left(l) => l.source(),
Self::Right(r) => r.source(),
}
}
#[allow(deprecated)]
fn description(&self) -> &str {
match self {
Self::Left(l) => l.description(),
Self::Right(r) => r.description(),
}
}
#[allow(deprecated)]
fn cause(&self) -> Option<&dyn Error> {
match self {
Self::Left(l) => l.cause(),
Self::Right(r) => r.cause(),
}
}
}
#[quither(!has_neither && !has_both)]
impl<L, R, T> Extend<T> for Quither<L, R>
where
L: Extend<T>,
R: Extend<T>,
{
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
match self {
#[either]
Self::Left(l) => l.extend(iter),
#[either]
Self::Right(r) => r.extend(iter),
}
}
}
#[quither(!has_neither && has_both)]
impl<L, R, T> Extend<T> for Quither<L, R>
where
L: Extend<T>,
R: Extend<T>,
T: Clone,
{
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
match self {
#[either]
Self::Left(l) => l.extend(iter),
#[either]
Self::Right(r) => r.extend(iter),
#[both]
Self::Both(l, r) => {
let tuple_iter = iter.into_iter().map(|t| (t.clone(), t));
struct Wrap<U>(U);
impl<U, V> Extend<V> for Wrap<&mut U>
where
U: Extend<V>,
{
fn extend<I: IntoIterator<Item = V>>(&mut self, iter: I) {
self.0.extend(iter);
}
}
(Wrap(l), Wrap(r)).extend(tuple_iter);
}
}
}
}
impl<L, R> Future for Either<L, R>
where
L: Future,
R: Future<Output = L::Output>,
{
type Output = L::Output;
fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> {
match self.as_pin_mut() {
Either::Left(l) => l.poll(ctx),
Either::Right(r) => r.poll(ctx),
}
}
}
#[quither]
impl<L, R, OL, OR> PartialEq<Quither<OL, OR>> for Quither<L, R>
where
L: PartialEq<OL>,
R: PartialEq<OR>,
{
fn eq(&self, other: &Quither<OL, OR>) -> bool {
match (self, other) {
#[either]
(Self::Left(l), Quither::Left(ol)) => l == ol,
#[either]
(Self::Right(r), Quither::Right(or)) => r == or,
#[neither]
(Self::Neither, Quither::Neither) => true,
#[both]
(Self::Both(l, r), Quither::Both(ol, or)) => l == ol && r == or,
#[allow(unreachable_patterns)]
_ => false,
}
}
}
#[quither]
impl<L, R, OL, OR> PartialOrd<Quither<OL, OR>> for Quither<L, R>
where
L: PartialOrd<OL>,
R: PartialOrd<OR>,
{
fn partial_cmp(&self, other: &Quither<OL, OR>) -> Option<std::cmp::Ordering> {
match (self, other) {
#[either]
(Self::Left(l), Quither::Left(ol)) => l.partial_cmp(ol),
#[either]
(Self::Right(r), Quither::Right(or)) => r.partial_cmp(or),
#[neither]
(Self::Neither, Quither::Neither) => Some(std::cmp::Ordering::Equal),
#[both]
(Self::Both(l, r), Quither::Both(ol, or)) => l
.partial_cmp(ol)
.and_then(|o| r.partial_cmp(or).map(|o2| o.cmp(&o2))),
#[neither]
#[allow(unreachable_patterns)]
(Self::Neither, _) => Some(std::cmp::Ordering::Less),
#[neither]
#[allow(unreachable_patterns)]
(_, Quither::Neither) => Some(std::cmp::Ordering::Greater),
#[either]
#[allow(unreachable_patterns)]
(Self::Left(_), _) => Some(std::cmp::Ordering::Less),
#[either]
#[allow(unreachable_patterns)]
(_, Quither::Left(_)) => Some(std::cmp::Ordering::Greater),
#[either]
#[allow(unreachable_patterns)]
(Self::Right(_), _) => Some(std::cmp::Ordering::Less),
#[either]
#[allow(unreachable_patterns)]
(_, Quither::Right(_)) => Some(std::cmp::Ordering::Greater),
}
}
}