Skip to content

Commit

Permalink
Re-design separator and rank system and remove WriteOneInto.
Browse files Browse the repository at this point in the history
  • Loading branch information
TheVeryDarkness committed Oct 6, 2024
1 parent df8d4b6 commit 5023463
Show file tree
Hide file tree
Showing 26 changed files with 488 additions and 260 deletions.
20 changes: 10 additions & 10 deletions examples/doc_macro_show.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ fn main() {

// This will write "42\n" to the standard output.
show!(42);
// This will write "42 Hello, World!\n" to the standard output.
show!(42, "Hello, World!");
// This will write "42 Hello, World! 1 2 3 4\n" to the standard output.
show!(42, "Hello, World!", [1, 2, 3, 4]);
// This will write "42 Hello, World! 1 2 3 4 1 2 3 4\n" to the standard output.
show!(42, "Hello, World!", [1, 2, 3, 4], [[1, 2], [3, 4]]);
// This will write "42, Hello, World!, 1 2 3 4, 1 2 3 4\n" to the standard output.
show!(42, "Hello, World!", [1, 2, 3, 4], [[1, 2], [3, 4]]; sep=", ");
// This will write "42, Hello, World!, 1 2 3 4, 1 2 3 4!" to the standard output.
show!(42, "Hello, World!", [1, 2, 3, 4], [[1, 2], [3, 4]]; sep=", ", end="!");
// This will write "Hello, World!\n" to the standard output.
show!("Hello, World!");
// This will write "1 2 3 4\n" to the standard output.
show!([1, 2, 3, 4]);
// This will write "1 2\n3 4\n" to the standard output.
show!([[1, 2], [3, 4]]);
// This will write "1, 2\n3, 4\n" to the standard output.
show!([[1, 2], [3, 4]], sep=["\n", ", "]);
// This will write "1, 2\n3, 4!" to the standard output.
show!([[1, 2], [3, 4]], sep=["\n", ", "], end="!");
}
14 changes: 7 additions & 7 deletions examples/doc_macro_show.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
42
42 Hello, World!
42 Hello, World! 1 2 3 4
42 Hello, World! 1 2 3 4 1 2
Hello, World!
1 2 3 4
1 2
3 4
42, Hello, World!, 1 2 3 4, 1 2
3 4
42, Hello, World!, 1 2 3 4, 1 2
3 4!
1, 2
3, 4
1, 2
3, 4!
3 changes: 2 additions & 1 deletion examples/doc_show.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ Hello, World!
.@/
#$$
1 2 3
1 2 3 4
1 2
3 4

8 changes: 3 additions & 5 deletions examples/macros-output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@
3 3
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18
, 2
2
3 3
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18
2, 2 2 :: 3 3 :: 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18
3 :: 3
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 :: 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18
8 changes: 4 additions & 4 deletions examples/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ fn main() {
show!(b);
show!(c);

show!(a, b, c; sep = "\n");
show!(a; end = "");
show!(", ", a, " "; sep = "", end = "");
show!(a, b, c; sep = " :: ");
show!((", ", a, " "), sep = [""], end = "\n");
show!(a, end = "\n");
show!(b, sep = [" :: "]);
show!(c, sep = [" :: ", " | "]);
}
2 changes: 1 addition & 1 deletion src/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ mod tests;
///
/// # Examples
///
/// ```rust,ignore
/// ```rust,ignore "This function is no longer exported."
/// use iof::array_try_from_fn;
/// let array: Result<[String; 3], ()> = array_try_from_fn(|| Ok("hello".to_string()));
/// assert_eq!(array, Ok(["hello", "hello", "hello"]));
Expand Down
35 changes: 31 additions & 4 deletions src/formatted.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use crate::sep_by;
use crate::write::{
sep_by::{self},
separator::Separator,
};

/// [std::fmt::Display] with given separator.
///
Expand All @@ -10,16 +13,40 @@ use crate::sep_by;
/// let s = format!("{}", v.sep_by(", "));
/// assert_eq!(s, "1, 2, 3");
/// ```
pub trait SepBy: IntoIterator {
pub trait SepBy: IntoIterator
where
<Self as IntoIterator>::IntoIter: Clone,
{
/// Create an iterator that implement [core::fmt::Display] using given separator.
fn sep_by(self, sep: &'_ str) -> sep_by::SepBy<'_, Self::IntoIter>;
fn sep_by<S: Separator + ?Sized>(self, sep: &'_ S) -> sep_by::SepBy<'_, Self::IntoIter, S>;

/// Create an iterator that implement [WriteInto](crate::WriteInto) using given separator.
fn sep_by_write_into<S: Separator + ?Sized>(
self,
sep: &'_ S,
) -> sep_by::SepBy<'_, Self::IntoIter, S>
where
Self::Item: crate::WriteInto;
}

impl<I: IntoIterator> SepBy for I
where
I::IntoIter: Clone,
{
fn sep_by(self, sep: &'_ str) -> sep_by::SepBy<'_, Self::IntoIter> {
fn sep_by<S: Separator + ?Sized>(self, sep: &'_ S) -> sep_by::SepBy<'_, Self::IntoIter, S> {
sep_by::SepBy::new(self.into_iter(), sep)
}

fn sep_by_write_into<S: Separator + ?Sized>(
self,
sep: &'_ S,
) -> sep_by::SepBy<'_, Self::IntoIter, S>
where
Self::Item: crate::WriteInto,
{
let iter = sep_by::SepBy::new(self.into_iter(), sep);
fn check_impl_write_into<T: crate::WriteInto>(_: &T) {}
check_impl_write_into(&iter);
iter
}
}
8 changes: 6 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,14 +313,18 @@ pub use {
},
stdio::{read_into::*, stdin, stdout, stream::*},
stream::{input_stream::InputStream, traits::BufReadExt},
write::{writer::Writer, WriteInto, WriteOneInto},
write::{
ranked,
separator::{GetDefaultSeparator, Separator},
writer::Writer,
WriteInto,
},
};

mod array;
mod formatted;
mod mat;
mod read;
mod sep_by;
mod stdio;
mod stream;
mod write;
Expand Down
113 changes: 81 additions & 32 deletions src/write/impls.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use super::WriteOneInto;
use crate::impl_write_into;
use super::{ranked::*, Separator, WriteInto};
use crate::impl_for_single;
use std::{io, num::*};

impl_write_into!(
impl_for_single!(
f32 f64
bool
str String
Expand All @@ -18,51 +18,100 @@ impl_write_into!(
NonZeroIsize NonZeroUsize
);

impl WriteOneInto for char {
const SEP_ITEM: &'static str = "";

fn try_write_one_into<S: io::Write + ?Sized>(&self, s: &mut S) -> io::Result<()> {
impl WriteInto for char {
fn try_write_into_with_sep<S: io::Write + ?Sized>(
&self,
s: &mut S,
sep: &[impl Separator],
) -> super::Result {
debug_assert_eq!(sep.len(), Self::RANK);
s.write_all(&[*self as u8])
}
}

macro_rules! impl_write_one_into_for_tuple {
($n0:ident $t0:ident $(, $n:ident $t:ident)* $(,)?) => {
impl<$t0: WriteOneInto, $($t: WriteOneInto),*> WriteOneInto for ($t0, $($t,)*) {
const SEP_ITEM: &'static str = " ";
impl Rank for char {
const RANK: usize = 0;
const SPACE: bool = false;
}

macro_rules! check_separators_count {
($sep:expr, $t0:ty $(, $t:ty)*) => {
debug_assert_eq!($sep.len(), Self::RANK, "Separator count mismatch.");
$(
debug_assert_eq!(
<$t0 as Rank>::RANK,
<$t as Rank>::RANK,
"Rank mismatch: {} != {}",
<$t0 as Rank>::RANK,
<$t as Rank>::RANK,
);
)*
};
($sep:expr $(,)?) => {
debug_assert_eq!($sep.len(), Self::RANK, "Separator count mismatch.");
};
}

macro_rules! impl_for_tuple {
($n0:ident $t0:ident $(, $n:ident $t:ident)+ $(,)?) => {
impl<$t0: WriteInto, $($t: WriteInto),*> WriteInto for ($t0, $($t,)*) {
fn try_write_into_with_sep<S: io::Write + ?Sized>(&self, s: &mut S, sep: &[impl Separator]) -> io::Result<()> {
check_separators_count!(sep, $t0 $(, $t)*);

fn try_write_one_into<S: io::Write + ?Sized>(&self, s: &mut S) -> io::Result<()> {
let ($n0, $($n, )*) = self;
$n0.try_write_one_into(s)?;
let (sep, residual) = sep.split_first().expect("Separator count mismatch.");
$n0.try_write_into_with_sep(s, residual)?;
$(
s.write_all(Self::SEP_ITEM.as_bytes())?;
$n.try_write_one_into(s)?;
sep.write(s)?;
$n.try_write_into_with_sep(s, residual)?;
)*
Ok(())
}
}
impl<$t0: Rank, $($t: Rank,)*> Rank for ($t0, $($t,)*) {
const RANK: usize = 1 + $t0::RANK;
const SPACE: bool = true;
}
};
($n0:ident $t0:ident $(,)?) => {
impl<$t0: WriteInto> WriteInto for ($t0, ) {
fn try_write_into_with_sep<S: io::Write + ?Sized>(&self, s: &mut S, sep: &[impl Separator]) -> io::Result<()> {
check_separators_count!(sep, $t0);
let ($n0, ) = self;
let (_sep, residual) = sep.split_first().expect("Separator count mismatch.");
$n0.try_write_into_with_sep(s, residual)?;
Ok(())
}
}
impl<$t0: Rank> Rank for ($t0, ) {
const RANK: usize = 1 + $t0::RANK;
const SPACE: bool = true;
}
};
() => {
impl WriteOneInto for () {
const SEP_ITEM: &'static str = " ";

fn try_write_one_into<S: io::Write + ?Sized>(&self, _s: &mut S) -> io::Result<()> {
impl WriteInto for () {
fn try_write_into_with_sep<S: io::Write + ?Sized>(&self, _s: &mut S, _sep: &[impl Separator]) -> io::Result<()> {
check_separators_count!(_sep, );
Ok(())
}
}
impl Rank for () {
const RANK: usize = 0;
const SPACE: bool = true;
}
};
}

impl_write_one_into_for_tuple!();
impl_write_one_into_for_tuple!(t1 T1);
impl_write_one_into_for_tuple!(t1 T1, t2 T2);
impl_write_one_into_for_tuple!(t1 T1, t2 T2, t3 T3);
impl_write_one_into_for_tuple!(t1 T1, t2 T2, t3 T3, t4 T4);
impl_write_one_into_for_tuple!(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5);
impl_write_one_into_for_tuple!(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6);
impl_write_one_into_for_tuple!(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7);
impl_write_one_into_for_tuple!(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8);
impl_write_one_into_for_tuple!(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9);
impl_write_one_into_for_tuple!(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9, t10 T10);
impl_write_one_into_for_tuple!(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9, t10 T10, t11 T11);
impl_write_one_into_for_tuple!(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9, t10 T10, t11 T11, t12 T12);
impl_for_tuple!();
impl_for_tuple!(t1 T1);
impl_for_tuple!(t1 T1, t2 T2);
impl_for_tuple!(t1 T1, t2 T2, t3 T3);
impl_for_tuple!(t1 T1, t2 T2, t3 T3, t4 T4);
impl_for_tuple!(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5);
impl_for_tuple!(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6);
impl_for_tuple!(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7);
impl_for_tuple!(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8);
impl_for_tuple!(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9);
impl_for_tuple!(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9, t10 T10);
impl_for_tuple!(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9, t10 T10, t11 T11);
impl_for_tuple!(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9, t10 T10, t11 T11, t12 T12);
23 changes: 13 additions & 10 deletions src/write/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,19 @@
/// [WriteInto]: crate::WriteInto
#[macro_export(local_inner_macros)]
macro_rules! show {
($($expr:expr),* $(,)? ; $($opt:ident=$val:expr),* $(,)?) => {
($expr:expr $(, $opt:ident=$val:expr)* $(,)? => $buf:expr) => {
unwrap!(|| -> ::std::io::Result<()> {
$crate::Writer::new()
$(.$opt($val))*
$(.write(&$expr)?)*
.finish()?;
$(.$opt(&$val))*
.write(&$expr, &mut $buf)?;
Ok(())
}())
};
($($expr:expr),* $(,)?) => {
($expr:expr $(, $opt:ident=$val:expr)* $(,)?) => {
unwrap!(|| -> ::std::io::Result<()> {
$crate::Writer::new()
$(.write(&$expr)?)*
.finish()?;
$(.$opt(&$val))*
.write(&$expr, &mut $crate::stdout())?;
Ok(())
}())
};
Expand All @@ -36,14 +35,18 @@ macro_rules! show {
///
/// [WriteInto]: crate::WriteInto
#[macro_export(local_inner_macros)]
macro_rules! impl_write_into {
macro_rules! impl_for_single {
($($ty:ty)*) => {
$(
impl $crate::WriteOneInto for $ty {
fn try_write_one_into<S: ::std::io::Write + ?::std::marker::Sized>(&self, s: &mut S) -> ::std::io::Result<()> {
impl $crate::WriteInto for $ty {
fn try_write_into_with_sep<S: ::std::io::Write + ?::std::marker::Sized>(&self, s: &mut S, _sep: &[impl Separator]) -> ::std::io::Result<()> {
::std::write!(s, "{}", self)
}
}
impl $crate::ranked::Rank for $ty {
const RANK: usize = 0;
const SPACE: bool = true;
}
)*
};
}
Loading

0 comments on commit 5023463

Please sign in to comment.