Skip to content

Commit 94b7688

Browse files
author
Sean Loiselle
committed
dec: add to/from u/i+8/16
1 parent e395695 commit 94b7688

File tree

2 files changed

+140
-6
lines changed

2 files changed

+140
-6
lines changed

dec/src/decimal.rs

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,46 @@ macro_rules! decnum_tryinto_primitive_uint {
703703
}};
704704
}
705705

706+
/// Refer to the comments on [`Context<Decimal<N>>::try_into_i32()`], which also apply to
707+
/// this trait.
708+
impl<const N: usize> TryFrom<Decimal<N>> for i8 {
709+
type Error = TryFromDecimalError;
710+
fn try_from(n: Decimal<N>) -> Result<i8, Self::Error> {
711+
let mut cx = Context::<Decimal<N>>::default();
712+
cx.try_into_i8(n)
713+
}
714+
}
715+
716+
/// Refer to the comments on [`Context<Decimal<N>>::try_into_i32()`], which also apply to
717+
/// this trait.
718+
impl<const N: usize> TryFrom<Decimal<N>> for u8 {
719+
type Error = TryFromDecimalError;
720+
fn try_from(n: Decimal<N>) -> Result<u8, Self::Error> {
721+
let mut cx = Context::<Decimal<N>>::default();
722+
cx.try_into_u8(n)
723+
}
724+
}
725+
726+
/// Refer to the comments on [`Context<Decimal<N>>::try_into_i32()`], which also apply to
727+
/// this trait.
728+
impl<const N: usize> TryFrom<Decimal<N>> for i16 {
729+
type Error = TryFromDecimalError;
730+
fn try_from(n: Decimal<N>) -> Result<i16, Self::Error> {
731+
let mut cx = Context::<Decimal<N>>::default();
732+
cx.try_into_i16(n)
733+
}
734+
}
735+
736+
/// Refer to the comments on [`Context<Decimal<N>>::try_into_i32()`], which also apply to
737+
/// this trait.
738+
impl<const N: usize> TryFrom<Decimal<N>> for u16 {
739+
type Error = TryFromDecimalError;
740+
fn try_from(n: Decimal<N>) -> Result<u16, Self::Error> {
741+
let mut cx = Context::<Decimal<N>>::default();
742+
cx.try_into_u16(n)
743+
}
744+
}
745+
706746
/// Refer to the comments on [`Context<Decimal<N>>::try_into_i32()`], which also apply to
707747
/// this trait.
708748
impl<const N: usize> TryFrom<Decimal<N>> for i32 {
@@ -856,6 +896,30 @@ impl<const N: usize> From<f64> for Decimal<N> {
856896
}
857897
}
858898

899+
impl<const N: usize> From<i8> for Decimal<N> {
900+
fn from(n: i8) -> Decimal<N> {
901+
Decimal::<N>::from(i32::from(n))
902+
}
903+
}
904+
905+
impl<const N: usize> From<u8> for Decimal<N> {
906+
fn from(n: u8) -> Decimal<N> {
907+
Decimal::<N>::from(u32::from(n))
908+
}
909+
}
910+
911+
impl<const N: usize> From<i16> for Decimal<N> {
912+
fn from(n: i16) -> Decimal<N> {
913+
Decimal::<N>::from(i32::from(n))
914+
}
915+
}
916+
917+
impl<const N: usize> From<u16> for Decimal<N> {
918+
fn from(n: u16) -> Decimal<N> {
919+
Decimal::<N>::from(u32::from(n))
920+
}
921+
}
922+
859923
impl<const N: usize> From<i32> for Decimal<N> {
860924
fn from(n: i32) -> Decimal<N> {
861925
let mut d = Decimal::default();
@@ -1284,6 +1348,42 @@ impl<const N: usize> Context<Decimal<N>> {
12841348
decimal_from_unsigned_int!(self, n)
12851349
}
12861350

1351+
/// Attempts to convert `d` to `u8` or fails if not possible.
1352+
///
1353+
/// Refer to the comments on [`Self::try_into_i32()`], which also apply to this
1354+
/// function.
1355+
pub fn try_into_u8(&mut self, d: Decimal<N>) -> Result<u8, TryFromDecimalError> {
1356+
let i = self.try_into_u32(d)?;
1357+
u8::try_from(i).map_err(|_| TryFromDecimalError)
1358+
}
1359+
1360+
/// Attempts to convert `d` to `i8` or fails if not possible.
1361+
///
1362+
/// Refer to the comments on [`Self::try_into_i32()`], which also apply to this
1363+
/// function.
1364+
pub fn try_into_i8(&mut self, d: Decimal<N>) -> Result<i8, TryFromDecimalError> {
1365+
let i = self.try_into_i32(d)?;
1366+
i8::try_from(i).map_err(|_| TryFromDecimalError)
1367+
}
1368+
1369+
/// Attempts to convert `d` to `u16` or fails if not possible.
1370+
///
1371+
/// Refer to the comments on [`Self::try_into_i32()`], which also apply to this
1372+
/// function.
1373+
pub fn try_into_u16(&mut self, d: Decimal<N>) -> Result<u16, TryFromDecimalError> {
1374+
let i = self.try_into_u32(d)?;
1375+
u16::try_from(i).map_err(|_| TryFromDecimalError)
1376+
}
1377+
1378+
/// Attempts to convert `d` to `i16` or fails if not possible.
1379+
///
1380+
/// Refer to the comments on [`Self::try_into_i32()`], which also apply to this
1381+
/// function.
1382+
pub fn try_into_i16(&mut self, d: Decimal<N>) -> Result<i16, TryFromDecimalError> {
1383+
let i = self.try_into_i32(d)?;
1384+
i16::try_from(i).map_err(|_| TryFromDecimalError)
1385+
}
1386+
12871387
/// Attempts to convert `d` to `i32` or fails if not possible. Note that
12881388
/// when returning an error, `self`'s [`context::Status`] is set to
12891389
/// `invalid_operation` in addition to using Rust's `Err` return value.

dec/tests/dec.rs

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1558,6 +1558,14 @@ fn test_cx_into_u128() {
15581558
fn test_decnum_tryinto_primitive() {
15591559
const WIDTH: usize = 14;
15601560
let mut cx = Context::<Decimal<WIDTH>>::default();
1561+
let min_u8 = Decimal::<WIDTH>::from(u8::MIN);
1562+
let max_u8 = Decimal::<WIDTH>::from(u8::MAX);
1563+
let min_i8 = Decimal::<WIDTH>::from(i8::MIN);
1564+
let max_i8 = Decimal::<WIDTH>::from(i8::MAX);
1565+
let min_u16 = Decimal::<WIDTH>::from(u16::MIN);
1566+
let max_u16 = Decimal::<WIDTH>::from(u16::MAX);
1567+
let min_i16 = Decimal::<WIDTH>::from(i16::MIN);
1568+
let max_i16 = Decimal::<WIDTH>::from(i16::MAX);
15611569
let min_u32 = Decimal::<WIDTH>::from(u32::MIN);
15621570
let max_u32 = Decimal::<WIDTH>::from(u32::MAX);
15631571
let min_i32 = Decimal::<WIDTH>::from(i32::MIN);
@@ -1575,13 +1583,45 @@ fn test_decnum_tryinto_primitive() {
15751583
let scientific_notation = cx.parse("2E5").unwrap();
15761584

15771585
let inner = |v: &Decimal<WIDTH>| {
1586+
let i_u8 = u8::try_from(*v);
1587+
let i_i8 = i8::try_from(*v);
1588+
let i_u16 = u16::try_from(*v);
1589+
let i_i16 = i16::try_from(*v);
15781590
let i_u32 = u32::try_from(*v);
15791591
let i_i32 = i32::try_from(*v);
15801592
let i_u64 = u64::try_from(*v);
15811593
let i_i64 = i64::try_from(*v);
15821594
let i_u128 = u128::try_from(*v);
15831595
let i_i128 = i128::try_from(*v);
15841596

1597+
// u8
1598+
if v >= &min_u8 && v <= &max_u8 {
1599+
assert!(i_u8.is_ok());
1600+
} else {
1601+
assert!(i_u8.is_err());
1602+
}
1603+
1604+
// i8
1605+
if v >= &min_i8 && v <= &max_i8 {
1606+
assert!(i_i8.is_ok());
1607+
} else {
1608+
assert!(i_i8.is_err());
1609+
}
1610+
1611+
// u16
1612+
if v >= &min_u16 && v <= &max_u16 {
1613+
assert!(i_u16.is_ok());
1614+
} else {
1615+
assert!(i_u16.is_err());
1616+
}
1617+
1618+
// i16
1619+
if v >= &min_i16 && v <= &max_i16 {
1620+
assert!(i_i16.is_ok());
1621+
} else {
1622+
assert!(i_i16.is_err());
1623+
}
1624+
15851625
// u32
15861626
if v >= &min_u32 && v <= &max_u32 {
15871627
assert!(i_u32.is_ok());
@@ -1644,12 +1684,6 @@ fn test_decnum_tryinto_primitive() {
16441684
fn inner_expect_failure(s: &str) {
16451685
let mut cx = Context::<Decimal<WIDTH>>::default();
16461686
let v = cx.parse(s).unwrap();
1647-
println!(
1648-
"v {:?}, v.exponent {}, v.digits {}",
1649-
v,
1650-
v.exponent(),
1651-
v.digits()
1652-
);
16531687
assert!(u32::try_from(v).is_err());
16541688
assert!(i32::try_from(v).is_err());
16551689
assert!(u64::try_from(v).is_err());

0 commit comments

Comments
 (0)