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

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

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;