Rust 如何从文本字节表达式构造常量整数?
有没有一种方法可以从文本字节表达式构造Rust 如何从文本字节表达式构造常量整数?,rust,byte,constants,data-conversion,Rust,Byte,Constants,Data Conversion,有没有一种方法可以从文本字节表达式构造const整数,可以使用字节字符串或构造整数的宏 例如: const MY_ID: u16 = u16_code!(ID); const MY_WORD: u32 = u32_code!(WORD); const MY_LONG: u64 = u64_code!(LONGWORD); 或者类似的东西,传入b“ID”而不是ID* 当传递的字符数也错误时,它应该无法编译,这是我在对文本字节字符串使用位移位时无法理解的 下面是一个简单的示例,它可以在基本级
const
整数,可以使用字节字符串或构造整数的宏
例如:
const MY_ID: u16 = u16_code!(ID);
const MY_WORD: u32 = u32_code!(WORD);
const MY_LONG: u64 = u64_code!(LONGWORD);
或者类似的东西,传入b“ID”
而不是ID
*
当传递的字符数也错误时,它应该无法编译,这是我在对文本字节字符串使用位移位时无法理解的
下面是一个简单的示例,它可以在基本级别上工作,但无法确保参数大小正确
// const MY_ID: u16 = u16_code!(b"ID");
#[cfg(target_endian = "little")]
macro_rules! u16_code {
($w:expr) => { ((($w[0] as u16) << 0) | (($w[1] as u16) << 8)) }
}
#[cfg(target_endian = "big")]
macro_rules! u16_code {
($w:expr) => { ((($w[1] as u16) << 0) | (($w[0] as u16) << 8)) }
}
//const MY\u ID:u16=u16\u code!(b)“身份证”);
#[cfg(target_endian=“little”)]
宏规则!u16_码{
($w:expr)=>{(($w[0]作为u16)您可以通过索引到数组中并将部分位移到正确的位置来为每种类型构建宏
((b"ID"[0] as u16) << 8) | (b"ID"[1] as u16)
((b“ID”[0]为u16)根据@ker的建议,以下是基于固定大小字节字符串创建常量标识符的可移植宏:
警告:这些常量存在一些不明显的限制(见下面的注释)
以下宏支持:
const MY_ID: u16 = u16_code!(b"ID");
const MY_WORD: u32 = u32_code!(b"WORD");
const MY_LONG: u64 = u64_code!(b"LONGWORD");
实施:
#[cfg(target_endian = "little")]
#[macro_export]
macro_rules! u16_code {
($w:expr) => {
((($w[0] as u16) << 0) |
(($w[1] as u16) << 8) |
((*$w as [u8; 2])[0] as u16 * 0))
}
}
#[cfg(target_endian = "big")]
#[macro_export]
macro_rules! u16_code {
($w:expr) => {
((($w[1] as u16) << 0) |
(($w[0] as u16) << 8) |
((*$w as [u8; 2])[0] as u16 * 0))
}
}
#[cfg(target_endian = "little")]
#[macro_export]
macro_rules! u32_code {
($w:expr) => {
((($w[0] as u32) << 0) |
(($w[1] as u32) << 8) |
(($w[2] as u32) << 16) |
(($w[3] as u32) << 24) |
((*$w as [u8; 4])[0] as u32 * 0))
}
}
#[cfg(target_endian = "big")]
#[macro_export]
macro_rules! u32_code {
($w:expr) => {
((($w[3] as u32) << 0) |
(($w[2] as u32) << 8) |
(($w[1] as u32) << 16) |
(($w[0] as u32) << 24) |
((*$w as [u8; 4])[0] as u32 * 0))
}
}
#[cfg(target_endian = "little")]
#[macro_export]
macro_rules! u64_code {
($w:expr) => {
((($w[0] as u64) << 0) |
(($w[1] as u64) << 8) |
(($w[2] as u64) << 16) |
(($w[3] as u64) << 24) |
(($w[4] as u64) << 32) |
(($w[5] as u64) << 40) |
(($w[6] as u64) << 48) |
(($w[7] as u64) << 56) |
((*$w as [u8; 8])[0] as u64 * 0))
}
}
#[cfg(target_endian = "big")]
#[macro_export]
macro_rules! u64_code {
($w:expr) => {
((($w[7] as u64) << 0) |
(($w[6] as u64) << 8) |
(($w[5] as u64) << 16) |
(($w[4] as u64) << 24) |
(($w[3] as u64) << 32) |
(($w[2] as u64) << 40) |
(($w[1] as u64) << 48) |
(($w[0] as u64) << 56) |
((*$w as [u8; 8])[0] as u64 * 0))
}
}
我不知道如何在对文本字节字符串使用位移位时实现。请在您询问question@ker,我开始这样做,但随后将其中一个问题标记为“代码审阅”,我发现如果我发布示例代码,答案太多地集中在挑选幼稚的代码,而不是可能的,尤其是当我的方法一开始可能是错误的时候。尽管如此,我不介意发布示例。也许一个match
表达式而不是let
语句会起作用?match$w{w=>…}
与此上下文中几乎所有聪明的技巧一样,它给出了:错误[E0016]:常量中的块仅限于项和尾部表达式。如果将匹配
包装在块中,则会出现内部编译器错误(oops!)。然后我能想到的唯一解决方案是常量fn
(这是一个不稳定的特性),将表达式绑定到参数(并且const fn
还提供类型检查)。不幸的是,使用此方法创建的常量不能用作匹配语句中的值(导致错误E0080,请参阅我自己答案中的注释).正确,这是一个已经存在了一段时间的夜间功能。您可以打开RFC使其稳定。
error[E0080]: constant evaluation error
--> src/mod.rs:112:23
|
112 | const MY_DATA: u32 = u32_code!(b"DATA");
| ^^^^^^^^^^^^^^^^^^ the index operation on const values is unstable
|
note: for pattern here
--> src/mod.rs:224:13
|
224 | MY_DATA => {
| ^^^^^^^