mqtt5_protocol/
numeric.rs1pub const F64_MAX_SAFE_INTEGER: u64 = 9_007_199_254_740_991;
2
3#[must_use]
4pub fn u128_to_u64_saturating(value: u128) -> u64 {
5 if value <= u128::from(u64::MAX) {
6 #[allow(clippy::cast_possible_truncation)]
7 let result = value as u64;
8 result
9 } else {
10 u64::MAX
11 }
12}
13
14#[must_use]
15pub fn u128_to_f64_saturating(value: u128) -> f64 {
16 if value <= u128::from(F64_MAX_SAFE_INTEGER) {
17 #[allow(clippy::cast_precision_loss)]
18 let result = value as f64;
19 result
20 } else {
21 f64::MAX
22 }
23}
24
25#[must_use]
26pub fn usize_to_f64_saturating(value: usize) -> f64 {
27 u64_to_f64_saturating(value as u64)
28}
29
30#[must_use]
31pub fn u64_to_f64_saturating(value: u64) -> f64 {
32 if value <= F64_MAX_SAFE_INTEGER {
33 #[allow(clippy::cast_precision_loss)]
34 let result = value as f64;
35 result
36 } else {
37 f64::MAX
38 }
39}
40
41#[must_use]
42pub fn u128_to_u32_saturating(value: u128) -> u32 {
43 if value <= u128::from(u32::MAX) {
44 #[allow(clippy::cast_possible_truncation)]
45 let result = value as u32;
46 result
47 } else {
48 u32::MAX
49 }
50}
51
52#[must_use]
53pub fn usize_to_u32_saturating(value: usize) -> u32 {
54 u32::try_from(value).unwrap_or(u32::MAX)
55}
56
57#[must_use]
58pub fn u64_to_u32_saturating(value: u64) -> u32 {
59 u32::try_from(value).unwrap_or(u32::MAX)
60}
61
62#[must_use]
63pub fn u64_to_u16_saturating(value: u64) -> u16 {
64 u16::try_from(value).unwrap_or(u16::MAX)
65}
66
67#[must_use]
68pub fn usize_to_u16_saturating(value: usize) -> u16 {
69 u16::try_from(value).unwrap_or(u16::MAX)
70}
71
72#[must_use]
73pub fn i32_to_u32_saturating(value: i32) -> u32 {
74 if value < 0 {
75 0
76 } else {
77 #[allow(clippy::cast_sign_loss)]
78 let result = value as u32;
79 result
80 }
81}
82
83#[must_use]
84#[allow(clippy::cast_precision_loss)]
85pub fn f64_to_u64_saturating(value: f64) -> u64 {
86 const U64_MAX_AS_F64: f64 = u64::MAX as f64;
87 if value < 0.0 {
88 0
89 } else if value >= U64_MAX_AS_F64 {
90 u64::MAX
91 } else {
92 #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
93 let result = value as u64;
94 result
95 }
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101
102 #[test]
103 fn test_u128_to_u64_saturating() {
104 assert_eq!(u128_to_u64_saturating(0), 0);
105 assert_eq!(u128_to_u64_saturating(1000), 1000);
106 assert_eq!(u128_to_u64_saturating(u128::from(u64::MAX)), u64::MAX);
107 assert_eq!(u128_to_u64_saturating(u128::MAX), u64::MAX);
108 }
109
110 #[test]
111 fn test_u128_to_f64_saturating() {
112 assert!((u128_to_f64_saturating(0) - 0.0).abs() < f64::EPSILON);
113 assert!((u128_to_f64_saturating(1000) - 1000.0).abs() < f64::EPSILON);
114 assert!((u128_to_f64_saturating(u128::MAX) - f64::MAX).abs() < f64::EPSILON);
115 }
116
117 #[test]
118 fn test_usize_to_f64_saturating() {
119 assert!((usize_to_f64_saturating(0) - 0.0).abs() < f64::EPSILON);
120 assert!((usize_to_f64_saturating(1000) - 1000.0).abs() < f64::EPSILON);
121 }
122
123 #[test]
124 fn test_usize_to_u32_saturating() {
125 assert_eq!(usize_to_u32_saturating(0), 0);
126 assert_eq!(usize_to_u32_saturating(1000), 1000);
127 assert_eq!(usize_to_u32_saturating(u32::MAX as usize), u32::MAX);
128 }
129
130 #[test]
131 fn test_u64_to_u16_saturating() {
132 assert_eq!(u64_to_u16_saturating(0), 0);
133 assert_eq!(u64_to_u16_saturating(1000), 1000);
134 assert_eq!(u64_to_u16_saturating(u64::from(u16::MAX)), u16::MAX);
135 assert_eq!(u64_to_u16_saturating(u64::MAX), u16::MAX);
136 }
137
138 #[test]
139 fn test_i32_to_u32_saturating() {
140 assert_eq!(i32_to_u32_saturating(-100), 0);
141 assert_eq!(i32_to_u32_saturating(0), 0);
142 assert_eq!(i32_to_u32_saturating(1000), 1000);
143 #[allow(clippy::cast_sign_loss)]
144 let expected = i32::MAX as u32;
145 assert_eq!(i32_to_u32_saturating(i32::MAX), expected);
146 }
147}