Skip to content

Commit ae95eb2

Browse files
committed
Extract numeric traits
1 parent e64251b commit ae95eb2

File tree

3 files changed

+56
-29
lines changed

3 files changed

+56
-29
lines changed

src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ pub mod util {
8080
pub mod iter;
8181
pub mod math;
8282
pub mod md5;
83+
pub mod numeric;
8384
pub mod parse;
8485
pub mod point;
8586
pub mod slice;

src/util/numeric.rs

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
use std::ops::{Add, Mul, Neg};
2+
3+
pub trait Unsigned<T>: From<u8> + Add<Output = T> + Mul<Output = T> {
4+
const ZERO: T;
5+
const ONE: T;
6+
const TEN: T;
7+
}
8+
9+
macro_rules! unsigned {
10+
($($t:ty)*) => ($(
11+
impl Unsigned<$t> for $t {
12+
const ZERO: $t = 0;
13+
const ONE: $t = 1;
14+
const TEN: $t = 10;
15+
}
16+
)*)
17+
}
18+
19+
unsigned!(u8 u16 u32 u64 usize);
20+
21+
pub trait Signed<T>: From<u8> + Add<Output = T> + Mul<Output = T> + Neg<Output = T> {
22+
const MINUS_ONE: T;
23+
const ZERO: T;
24+
const ONE: T;
25+
const TEN: T;
26+
}
27+
28+
macro_rules! signed {
29+
($($t:ty)*) => ($(
30+
impl Signed<$t> for $t {
31+
const MINUS_ONE: $t = -1;
32+
const ZERO: $t = 0;
33+
const ONE: $t = 1;
34+
const TEN: $t = 10;
35+
}
36+
)*)
37+
}
38+
39+
signed!(i16 i32 i64);

src/util/parse.rs

+16-29
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
//!
1414
//! [`iter_unsigned`]: ParseOps::iter_unsigned
1515
//! [`iter_signed`]: ParseOps::iter_signed
16+
use crate::util::numeric::*;
1617
use std::marker::PhantomData;
17-
use std::ops::{Add, Mul, Neg};
1818
use std::str::Bytes;
1919

2020
pub trait ParseByte {
@@ -28,19 +28,6 @@ impl ParseByte for u8 {
2828
}
2929
}
3030

31-
// Traits allow us to keep type safety, restricting the possiblities to only integer types.
32-
pub trait Unsigned: From<u8> + Add<Output = Self> + Mul<Output = Self> {}
33-
impl Unsigned for u8 {}
34-
impl Unsigned for u16 {}
35-
impl Unsigned for u32 {}
36-
impl Unsigned for u64 {}
37-
impl Unsigned for usize {}
38-
39-
pub trait Signed: From<u8> + Add<Output = Self> + Mul<Output = Self> + Neg<Output = Self> {}
40-
impl Signed for i16 {}
41-
impl Signed for i32 {}
42-
impl Signed for i64 {}
43-
4431
pub struct ParseUnsigned<'a, T> {
4532
bytes: Bytes<'a>,
4633
phantom: PhantomData<T>,
@@ -52,37 +39,37 @@ pub struct ParseSigned<'a, T> {
5239
}
5340

5441
pub trait ParseOps {
55-
fn unsigned<T: Unsigned>(&self) -> T;
56-
fn signed<T: Signed>(&self) -> T;
57-
fn iter_unsigned<T: Unsigned>(&self) -> ParseUnsigned<'_, T>;
58-
fn iter_signed<T: Signed>(&self) -> ParseSigned<'_, T>;
42+
fn unsigned<T: Unsigned<T>>(&self) -> T;
43+
fn signed<T: Signed<T>>(&self) -> T;
44+
fn iter_unsigned<T: Unsigned<T>>(&self) -> ParseUnsigned<'_, T>;
45+
fn iter_signed<T: Signed<T>>(&self) -> ParseSigned<'_, T>;
5946
}
6047

6148
impl ParseOps for &str {
62-
fn unsigned<T: Unsigned>(&self) -> T {
49+
fn unsigned<T: Unsigned<T>>(&self) -> T {
6350
match try_unsigned(&mut self.bytes()) {
6451
Some(t) => t,
6552
None => panic!("Unable to parse \"{self}\""),
6653
}
6754
}
6855

69-
fn signed<T: Signed>(&self) -> T {
56+
fn signed<T: Signed<T>>(&self) -> T {
7057
match try_signed(&mut self.bytes()) {
7158
Some(t) => t,
7259
None => panic!("Unable to parse \"{self}\""),
7360
}
7461
}
7562

76-
fn iter_unsigned<T: Unsigned>(&self) -> ParseUnsigned<'_, T> {
63+
fn iter_unsigned<T: Unsigned<T>>(&self) -> ParseUnsigned<'_, T> {
7764
ParseUnsigned { bytes: self.bytes(), phantom: PhantomData }
7865
}
7966

80-
fn iter_signed<T: Signed>(&self) -> ParseSigned<'_, T> {
67+
fn iter_signed<T: Signed<T>>(&self) -> ParseSigned<'_, T> {
8168
ParseSigned { bytes: self.bytes(), phantom: PhantomData }
8269
}
8370
}
8471

85-
impl<T: Unsigned> Iterator for ParseUnsigned<'_, T> {
72+
impl<T: Unsigned<T>> Iterator for ParseUnsigned<'_, T> {
8673
type Item = T;
8774

8875
fn size_hint(&self) -> (usize, Option<usize>) {
@@ -95,7 +82,7 @@ impl<T: Unsigned> Iterator for ParseUnsigned<'_, T> {
9582
}
9683
}
9784

98-
impl<T: Signed> Iterator for ParseSigned<'_, T> {
85+
impl<T: Signed<T>> Iterator for ParseSigned<'_, T> {
9986
type Item = T;
10087

10188
fn size_hint(&self) -> (usize, Option<usize>) {
@@ -108,7 +95,7 @@ impl<T: Signed> Iterator for ParseSigned<'_, T> {
10895
}
10996
}
11097

111-
fn try_unsigned<T: Unsigned>(bytes: &mut Bytes<'_>) -> Option<T> {
98+
fn try_unsigned<T: Unsigned<T>>(bytes: &mut Bytes<'_>) -> Option<T> {
11299
let mut n = loop {
113100
let byte = bytes.next()?;
114101
let digit = byte.to_decimal();
@@ -123,20 +110,20 @@ fn try_unsigned<T: Unsigned>(bytes: &mut Bytes<'_>) -> Option<T> {
123110
let digit = byte.to_decimal();
124111

125112
if digit < 10 {
126-
n = T::from(10) * n + T::from(digit);
113+
n = T::TEN * n + T::from(digit);
127114
} else {
128115
break Some(n);
129116
}
130117
}
131118
}
132119

133-
fn try_signed<T: Signed>(bytes: &mut Bytes<'_>) -> Option<T> {
120+
fn try_signed<T: Signed<T>>(bytes: &mut Bytes<'_>) -> Option<T> {
134121
let (mut n, negative) = loop {
135122
let byte = bytes.next()?;
136123
let digit = byte.to_decimal();
137124

138125
if digit == 253 {
139-
break (T::from(0), true);
126+
break (T::ZERO, true);
140127
}
141128
if digit < 10 {
142129
break (T::from(digit), false);
@@ -150,7 +137,7 @@ fn try_signed<T: Signed>(bytes: &mut Bytes<'_>) -> Option<T> {
150137
let digit = byte.to_decimal();
151138

152139
if digit < 10 {
153-
n = T::from(10) * n + T::from(digit);
140+
n = T::TEN * n + T::from(digit);
154141
} else {
155142
break Some(if negative { -n } else { n });
156143
}

0 commit comments

Comments
 (0)