Skip to main content

quither/
std_impls.rs

1// Copyright 2021 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! A file to implement standard traits for `Xither` types.
16//!
17//! Note some of the `std` traits like `AsRef`, `AsMut` are in other file ([`as_ref.rs`]).
18
19use super::*;
20use ::core::error::Error;
21use ::core::fmt::Display;
22use ::core::ops::{Deref, DerefMut};
23use ::core::pin::Pin;
24use ::core::task::{Context, Poll};
25use ::quither_proc_macros::quither;
26#[cfg(feature = "use_std")]
27use ::std::io::{BufRead, Read, Result as IoResult, Seek, SeekFrom};
28
29/// Provides Read, chaining Left then Right for Both, otherwise delegating.
30///
31/// Requires both `L: Read` and `R: Read`. For the `Left`, `Right`, or `Neither` variants, this
32/// simply delegates to the inner value or returns `Ok(0)`. For the `Both` variant, it first tries
33/// to read from `Left`; if that returns 0, it then reads from `Right`. This behavior differs from
34/// `std::io::Read::chain`, which never retries the first reader after it returns 0 bytes.
35#[cfg(feature = "use_std")]
36#[quither]
37impl<L, R> Read for Xither<L, R>
38where
39    L: Read,
40    R: Read,
41{
42    fn read(&mut self, #[allow(unused)] buf: &mut [u8]) -> IoResult<usize> {
43        match self {
44            #[either]
45            Self::Left(l) => l.read(buf),
46            #[either]
47            Self::Right(r) => r.read(buf),
48            #[neither]
49            Self::Neither => Ok(0),
50            #[both]
51            Self::Both(l, r) => {
52                if buf.is_empty() {
53                    return Ok(0);
54                }
55                let left_len = l.read(buf)?;
56                if left_len == 0 {
57                    r.read(buf)
58                } else {
59                    Ok(left_len)
60                }
61            }
62        }
63    }
64}
65
66/// Provides BufRead, but only for types that do not include the Both variant.
67///
68/// Requires both `L: BufRead` and `R: BufRead`. This implementation is only available for types
69/// that do not include the Both variant, because `BufRead::consume` cannot safely choose which
70/// reader to consume from if Both is present. If you want to combine two readers, use
71/// `std::io::Read::chain` instead.
72#[cfg(feature = "use_std")]
73#[quither(!has_both)]
74impl<L, R> BufRead for Xither<L, R>
75where
76    L: BufRead,
77    R: BufRead,
78{
79    fn fill_buf(&mut self) -> IoResult<&[u8]> {
80        match self {
81            #[either]
82            Self::Left(l) => l.fill_buf(),
83            #[either]
84            Self::Right(r) => r.fill_buf(),
85            #[neither]
86            Self::Neither => Ok(&[]),
87        }
88    }
89
90    fn consume(&mut self, #[allow(unused)] amt: usize) {
91        match self {
92            #[either]
93            Self::Left(l) => l.consume(amt),
94            #[either]
95            Self::Right(r) => r.consume(amt),
96            #[neither]
97            Self::Neither => {}
98        }
99    }
100}
101
102/// Provides Seek, but only for types that do not include the Both variant.
103///
104/// Requires both `L: Seek` and `R: Seek`. This implementation is only available for types that do
105/// not include the Both variant. It delegates to the inner value or returns `Ok(0)` for the Neither
106/// variant.
107#[cfg(feature = "use_std")]
108#[quither(!has_both)]
109impl<L, R> Seek for Xither<L, R>
110where
111    L: Seek,
112    R: Seek,
113{
114    fn seek(&mut self, #[allow(unused)] pos: SeekFrom) -> IoResult<u64> {
115        match self {
116            #[either]
117            Self::Left(l) => l.seek(pos),
118            #[either]
119            Self::Right(r) => r.seek(pos),
120            #[neither]
121            Self::Neither => Ok(0),
122        }
123    }
124}
125
126/// Dereferences to the inner value, regardless of variant.
127///
128/// Requires both `L: Deref` and `R: Deref<Target = L::Target>`. This allows dereferencing to the
129/// inner value, regardless of which variant is used.
130impl<L, R> Deref for Either<L, R>
131where
132    L: Deref,
133    R: Deref<Target = L::Target>,
134{
135    type Target = L::Target;
136
137    fn deref(&self) -> &Self::Target {
138        match self {
139            Self::Left(l) => l,
140            Self::Right(r) => r,
141        }
142    }
143}
144
145/// Allows mutable dereference to the inner value, for any variant.
146///
147/// Requires both `L: DerefMut` and `R: DerefMut<Target = L::Target>`. This allows mutable
148/// dereferencing to the inner value for any variant.
149impl<L, R> DerefMut for Either<L, R>
150where
151    L: DerefMut,
152    R: DerefMut<Target = L::Target>,
153{
154    fn deref_mut(&mut self) -> &mut Self::Target {
155        match self {
156            Self::Left(l) => l,
157            Self::Right(r) => r,
158        }
159    }
160}
161
162/// Formats the pair type for display, showing the variant and its contents.
163///
164/// Requires both `L: Display` and `R: Display`. The output format reflects the variant and its
165/// inner value(s).
166#[quither]
167impl<L, R> Display for Xither<L, R>
168where
169    L: Display,
170    R: Display,
171{
172    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
173        match self {
174            #[either]
175            Self::Left(l) => write!(f, "Left({})", l),
176            #[either]
177            Self::Right(r) => write!(f, "Right({})", r),
178            #[neither]
179            Self::Neither => write!(f, "Neither"),
180            #[both]
181            Self::Both(l, r) => write!(f, "Both({}, {})", l, r),
182        }
183    }
184}
185
186/// Delegates Error trait methods to the inner value.
187///
188/// Requires both `L: Error` and `R: Error`. Error source, description, and cause are delegated to
189/// the inner value.
190impl<L, R> Error for Either<L, R>
191where
192    L: Error,
193    R: Error,
194{
195    fn source(&self) -> Option<&(dyn Error + 'static)> {
196        match self {
197            Self::Left(l) => l.source(),
198            Self::Right(r) => r.source(),
199        }
200    }
201
202    #[allow(deprecated)]
203    fn description(&self) -> &str {
204        match self {
205            Self::Left(l) => l.description(),
206            Self::Right(r) => r.description(),
207        }
208    }
209
210    #[allow(deprecated)]
211    fn cause(&self) -> Option<&dyn Error> {
212        match self {
213            Self::Left(l) => l.cause(),
214            Self::Right(r) => r.cause(),
215        }
216    }
217
218    // TODO: nightly methods?
219}
220
221/// Extends with items, only for types that do not include the Neither or Both variants.
222///
223/// Requires both `L: Extend<T>` and `R: Extend<T>`. This implementation is only available for types
224/// that do not include the Neither or Both variants. If the type includes the Both variant, use the
225/// implementation that requires `T: Clone`, which extends both inner values with cloned items.
226#[quither(!has_neither && !has_both)]
227impl<L, R, T> Extend<T> for Xither<L, R>
228where
229    L: Extend<T>,
230    R: Extend<T>,
231{
232    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
233        match self {
234            #[either]
235            Self::Left(l) => l.extend(iter),
236            #[either]
237            Self::Right(r) => r.extend(iter),
238        }
239    }
240}
241
242/// Extends both inner values of Both with cloned items, only for types that include the Both variant.
243///
244/// Requires `L: Extend<T>`, `R: Extend<T>`, and `T: Clone`. For types that include the Both variant,
245/// both inner values are extended with cloned items from the iterator.
246#[quither(!has_neither && has_both)]
247impl<L, R, T> Extend<T> for Xither<L, R>
248where
249    L: Extend<T>,
250    R: Extend<T>,
251    T: Clone,
252{
253    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
254        match self {
255            #[either]
256            Self::Left(l) => l.extend(iter),
257            #[either]
258            Self::Right(r) => r.extend(iter),
259            #[both]
260            Self::Both(l, r) => {
261                let tuple_iter = iter.into_iter().map(|t| (t.clone(), t));
262
263                // Why `Extend` not implemented for `&mut T where T: Extend`?
264                struct Wrap<U>(U);
265                impl<U, V> Extend<V> for Wrap<&mut U>
266                where
267                    U: Extend<V>,
268                {
269                    fn extend<I: IntoIterator<Item = V>>(&mut self, iter: I) {
270                        self.0.extend(iter);
271                    }
272                }
273                (Wrap(l), Wrap(r)).extend(tuple_iter);
274            }
275        }
276    }
277}
278
279/// Polls the inner future, matching the current variant.
280///
281/// Requires both `L: Future` and `R: Future<Output = L::Output>`. Polling this type will poll the
282/// inner future, matching the current variant.
283impl<L, R> Future for Either<L, R>
284where
285    L: Future,
286    R: Future<Output = L::Output>,
287{
288    type Output = L::Output;
289    fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> {
290        match self.as_pin_mut() {
291            Either::Left(l) => l.poll(ctx),
292            Either::Right(r) => r.poll(ctx),
293        }
294    }
295}
296
297#[quither]
298impl<L, R, OL, OR> PartialEq<Xither<OL, OR>> for Xither<L, R>
299where
300    L: PartialEq<OL>,
301    R: PartialEq<OR>,
302{
303    fn eq(&self, other: &Xither<OL, OR>) -> bool {
304        match (self, other) {
305            #[either]
306            (Self::Left(l), Xither::Left(ol)) => l == ol,
307            #[either]
308            (Self::Right(r), Xither::Right(or)) => r == or,
309            #[neither]
310            (Self::Neither, Xither::Neither) => true,
311            #[both]
312            (Self::Both(l, r), Xither::Both(ol, or)) => l == ol && r == or,
313            #[allow(unreachable_patterns)]
314            _ => false,
315        }
316    }
317}
318
319#[quither]
320impl<L, R, OL, OR> PartialOrd<Xither<OL, OR>> for Xither<L, R>
321where
322    L: PartialOrd<OL>,
323    R: PartialOrd<OR>,
324{
325    fn partial_cmp(&self, other: &Xither<OL, OR>) -> Option<std::cmp::Ordering> {
326        match (self, other) {
327            #[either]
328            (Self::Left(l), Xither::Left(ol)) => l.partial_cmp(ol),
329            #[either]
330            (Self::Right(r), Xither::Right(or)) => r.partial_cmp(or),
331            #[neither]
332            (Self::Neither, Xither::Neither) => Some(std::cmp::Ordering::Equal),
333            #[both]
334            (Self::Both(l, r), Xither::Both(ol, or)) => l
335                .partial_cmp(ol)
336                .and_then(|o| r.partial_cmp(or).map(|o2| o.cmp(&o2))),
337            // Non-equal variants patterns
338            #[neither]
339            #[allow(unreachable_patterns)]
340            (Self::Neither, _) => Some(std::cmp::Ordering::Less),
341            #[neither]
342            #[allow(unreachable_patterns)]
343            (_, Xither::Neither) => Some(std::cmp::Ordering::Greater),
344            #[either]
345            #[allow(unreachable_patterns)]
346            (Self::Left(_), _) => Some(std::cmp::Ordering::Less),
347            #[either]
348            #[allow(unreachable_patterns)]
349            (_, Xither::Left(_)) => Some(std::cmp::Ordering::Greater),
350            #[either]
351            #[allow(unreachable_patterns)]
352            (Self::Right(_), _) => Some(std::cmp::Ordering::Less),
353            #[either]
354            #[allow(unreachable_patterns)]
355            (_, Xither::Right(_)) => Some(std::cmp::Ordering::Greater),
356        }
357    }
358}