#转换 #近似 #转换 # #

conv

此软件包提供了一些转换特性,其语义比 'as' 或 'From'/'Into' 提供的更具体。

7 个版本

使用旧的 Rust 2015

0.3.3 2016 年 3 月 30 日
0.3.2 2016 年 3 月 14 日
0.3.1 2015 年 11 月 30 日
0.3.0 2015 年 10 月 13 日
0.1.0 2015 年 8 月 7 日

#801 in Rust 模式

Download history 28939/week @ 2024-03-14 28569/week @ 2024-03-21 22277/week @ 2024-03-28 21682/week @ 2024-04-04 22494/week @ 2024-04-11 22872/week @ 2024-04-18 22392/week @ 2024-04-25 23163/week @ 2024-05-02 26080/week @ 2024-05-09 33683/week @ 2024-05-16 35098/week @ 2024-05-23 44024/week @ 2024-05-30 37963/week @ 2024-06-06 31334/week @ 2024-06-13 24402/week @ 2024-06-20 18401/week @ 2024-06-27

122,124 下载/月
用于 313 个软件包 (57 个直接)

MIT 许可证

77KB
1K SLoC

conv

此软件包提供了一些转换特性,其语义比 asFrom/Into 提供的更具体。

提供这些特性的目标是要更具体地说明泛型代码可以依赖的内容,以及提供对标准 From/Into 特性的合理自我描述替代方案。例如,虽然 T: From<U> 在泛型代码中可能成立,但这并没有说明这种转换代表了什么 类型 的转换。

此外,From/Into 并没有提供转换失败的功能,这意味着实现者可能需要在可能不合法的转换或崩溃之间进行选择;这两种选择在一般情况下都不吸引人。

链接

兼容性

conv 与 Rust 1.2 及更高版本兼容。

示例

# extern crate conv;
# use conv::*;
# fn main() {
// This *cannot* fail, so we can use `unwrap_ok` to discard the `Result`.
assert_eq!(u8::value_from(0u8).unwrap_ok(), 0u8);

// This *can* fail.  Specifically, it can overflow toward negative infinity.
assert_eq!(u8::value_from(0i8),     Ok(0u8));
assert_eq!(u8::value_from(-1i8),    Err(NegOverflow(-1)));

// This can overflow in *either* direction; hence the change to `RangeError`.
assert_eq!(u8::value_from(-1i16),   Err(RangeError::NegOverflow(-1)));
assert_eq!(u8::value_from(0i16),    Ok(0u8));
assert_eq!(u8::value_from(256i16),  Err(RangeError::PosOverflow(256)));

// We can use the extension traits to simplify this a little.
assert_eq!(u8::value_from(-1i16).unwrap_or_saturate(),  0u8);
assert_eq!(u8::value_from(0i16).unwrap_or_saturate(),   0u8);
assert_eq!(u8::value_from(256i16).unwrap_or_saturate(), 255u8);

// Obviously, all integers can be "approximated" using the default scheme (it
// doesn't *do* anything), but they can *also* be approximated with the
// `Wrapping` scheme.
assert_eq!(
    <u8 as ApproxFrom<_, DefaultApprox>>::approx_from(400u16),
    Err(PosOverflow(400)));
assert_eq!(
    <u8 as ApproxFrom<_, Wrapping>>::approx_from(400u16),
    Ok(144u8));

// This is rather inconvenient; as such, there are a number of convenience
// extension methods available via `ConvUtil` and `ConvAsUtil`.
assert_eq!(400u16.approx(),                       Err::<u8, _>(PosOverflow(400)));
assert_eq!(400u16.approx_by::<Wrapping>(),        Ok::<u8, _>(144u8));
assert_eq!(400u16.approx_as::<u8>(),              Err(PosOverflow(400)));
assert_eq!(400u16.approx_as_by::<u8, Wrapping>(), Ok(144));

// Integer -> float conversions *can* fail due to limited precision.
// Once the continuous range of exactly representable integers is exceeded, the
// provided implementations fail with overflow errors.
assert_eq!(f32::value_from(16_777_216i32), Ok(16_777_216.0f32));
assert_eq!(f32::value_from(16_777_217i32), Err(RangeError::PosOverflow(16_777_217)));

// Float -> integer conversions have to be done using approximations.  Although
// exact conversions are *possible*, "advertising" this with an implementation
// is misleading.
//
// Note that `DefaultApprox` for float -> integer uses whatever rounding
// mode is currently active (*i.e.* whatever `as` would do).
assert_eq!(41.0f32.approx(), Ok(41u8));
assert_eq!(41.3f32.approx(), Ok(41u8));
assert_eq!(41.5f32.approx(), Ok(41u8));
assert_eq!(41.8f32.approx(), Ok(41u8));
assert_eq!(42.0f32.approx(), Ok(42u8));

assert_eq!(255.0f32.approx(), Ok(255u8));
assert_eq!(256.0f32.approx(), Err::<u8, _>(FloatError::PosOverflow(256.0)));

// Sometimes, it can be useful to saturate the conversion from float to
// integer directly, then account for NaN as input separately.  The `Saturate`
// extension trait exists for this reason.
assert_eq!((-23.0f32).approx_as::<u8>().saturate(), Ok(0));
assert_eq!(302.0f32.approx_as::<u8>().saturate(), Ok(255u8));
assert!(std::f32::NAN.approx_as::<u8>().saturate().is_err());

// If you really don't care about the specific kind of error, you can just rely
// on automatic conversion to `GeneralErrorKind`.
fn too_many_errors() -> Result<(), GeneralErrorKind> {
    assert_eq!({let r: u8 = try!(0u8.value_into()); r},  0u8);
    assert_eq!({let r: u8 = try!(0i8.value_into()); r},  0u8);
    assert_eq!({let r: u8 = try!(0i16.value_into()); r}, 0u8);
    assert_eq!({let r: u8 = try!(0.0f32.approx()); r},   0u8);
    Ok(())
}
# let _ = too_many_errors();
# }

变更日志

v0.3.2

  • 添加了整数 ↔ char 转换。
  • 添加了缺失的 isize/usizef32/f64 转换。
  • 修复了 64 位目标上 i64usize 的错误类型。

v0.3.1

  • unwrap_ok 修改为更好的代码生成(感谢 bluss)。
  • 修复 Rust 破坏性变更(有问题的代码本身也不太对;感谢 m4rw3r)。

v0.3.0

  • 为所有 Err 关联类型添加了 Error 约束。这将破坏任何用户定义的转换,其中 Err 类型没有实现 Error
  • 已将 OverflowUnderflow 错误分别重命名为 PosOverflowNegOverflow。在浮点数转换的上下文中,“下溢”通常意味着值太接近零,无法正确表示。

v0.2.1

  • 添加了 ConvUtil::into_as<Dst> 作为 Into::<Dst>::into 的快捷方式。
  • 添加了 #[inline] 属性。
  • 添加了 Saturate::saturate,它可以饱和来自溢出/下溢的 Result

v0.2.0

  • 将所有错误类型更改为包含原始输入作为有效负载。这几乎破坏了所有东西。对此表示歉意。从积极的一面来看,现在使用非 Copy 类型的转换特性没有任何缺点。
  • 添加了浮点数到整数的近似值的标准舍入模式:RoundToNearestRoundToNegInfRoundToPosInfRoundToZero
  • ApproxWith 现在包含在一个扩展特性对 (ConvUtilConvAsUtil) 中,它还有 TryIntoValueInto 的快捷方式,这样您就可以在方法中指定目标类型。

依赖项