Skip to content

Commit ed76930

Browse files
authored
Merge pull request #427 from mulkieran/master-macros-final
Consolidate range macros (final)
2 parents 13716b3 + f4f2fdd commit ed76930

3 files changed

Lines changed: 353 additions & 270 deletions

File tree

src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ extern crate tempfile;
9090
#[cfg(test)]
9191
extern crate uuid;
9292

93+
/// Range macros
94+
#[macro_use]
95+
mod range_macros;
9396
/// shared constants
9497
mod consts;
9598
/// rust definitions of ioctl structs and consts

src/range_macros.rs

Lines changed: 346 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,346 @@
1+
// This Source Code Form is subject to the terms of the Mozilla Public
2+
// License, v. 2.0. If a copy of the MPL was not distributed with this
3+
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4+
5+
// An omnibus macro that includes all simple macros.
6+
macro_rules! range {
7+
($T: ident) => {
8+
macro_attr! {
9+
#[derive(Clone, Copy, Default, Eq, Ord, PartialEq, PartialOrd)]
10+
/// A type for $T
11+
pub struct $T(pub u64);
12+
}
13+
14+
checked_add!($T);
15+
16+
NewtypeAdd! { () pub struct $T(u64); }
17+
NewtypeAddAssign! { () pub struct $T(u64); }
18+
NewtypeDeref! { () pub struct $T(u64); }
19+
NewtypeFrom! { () pub struct $T(u64); }
20+
NewtypeSub! { () pub struct $T(u64); }
21+
NewtypeSubAssign! { () pub struct $T(u64); }
22+
23+
debug_macro!($T);
24+
serde!($T);
25+
sum!($T);
26+
27+
mul!($T);
28+
div!($T);
29+
rem!($T);
30+
};
31+
}
32+
33+
macro_rules! self_div {
34+
($T:ident) => {
35+
impl Div<$T> for $T {
36+
type Output = u64;
37+
fn div(self, rhs: $T) -> u64 {
38+
self.0 / *rhs
39+
}
40+
}
41+
};
42+
}
43+
44+
macro_rules! debug_macro {
45+
($T:ident) => {
46+
impl fmt::Debug for $T {
47+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
48+
write!(f, stringify!($T))?;
49+
write!(f, "({})", **self)
50+
}
51+
}
52+
};
53+
}
54+
55+
macro_rules! serde {
56+
($T:ident) => {
57+
impl serde::Serialize for $T {
58+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
59+
where
60+
S: serde::Serializer,
61+
{
62+
serializer.serialize_u64(**self)
63+
}
64+
}
65+
66+
impl<'de> serde::Deserialize<'de> for $T {
67+
fn deserialize<D>(deserializer: D) -> Result<$T, D::Error>
68+
where
69+
D: serde::de::Deserializer<'de>,
70+
{
71+
Ok($T(serde::Deserialize::deserialize(deserializer)?))
72+
}
73+
}
74+
};
75+
}
76+
77+
macro_rules! sum {
78+
($T:ident) => {
79+
impl Sum for $T {
80+
fn sum<I: Iterator<Item = $T>>(iter: I) -> $T {
81+
iter.fold($T::default(), Add::add)
82+
}
83+
}
84+
};
85+
}
86+
87+
// Define a complete set of division operations.
88+
macro_rules! div {
89+
($T: ident) => {
90+
unsigned_div!(u64, $T);
91+
unsigned_div!(u32, $T);
92+
unsigned_div!(u16, $T);
93+
unsigned_div!(u8, $T);
94+
usize_div!($T);
95+
self_div!($T);
96+
};
97+
}
98+
99+
macro_rules! unsigned_div {
100+
($t:ty, $T:ident) => {
101+
impl Div<$t> for $T {
102+
type Output = $T;
103+
fn div(self, rhs: $t) -> $T {
104+
$T(self.0 / u64::from(rhs))
105+
}
106+
}
107+
};
108+
}
109+
110+
macro_rules! usize_div {
111+
($T:ident) => {
112+
impl Div<usize> for $T {
113+
type Output = $T;
114+
fn div(self, rhs: usize) -> $T {
115+
#[allow(clippy::cast_lossless)]
116+
$T(self.0 / rhs as u64)
117+
}
118+
}
119+
};
120+
}
121+
122+
// Define a complete set of multiplication operations.
123+
macro_rules! mul {
124+
($T: ident) => {
125+
unsigned_mul!(u64, $T);
126+
unsigned_mul!(u32, $T);
127+
unsigned_mul!(u16, $T);
128+
unsigned_mul!(u8, $T);
129+
usize_mul!($T);
130+
};
131+
}
132+
133+
macro_rules! unsigned_mul {
134+
($t:ty, $T:ident) => {
135+
impl Mul<$t> for $T {
136+
type Output = $T;
137+
fn mul(self, rhs: $t) -> $T {
138+
$T(self.0 * u64::from(rhs))
139+
}
140+
}
141+
142+
impl Mul<$T> for $t {
143+
type Output = $T;
144+
fn mul(self, rhs: $T) -> $T {
145+
$T(u64::from(self) * rhs.0)
146+
}
147+
}
148+
};
149+
}
150+
151+
macro_rules! usize_mul {
152+
($T:ident) => {
153+
impl Mul<usize> for $T {
154+
type Output = $T;
155+
fn mul(self, rhs: usize) -> $T {
156+
#[allow(clippy::cast_lossless)]
157+
$T(self.0 * rhs as u64)
158+
}
159+
}
160+
161+
impl Mul<$T> for usize {
162+
type Output = $T;
163+
fn mul(self, rhs: $T) -> $T {
164+
#[allow(clippy::cast_lossless)]
165+
$T(self as u64 * rhs.0)
166+
}
167+
}
168+
};
169+
}
170+
171+
// Define a complete set of remainder operations.
172+
macro_rules! rem {
173+
($T: ident) => {
174+
unsigned_rem!(u64, $T);
175+
unsigned_rem!(u32, $T);
176+
unsigned_rem!(u16, $T);
177+
unsigned_rem!(u8, $T);
178+
usize_rem!($T);
179+
self_rem!($T);
180+
};
181+
}
182+
183+
macro_rules! unsigned_rem {
184+
($t:ty, $T:ident) => {
185+
impl Rem<$t> for $T {
186+
type Output = $T;
187+
fn rem(self, rhs: $t) -> $T {
188+
$T(self.0 % u64::from(rhs))
189+
}
190+
}
191+
};
192+
}
193+
194+
macro_rules! usize_rem {
195+
($T:ident) => {
196+
impl Rem<usize> for $T {
197+
type Output = $T;
198+
fn rem(self, rhs: usize) -> $T {
199+
#[allow(clippy::cast_lossless)]
200+
$T(self.0 % rhs as u64)
201+
}
202+
}
203+
};
204+
}
205+
206+
macro_rules! self_rem {
207+
($T:ident) => {
208+
impl Rem<$T> for $T {
209+
type Output = $T;
210+
fn rem(self, rhs: $T) -> $T {
211+
$T(self.0 % u64::from(rhs.0))
212+
}
213+
}
214+
};
215+
}
216+
217+
macro_rules! checked_add {
218+
($T: ident) => {
219+
impl $T {
220+
/// Add two items of type $T, return None if overflow.
221+
pub fn checked_add(&self, other: $T) -> Option<$T> {
222+
self.0.checked_add(other.0).map($T)
223+
}
224+
}
225+
};
226+
}
227+
228+
mod tests {
229+
230+
use std::fmt;
231+
use std::iter::Sum;
232+
use std::ops::{Add, Div, Mul, Rem};
233+
use std::u64;
234+
235+
range!(Units);
236+
237+
#[test]
238+
/// Test implicit derivations for Units
239+
fn test_implicit_derivations() {
240+
// Test Clone. Note cloning within an assertion disables the clippy
241+
// allow, so no assertion here.
242+
#[allow(clippy::clone_on_copy)]
243+
let _ = Units(1).clone();
244+
245+
// Test Default
246+
assert_eq!(Units::default(), Units(0));
247+
248+
// Test Ord, PartialOrd
249+
assert!(Units::default() < Units(1));
250+
assert!(!(Units(1) < Units::default()));
251+
252+
// Test Copy
253+
let z = Units(3);
254+
let mut d = z;
255+
d += Units(1);
256+
assert_eq!(z, Units(3));
257+
assert_eq!(d, Units(4));
258+
}
259+
260+
#[test]
261+
/// Test non-arithmetic derivations that are derived explicitly
262+
fn test_explicit_derivations() {
263+
// Test From
264+
assert_eq!(Units::from(3) + Units(3), Units(6));
265+
266+
// Test Deref
267+
assert_eq!(*Units(3) + 3, 6);
268+
269+
// Test Debug
270+
assert_eq!(format!("{:?}", Units(3)), "Units(3)");
271+
}
272+
273+
#[test]
274+
/// Test operations that work on an iterator of values, like sum and
275+
/// product.
276+
fn test_summary_operations() {
277+
// Test Sum
278+
assert_eq!(
279+
vec![Units(2), Units(3)].iter().cloned().sum::<Units>(),
280+
Units(5)
281+
);
282+
}
283+
284+
#[test]
285+
/// Test addition.
286+
fn test_addition() {
287+
assert_eq!(Units(1) + Units(3), Units(4));
288+
289+
let mut z = Units(1);
290+
z += Units(3);
291+
assert_eq!(z, Units(4));
292+
293+
assert_eq!(Units(u64::MAX).checked_add(Units(1)), None);
294+
}
295+
296+
#[test]
297+
/// Test subtraction
298+
fn test_subtraction() {
299+
assert_eq!(Units(3) - Units(1), Units(2));
300+
301+
let mut z = Units(3);
302+
z -= Units(1);
303+
assert_eq!(z, Units(2));
304+
}
305+
306+
#[test]
307+
/// Test multiplication
308+
fn test_multiplication() {
309+
assert_eq!(Units(3) * 2u8, Units(6));
310+
assert_eq!(2u8 * Units(3), Units(6));
311+
312+
assert_eq!(Units(3) * 2u16, Units(6));
313+
assert_eq!(2u16 * Units(3), Units(6));
314+
315+
assert_eq!(Units(3) * 2u32, Units(6));
316+
assert_eq!(2u32 * Units(3), Units(6));
317+
318+
assert_eq!(Units(3) * 2u64, Units(6));
319+
assert_eq!(2u64 * Units(3), Units(6));
320+
321+
assert_eq!(Units(3) * 2usize, Units(6));
322+
assert_eq!(2usize * Units(3), Units(6));
323+
}
324+
325+
#[test]
326+
/// Test division and remainder together
327+
fn test_division_and_remainder() {
328+
assert_eq!(Units(3) / Units(2), 1);
329+
assert_eq!(Units(3) % Units(2), Units(1));
330+
331+
assert_eq!(Units(5) / 2u8, Units(2));
332+
assert_eq!(Units(3) % 2u8, Units(1));
333+
334+
assert_eq!(Units(5) / 2u16, Units(2));
335+
assert_eq!(Units(3) % 2u16, Units(1));
336+
337+
assert_eq!(Units(5) / 2u32, Units(2));
338+
assert_eq!(Units(3) % 2u32, Units(1));
339+
340+
assert_eq!(Units(5) / 2u64, Units(2));
341+
assert_eq!(Units(3) % 2u64, Units(1));
342+
343+
assert_eq!(Units(5) / 2usize, Units(2));
344+
assert_eq!(Units(3) % 2usize, Units(1));
345+
}
346+
}

0 commit comments

Comments
 (0)