有没有一种好的方法可以从 Arc<String> 转换/转变为 Arc<Vec<u8>>

问题描述 投票:0回答:1

String
Vec<u8>
具有相同的内存布局,尽管不能保证这一点。

String 还有一个

into_bytes
方法返回
Vec<u8>

有没有一种好的方法可以从

Arc<String>
转换为
Arc<Vec<u8>>
而不为新的
Arc
分配任何内存?我们可以断言弧引用计数为1。我不介意使用unsafe。我也不介意断言它们具有相同的大小/在这种情况下回落到分配。这可能吗?

rust automatic-ref-counting unsafe
1个回答
0
投票

说了我在上面的评论中所做的事情,我实际上认为你完全可以通过

String::as_mut_vec
到达那里:

use static_assertions::{assert_eq_align, assert_eq_size};
use std::sync::Arc;

const _: () = {
    assert_eq_align!(String, Vec<u8>);
    assert_eq_size!(String, Vec<u8>);
};

pub unsafe fn convert(mut arc: Arc<String>) -> Arc<Vec<u8>> {
    Arc::get_mut(&mut arc).unwrap();

    let raw_string = Arc::into_raw(arc).cast_mut();

    // SAFETY: `get_mut...unwrap` above ensured that we have exclusive access
    let ref_string = unsafe { &mut *raw_string };

    // SAFETY: We do not modify the `Vec` before dropping `ref_string`
    let raw_vec = unsafe { ref_string.as_mut_vec() } as *const Vec<u8>;
    let _ = ref_string;

    assert_eq!(raw_vec.cast(), raw_string);

    // SAFETY: assertion above ensures that `raw_vec` points to the same memory
    //         as `raw_string`, and static assertions above guarantee that `String`
    //         has the same size and alignment as `Vec<u8>`
    unsafe { Arc::from_raw(raw_vec) }
}
© www.soinside.com 2019 - 2024. All rights reserved.