From 6fc05446fbd75fdbfac1faf77711ed75a5fbfa9f Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 25 Sep 2022 13:27:49 +0200 Subject: [PATCH] cfg --- Cargo.toml | 7 +- src/formatter.rs | 8 +-- src/lib.rs | 10 ++- src/rust_core_impl/aggregated.rs | 21 +++--- src/rust_core_impl/mod.rs | 4 +- src/rust_core_impl/num.rs | 4 +- src/write.rs | 119 +++++++++++++++++++++++++++---- 7 files changed, 143 insertions(+), 30 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f2c12fe..1d4dc41 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,4 +12,9 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -mono-fmt-macro = { path = "./mono-fmt-macro" } \ No newline at end of file +mono-fmt-macro = { path = "./mono-fmt-macro" } + +[features] +alloc = [] +std = ["alloc"] +default = ["std"] \ No newline at end of file diff --git a/src/formatter.rs b/src/formatter.rs index 5713211..b1717d2 100644 --- a/src/formatter.rs +++ b/src/formatter.rs @@ -6,11 +6,11 @@ pub struct Formatter { } impl core::fmt::Write for Formatter { - fn write_char(&mut self, c: char) -> std::fmt::Result { - self.buf.write_char(c).map_err(|_| std::fmt::Error) + fn write_char(&mut self, c: char) -> core::fmt::Result { + self.buf.write_char(c).map_err(|_| core::fmt::Error) } - fn write_str(&mut self, s: &str) -> std::fmt::Result { - self.buf.write_str(s).map_err(|_| std::fmt::Error) + fn write_str(&mut self, s: &str) -> core::fmt::Result { + self.buf.write_str(s).map_err(|_| core::fmt::Error) } } diff --git a/src/lib.rs b/src/lib.rs index b97fd32..17273fe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,8 @@ +#![cfg_attr(not(feature = "std"), no_std)] #![allow(dead_code)] +extern crate alloc; + mod args; mod formatter; mod opts; @@ -19,7 +22,7 @@ pub use crate::{ opts::FmtOpts, }; -pub type Result = std::result::Result<(), Error>; +pub type Result = core::result::Result<(), Error>; #[derive(Debug, Clone, Copy)] pub struct Error; @@ -34,6 +37,9 @@ pub trait Write { } pub mod helpers { + #[cfg(feature = "alloc")] + use alloc::string::String; + use crate::{Arguments, Formatter, Result, Write}; pub fn write(buffer: W, args: A) -> Result { @@ -41,6 +47,7 @@ pub mod helpers { args.fmt(&mut fmt) } + #[cfg(feature = "alloc")] pub fn format(args: A) -> String { let mut string = String::new(); write(&mut string, args).unwrap(); @@ -59,6 +66,7 @@ pub mod _private { }; } +#[cfg(feature = "alloc")] #[macro_export] macro_rules! format { ($($tt:tt)*) => { diff --git a/src/rust_core_impl/aggregated.rs b/src/rust_core_impl/aggregated.rs index 0c93f8c..016d114 100644 --- a/src/rust_core_impl/aggregated.rs +++ b/src/rust_core_impl/aggregated.rs @@ -92,8 +92,21 @@ mod char { } mod strings { + #[cfg(feature = "alloc")] + use alloc::string::String; + use super::impl_prelude::*; + #[cfg(feature = "alloc")] + impl Debug for String { + fn fmt(&self, f: &mut Formatter) -> Result { + f.write_char('"')?; + f.write_str(self)?; + f.write_char('"') + } + } + + #[cfg(feature = "alloc")] impl Display for String { fn fmt(&self, f: &mut Formatter) -> Result { f.write_str(self) @@ -113,12 +126,4 @@ mod strings { f.write_char('"') } } - - impl Debug for String { - fn fmt(&self, f: &mut Formatter) -> Result { - f.write_char('"')?; - f.write_str(self)?; - f.write_char('"') - } - } } diff --git a/src/rust_core_impl/mod.rs b/src/rust_core_impl/mod.rs index bbea42f..051e868 100644 --- a/src/rust_core_impl/mod.rs +++ b/src/rust_core_impl/mod.rs @@ -249,7 +249,7 @@ impl Formatter { default: Alignment, self_fill: char, self_align: Alignment, - ) -> std::result::Result { + ) -> core::result::Result { // WARN: We might have `self` in an invalid state, don't touch `self` opts let align = match self_align { Alignment::Unknown => default, @@ -279,7 +279,7 @@ impl Formatter { // in a bad value for `buf` into `numfmt::to_shortest_str` since it is a // public function. // FIXME: Determine whether this could result in UB. - buf.write_str(unsafe { std::str::from_utf8_unchecked(s) }) + buf.write_str(unsafe { core::str::from_utf8_unchecked(s) }) } if !formatted.sign.is_empty() { diff --git a/src/rust_core_impl/num.rs b/src/rust_core_impl/num.rs index 4f5e60f..e9e5ae4 100644 --- a/src/rust_core_impl/num.rs +++ b/src/rust_core_impl/num.rs @@ -1,6 +1,6 @@ //! Integer and floating-point number formatting -use std::{ +use core::{ mem::MaybeUninit, ops::{Div, Rem, Sub}, ptr, slice, str, @@ -223,7 +223,7 @@ macro_rules! impl_Display { // is safe to access. unsafe { // need at least 16 bits for the 4-characters-at-a-time to work. - assert!(std::mem::size_of::<$u>() >= 2); + assert!(core::mem::size_of::<$u>() >= 2); // eagerly decode 4 characters at a time while n >= 10000 { diff --git a/src/write.rs b/src/write.rs index 55b0345..b5a0631 100644 --- a/src/write.rs +++ b/src/write.rs @@ -1,17 +1,5 @@ use crate::{Result, Write}; -impl Write for String { - fn write_str(&mut self, str: &str) -> Result { - self.push_str(str); - Ok(()) - } - - fn write_char(&mut self, char: char) -> Result { - self.push(char); - Ok(()) - } -} - impl Write for &mut W { fn write_str(&mut self, str: &str) -> Result { ::write_str(self, str) @@ -21,3 +9,110 @@ impl Write for &mut W { ::write_char(self, char) } } + +impl Write for &'_ mut [u8] { + fn write_str(&mut self, str: &str) -> Result { + let data = str.as_bytes(); + let amt = core::cmp::min(str.len(), self.len()); + let (a, b) = core::mem::replace(self, &mut []).split_at_mut(amt); + a.copy_from_slice(&data[..amt]); + *self = b; + Ok(()) + } +} + +#[cfg(feature = "alloc")] +mod alloc_impls { + use alloc::{boxed::Box, collections::VecDeque, string::String, vec::Vec}; + + use crate::{Result, Write}; + + impl Write for String { + fn write_str(&mut self, str: &str) -> Result { + self.push_str(str); + Ok(()) + } + + fn write_char(&mut self, char: char) -> Result { + self.push(char); + Ok(()) + } + } + + impl Write for Box { + fn write_str(&mut self, str: &str) -> Result { + ::write_str(self, str) + } + + fn write_char(&mut self, char: char) -> Result { + ::write_char(self, char) + } + } + + impl Write for Vec { + fn write_str(&mut self, str: &str) -> Result { + self.extend(str.as_bytes()); + Ok(()) + } + } + + impl Write for VecDeque { + fn write_str(&mut self, str: &str) -> Result { + self.extend(str.as_bytes()); + Ok(()) + } + } +} + +#[cfg(feature = "std")] +mod std_impls { + use std::{ + fs, + io::{self, Write as IoWrite}, + net, process, + }; + + use crate::Result; + + trait IoWriteForwad: IoWrite { + fn write_str(&mut self, str: &str) -> Result { + ::write_all(self, str.as_bytes()).map_err(|_| crate::Error) + } + + fn write_char(&mut self, char: char) -> Result { + let mut buf = [0; 4]; + + ::write_all(self, char.encode_utf8(&mut buf).as_bytes()) + .map_err(|_| crate::Error) + } + } + + macro_rules! impl_io_forward { + ($($name:ty),* $(,)?) => { + $( + impl IoWriteForwad for $name {} + )* + }; + } + + impl_io_forward!( + fs::File, + net::TcpStream, + process::ChildStdin, + io::Cursor<&'_ mut [u8]>, + io::Sink, + io::Stderr, + io::StderrLock<'_>, + io::Stdout, + io::StdoutLock<'_>, + io::Cursor<&'_ mut Vec>, + io::Cursor>, + io::Cursor>, + &fs::File, + &net::TcpStream, + &process::ChildStdin, + &io::Sink, + &io::Stderr, + &io::Stdout, + ); +}