Skip to content

Commit dbed5d2

Browse files
committed
Added custom FromLossy trait implementation to work around lack of lossy conversions
See: rust-lang/rfcs#2484 Note due to blanket-trait limitations, we can really only implement this for new types in the current crate
1 parent 4667933 commit dbed5d2

File tree

4 files changed

+277
-8
lines changed

4 files changed

+277
-8
lines changed

examples/crc.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
1616
use std::iter;
1717
use std::convert::TryFrom;
18+
use gf256::traits::FromLossy;
1819
use gf256::*;
1920

2021
/// This is a common polynomial for 32-bit CRCs, normally the highest
@@ -173,7 +174,7 @@ pub fn barret_crc(data: &[u8]) -> u32 {
173174
for b in data {
174175
crc = crc ^ (p32::from(b.reverse_bits()) << 24);
175176
let q = (p64::from(crc >> 24)*BARRET_CONSTANT) >> 32;
176-
crc = p32::try_from((q*POLYNOMIAL) & 0xffffffffu64).unwrap() + (crc << 8);
177+
crc = p32::from_lossy(q*POLYNOMIAL) + (crc << 8);
177178
}
178179

179180
u32::from(crc).reverse_bits() ^ 0xffffffff
@@ -196,13 +197,13 @@ pub fn word_barret_crc(data: &[u8]) -> u32 {
196197
let word = <[u8; 4]>::try_from(word).unwrap();
197198
crc = crc ^ p32::from_le_bytes(word).reverse_bits();
198199
let q = (p64::from(crc)*BARRET_CONSTANT) >> 32;
199-
crc = p32::try_from((q*POLYNOMIAL) & 0xffffffffu64).unwrap();
200+
crc = p32::from_lossy(q*POLYNOMIAL);
200201
}
201202

202203
for b in words.remainder() {
203204
crc = crc ^ (p32::from(b.reverse_bits()) << 24);
204205
let q = (p64::from(crc >> 24)*BARRET_CONSTANT) >> 32;
205-
crc = p32::try_from((q*POLYNOMIAL) & 0xffffffffu64).unwrap() + (crc << 8);
206+
crc = p32::from_lossy(q*POLYNOMIAL) + (crc << 8);
206207
}
207208

208209
u32::from(crc).reverse_bits() ^ 0xffffffff

gf256-macros/src/p.rs

Lines changed: 216 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@
33
use std::mem::size_of;
44
use std::ops::*;
55
use std::iter::*;
6-
use std::convert::TryFrom;
76
use std::num::TryFromIntError;
87
use std::num::ParseIntError;
98
use std::fmt;
109
use std::str::FromStr;
10+
use __crate::traits::TryFrom;
11+
use __crate::traits::FromLossy;
1112
use __crate::internal::cfg_if::cfg_if;
1213

14+
1315
/// A type representing a gf(2) polynomial
1416
#[allow(non_camel_case_types)]
1517
#[derive(Default, Copy, Clone, Eq, PartialEq, Hash)]
@@ -685,6 +687,70 @@ impl TryFrom<__crate::p128> for __p {
685687
}
686688
}
687689

690+
#[cfg(__if(__width < 16))]
691+
impl FromLossy<u16> for __p {
692+
#[inline]
693+
fn from_lossy(x: u16) -> __p {
694+
__p(x as __u)
695+
}
696+
}
697+
698+
#[cfg(__if(__width < 32))]
699+
impl FromLossy<u32> for __p {
700+
#[inline]
701+
fn from_lossy(x: u32) -> __p {
702+
__p(x as __u)
703+
}
704+
}
705+
706+
#[cfg(__if(__width < 64))]
707+
impl FromLossy<u64> for __p {
708+
#[inline]
709+
fn from_lossy(x: u64) -> __p {
710+
__p(x as __u)
711+
}
712+
}
713+
714+
#[cfg(__if(__width < 128))]
715+
impl FromLossy<u128> for __p {
716+
#[inline]
717+
fn from_lossy(x: u128) -> __p {
718+
__p(x as __u)
719+
}
720+
}
721+
722+
#[cfg(__if(__width < 16))]
723+
impl FromLossy<__crate::p16> for __p {
724+
#[inline]
725+
fn from_lossy(x: __crate::p16) -> __p {
726+
__p(x.0 as __u)
727+
}
728+
}
729+
730+
#[cfg(__if(__width < 32))]
731+
impl FromLossy<__crate::p32> for __p {
732+
#[inline]
733+
fn from_lossy(x: __crate::p32) -> __p {
734+
__p(x.0 as __u)
735+
}
736+
}
737+
738+
#[cfg(__if(__width < 64))]
739+
impl FromLossy<__crate::p64> for __p {
740+
#[inline]
741+
fn from_lossy(x: __crate::p64) -> __p {
742+
__p(x.0 as __u)
743+
}
744+
}
745+
746+
#[cfg(__if(__width < 128))]
747+
impl FromLossy<__crate::p128> for __p {
748+
#[inline]
749+
fn from_lossy(x: __crate::p128) -> __p {
750+
__p(x.0 as __u)
751+
}
752+
}
753+
688754

689755
//// Conversions from __p ////
690756

@@ -763,6 +829,155 @@ impl TryFrom<__p> for u64 {
763829
}
764830
}
765831

832+
#[cfg(__if(__width > 8))]
833+
impl FromLossy<__p> for u8 {
834+
#[inline]
835+
fn from_lossy(x: __p) -> u8 {
836+
x.0 as u8
837+
}
838+
}
839+
840+
#[cfg(__if(__width > 16))]
841+
impl FromLossy<__p> for u16 {
842+
#[inline]
843+
fn from_lossy(x: __p) -> u16 {
844+
x.0 as u16
845+
}
846+
}
847+
848+
#[cfg(__if(__width > 32))]
849+
impl FromLossy<__p> for u32 {
850+
#[inline]
851+
fn from_lossy(x: __p) -> u32 {
852+
x.0 as u32
853+
}
854+
}
855+
856+
#[cfg(__if(__width > 64))]
857+
impl FromLossy<__p> for u64 {
858+
#[inline]
859+
fn from_lossy(x: __p) -> u64 {
860+
x.0 as u64
861+
}
862+
}
863+
864+
#[cfg(__if(__width < 16))]
865+
impl From<__p> for i16 {
866+
#[inline]
867+
fn from(x: __p) -> i16 {
868+
i16::from(x.0)
869+
}
870+
}
871+
872+
#[cfg(__if(__width < 32))]
873+
impl From<__p> for i32 {
874+
#[inline]
875+
fn from(x: __p) -> i32 {
876+
i32::from(x.0)
877+
}
878+
}
879+
880+
#[cfg(__if(__width < 64))]
881+
impl From<__p> for i64 {
882+
#[inline]
883+
fn from(x: __p) -> i64 {
884+
i64::from(x.0)
885+
}
886+
}
887+
888+
#[cfg(__if(__width < 128))]
889+
impl From<__p> for i128 {
890+
#[inline]
891+
fn from(x: __p) -> i128 {
892+
i128::from(x.0)
893+
}
894+
}
895+
896+
#[cfg(__if(__width >= 8))]
897+
impl TryFrom<__p> for i8 {
898+
type Error = TryFromIntError;
899+
#[inline]
900+
fn try_from(x: __p) -> Result<i8, Self::Error> {
901+
i8::try_from(x.0)
902+
}
903+
}
904+
905+
#[cfg(__if(__width >= 16))]
906+
impl TryFrom<__p> for i16 {
907+
type Error = TryFromIntError;
908+
#[inline]
909+
fn try_from(x: __p) -> Result<i16, Self::Error> {
910+
i16::try_from(x.0)
911+
}
912+
}
913+
914+
#[cfg(__if(__width >= 32))]
915+
impl TryFrom<__p> for i32 {
916+
type Error = TryFromIntError;
917+
#[inline]
918+
fn try_from(x: __p) -> Result<i32, Self::Error> {
919+
i32::try_from(x.0)
920+
}
921+
}
922+
923+
#[cfg(__if(__width >= 64))]
924+
impl TryFrom<__p> for i64 {
925+
type Error = TryFromIntError;
926+
#[inline]
927+
fn try_from(x: __p) -> Result<i64, Self::Error> {
928+
i64::try_from(x.0)
929+
}
930+
}
931+
932+
#[cfg(__if(__width >= 128))]
933+
impl TryFrom<__p> for i128 {
934+
type Error = TryFromIntError;
935+
#[inline]
936+
fn try_from(x: __p) -> Result<i128, Self::Error> {
937+
i128::try_from(x.0)
938+
}
939+
}
940+
941+
#[cfg(__if(__width >= 8))]
942+
impl FromLossy<__p> for i8 {
943+
#[inline]
944+
fn from_lossy(x: __p) -> i8 {
945+
x.0 as i8
946+
}
947+
}
948+
949+
#[cfg(__if(__width >= 16))]
950+
impl FromLossy<__p> for i16 {
951+
#[inline]
952+
fn from_lossy(x: __p) -> i16 {
953+
x.0 as i16
954+
}
955+
}
956+
957+
#[cfg(__if(__width >= 32))]
958+
impl FromLossy<__p> for i32 {
959+
#[inline]
960+
fn from_lossy(x: __p) -> i32 {
961+
x.0 as i32
962+
}
963+
}
964+
965+
#[cfg(__if(__width >= 64))]
966+
impl FromLossy<__p> for i64 {
967+
#[inline]
968+
fn from_lossy(x: __p) -> i64 {
969+
x.0 as i64
970+
}
971+
}
972+
973+
#[cfg(__if(__width >= 128))]
974+
impl FromLossy<__p> for i128 {
975+
#[inline]
976+
fn from_lossy(x: __p) -> i128 {
977+
x.0 as i128
978+
}
979+
}
980+
766981

767982
//// Negate ////
768983

src/lib.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11

22

3+
/// Common traits
4+
pub mod traits;
5+
6+
/// Polynomial types
7+
pub mod p;
8+
pub use p::*;
9+
310
/// re-exported for proc_macros
411
pub mod internal {
512
pub use cfg_if;
613
}
7-
8-
mod p;
9-
pub use p::*;
10-

src/traits.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//! Common traits
2+
//!
3+
//! Currently just a workaround for FromLossy/IntoLossy traits
4+
//!
5+
6+
// TryFrom/TryInto forwarded for convenience
7+
pub use std::convert::TryFrom;
8+
pub use std::convert::TryInto;
9+
10+
/// A From trait for conversions which may lose precision
11+
///
12+
/// Note this is just a temporary workaround. Once [RFC2484] is implemented
13+
/// these traits should go away.
14+
///
15+
/// [RFC2484]: https://github.com/rust-lang/rfcs/pull/2484
16+
///
17+
pub trait FromLossy<T> {
18+
fn from_lossy(t: T) -> Self;
19+
}
20+
21+
/// An Into trait for conversions which may lose precision
22+
///
23+
/// This is similar to Into, but for FromLossy
24+
///
25+
pub trait IntoLossy<T> {
26+
fn into_lossy(self) -> T;
27+
}
28+
29+
/// IntoLossy is the inverse of FromLossy
30+
impl<T, U> IntoLossy<T> for U
31+
where
32+
T: FromLossy<U>
33+
{
34+
#[inline]
35+
fn into_lossy(self) -> T {
36+
T::from_lossy(self)
37+
}
38+
}
39+
40+
/// All types that provide From provide FromLossy
41+
impl<T, U> FromLossy<T> for U
42+
where
43+
U: From<T>
44+
{
45+
#[inline]
46+
fn from_lossy(t: T) -> Self {
47+
Self::from(t)
48+
}
49+
}
50+

0 commit comments

Comments
 (0)