human_repr/
lib.rs

1#![cfg_attr(
2    not(any(feature = "1024", feature = "iec", feature = "space")), 
3    doc = include_str!("../README.md")
4)]
5
6mod human_count;
7mod human_duration;
8mod human_throughput;
9mod utils;
10
11use std::borrow::Cow;
12
13/// Human Count data, ready to generate Debug and Display representations.
14#[derive(PartialEq, PartialOrd)] // Debug and Display impls in the specific module.
15#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
16pub struct HumanCountData<'a> {
17    val: f64,
18    unit: Cow<'a, str>,
19}
20
21/// Human Duration data, ready to generate Debug and Display representations.
22#[derive(PartialEq, PartialOrd)] // Debug and Display impls in the specific module.
23#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
24pub struct HumanDurationData {
25    val: f64,
26}
27
28/// Human Throughput data, ready to generate Debug and Display representations.
29#[derive(PartialEq, PartialOrd)] // Debug and Display impls in the specific module.
30#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
31pub struct HumanThroughputData<'a> {
32    val: f64,
33    unit: Cow<'a, str>,
34}
35
36const BYTES: &str = "B";
37
38/// Human Count trait, supporting all Rust primitive number types.
39pub trait HumanCount: sealed::Sealed + Sized {
40    /// Generate beautiful human-readable counts supporting automatic prefixes and custom units.
41    #[cfg_attr(
42        not(any(feature = "1024", feature = "iec", feature = "space")),
43        doc = r#"
44
45```
46use human_repr::HumanCount;
47assert_eq!("4.2Mcoins", 4221432u32.human_count("coins"));
48```
49"#
50    )]
51    fn human_count<'a>(self, unit: impl Into<Cow<'a, str>>) -> HumanCountData<'a>;
52
53    /// Generate beautiful human-readable counts supporting automatic prefixes.
54    #[cfg_attr(
55        not(any(feature = "1024", feature = "iec", feature = "space")),
56        doc = r#"
57
58```
59use human_repr::HumanCount;
60assert_eq!("4.2M", 4221432u32.human_count_bare());
61```
62"#
63    )]
64    fn human_count_bare(self) -> HumanCountData<'static> {
65        self.human_count("")
66    }
67
68    /// Generate beautiful human-readable counts supporting automatic prefixes and Bytes `B` as the unit.
69    #[cfg_attr(
70        not(any(feature = "1024", feature = "iec", feature = "space")),
71        doc = r#"
72
73```
74use human_repr::HumanCount;
75assert_eq!("4.2MB", 4221432u32.human_count_bytes());
76```
77"#
78    )]
79    fn human_count_bytes(self) -> HumanCountData<'static> {
80        self.human_count(BYTES)
81    }
82}
83
84/// Human Duration trait, supporting all Rust primitive number types and Duration.
85pub trait HumanDuration: sealed::Sealed + Sized {
86    /// Generate beautiful human-readable durations supporting automatic prefixes.
87    #[cfg_attr(
88        not(any(feature = "1024", feature = "iec", feature = "space")),
89        doc = r#"
90
91Use either with primitives:
92```
93use human_repr::HumanDuration;
94assert_eq!("160ms", 0.1599999.human_duration());
95```
96
97Or with [`Duration`](`std::time::Duration`)s:
98```
99use human_repr::HumanDuration;
100use std::time::Duration;
101
102let d = Duration::from_secs_f64(0.1599999);
103assert_eq!("160ms", d.human_duration());
104```
105"#
106    )]
107    fn human_duration(self) -> HumanDurationData;
108}
109
110/// Human Throughput trait, supporting all Rust primitive number types.
111pub trait HumanThroughput: sealed::Sealed + Sized {
112    /// Generate beautiful human-readable throughputs supporting automatic prefixes and custom units.
113    #[cfg_attr(
114        not(any(feature = "1024", feature = "iec", feature = "space")),
115        doc = r#"
116
117```
118use human_repr::HumanThroughput;
119assert_eq!("1.2k°C/s", 1234.5.human_throughput("°C"));
120```
121"#
122    )]
123    fn human_throughput<'a>(self, unit: impl Into<Cow<'a, str>>) -> HumanThroughputData<'a>;
124
125    /// Generate beautiful human-readable throughputs supporting automatic prefixes.
126    #[cfg_attr(
127        not(any(feature = "1024", feature = "iec", feature = "space")),
128        doc = r#"
129
130```
131use human_repr::HumanThroughput;
132assert_eq!("1.2k/s", 1234.5.human_throughput_bare());
133```
134"#
135    )]
136    fn human_throughput_bare(self) -> HumanThroughputData<'static> {
137        self.human_throughput("")
138    }
139
140    /// Generate beautiful human-readable throughputs supporting automatic prefixes and Bytes `B` as the unit.
141    #[cfg_attr(
142        not(any(feature = "1024", feature = "iec", feature = "space")),
143        doc = r#"
144
145```
146use human_repr::HumanThroughput;
147assert_eq!("1.2kB/s", 1234.5.human_throughput_bytes());
148```
149"#
150    )]
151    fn human_throughput_bytes(self) -> HumanThroughputData<'static> {
152        self.human_throughput(BYTES)
153    }
154}
155
156macro_rules! impl_trait {
157    {$($t:ty),+} => {$(
158        impl HumanCount for $t {
159            fn human_count<'a>(self, unit: impl Into<Cow<'a, str>>) -> HumanCountData<'a> {
160                HumanCountData{val: self as f64, unit: unit.into()}
161            }
162        }
163        impl HumanDuration for $t {
164            fn human_duration(self) -> HumanDurationData {
165                HumanDurationData{val: self as f64}
166            }
167        }
168        impl HumanThroughput for $t {
169            fn human_throughput<'a>(self, unit: impl Into<Cow<'a, str>>) -> HumanThroughputData<'a> {
170                HumanThroughputData{val: self as f64, unit: unit.into()}
171            }
172        }
173    )+}
174}
175impl_trait!(u8, u16, u32, u64, u128, usize, f32, f64, i8, i16, i32, i64, i128, isize);
176
177mod sealed {
178    use std::time::Duration;
179
180    pub trait Sealed {}
181    macro_rules! impl_sealed {
182        {$($t:ty),+} => {
183            $(impl Sealed for $t {})+
184        }
185    }
186    impl_sealed!(
187        u8, u16, u32, u64, u128, usize, f32, f64, i8, i16, i32, i64, i128, isize, Duration
188    );
189}