Compare commits
4
Commits
44e27e9d23
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7858cd68cf | ||
|
|
706e8ca22a | ||
|
|
3dcb61021f | ||
|
|
fc6caf0de6 |
No files matched your search
@@ -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
@@ -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
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user