diff --git a/mono-fmt-macro/src/to_tokens.rs b/mono-fmt-macro/src/to_tokens.rs index e0b87cc..a7fb6db 100644 --- a/mono-fmt-macro/src/to_tokens.rs +++ b/mono-fmt-macro/src/to_tokens.rs @@ -1,6 +1,6 @@ use std::cell::Cell; -use proc_macro2::{Ident, Span, TokenStream}; +use proc_macro2::{Ident, TokenStream}; use quote::{quote, ToTokens}; use crate::{ @@ -90,13 +90,14 @@ impl ToTokens for Scoped<'_, FormatArg<'_>> { .iter() .find(|(arg, _)| arg == name) .map(|(_, expr)| expr.to_token_stream()) - .unwrap_or_else(|| Ident::new(name, Span::call_site()).to_token_stream()), + .unwrap_or_else(|| { + Ident::new(name, self.input.format_str.span()).to_token_stream() + }), }; let opt_ty = opt_ty_tokens(self.scope(&self.inner.format_spec.formatter_args)); let opt_values = opt_value_tokens(self.scope(&self.inner.format_spec.formatter_args)); - tokens.extend(quote! { #prefix::#base::<_, #opt_ty>(#expr, #opt_values) }) } } diff --git a/src/args.rs b/src/args.rs index 12050b9..2028821 100644 --- a/src/args.rs +++ b/src/args.rs @@ -27,18 +27,18 @@ macro_rules! tuple_args { } #[rustfmt::skip] - tuple_args!( - 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 - ); +tuple_args!( + 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); diff --git a/src/rust_core_impl/aggregated.rs b/src/rust_core_impl/aggregated.rs index 4621ba5..10024fd 100644 --- a/src/rust_core_impl/aggregated.rs +++ b/src/rust_core_impl/aggregated.rs @@ -1,6 +1,10 @@ //! A bunch of impls copied from all over the place -use crate::{Debug, FmtOpts, Formatter, Result, Write}; +use impl_prelude::*; + +mod impl_prelude { + pub use crate::*; +} impl Debug for &T { fn fmt(&self, f: &mut Formatter) -> Result { @@ -19,3 +23,81 @@ impl Debug for [T] { f.debug_list().entries(self.iter()).finish() } } + +// pointers +mod pointers { + use super::impl_prelude::*; + + impl Pointer for *const T { + fn fmt(&self, f: &mut Formatter) -> Result { + pointer_fmt_inner((*self as *const ()) as usize, f) + } + } + + impl Pointer for *mut T { + fn fmt(&self, f: &mut Formatter) -> Result { + pointer_fmt_inner((*self as *mut ()) as usize, f) + } + } + + + impl Pointer for &T { + fn fmt(&self, f: &mut Formatter) -> Result { + Pointer::fmt(&(*self as *const T), f) + } + } + + impl Pointer for &mut T { + fn fmt(&self, f: &mut Formatter) -> Result { + Pointer::fmt(&(&**self as *const T), f) + } + } + + pub(crate) fn pointer_fmt_inner( + ptr_addr: usize, + f: &mut Formatter, + ) -> Result { + // The alternate flag is already treated by LowerHex as being special- + // it denotes whether to prefix with 0x. We use it to work out whether + // or not to zero extend, and then unconditionally set it to get the + // prefix. + if f.alternate() { + let mut f = f.wrap_with(&crate::opts::WithSignAwareZeroPad(())); + + if f.width().is_none() { + const WIDTH: usize = (usize::BITS / 4) as usize + 2; + + let mut f = f.wrap_with(&crate::opts::WithWidth::<(), WIDTH>(())); + + let mut f = f.wrap_with(&crate::opts::WithAlternate(())); + let ret = LowerHex::fmt(&ptr_addr, &mut f); + + return ret; + } + + let mut f = f.wrap_with(&crate::opts::WithAlternate(())); + let ret = LowerHex::fmt(&ptr_addr, &mut f); + + return ret; + } + + let mut f = f.wrap_with(&crate::opts::WithAlternate(())); + let ret = LowerHex::fmt(&ptr_addr, &mut f); + + ret + } +} + +mod char { + use super::impl_prelude::*; + + impl Display for char { + fn fmt(&self, f: &mut Formatter) -> Result { + if f.width().is_none() && f.precision().is_none() { + f.write_char(*self) + } else { + f.pad(self.encode_utf8(&mut [0; 4])) + } + } + } +} diff --git a/src/rust_core_impl/mod.rs b/src/rust_core_impl/mod.rs index 05ac7b3..11833c7 100644 --- a/src/rust_core_impl/mod.rs +++ b/src/rust_core_impl/mod.rs @@ -314,4 +314,52 @@ impl Formatter { } Ok(()) } + + pub fn pad(&mut self, s: &str) -> Result { + // Make sure there's a fast path up front + if self.width().is_none() && self.precision().is_none() { + return self.buf.write_str(s); + } + // The `precision` field can be interpreted as a `max-width` for the + // string being formatted. + let s = if let Some(max) = self.precision() { + // If our string is longer that the precision, then we must have + // truncation. However other flags like `fill`, `width` and `align` + // must act as always. + if let Some((i, _)) = s.char_indices().nth(max) { + // LLVM here can't prove that `..i` won't panic `&s[..i]`, but + // we know that it can't panic. Use `get` + `unwrap_or` to avoid + // `unsafe` and otherwise don't emit any panic-related code + // here. + s.get(..i).unwrap_or(s) + } else { + &s + } + } else { + &s + }; + // The `width` field is more of a `min-width` parameter at this point. + match self.width() { + // If we're under the maximum length, and there's no minimum length + // requirements, then we can just emit the string + None => self.buf.write_str(s), + Some(width) => { + let chars_count = s.chars().count(); + // If we're under the maximum width, check if we're over the minimum + // width, if so it's as easy as just emitting the string. + if chars_count >= width { + self.buf.write_str(s) + } + // If we're under both the maximum and the minimum width, then fill + // up the minimum width with the specified string + some alignment. + else { + let align = Alignment::Left; + let post_padding = + self.padding(width - chars_count, Alignment::Right, self.fill(), align)?; + self.buf.write_str(s)?; + post_padding.write(self) + } + } + } + } } diff --git a/tests/base.rs b/tests/base.rs index 6385792..8d3daef 100644 --- a/tests/base.rs +++ b/tests/base.rs @@ -1,5 +1,3 @@ -use mono_fmt::{FmtOpts, Write}; - #[macro_use] extern crate mono_fmt;