From c458902a6bcfc45aaa1b496afcf1186a89152d07 Mon Sep 17 00:00:00 2001 From: nils <48135649+Nilstrieb@users.noreply.github.com> Date: Mon, 12 Sep 2022 14:24:49 +0200 Subject: [PATCH] oh no --- src/args.rs | 86 ++++++++++++++++++++++++++++++++++ src/lib.rs | 127 +++++++++++++-------------------------------------- src/opts.rs | 122 +++++++++++++++++++++++++++++++++++++++++++++++++ src/write.rs | 58 +++++++++++++++++++++++ 4 files changed, 298 insertions(+), 95 deletions(-) create mode 100644 src/args.rs create mode 100644 src/opts.rs create mode 100644 src/write.rs diff --git a/src/args.rs b/src/args.rs new file mode 100644 index 0000000..494c26b --- /dev/null +++ b/src/args.rs @@ -0,0 +1,86 @@ +use std::marker::PhantomData; + +use crate::{Debug, Display, FmtOpts, Formatter, Result, Write}; +pub trait Arguments { + fn fmt(&self, f: &mut Formatter) -> Result; +} + +macro_rules! impl_arguments { + () => {}; + ($first:ident $($rest:ident)*) => { + impl<$first, $($rest),*> Arguments for ($first, $($rest),*) + where + $first: Arguments, + $($rest: Arguments),* + { + #[allow(non_snake_case)] + fn fmt(&self, f: &mut Formatter) -> Result { + let ($first, $($rest),*) = self; + Arguments::fmt($first, f)?; + $( + Arguments::fmt($rest, f)?; + )* + Ok(()) + } + } + + impl_arguments!($($rest)*); + }; + } + +#[rustfmt::skip] + impl_arguments!( + A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 + // A11 A12 A13 A14 A15 A16 A17 A18 A19 A20 + // A21 A22 A23 A24 A25 A26 A27 A28 A29 A30 + // A31 A32 A33 A34 A35 A36 A37 A38 A39 A40 + // A41 A42 A43 A44 A45 A46 A47 A48 A49 A50 + // A51 A52 A53 A54 A55 A56 A57 A58 A59 A60 + // A61 A62 A63 A64 A65 A66 A67 A68 A69 A70 + // A71 A72 A73 A74 A75 A76 A77 A78 A79 A80 + // A81 A82 A83 A84 A85 A86 A87 A88 A89 A90 + // A91 A92 A93 A94 A95 A96 A97 A98 A99 A100 + ); + +pub struct Str(pub &'static str); + +impl Arguments for Str { + fn fmt(&self, f: &mut Formatter) -> Result { + f.write_str(self.0) + } +} + +pub struct DebugArg(pub T); + +impl Arguments for DebugArg { + fn fmt(&self, f: &mut Formatter) -> Result { + Debug::fmt(&self.0, f) + } +} + +pub struct DisplayArg(pub T); + +impl Arguments for DisplayArg { + fn fmt(&self, f: &mut Formatter) -> Result { + Display::fmt(&self.0, f) + } +} + +pub struct ConstWidthArg { + value: T, + _boo: PhantomData<[(); WIDTH]>, +} + +#[allow(non_snake_case)] +pub fn ConstWidthArg(value: T) -> ConstWidthArg { + ConstWidthArg { + value, + _boo: PhantomData, + } +} + +impl Arguments for ConstWidthArg { + fn fmt(&self, f: &mut Formatter) -> Result { + todo!() + } +} diff --git a/src/lib.rs b/src/lib.rs index f3a77b1..cbbe61e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,9 +2,14 @@ #[cfg(test)] extern crate self as mono_fmt; +mod args; +mod opts; +mod write; + pub use mono_fmt_macro::format_args; -use crate::arguments::Arguments; +pub use crate::args::Arguments; +pub use crate::opts::FmtOpts; pub type Result = std::result::Result<(), Error>; @@ -38,39 +43,35 @@ impl Write for &mut W { } } -trait Debug { - fn fmt(&self, f: &mut Formatter) -> Result; +pub trait Debug { + fn fmt(&self, f: &mut Formatter) -> Result; } -trait Display { - fn fmt(&self, f: &mut Formatter) -> Result; +pub trait Display { + fn fmt(&self, f: &mut Formatter) -> Result; } -impl Debug for &'_ str { - fn fmt(&self, f: &mut Formatter) -> Result { - f.write_char('"')?; - f.write_str(self)?; - f.write_char('"') - } -} - -impl Display for &'_ str { - fn fmt(&self, f: &mut Formatter) -> Result { - f.write_str(self) - } -} - -pub struct Formatter { +pub struct Formatter { buf: W, + opts: O, } -impl Formatter { - fn new(buf: W) -> Self { - Self { buf } +impl core::fmt::Write for Formatter { + fn write_char(&mut self, c: char) -> std::fmt::Result { + self.buf.write_char(c).map_err(|_| std::fmt::Error) + } + fn write_str(&mut self, s: &str) -> std::fmt::Result { + self.buf.write_str(s).map_err(|_| std::fmt::Error) } } -impl Formatter { +impl Formatter { + fn new(buf: W) -> Self { + Self { buf, opts: () } + } +} + +impl Formatter { pub fn write_char(&mut self, char: char) -> Result { self.buf.write_char(char) } @@ -80,83 +81,19 @@ impl Formatter { } } +pub fn write(buffer: W, args: A) -> Result { + let mut fmt = Formatter::new(buffer); + args.fmt(&mut fmt) +} + pub fn format(args: A) -> String { let mut string = String::new(); - let mut fmt = Formatter::new(&mut string); - args.fmt(&mut fmt).unwrap(); + write(&mut string, args).unwrap(); string } -mod arguments { - use crate::{Debug, Display, Formatter, Result, Write}; - pub trait Arguments { - fn fmt(&self, f: &mut Formatter) -> Result; - } - - macro_rules! impl_arguments { - () => {}; - ($first:ident $($rest:ident)*) => { - impl<$first, $($rest),*> Arguments for ($first, $($rest),*) - where - $first: Arguments, - $($rest: Arguments),* - { - #[allow(non_snake_case)] - fn fmt(&self, f: &mut Formatter) -> Result { - let ($first, $($rest),*) = self; - Arguments::fmt($first, f)?; - $( - Arguments::fmt($rest, f)?; - )* - Ok(()) - } - } - - impl_arguments!($($rest)*); - }; - } - - #[rustfmt::skip] - impl_arguments!( - A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 - // A11 A12 A13 A14 A15 A16 A17 A18 A19 A20 - // A21 A22 A23 A24 A25 A26 A27 A28 A29 A30 - // A31 A32 A33 A34 A35 A36 A37 A38 A39 A40 - // A41 A42 A43 A44 A45 A46 A47 A48 A49 A50 - // A51 A52 A53 A54 A55 A56 A57 A58 A59 A60 - // A61 A62 A63 A64 A65 A66 A67 A68 A69 A70 - // A71 A72 A73 A74 A75 A76 A77 A78 A79 A80 - // A81 A82 A83 A84 A85 A86 A87 A88 A89 A90 - // A91 A92 A93 A94 A95 A96 A97 A98 A99 A100 - ); - - pub struct Str(pub &'static str); - - impl Arguments for Str { - fn fmt(&self, f: &mut Formatter) -> Result { - f.write_str(self.0) - } - } - - pub struct DebugArg(pub T); - - impl Arguments for DebugArg { - fn fmt(&self, f: &mut Formatter) -> Result { - Debug::fmt(&self.0, f) - } - } - - pub struct DisplayArg(pub T); - - impl Arguments for DisplayArg { - fn fmt(&self, f: &mut Formatter) -> Result { - Display::fmt(&self.0, f) - } - } -} - mod _private { - pub use super::arguments::{DebugArg, DisplayArg, Str}; + pub use super::args::{ConstWidthArg, DebugArg, DisplayArg, Str}; } #[macro_export] diff --git a/src/opts.rs b/src/opts.rs new file mode 100644 index 0000000..09b421f --- /dev/null +++ b/src/opts.rs @@ -0,0 +1,122 @@ +pub enum Alignment { + Left, + Center, + Right, +} + +pub trait FmtOpts { + #[doc(hidden)] + type Inner: FmtOpts; + + fn alternate() -> bool { + Self::Inner::alternate() + } + + fn width() -> Option { + Self::Inner::width() + } + + fn align() -> Option { + Self::Inner::align() + } + + fn fill() -> Option { + Self::Inner::fill() + } +} + +pub struct Default; + +mod never { + use crate::FmtOpts; + + pub trait Func { + type Output; + } + + impl Func for fn() -> T { + type Output = T; + } + + pub type Never = ! as Func>::Output; + + impl FmtOpts for Never { + type Inner = Self; + } +} + +impl FmtOpts for () { + type Inner = never::Never; + + fn alternate() -> bool { + false + } + + fn width() -> Option { + None + } + + fn align() -> Option { + None + } + + fn fill() -> Option { + None + } +} + +macro_rules! with_fmts { + (@ty $ty:ty, $($tt:tt)*) => { $ty }; + ($(struct $name:ident $()? { + fn $override:ident() -> $override_ret:ty { + $($override_body:tt)* + } + })*) => { + $( + pub struct $name(I); + + impl FmtOpts for $name { + type Inner = I; + + fn $override() -> $override_ret { + $($override_body)* + } + } + )* + }; + + (struct $name:ident) => {}; +} + +with_fmts! { + struct WithAlternate { + fn alternate() -> bool { + true + } + } + struct WithWidth { + fn width() -> Option { + Some(A) + } + } + struct WithLeftAlign { + fn align() -> Option { + Some(Alignment::Left) + } + } + struct WithRightAlign { + fn align() -> Option { + Some(Alignment::Right) + } + } + struct WithCenterAlign { + fn align() -> Option { + Some(Alignment::Center) + } + } + struct WithFill { + fn fill() -> Option { + Some(A) + } + } +} diff --git a/src/write.rs b/src/write.rs new file mode 100644 index 0000000..84e5f7a --- /dev/null +++ b/src/write.rs @@ -0,0 +1,58 @@ +use crate::{Debug, Display, FmtOpts, Formatter, Result, Write}; + +impl Debug for &'_ str { + fn fmt(&self, f: &mut Formatter) -> Result { + f.write_char('"')?; + f.write_str(self)?; + f.write_char('"') + } +} + +impl Display for &'_ str { + fn fmt(&self, f: &mut Formatter) -> Result { + f.write_str(self) + } +} + +impl Debug for String { + fn fmt(&self, f: &mut Formatter) -> Result { + f.write_char('"')?; + f.write_str(self)?; + f.write_char('"') + } +} + +impl Display for String { + fn fmt(&self, f: &mut Formatter) -> Result { + f.write_str(self) + } +} + +macro_rules! naive_fmt { + ($($int:ty)*) => { + $( + impl Debug for $int { + fn fmt(&self, f: &mut Formatter) -> Result { + // FIXME lol + let string = format!("{:?}", self); + f.write_str(&string) + } + } + + impl Display for $int { + fn fmt(&self, f: &mut Formatter) -> Result { + // FIXME lol + let string = self.to_string(); + f.write_str(&string) + } + } + )* + }; +} + +naive_fmt!( + u8 u16 u32 u64 u128 usize + i8 i16 i32 i64 i128 isize + + f32 f64 +);