代码之家  ›  专栏  ›  技术社区  ›  fadedbee

如何获得对数组子集的有效可变引用?

  •  0
  • fadedbee  · 技术社区  · 3 年前

    这正如预期的那样:

    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 。(也许它指向一份副本?)

    即 低64 的前八个字节 缓冲器 在上面的例子中是不同的。

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

    (我的意图是,这也应该优化为在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,
    ]
    
    1 回复  |  直到 3 年前
        1
  •  5
  •   PitaJ    3 年前

    你需要包装 &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();