percentage_rs/
lib.rs

1//! # percentage-rs
2//! `percentage-rs` Get the percentage of any number
3
4#[cfg(test)] mod tests;
5
6use std::{fmt, ops::{Add, AddAssign, Mul, MulAssign}};
7
8use num_traits::NumCast;
9
10/// Transform any number into [`Percentage`]
11pub trait Percent {
12	/// Transform any number into [`Percentage`]
13	/// # Examples
14	/// 
15	/// ```
16	/// use percentage_rs::Percent;
17	///
18	/// let percent = 50.percent();
19	/// println!("{}", percent);
20	/// ```
21	fn percent(self) -> Percentage;
22}
23
24macro_rules! percent_impl {
25	($($ty:ty)*) => {
26		$(
27			impl Percent for $ty {
28				fn percent(self) -> Percentage {
29					Percentage::new(self)
30				}
31			}
32		)*
33	};
34}
35
36percent_impl!{
37	usize u8 u16 u32 u64 u128
38	isize i8 i16 i32 i64 i128
39	f32 f64
40}
41
42/// Allows to calculate the percentage of any number
43/// # Examples
44/// 
45/// ### Create a [`Percentage`] with the default constructor
46/// ```
47/// use percentage_rs::Percentage;
48/// 
49/// let p = Percentage::new(50);
50/// assert!("50%" == format!("{}", p)); // the result is "50%"
51/// ```
52/// 
53/// ### Create a [`Percentage`] with the trait [`Percent`]
54/// ```
55/// use percentage_rs::Percent;
56/// 
57/// assert!(format!("{}", 50.percent()) == "50%"); // the result is "50%"
58/// ```
59/// 
60/// ### Calculate the percentage
61/// To do that you just need to multiply the percentage by your number
62/// ```
63/// use percentage_rs::Percent;
64/// 
65/// let p = 1234*50.percent(); // 50% of 1234
66/// assert!(p == 617.0 as f32); // the result is "617"
67/// ```
68#[derive(Default, Clone, Copy, PartialEq, Debug)]
69#[cfg_attr(feature = "serde_support", derive(serde::Serialize, serde::Deserialize))]
70pub struct Percentage(f32);
71
72impl Percentage {
73	/// Create a percentage with the given value into percen
74	pub fn new<T: NumCast>(value: T) -> Percentage {
75		Self(value.to_f32().unwrap() / 100.0)
76	}
77}
78
79impl fmt::Display for Percentage {
80	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81		write!(f, "{}%", self.0*100.0)
82	}
83}
84
85impl Add for Percentage {
86	type Output = Self;
87	fn add(self, rhs: Self) -> Self::Output {
88		Self(self.0 + rhs.0)
89	}
90}
91
92impl AddAssign for Percentage {
93	fn add_assign(&mut self, rhs: Percentage) {
94		*self = *self + rhs;
95	}
96}
97
98impl<T: NumCast> AddAssign<T> for Percentage {
99	fn add_assign(&mut self, rhs: T) {
100		*self = Self(self.0 + rhs.to_f32().unwrap());
101	}
102}
103
104impl Mul for Percentage {
105	type Output = Self;
106	fn mul(self, rhs: Self) -> Self::Output {
107		Self(rhs.0*self.0)
108	}
109}
110
111impl MulAssign for Percentage {
112	fn mul_assign(&mut self, rhs: Self) {
113		*self = *self * rhs;
114	}
115}
116
117macro_rules! ops_percentage_impl {
118	($($type: ty)*) => {
119		$(
120			impl Add<Percentage> for $type {
121				type Output = Percentage;
122				fn add(self, rhs: Percentage) -> Self::Output {
123					Percentage(rhs.0 + self as f32)
124				}
125			}
126
127			impl Mul<Percentage> for $type {
128				type Output = f32;
129				fn mul(self, rhs: Percentage) -> Self::Output {
130					self as f32 * rhs.0
131				}
132			}
133
134			impl MulAssign<Percentage> for $type {
135				fn mul_assign(&mut self, rhs: Percentage) {
136					*self = (*self * rhs) as $type;
137				}
138			}
139		)*
140	};
141}
142
143ops_percentage_impl!{
144	usize u8 u16 u32 u64 u128
145	isize i8 i16 i32 i64 i128
146	f32 f64
147}