From 1152f8ab99c6abc569f8a0a9709d654b42324ffe Mon Sep 17 00:00:00 2001 From: nils <48135649+Nilstrieb@users.noreply.github.com> Date: Mon, 12 Sep 2022 08:12:29 +0200 Subject: [PATCH] debug fmt --- mono-fmt-macro/src/lib.rs | 54 +++++++++++++++++++++++++++++---------- src/lib.rs | 19 ++++++++++++-- 2 files changed, 58 insertions(+), 15 deletions(-) diff --git a/mono-fmt-macro/src/lib.rs b/mono-fmt-macro/src/lib.rs index 18c5862..d817229 100644 --- a/mono-fmt-macro/src/lib.rs +++ b/mono-fmt-macro/src/lib.rs @@ -1,3 +1,4 @@ +use core::panic; use std::{iter::Peekable, str::Chars}; use proc_macro::TokenStream; @@ -58,21 +59,48 @@ impl<'a, I> Formatter<'a, I> where I: Iterator, { + + fn expect_expr(&mut self) -> Expr { + self.exprs + .next() + .expect("missing argument for display formatting") + } + + fn expect_char(&mut self, char: char) { + let next = self.string.next(); + if next != Some(char) { + panic!( + "expected {char}, found {}", + next.map(|c| c.to_string()) + .unwrap_or_else(|| "end of input".to_string()) + ); + } + } + fn parse(mut self) -> Vec { let mut next_string = String::new(); while let Some(char) = self.string.next() { match char { - '{' => { - self.save_string(std::mem::take(&mut next_string)); - if self.string.next() != Some('}') { - panic!("only supports display formatting!"); + '{' => match self.string.next() { + Some('}') => { + self.save_string(std::mem::take(&mut next_string)); + let expr = self.expect_expr(); + self.fmt_parts.push(FmtPart::Display(expr)); } - let expr = self - .exprs - .next() - .expect("missing argument for display formatting"); - self.fmt_parts.push(FmtPart::Display(expr)); - } + Some(':') => { + self.save_string(std::mem::take(&mut next_string)); + self.expect_char('?'); + self.expect_char('}'); + let expr = self.expect_expr(); + self.fmt_parts.push(FmtPart::Debug(expr)) + } + Some(other) => { + panic!("expected }}, found '{}'", other) + } + None => { + panic!("expected '}}'") + } + }, other => { next_string.push(other); } @@ -96,13 +124,13 @@ impl ToTokens for FmtPart { let own_tokens = match self { FmtPart::Literal(lit) => { let literal = LitStr::new(lit, Span::call_site()); - quote! { mono_fmt::_private::Str(#literal) } + quote! { ::mono_fmt::_private::Str(#literal) } } FmtPart::Display(expr) => { - quote! { mono_fmt::_private::DisplayArg(#expr) } + quote! { ::mono_fmt::_private::DisplayArg(#expr) } } FmtPart::Debug(expr) => { - quote! { mono_fmt::_private::DebugArg(#expr) } + quote! { ::mono_fmt::_private::DebugArg(#expr) } } }; diff --git a/src/lib.rs b/src/lib.rs index e4a7af9..7ec0122 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,7 @@ +// for the test macro expansion +#[cfg(test)] +extern crate self as mono_fmt; + pub use mono_fmt_macro::format_args; use std::fmt::{Error, Write}; @@ -136,8 +140,6 @@ macro_rules! format { #[cfg(test)] mod tests { - // for the macros - use crate as mono_fmt; use crate::format; @@ -152,4 +154,17 @@ mod tests { let result = format!("{}", "uwu"); assert_eq!(result, "uwu"); } + + #[test] + fn display_with_strings() { + let result = format!("oow{} omg", "uwu"); + assert_eq!(result, "oowuwu omg"); + } + + + #[test] + fn debug() { + let result = format!("test {:?} hello", "uwu"); + assert_eq!(result, r#"test "uwu" hello"#); + } }