Ответ 1
On ToPrimitive
/FromPrimitive
RFC 369, Num Reform, заявляет:
В идеале все [...]
ToPrimitive
[...] должны быть удалены в пользу более принципиального способа работы с C-подобными перечислениями
В то же время, эти черты живут в ящике:
Работа без черт
От типа, который полностью вписывается в другой
Здесь нет проблем. Используйте From
чтобы указать, что потери не происходят:
fn example(v: i8) -> i32 {
i32::from(v) // or v.into()
}
Вы можете использовать as
, но рекомендуется избегать этого, когда вам это не нужно (см. Ниже):
fn example(v: i8) -> i32 {
v as i32
}
От типа, который не вписывается полностью в другой
Нет единого метода, который имеет общий смысл - вы спрашиваете, как разместить две вещи в пространстве, предназначенном для одной. Одна хорошая первоначальная попытка состоит в том, чтобы использовать Option
- Some
когда значение подходит, и None
противном случае. Затем вы можете потерпеть неудачу в вашей программе или заменить значение по умолчанию, в зависимости от ваших потребностей.
Начиная с Rust 1.34, вы можете использовать TryFrom
:
use std::convert::TryFrom;
fn example(v: i32) -> Option<i8> {
i8::try_from(v).ok()
}
Перед этим вам придется написать подобный код самостоятельно:
fn example(v: i32) -> Option<i8> {
if v > std::i8::MAX as i32 {
None
} else {
Some(v as i8)
}
}
Что as
делает
но
4294967296us as u32
будет тихо переполнен и даст результат 0
При преобразовании в меньший тип, так as
просто принимает младшие биты числа, игнорируя старшие биты, включая знак:
fn main() {
let a: u16 = 0x1234;
let b: u8 = a as u8;
println!("0x{:04x}, 0x{:02x}", a, b); // 0x1234, 0x34
let a: i16 = -257;
let b: u8 = a as u8;
println!("0x{:02x}, 0x{:02x}", a, b); // 0xfeff, 0xff
}