add {saturating,wrapping_overflowing}_from_str{,_binary,_octal,_hex}

This commit is contained in:
Trevor Spiteri 2019-08-19 00:30:02 +02:00
parent 8bd4d5e9a7
commit a2249ea232
5 changed files with 550 additions and 0 deletions

View File

@ -53,6 +53,9 @@ Various conversion methods are available:
* The [*fixed* crate] now requires rustc version 1.34.0 or later.
* Parsing strings now rounds to the nearest with ties rounding to even.
* Checked versions of string parsing methods are now available as
inherent methods to all fixed-point numbers, as methods in the
[`Fixed`] trait, and as methods in the [`Wrapping`] wrapper.
* The following methods are now `const` functions:
* [`min_value`], [`max_value`], [`from_bits`], [`to_bits`]
* [`count_ones`], [`count_zeros`], [`leading_zeros`],
@ -66,7 +69,9 @@ Various conversion methods are available:
* The associated constants [`INT_NBITS`] and [`FRAC_NBITS`] were added.
[`FRAC_NBITS`]: https://docs.rs/fixed/0.4.2/fixed/struct.FixedI32.html#associatedconstant.FRAC_NBITS
[`Fixed`]: https://docs.rs/fixed/0.4.2/fixed/traits/trait.Fixed.html
[`INT_NBITS`]: https://docs.rs/fixed/0.4.2/fixed/struct.FixedI32.html#associatedconstant.INT_NBITS
[`Wrapping`]: https://docs.rs/fixed/0.4.2/fixed/struct.Wrapping.html
[`count_ones`]: https://docs.rs/fixed/0.4.2/fixed/struct.FixedI32.html#method.count_ones
[`count_zeros`]: https://docs.rs/fixed/0.4.2/fixed/struct.FixedI32.html#method.count_zeros
[`from_bits`]: https://docs.rs/fixed/0.4.2/fixed/struct.FixedI32.html#method.from_bits

View File

@ -10,6 +10,9 @@ Version 0.4.3 (unreleased)
* The *fixed* crate now requires rustc version 1.34.0 or later.
* Parsing strings now rounds to the nearest with ties rounding to even.
* Checked versions of string parsing methods are now available as
inherent methods to all fixed-point numbers, as methods in the
`Fixed` trait, and as methods in the `Wrapping` wrapper.
* The following methods are now `const` functions:
* `min_value`, `max_value`, `from_bits`, `to_bits`
* `count_ones`, `count_zeros`, `leading_zeros`, `trailing_zeros`

View File

@ -933,5 +933,377 @@ assert_eq!(neg, Ok(-check));
FromStrRadix::from_str_radix(src, 16)
}
);
comment!(
"Converts a string slice containing decimal digits to a fixed-point number,
saturating on overflow.
# Examples
```rust
",
if_signed_unsigned!(
$Signedness,
"use fixed::types::I8F8;
assert_eq!(I8F8::saturating_from_str(\"9999\"), Ok(I8F8::max_value()));
assert_eq!(I8F8::saturating_from_str(\"-9999\"), Ok(I8F8::min_value()));
",
"use fixed::types::U8F8;
assert_eq!(U8F8::saturating_from_str(\"9999\"), Ok(U8F8::max_value()));
assert_eq!(U8F8::saturating_from_str(\"-1\"), Ok(U8F8::from_num(0)));
",
),
"```
";
#[inline]
pub fn saturating_from_str(src: &str) -> Result<$Fixed<Frac>, ParseFixedError> {
FromStrRadix::saturating_from_str_radix(src, 10)
}
);
comment!(
"Converts a string slice containing binary digits to a fixed-point number,
saturating on overflow.
# Examples
```rust
",
if_signed_unsigned!(
$Signedness,
"use fixed::types::I8F8;
assert_eq!(I8F8::saturating_from_str_binary(\"101100111000\"), Ok(I8F8::max_value()));
assert_eq!(I8F8::saturating_from_str_binary(\"-101100111000\"), Ok(I8F8::min_value()));
",
"use fixed::types::U8F8;
assert_eq!(U8F8::saturating_from_str_binary(\"101100111000\"), Ok(U8F8::max_value()));
assert_eq!(U8F8::saturating_from_str_binary(\"-1\"), Ok(U8F8::from_num(0)));
",
),
"```
";
#[inline]
pub fn saturating_from_str_binary(src: &str) -> Result<$Fixed<Frac>, ParseFixedError> {
FromStrRadix::saturating_from_str_radix(src, 2)
}
);
comment!(
"Converts a string slice containing octal digits to a fixed-point number,
saturating on overflow.
# Examples
```rust
",
if_signed_unsigned!(
$Signedness,
"use fixed::types::I8F8;
assert_eq!(I8F8::saturating_from_str_octal(\"7777\"), Ok(I8F8::max_value()));
assert_eq!(I8F8::saturating_from_str_octal(\"-7777\"), Ok(I8F8::min_value()));
",
"use fixed::types::U8F8;
assert_eq!(U8F8::saturating_from_str_octal(\"7777\"), Ok(U8F8::max_value()));
assert_eq!(U8F8::saturating_from_str_octal(\"-1\"), Ok(U8F8::from_num(0)));
",
),
"```
";
#[inline]
pub fn saturating_from_str_octal(src: &str) -> Result<$Fixed<Frac>, ParseFixedError> {
FromStrRadix::saturating_from_str_radix(src, 8)
}
);
comment!(
"Converts a string slice containing hexadecimal digits to a fixed-point number,
saturating on overflow.
# Examples
```rust
",
if_signed_unsigned!(
$Signedness,
"use fixed::types::I8F8;
assert_eq!(I8F8::saturating_from_str_hex(\"FFFF\"), Ok(I8F8::max_value()));
assert_eq!(I8F8::saturating_from_str_hex(\"-FFFF\"), Ok(I8F8::min_value()));
",
"use fixed::types::U8F8;
assert_eq!(U8F8::saturating_from_str_hex(\"FFFF\"), Ok(U8F8::max_value()));
assert_eq!(U8F8::saturating_from_str_hex(\"-1\"), Ok(U8F8::from_num(0)));
",
),
"```
";
#[inline]
pub fn saturating_from_str_hex(src: &str) -> Result<$Fixed<Frac>, ParseFixedError> {
FromStrRadix::saturating_from_str_radix(src, 16)
}
);
comment!(
"Converts a string slice containing decimal digits to a fixed-point number,
wrapping on overflow.
# Examples
```rust
",
if_signed_unsigned!(
$Signedness,
"use fixed::types::I8F8;
// 9999.5 = 15.5 + 256 × n
assert_eq!(I8F8::wrapping_from_str(\"9999.5\"), Ok(I8F8::from_num(15.5)));
assert_eq!(I8F8::wrapping_from_str(\"-9999.5\"), Ok(I8F8::from_num(-15.5)));
",
"use fixed::types::U8F8;
// 9999.5 = 15.5 + 256 × n
assert_eq!(U8F8::wrapping_from_str(\"9999.5\"), Ok(U8F8::from_num(15.5)));
assert_eq!(U8F8::wrapping_from_str(\"-9999.5\"), Ok(U8F8::from_num(240.5)));
",
),
"```
";
#[inline]
pub fn wrapping_from_str(src: &str) -> Result<$Fixed<Frac>, ParseFixedError> {
FromStrRadix::wrapping_from_str_radix(src, 10)
}
);
comment!(
"Converts a string slice containing binary digits to a fixed-point number,
wrapping on overflow.
# Examples
```rust
",
if_signed_unsigned!(
$Signedness,
"use fixed::types::I8F8;
let check = I8F8::from_bits(0b1110001 << (8 - 1));
assert_eq!(I8F8::wrapping_from_str_binary(\"101100111000.1\"), Ok(check));
assert_eq!(I8F8::wrapping_from_str_binary(\"-101100111000.1\"), Ok(-check));
",
"use fixed::types::U8F8;
let check = U8F8::from_bits(0b1110001 << (8 - 1));
assert_eq!(U8F8::wrapping_from_str_binary(\"101100111000.1\"), Ok(check));
assert_eq!(U8F8::wrapping_from_str_binary(\"-101100111000.1\"), Ok(check.wrapping_neg()));
",
),
"```
";
#[inline]
pub fn wrapping_from_str_binary(src: &str) -> Result<$Fixed<Frac>, ParseFixedError> {
FromStrRadix::wrapping_from_str_radix(src, 2)
}
);
comment!(
"Converts a string slice containing octal digits to a fixed-point number,
wrapping on overflow.
# Examples
```rust
",
if_signed_unsigned!(
$Signedness,
"use fixed::types::I8F8;
let check = I8F8::from_bits(0o1654 << (8 - 3));
assert_eq!(I8F8::wrapping_from_str_octal(\"7165.4\"), Ok(check));
assert_eq!(I8F8::wrapping_from_str_octal(\"-7165.4\"), Ok(-check));
",
"use fixed::types::U8F8;
let check = U8F8::from_bits(0o1654 << (8 - 3));
assert_eq!(U8F8::wrapping_from_str_octal(\"7165.4\"), Ok(check));
assert_eq!(U8F8::wrapping_from_str_octal(\"-7165.4\"), Ok(check.wrapping_neg()));
",
),
"```
";
#[inline]
pub fn wrapping_from_str_octal(src: &str) -> Result<$Fixed<Frac>, ParseFixedError> {
FromStrRadix::wrapping_from_str_radix(src, 8)
}
);
comment!(
"Converts a string slice containing hexadecimal digits to a fixed-point number,
wrapping on overflow.
# Examples
```rust
",
if_signed_unsigned!(
$Signedness,
"use fixed::types::I8F8;
let check = I8F8::from_bits(0xFFE);
assert_eq!(I8F8::wrapping_from_str_hex(\"C0F.FE\"), Ok(check));
assert_eq!(I8F8::wrapping_from_str_hex(\"-C0F.FE\"), Ok(-check));
",
"use fixed::types::U8F8;
let check = U8F8::from_bits(0xFFE);
assert_eq!(U8F8::wrapping_from_str_hex(\"C0F.FE\"), Ok(check));
assert_eq!(U8F8::wrapping_from_str_hex(\"-C0F.FE\"), Ok(check.wrapping_neg()));
",
),
"```
";
#[inline]
pub fn wrapping_from_str_hex(src: &str) -> Result<$Fixed<Frac>, ParseFixedError> {
FromStrRadix::wrapping_from_str_radix(src, 16)
}
);
comment!(
"Converts a string slice containing decimal digits to a fixed-point number.
Returns a [tuple] of the fixed-point number and a [`bool`] indicating
whether an overflow has occurred. On overflow, the wrapped value is
returned.
# Examples
```rust
",
if_signed_unsigned!(
$Signedness,
"use fixed::types::I8F8;
assert_eq!(I8F8::overflowing_from_str(\"99.5\"), Ok((I8F8::from_num(99.5), false)));
// 9999.5 = 15.5 + 256 × n
assert_eq!(I8F8::overflowing_from_str(\"-9999.5\"), Ok((I8F8::from_num(-15.5), true)));
",
"use fixed::types::U8F8;
assert_eq!(U8F8::overflowing_from_str(\"99.5\"), Ok((U8F8::from_num(99.5), false)));
// 9999.5 = 15.5 + 256 × n
assert_eq!(U8F8::overflowing_from_str(\"9999.5\"), Ok((U8F8::from_num(15.5), true)));
",
),
"```
[`bool`]: https://doc.rust-lang.org/nightly/std/primitive.bool.html
[tuple]: https://doc.rust-lang.org/nightly/std/primitive.tuple.html
";
#[inline]
pub fn overflowing_from_str(
src: &str,
) -> Result<($Fixed<Frac>, bool), ParseFixedError> {
FromStrRadix::overflowing_from_str_radix(src, 10)
}
);
comment!(
"Converts a string slice containing binary digits to a fixed-point number.
Returns a [tuple] of the fixed-point number and a [`bool`] indicating
whether an overflow has occurred. On overflow, the wrapped value is
returned.
# Examples
```rust
",
if_signed_unsigned!(
$Signedness,
"use fixed::types::I8F8;
let check = I8F8::from_bits(0b1110001 << (8 - 1));
assert_eq!(I8F8::overflowing_from_str_binary(\"111000.1\"), Ok((check, false)));
assert_eq!(I8F8::overflowing_from_str_binary(\"-101100111000.1\"), Ok((-check, true)));
",
"use fixed::types::U8F8;
let check = U8F8::from_bits(0b1110001 << (8 - 1));
assert_eq!(U8F8::overflowing_from_str_binary(\"111000.1\"), Ok((check, false)));
assert_eq!(U8F8::overflowing_from_str_binary(\"101100111000.1\"), Ok((check, true)));
",
),
"```
[`bool`]: https://doc.rust-lang.org/nightly/std/primitive.bool.html
[tuple]: https://doc.rust-lang.org/nightly/std/primitive.tuple.html
";
#[inline]
pub fn overflowing_from_str_binary(
src: &str,
) -> Result<($Fixed<Frac>, bool), ParseFixedError> {
FromStrRadix::overflowing_from_str_radix(src, 2)
}
);
comment!(
"Converts a string slice containing octal digits to a fixed-point number.
Returns a [tuple] of the fixed-point number and a [`bool`] indicating
whether an overflow has occurred. On overflow, the wrapped value is
returned.
# Examples
```rust
",
if_signed_unsigned!(
$Signedness,
"use fixed::types::I8F8;
let check = I8F8::from_bits(0o1654 << (8 - 3));
assert_eq!(I8F8::overflowing_from_str_octal(\"165.4\"), Ok((check, false)));
assert_eq!(I8F8::overflowing_from_str_octal(\"-7165.4\"), Ok((-check, true)));
",
"use fixed::types::U8F8;
let check = U8F8::from_bits(0o1654 << (8 - 3));
assert_eq!(U8F8::overflowing_from_str_octal(\"165.4\"), Ok((check, false)));
assert_eq!(U8F8::overflowing_from_str_octal(\"7165.4\"), Ok((check, true)));
",
),
"```
[`bool`]: https://doc.rust-lang.org/nightly/std/primitive.bool.html
[tuple]: https://doc.rust-lang.org/nightly/std/primitive.tuple.html
";
#[inline]
pub fn overflowing_from_str_octal(
src: &str,
) -> Result<($Fixed<Frac>, bool), ParseFixedError> {
FromStrRadix::overflowing_from_str_radix(src, 8)
}
);
comment!(
"Converts a string slice containing hexadecimal digits to a fixed-point number.
Returns a [tuple] of the fixed-point number and a [`bool`] indicating
whether an overflow has occurred. On overflow, the wrapped value is
returned.
# Examples
```rust
",
if_signed_unsigned!(
$Signedness,
"use fixed::types::I8F8;
let check = I8F8::from_bits(0xFFE);
assert_eq!(I8F8::overflowing_from_str_hex(\"F.FE\"), Ok((check, false)));
assert_eq!(I8F8::overflowing_from_str_hex(\"-C0F.FE\"), Ok((-check, true)));
",
"use fixed::types::U8F8;
let check = U8F8::from_bits(0xFFE);
assert_eq!(U8F8::overflowing_from_str_hex(\"F.FE\"), Ok((check, false)));
assert_eq!(U8F8::overflowing_from_str_hex(\"C0F.FE\"), Ok((check, true)));
",
),
"```
[`bool`]: https://doc.rust-lang.org/nightly/std/primitive.bool.html
[tuple]: https://doc.rust-lang.org/nightly/std/primitive.tuple.html
";
#[inline]
pub fn overflowing_from_str_hex(
src: &str,
) -> Result<($Fixed<Frac>, bool), ParseFixedError> {
FromStrRadix::overflowing_from_str_radix(src, 16)
}
);
};
}

View File

@ -330,6 +330,82 @@ where
/// Converts a string slice containing hexadecimal digits to a fixed-point number.
fn from_str_hex(src: &str) -> Result<Self, ParseFixedError>;
/// Converts a string slice containing decimal digits to a
/// fixed-point number, saturating on overflow.
fn saturating_from_str(src: &str) -> Result<Self, ParseFixedError>;
/// Converts a string slice containing binary digits to a
/// fixed-point number, saturating on overflow.
fn saturating_from_str_binary(src: &str) -> Result<Self, ParseFixedError>;
/// Converts a string slice containing octal digits to a
/// fixed-point number, saturating on overflow.
fn saturating_from_str_octal(src: &str) -> Result<Self, ParseFixedError>;
/// Converts a string slice containing hexadecimal digits to a
/// fixed-point number, saturating on overflow.
fn saturating_from_str_hex(src: &str) -> Result<Self, ParseFixedError>;
/// Converts a string slice containing decimal digits to a
/// fixed-point number, wrapping on overflow.
fn wrapping_from_str(src: &str) -> Result<Self, ParseFixedError>;
/// Converts a string slice containing binary digits to a
/// fixed-point number, wrapping on overflow.
fn wrapping_from_str_binary(src: &str) -> Result<Self, ParseFixedError>;
/// Converts a string slice containing octal digits to a
/// fixed-point number, wrapping on overflow.
fn wrapping_from_str_octal(src: &str) -> Result<Self, ParseFixedError>;
/// Converts a string slice containing hexadecimal digits to a
/// fixed-point number, wrapping on overflow.
fn wrapping_from_str_hex(src: &str) -> Result<Self, ParseFixedError>;
/// Converts a string slice containing decimal digits to a
/// fixed-point number.
///
/// Returns a [tuple] of the fixed-point number and a [`bool`],
/// indicating whether an overflow has occurred. On overflow, the
/// wrapped value is returned.
///
/// [`bool`]: https://doc.rust-lang.org/nightly/std/primitive.bool.html
/// [tuple]: https://doc.rust-lang.org/nightly/std/primitive.tuple.html
fn overflowing_from_str(src: &str) -> Result<(Self, bool), ParseFixedError>;
/// Converts a string slice containing binary digits to a
/// fixed-point number.
///
/// Returns a [tuple] of the fixed-point number and a [`bool`],
/// indicating whether an overflow has occurred. On overflow, the
/// wrapped value is returned.
///
/// [`bool`]: https://doc.rust-lang.org/nightly/std/primitive.bool.html
/// [tuple]: https://doc.rust-lang.org/nightly/std/primitive.tuple.html
fn overflowing_from_str_binary(src: &str) -> Result<(Self, bool), ParseFixedError>;
/// Converts a string slice containing octal digits to a
/// fixed-point number.
///
/// Returns a [tuple] of the fixed-point number and a [`bool`],
/// indicating whether an overflow has occurred. On overflow, the
/// wrapped value is returned.
///
/// [`bool`]: https://doc.rust-lang.org/nightly/std/primitive.bool.html
/// [tuple]: https://doc.rust-lang.org/nightly/std/primitive.tuple.html
fn overflowing_from_str_octal(src: &str) -> Result<(Self, bool), ParseFixedError>;
/// Converts a string slice containing hexadecimal digits to a
/// fixed-point number.
///
/// Returns a [tuple] of the fixed-point number and a [`bool`],
/// indicating whether an overflow has occurred. On overflow, the
/// wrapped value is returned.
///
/// [`bool`]: https://doc.rust-lang.org/nightly/std/primitive.bool.html
/// [tuple]: https://doc.rust-lang.org/nightly/std/primitive.tuple.html
fn overflowing_from_str_hex(src: &str) -> Result<(Self, bool), ParseFixedError>;
/// Returns the integer part.
fn int(self) -> Self;
@ -1321,6 +1397,42 @@ macro_rules! impl_fixed {
trait_delegate! { fn from_str_binary(src: &str) -> Result<Self, ParseFixedError> }
trait_delegate! { fn from_str_octal(src: &str) -> Result<Self, ParseFixedError> }
trait_delegate! { fn from_str_hex(src: &str) -> Result<Self, ParseFixedError> }
trait_delegate! {
fn saturating_from_str(src: &str) -> Result<Self, ParseFixedError>
}
trait_delegate! {
fn saturating_from_str_binary(src: &str) -> Result<Self, ParseFixedError>
}
trait_delegate! {
fn saturating_from_str_octal(src: &str) -> Result<Self, ParseFixedError>
}
trait_delegate! {
fn saturating_from_str_hex(src: &str) -> Result<Self, ParseFixedError>
}
trait_delegate! {
fn wrapping_from_str(src: &str) -> Result<Self, ParseFixedError>
}
trait_delegate! {
fn wrapping_from_str_binary(src: &str) -> Result<Self, ParseFixedError>
}
trait_delegate! {
fn wrapping_from_str_octal(src: &str) -> Result<Self, ParseFixedError>
}
trait_delegate! {
fn wrapping_from_str_hex(src: &str) -> Result<Self, ParseFixedError>
}
trait_delegate! {
fn overflowing_from_str(src: &str) -> Result<(Self, bool), ParseFixedError>
}
trait_delegate! {
fn overflowing_from_str_binary(src: &str) -> Result<(Self, bool), ParseFixedError>
}
trait_delegate! {
fn overflowing_from_str_octal(src: &str) -> Result<(Self, bool), ParseFixedError>
}
trait_delegate! {
fn overflowing_from_str_hex(src: &str) -> Result<(Self, bool), ParseFixedError>
}
trait_delegate! { fn int(self) -> Self }
trait_delegate! { fn frac(self) -> Self }
trait_delegate! { fn ceil(self) -> Self }

View File

@ -14,6 +14,7 @@
// <https://opensource.org/licenses/MIT>.
use crate::{
from_str::ParseFixedError,
traits::{Fixed, FixedSigned, ToFixed},
types::{LeEqU128, LeEqU16, LeEqU32, LeEqU64, LeEqU8},
FixedI128, FixedI16, FixedI32, FixedI64, FixedI8, FixedU128, FixedU16, FixedU32, FixedU64,
@ -115,6 +116,63 @@ impl<F: Fixed> Wrapping<F> {
Wrapping(src.wrapping_to_fixed())
}
/// Converts a string slice containing decimal digits to a fixed-point number.
///
/// # Examples
///
/// ```rust
/// use fixed::{types::I8F8, Wrapping};
/// // 9999.5 = 15.5 + 256 × n
/// let check = Wrapping(I8F8::from_num(15.5));
/// assert_eq!(Wrapping::<I8F8>::wrapping_from_str("9999.5"), Ok(check));
/// ```
#[inline]
pub fn wrapping_from_str(src: &str) -> Result<Self, ParseFixedError> {
F::wrapping_from_str(src).map(Wrapping)
}
/// Converts a string slice containing binary digits to a fixed-point number.
///
/// # Examples
///
/// ```rust
/// use fixed::{types::I8F8, Wrapping};
/// let check = Wrapping(I8F8::from_bits(0b1110001 << (8 - 1)));
/// assert_eq!(Wrapping::<I8F8>::wrapping_from_str_binary("101100111000.1"), Ok(check));
/// ```
#[inline]
pub fn wrapping_from_str_binary(src: &str) -> Result<Self, ParseFixedError> {
F::wrapping_from_str_binary(src).map(Wrapping)
}
/// Converts a string slice containing octal digits to a fixed-point number.
///
/// # Examples
///
/// ```rust
/// use fixed::{types::I8F8, Wrapping};
/// let check = Wrapping(I8F8::from_bits(0o1654 << (8 - 3)));
/// assert_eq!(Wrapping::<I8F8>::wrapping_from_str_octal("7165.4"), Ok(check));
/// ```
#[inline]
pub fn wrapping_from_str_octal(src: &str) -> Result<Self, ParseFixedError> {
F::wrapping_from_str_octal(src).map(Wrapping)
}
/// Converts a string slice containing hexadecimal digits to a fixed-point number.
///
/// # Examples
///
/// ```rust
/// use fixed::{types::I8F8, Wrapping};
/// let check = Wrapping(I8F8::from_bits(0xFFE));
/// assert_eq!(Wrapping::<I8F8>::wrapping_from_str_hex("C0F.FE"), Ok(check));
/// ```
#[inline]
pub fn wrapping_from_str_hex(src: &str) -> Result<Self, ParseFixedError> {
F::wrapping_from_str_hex(src).map(Wrapping)
}
/// Wrapping ceil. Rounds to the next integer towards +∞, wrapping
/// on overflow.
///