mirror of
https://github.com/Noratrieb/mono-fmt.git
synced 2026-01-14 15:25:08 +01:00
oh no
This commit is contained in:
parent
0a9e7c5743
commit
c458902a6b
4 changed files with 298 additions and 95 deletions
86
src/args.rs
Normal file
86
src/args.rs
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
use crate::{Debug, Display, FmtOpts, Formatter, Result, Write};
|
||||||
|
pub trait Arguments {
|
||||||
|
fn fmt<W: Write, O: FmtOpts>(&self, f: &mut Formatter<W, O>) -> 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<W: Write, O: FmtOpts>(&self, f: &mut Formatter<W, O>) -> 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<W: Write, O: FmtOpts>(&self, f: &mut Formatter<W, O>) -> Result {
|
||||||
|
f.write_str(self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DebugArg<T>(pub T);
|
||||||
|
|
||||||
|
impl<T: Debug> Arguments for DebugArg<T> {
|
||||||
|
fn fmt<W: Write, O: FmtOpts>(&self, f: &mut Formatter<W, O>) -> Result {
|
||||||
|
Debug::fmt(&self.0, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DisplayArg<T>(pub T);
|
||||||
|
|
||||||
|
impl<T: Display> Arguments for DisplayArg<T> {
|
||||||
|
fn fmt<W: Write, O: FmtOpts>(&self, f: &mut Formatter<W, O>) -> Result {
|
||||||
|
Display::fmt(&self.0, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ConstWidthArg<T, const WIDTH: usize> {
|
||||||
|
value: T,
|
||||||
|
_boo: PhantomData<[(); WIDTH]>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub fn ConstWidthArg<T, const WIDTH: usize>(value: T) -> ConstWidthArg<T, WIDTH> {
|
||||||
|
ConstWidthArg {
|
||||||
|
value,
|
||||||
|
_boo: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Display, const WIDTH: usize> Arguments for ConstWidthArg<T, WIDTH> {
|
||||||
|
fn fmt<W: Write, O: FmtOpts>(&self, f: &mut Formatter<W, O>) -> Result {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
127
src/lib.rs
127
src/lib.rs
|
|
@ -2,9 +2,14 @@
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
extern crate self as mono_fmt;
|
extern crate self as mono_fmt;
|
||||||
|
|
||||||
|
mod args;
|
||||||
|
mod opts;
|
||||||
|
mod write;
|
||||||
|
|
||||||
pub use mono_fmt_macro::format_args;
|
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>;
|
pub type Result = std::result::Result<(), Error>;
|
||||||
|
|
||||||
|
|
@ -38,39 +43,35 @@ impl<W: Write> Write for &mut W {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Debug {
|
pub trait Debug {
|
||||||
fn fmt<W: Write>(&self, f: &mut Formatter<W>) -> Result;
|
fn fmt<W: Write, O: FmtOpts>(&self, f: &mut Formatter<W, O>) -> Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Display {
|
pub trait Display {
|
||||||
fn fmt<W: Write>(&self, f: &mut Formatter<W>) -> Result;
|
fn fmt<W: Write, O: FmtOpts>(&self, f: &mut Formatter<W, O>) -> Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for &'_ str {
|
pub struct Formatter<W, O> {
|
||||||
fn fmt<W: Write>(&self, f: &mut Formatter<W>) -> Result {
|
|
||||||
f.write_char('"')?;
|
|
||||||
f.write_str(self)?;
|
|
||||||
f.write_char('"')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for &'_ str {
|
|
||||||
fn fmt<W: Write>(&self, f: &mut Formatter<W>) -> Result {
|
|
||||||
f.write_str(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Formatter<W> {
|
|
||||||
buf: W,
|
buf: W,
|
||||||
|
opts: O,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W> Formatter<W> {
|
impl<W: Write, O: FmtOpts> core::fmt::Write for Formatter<W, O> {
|
||||||
fn new(buf: W) -> Self {
|
fn write_char(&mut self, c: char) -> std::fmt::Result {
|
||||||
Self { buf }
|
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<W: Write> Formatter<W> {
|
impl<W> Formatter<W, ()> {
|
||||||
|
fn new(buf: W) -> Self {
|
||||||
|
Self { buf, opts: () }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<W: Write, O: FmtOpts> Formatter<W, O> {
|
||||||
pub fn write_char(&mut self, char: char) -> Result {
|
pub fn write_char(&mut self, char: char) -> Result {
|
||||||
self.buf.write_char(char)
|
self.buf.write_char(char)
|
||||||
}
|
}
|
||||||
|
|
@ -80,83 +81,19 @@ impl<W: Write> Formatter<W> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn write<W: Write, A: Arguments>(buffer: W, args: A) -> Result {
|
||||||
|
let mut fmt = Formatter::new(buffer);
|
||||||
|
args.fmt(&mut fmt)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn format<A: Arguments>(args: A) -> String {
|
pub fn format<A: Arguments>(args: A) -> String {
|
||||||
let mut string = String::new();
|
let mut string = String::new();
|
||||||
let mut fmt = Formatter::new(&mut string);
|
write(&mut string, args).unwrap();
|
||||||
args.fmt(&mut fmt).unwrap();
|
|
||||||
string
|
string
|
||||||
}
|
}
|
||||||
|
|
||||||
mod arguments {
|
|
||||||
use crate::{Debug, Display, Formatter, Result, Write};
|
|
||||||
pub trait Arguments {
|
|
||||||
fn fmt<W: Write>(&self, f: &mut Formatter<W>) -> 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<W: Write>(&self, f: &mut Formatter<W>) -> 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<W: Write>(&self, f: &mut Formatter<W>) -> Result {
|
|
||||||
f.write_str(self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct DebugArg<T>(pub T);
|
|
||||||
|
|
||||||
impl<T: Debug> Arguments for DebugArg<T> {
|
|
||||||
fn fmt<W: Write>(&self, f: &mut Formatter<W>) -> Result {
|
|
||||||
Debug::fmt(&self.0, f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct DisplayArg<T>(pub T);
|
|
||||||
|
|
||||||
impl<T: Display> Arguments for DisplayArg<T> {
|
|
||||||
fn fmt<W: Write>(&self, f: &mut Formatter<W>) -> Result {
|
|
||||||
Display::fmt(&self.0, f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod _private {
|
mod _private {
|
||||||
pub use super::arguments::{DebugArg, DisplayArg, Str};
|
pub use super::args::{ConstWidthArg, DebugArg, DisplayArg, Str};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
|
|
||||||
122
src/opts.rs
Normal file
122
src/opts.rs
Normal file
|
|
@ -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<usize> {
|
||||||
|
Self::Inner::width()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn align() -> Option<Alignment> {
|
||||||
|
Self::Inner::align()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fill() -> Option<char> {
|
||||||
|
Self::Inner::fill()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Default;
|
||||||
|
|
||||||
|
mod never {
|
||||||
|
use crate::FmtOpts;
|
||||||
|
|
||||||
|
pub trait Func {
|
||||||
|
type Output;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Func for fn() -> T {
|
||||||
|
type Output = T;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Never = <fn() -> ! as Func>::Output;
|
||||||
|
|
||||||
|
impl FmtOpts for Never {
|
||||||
|
type Inner = Self;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FmtOpts for () {
|
||||||
|
type Inner = never::Never;
|
||||||
|
|
||||||
|
fn alternate() -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn width() -> Option<usize> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn align() -> Option<Alignment> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fill() -> Option<char> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! with_fmts {
|
||||||
|
(@ty $ty:ty, $($tt:tt)*) => { $ty };
|
||||||
|
($(struct $name:ident $(<const A: $param:ty>)? {
|
||||||
|
fn $override:ident() -> $override_ret:ty {
|
||||||
|
$($override_body:tt)*
|
||||||
|
}
|
||||||
|
})*) => {
|
||||||
|
$(
|
||||||
|
pub struct $name<I, $(const A: $param)?>(I);
|
||||||
|
|
||||||
|
impl<I: FmtOpts, $(const A: $param)?> FmtOpts for $name<I, $(with_fmts!(@ty A, $param))?> {
|
||||||
|
type Inner = I;
|
||||||
|
|
||||||
|
fn $override() -> $override_ret {
|
||||||
|
$($override_body)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
|
||||||
|
(struct $name:ident) => {};
|
||||||
|
}
|
||||||
|
|
||||||
|
with_fmts! {
|
||||||
|
struct WithAlternate {
|
||||||
|
fn alternate() -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
struct WithWidth<const A: usize> {
|
||||||
|
fn width() -> Option<usize> {
|
||||||
|
Some(A)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
struct WithLeftAlign {
|
||||||
|
fn align() -> Option<Alignment> {
|
||||||
|
Some(Alignment::Left)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
struct WithRightAlign {
|
||||||
|
fn align() -> Option<Alignment> {
|
||||||
|
Some(Alignment::Right)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
struct WithCenterAlign {
|
||||||
|
fn align() -> Option<Alignment> {
|
||||||
|
Some(Alignment::Center)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
struct WithFill<const A: char> {
|
||||||
|
fn fill() -> Option<char> {
|
||||||
|
Some(A)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
58
src/write.rs
Normal file
58
src/write.rs
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
use crate::{Debug, Display, FmtOpts, Formatter, Result, Write};
|
||||||
|
|
||||||
|
impl Debug for &'_ str {
|
||||||
|
fn fmt<W: Write, O: FmtOpts>(&self, f: &mut Formatter<W, O>) -> Result {
|
||||||
|
f.write_char('"')?;
|
||||||
|
f.write_str(self)?;
|
||||||
|
f.write_char('"')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for &'_ str {
|
||||||
|
fn fmt<W: Write, O: FmtOpts>(&self, f: &mut Formatter<W, O>) -> Result {
|
||||||
|
f.write_str(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for String {
|
||||||
|
fn fmt<W: Write, O: FmtOpts>(&self, f: &mut Formatter<W, O>) -> Result {
|
||||||
|
f.write_char('"')?;
|
||||||
|
f.write_str(self)?;
|
||||||
|
f.write_char('"')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for String {
|
||||||
|
fn fmt<W: Write, O: FmtOpts>(&self, f: &mut Formatter<W, O>) -> Result {
|
||||||
|
f.write_str(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! naive_fmt {
|
||||||
|
($($int:ty)*) => {
|
||||||
|
$(
|
||||||
|
impl Debug for $int {
|
||||||
|
fn fmt<W: Write, O: FmtOpts>(&self, f: &mut Formatter<W, O>) -> Result {
|
||||||
|
// FIXME lol
|
||||||
|
let string = format!("{:?}", self);
|
||||||
|
f.write_str(&string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for $int {
|
||||||
|
fn fmt<W: Write, O: FmtOpts>(&self, f: &mut Formatter<W, O>) -> 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
|
||||||
|
);
|
||||||
Loading…
Add table
Add a link
Reference in a new issue