我的程序中有一对相关的结构Rom
和ProfiledRom
。它们都存储u8
值的列表,并实现一个公共特征GetRom
,以提供对这些值的访问。
trait GetRom {
fn get(&self, index: usize) -> u8;
}
区别在于Rom
仅包装了一个简单的Vec<u8>
,但是ProfiledRom
将每个字节包装为ProfiledByte
类型,该类型计算{ {1}}。
get
我的大部分程序都在struct Rom(Vec<u8>);
struct ProfiledRom(Vec<ProfiledByte>);
struct ProfiledByte {
value: u8;
get_count: u32;
};
值上运行,因此我可以根据是否要进行概要分析来替换trait GetRom
或Rom
类型/值。
我实现了ProfiledRom
,因为将From<Rom> for ProfiledRom
转换为Rom
仅涉及将每个字节包装在新的ProfiledRom
中:这是一种简单且无损的操作。
但是,我不确定实现ProfiledByte
是否合适,因为From<ProfiledRom> for Rom
包含无法在ProfiledRom
中表示的信息(获取计数)。如果进行往返转换,这些值将丢失/重置。
仅使用部分源对象时,实现Rom
特性是否合适?
我已经看到标准库没有实现From
之类的整数转换,因为这些转换可能导致字节被截断/丢失。但是,这似乎与我们这里的情况有些不同。
使用可能会被截断的整数转换,您需要检查原始的From<i64> for i32
才能知道它是否将被适当地转换。否则,当您获得超出范围的值时,行为或代码可能会意外更改。但是,在上述情况下,始终会静态清除正在保留哪些数据以及正在丢失哪些数据。转换的行为不会突然改变。它应该更安全,但是可以适当使用i64
特性吗?
答案 0 :(得分:2)
From
实现通常是无损的,但目前尚无严格要求。
rust-lang/rfcs#2484正在进行的讨论是相关的。一些可能性包括添加FromLossy
特征和更准确地规定From
的行为。我们将不得不去看看。
请考虑一下,这是标准库中的一些Target::from(Source)
实现:
每个Source
值都转换为一个不同的Target
值。
u16::from(u8)
,i16::from(u8)
和其他转换为严格更大的整数类型。
Vec<T>::from(BinaryHeap<T>)
OsString::from(String)
char::from(u8)
多个Source
值可以转换为相同的Target
值。
BinaryHeap<T>::from(Vec<T>)
失去了元素的顺序。 Box<[T]>::from(Vec<T>)
和Box<str>::from(String)
失去任何多余的容量。
Vec<T>::from(VecDeque<T>)
失去了.as_slices()
公开的元素内部拆分。