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

如何在Rust中的Arc<Vec>上创建游标(或其他Read+Seek对象)?

  •  0
  • PiotrK  · 技术社区  · 2 年前

    实际问题(为了避免A/B场景):

    我在Arc对象后面有一个很大的缓冲区:

    pub struct LargeData {
        data: Arc<Vec<u8>>,
    }
    

    我需要通过 Read + Seek 版本作为函数的Boxed返回到网络API(不复制整个缓冲区)。

    首先,我尝试将Cursor置于Vec之上:

    fn open_for_read(&self) -> io::Result<Box<dyn ReadAndSeek>> {
        Ok(Box::new(Cursor::new(self.data.as_ref())))
    }
    

    但是编译器正确地警告了这个游标实际上可能比所有ARC实例都要长寿。

    不过,我的第二个选择是把两者都打包 Cursor Arc 进入新的结构并实现 读取+搜索 为了它

    
    struct ReaderData {
        data: Arc<Vec<u8>>,
        cursor: Cursor<Vec<u8>>,
    }
    
    impl ReaderData {
        fn new(source: &LargeData) -> Self {
            let data = source.data.clone();
            Self {
                data,
                cursor: Cursor::new(data),
            }
        }
    }
    // Read + Seek implementation that only passes into cursor Read and Seek 
    

    但这次我犯了一个更神秘的错误:

    cursor: Cursor::new(data),
            ----------- ^^^^- help: try using a conversion method: `.to_vec()`
            |           |
            |           expected `Vec<u8>`, found `Arc<Vec<u8>>`
            arguments to this function are incorrect
    

    使用 to_vec() 会复制矢量,这是我想避免的。

    这是我放弃的地方。

    我是不是遗漏了什么?我该怎么做 读取+搜索 对象来自 Arc<Vec<u8>> ?

    1 回复  |  直到 2 年前
        1
  •  2
  •   Chayim Friedman    2 年前

    Cursor 需要实现的类型 AsRef<[u8]> . Arc<Vec<u8>> 不幸的是没有,但你可以自己实施 LargeData :

    #[derive(Clone)]
    pub struct LargeData {
        data: Arc<Vec<u8>>,
    }
    
    impl AsRef<[u8]> for LargeData {
        fn as_ref(&self) -> &[u8] {
            &self.data
        }
    }
    
    impl LargeData {
        fn open_for_read(&self) -> Cursor<LargeData> {
            Cursor::new(self.clone())
        }
    }
    

    如果 LargeData 包含其他字段,可以提取 弧形<Vec<u8>> 到不同的结构。