这与阅读时预期的工作方式相同:

fn u64_from_low_eight(buf: &[u8; 9]) -> u64 {
    let bytes: &[u8; size_of::<u64>()] = buf[..size_of::<u64>()].try_into().unwrap();
    u64::from_le_bytes(*bytes)
}

(它可以很好地优化为AArch64和x86_64上的单个汇编指令.)

我原以为U64对缓冲区的非对齐写入也能起到类似的作用.

/// Encodes a u64 into 1-9 bytes and returns the number of bytes updated.
pub fn encode(value: u64, buf: &mut [u8; 9]) -> usize {
    let low64: &mut [u8; size_of::<u64>()] = &mut buf[..(size_of::<u64>())].try_into().unwrap();

    match value {
        // FIXME: Change to exclusive ranges once the feature's stabilised.
        OFFSET0..=OFFSET1_LESS_ONE => {
            let num = inner_encode::<1>(value, low64);
            #[cfg(test)] eprintln!("low64: {low64:?}");
            #[cfg(test)] eprintln!("buf: {buf:?}");

            num
        },

low64(上图)似乎不是对buf的前八个字节的可变引用.(也许它指的是副本?)

low64buf的前八个字节在上面的例子中是不同的.

我可以使用什么而不是let low64: &mut [u8; size_of::<u64>()] = &mut buf[..(size_of::<u64>())].try_into().unwrap();来获得指向&mut [u8; 9]的前八个字节的&mut [u8; 8]

(我的意图是,这也应该优化为AArch64和x86_64上的单个未对齐写入.)


更新:操场上的问题是:https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=294a9dd9ba1400eceb2d945a10028a6b

use std::mem::size_of;

fn u64_to_low_eight(value: u64, buf: &mut [u8; 9]) {
    let low64: &mut [u8; size_of::<u64>()] = &mut buf[..size_of::<u64>()].try_into().unwrap();
    *low64 = u64::to_le_bytes(value);    
    dbg!(low64);
}

fn main() {
    let mut src: [u8; 9] = [1, 2, 3, 4, 5, 6, 7, 8, 9];
    u64_to_low_eight(0x0A_0B_0C_0D_0E_0F_10_11, &mut src);
    dbg!(src);
}

以及输出,我希望src也能更改:

   Compiling playground v0.0.1 (/playground)
    Finished dev [unoptimized + debuginfo] target(s) in 0.62s
     Running `target/debug/playground`
[src/main.rs:6] low64 = [
    17,
    16,
    15,
    14,
    13,
    12,
    11,
    10,
]
[src/main.rs:12] src = [
    1,
    2,
    3,
    4,
    5,
    6,
    7,
    8,
    9,
]

推荐答案

你需要把&mut buf[..size_of::<u64>()]放在括号里.&mut是一个低优先级运算符,因此首先计算右侧的所有内容,使您的代码等同于:

// takes a mutable reference to those 8 copied bytes
let low64: &mut [u8; size_of::<u64>()] = &mut (
    // copies 8 bytes out of `buf`
    buf[..size_of::<u64>()].try_into().unwrap()
);

因此,您需要改为执行以下操作:

let low64: &mut [u8; size_of::<u64>()] = (&mut buf[..size_of::<u64>()]).try_into().unwrap();

Rust相关问答推荐

如何将元素添加到向量并返回对该元素的引用?

这个规则关于或模式到底是什么意思?如果表达片段的类型与p_i|q_i...&q;不一致,就会形成

如何定义实现同名但返回类型不同的 struct 的函数

如何向下转换到MyStruct并访问Arc Mutex MyStruct实现的方法?

为什么TcpListener的文件描述符和生成的TcpStream不同?

`RwLockWriteGuard_,T`不实现T实现的特征

在Rust中克隆源自INTO_ITER()的迭代器的成本?

实现 Deref 的 struct 可以返回对外部数据的引用吗?

Rust 如何将链表推到前面?

如何使用 Bincode 在 Rust 中序列化 Enum,同时保留 Enum 判别式而不是索引?

Rust typestate 模式:实现多个状态?

decltype、dyn、impl traits,重构时如何声明函数的返回类型

具有在宏扩展中指定的生命周期的枚举变体数据类型

类型判断模式匹配panic

返回引用字符串的future

`use std::error::Error` 声明中断编译

如何在 Rust 中编写涉及异步的重试函数

深度嵌套枚举的清洁匹配臂

制作嵌套迭代器的迭代器

使用 rust-sqlx/tokio 时如何取消长时间运行的查询