Compare commits

..
4 Commits
3 changed files with 189 additions and 27 deletions

No files matched your search

+20
View File
@@ -1,5 +1,25 @@
use core::convert::Infallible; use core::convert::Infallible;
pub trait Apply: Sized {
fn apply<U, F>(self, f: F) -> U
where
F: FnOnce(Self) -> U;
}
impl<T> Apply for T
where
T: Sized,
{
#[inline]
#[must_use]
fn apply<U, F>(self, f: F) -> U
where
F: FnOnce(Self) -> U
{
f(self)
}
}
/// Consumes an element of type `Infallible` and produces an element of any type `T`. This is /// Consumes an element of type `Infallible` and produces an element of any type `T`. This is
/// possible because `Infallible` has no elements and thus this function can never be called, so /// possible because `Infallible` has no elements and thus this function can never be called, so
/// the statement "for any given type `T`, whenever this function returns, it returns an element of /// the statement "for any given type `T`, whenever this function returns, it returns an element of
+79 -1
View File
@@ -2,7 +2,7 @@ use core::{
convert::identity, convert::identity,
fmt, fmt,
hint, hint,
ops::{Deref, DerefMut}, ops::{Deref, DerefMut}, iter::FusedIterator,
}; };
use crate::convert::{clone, clone_mut, copy, copy_mut, Empty}; use crate::convert::{clone, clone_mut, copy, copy_mut, Empty};
@@ -398,6 +398,16 @@ impl<L, R> Either<L, R> {
} }
self self
} }
pub fn iter<'a>(&'a self)
-> Iter<<&'a L as IntoIterator>::IntoIter, <&'a R as IntoIterator>::IntoIter>
where
&'a L: IntoIterator,
&'a R: IntoIterator,
{
self.as_ref().into_iter()
}
} }
impl<L, R> Either<&L, &R> { impl<L, R> Either<&L, &R> {
@@ -610,3 +620,71 @@ where
} }
} }
} }
impl<L, R> IntoIterator for Either<L, R>
where
L: IntoIterator,
R: IntoIterator,
{
type Item = Either<<L as IntoIterator>::Item, <R as IntoIterator>::Item>;
type IntoIter = Iter<<L as IntoIterator>::IntoIter, <R as IntoIterator>::IntoIter>;
fn into_iter(self) -> Self::IntoIter {
Iter {
inner: self.map(<L as IntoIterator>::into_iter, <R as IntoIterator>::into_iter),
}
}
}
pub struct Iter<L, R> {
inner: Either<L, R>,
}
impl<L, R> Iterator for Iter<L, R>
where
L: Iterator,
R: Iterator,
{
type Item = Either<<L as IntoIterator>::Item, <R as IntoIterator>::Item>;
fn next(&mut self) -> Option<Self::Item> {
match &mut self.inner {
Inl(l) => l.next().map(Inl),
Inr(r) => r.next().map(Inr),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.as_ref().fold(L::size_hint, R::size_hint)
}
fn count(self) -> usize {
self.inner.fold(L::count, R::count)
}
}
impl<L, R> DoubleEndedIterator for Iter<L, R>
where
L: DoubleEndedIterator,
R: DoubleEndedIterator,
{
fn next_back(&mut self) -> Option<Self::Item> {
match &mut self.inner {
Inl(l) => l.next_back().map(Inl),
Inr(r) => r.next_back().map(Inr),
}
}
}
impl<L, R> ExactSizeIterator for Iter<L, R>
where
L: ExactSizeIterator,
R: ExactSizeIterator,
{}
impl<L, R> FusedIterator for Iter<L, R>
where
L: FusedIterator,
R: FusedIterator,
{}
+90 -26
View File
@@ -12,36 +12,10 @@ pub trait StrSink {
} }
} }
impl<W> StrSink for W
where
W: fmt::Write,
{
type Error = fmt::Error;
#[inline]
fn sink_str(&mut self, s: &str) -> Result<(), Self::Error> {
self.write_str(s)
}
#[inline]
fn sink_char(&mut self, c: char) -> Result<(), Self::Error> {
self.write_char(c)
}
}
pub trait FmtSink: StrSink { pub trait FmtSink: StrSink {
fn sink_fmt<'a>(&mut self, args: Arguments<'a>) -> Result<(), <Self as StrSink>::Error>; fn sink_fmt<'a>(&mut self, args: Arguments<'a>) -> Result<(), <Self as StrSink>::Error>;
} }
impl<W> FmtSink for W
where
W: fmt::Write,
{
fn sink_fmt<'a>(&mut self, args: Arguments<'a>) -> Result<(), <Self as StrSink>::Error> {
self.write_fmt(args)
}
}
#[macro_export] #[macro_export]
macro_rules! sink_fmt { macro_rules! sink_fmt {
($dst:expr, $($arg:tt)*) => { ($dst:expr, $($arg:tt)*) => {
@@ -51,6 +25,48 @@ macro_rules! sink_fmt {
pub use sink_fmt; pub use sink_fmt;
#[repr(transparent)]
pub struct FmtWriteSink<W: fmt::Write>(pub W);
impl<W: fmt::Write> FmtWriteSink<W> {
#[inline]
#[must_use]
pub fn from_ref(w: &W) -> &Self {
// SAFETY:
// `FmtWriteSink` uses `repr(transparent)`, so it has the same memory layout as `W`.
unsafe { &*(w as *const W as *const Self) }
}
#[inline]
#[must_use]
pub fn from_mut(w: &mut W) -> &mut Self {
// SAFETY:
// `FmtWriteSink` uses `repr(transparent)`, so it has the same memory layout as `W`.
unsafe { &mut *(w as *mut W as *mut Self) }
}
}
impl<W: fmt::Write> StrSink for FmtWriteSink<W> {
type Error = fmt::Error;
#[inline]
fn sink_str(&mut self, s: &str) -> Result<(), Self::Error> {
self.0.write_str(s)
}
#[inline]
fn sink_char(&mut self, c: char) -> Result<(), Self::Error> {
self.0.write_char(c)
}
}
impl<W: fmt::Write> FmtSink for FmtWriteSink<W> {
#[inline]
fn sink_fmt<'a>(&mut self, args: Arguments<'a>) -> Result<(), <Self as StrSink>::Error> {
self.0.write_fmt(args)
}
}
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
pub use string_sink::SinkString; pub use string_sink::SinkString;
@@ -138,3 +154,51 @@ mod string_sink {
} }
} }
} }
#[cfg(feature = "std")]
pub use io_sink::IoWriteSink;
#[cfg(feature = "std")]
mod io_sink {
use core::fmt::Arguments;
use std::io;
use super::{StrSink, FmtSink};
#[repr(transparent)]
pub struct IoWriteSink<W: io::Write>(pub W);
impl<W: io::Write> IoWriteSink<W> {
#[inline]
#[must_use]
pub fn from_ref(w: &W) -> &Self {
// SAFETY:
// `IoWriteSink` uses `repr(transparent)`, so it has the same memory layout as `W`.
unsafe { &*(w as *const W as *const Self) }
}
#[inline]
#[must_use]
pub fn from_mut(w: &mut W) -> &mut Self {
// SAFETY:
// `IoWriteSink` uses `repr(transparent)`, so it has the same memory layout as `W`.
unsafe { &mut *(w as *mut W as *mut Self) }
}
}
impl<W: io::Write> StrSink for IoWriteSink<W> {
type Error = io::Error;
#[inline]
fn sink_str(&mut self, s: &str) -> Result<(), Self::Error> {
self.0.write_all(s.as_bytes())
}
}
impl<W: io::Write> FmtSink for IoWriteSink<W> {
#[inline]
fn sink_fmt<'a>(&mut self, args: Arguments<'a>) -> Result<(), <Self as StrSink>::Error> {
self.0.write_fmt(args)
}
}
}