【问题标题】:Slice of known compile-time size to array, infallibly已知编译时大小的切片到数组,无误
【发布时间】:2020-04-04 22:47:02
【问题描述】:
let some_datagram [u8; 8] = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
let a : &[u8; 2] = some_datagram[0..2];
let b : &[u8; 4] = some_datagram[2..6];
let c : &[u8; 2] = some_datagram[6..8];

上面的行不通,因为some_datagram[0..2]&[u8],而不是&[u8; 2]。这在使用其他类型的Range* 时非常有意义,因为在编译时开始/结束点是未知的。我知道有一个将TryInto 用于&[u8]&[u8; n] 的实现,但是由于这在编译时就已经知道了,所以我不得不处理我知道不可能发生的错误情况。

除了[] 之外还有其他方法可以返回一个固定大小的数组吗?可能是标准宏?

【问题讨论】:

  • “我不得不处理我知道不可能发生的错误情况”。这就是.unwrap.expect 的用途。由于编译器在何时允许转换方面存在不一致的规则,实际上没有任何其他方式可以表达这一点。
  • @Brian “真的没有任何其他方式可以表达这一点”,有,但它超级丑陋。 &[some_datagram[0], some_datagram[1]]&[u8; 2] - 但如果语言能给你一些语法糖就更好了。

标签: arrays rust slice


【解决方案1】:

array_macro crate 导出宏 array!,它允许使用对新数组索引的回调来构造数组。文档通过以下示例说明了这一点:

assert_eq!(array![|x| x; 3], [0, 1, 2]);

在您的情况下,您可以使用语句完成切片到数组的转换

let a : &[u8; 2] = array![|i| some_datagram[i    ]; 2];
let b : &[u8; 4] = array![|i| some_datagram[i + 2]; 4];
let c : &[u8; 2] = array![|i| some_datagram[i + 6]; 2];

这是否比使用标准的TryInto 实现和.unwrap 更具可读性是一个见仁见智的问题。由于这是第三方 crate,您还需要考虑到大多数阅读此代码的开发人员不一定熟悉 array! 宏的作用。

【讨论】:

  • 赞成,因为这是一个技术上可行的答案,但由于你提到的原因,我会通过。不幸的是,在实践中我需要[u8; 44],这超出了TryInto(目前)所支持的范围。
  • 最终找到了arrayref crate,它有一个array_ref!(array, start, end) 宏。直到rustc 增加了本地执行此操作的能力,这将是可行的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-11
  • 2015-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多