core tests build

This commit is contained in:
nora 2022-09-24 21:25:52 +02:00
parent bfd86b1338
commit 010126ce0b
5 changed files with 147 additions and 18 deletions

View file

@ -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) })
}
}

View file

@ -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<T: Debug + ?Sized> Debug for &T {
fn fmt<W: Write, O: FmtOpts>(&self, f: &mut Formatter<W, O>) -> Result {
@ -19,3 +23,81 @@ impl<T: Debug> Debug for [T] {
f.debug_list().entries(self.iter()).finish()
}
}
// pointers
mod pointers {
use super::impl_prelude::*;
impl<T: ?Sized> Pointer for *const T {
fn fmt<W: Write, O: FmtOpts>(&self, f: &mut Formatter<W, O>) -> Result {
pointer_fmt_inner((*self as *const ()) as usize, f)
}
}
impl<T: ?Sized> Pointer for *mut T {
fn fmt<W: Write, O: FmtOpts>(&self, f: &mut Formatter<W, O>) -> Result {
pointer_fmt_inner((*self as *mut ()) as usize, f)
}
}
impl<T: ?Sized> Pointer for &T {
fn fmt<W: Write, O: FmtOpts>(&self, f: &mut Formatter<W, O>) -> Result {
Pointer::fmt(&(*self as *const T), f)
}
}
impl<T: ?Sized> Pointer for &mut T {
fn fmt<W: Write, O: FmtOpts>(&self, f: &mut Formatter<W, O>) -> Result {
Pointer::fmt(&(&**self as *const T), f)
}
}
pub(crate) fn pointer_fmt_inner<W: Write, O: FmtOpts>(
ptr_addr: usize,
f: &mut Formatter<W, O>,
) -> 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<W: Write, O: FmtOpts>(&self, f: &mut Formatter<W, O>) -> Result {
if f.width().is_none() && f.precision().is_none() {
f.write_char(*self)
} else {
f.pad(self.encode_utf8(&mut [0; 4]))
}
}
}
}

View file

@ -314,4 +314,52 @@ impl<W: Write, O: FmtOpts> Formatter<W, O> {
}
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)
}
}
}
}
}

View file

@ -1,5 +1,3 @@
use mono_fmt::{FmtOpts, Write};
#[macro_use]
extern crate mono_fmt;