vtx_sdk/
stream.rs

1use crate::bindings::vtx::api::stream_io;
2use crate::bindings::vtx::api::stream_io::Buffer;
3use crate::error::{VtxError, VtxResult};
4use serde::de::DeserializeOwned;
5
6pub type StreamBuffer = Buffer;
7
8/// 通过宿主的 UUID 打开文件并返回 `Buffer` 资源句柄。
9pub fn open_file(uuid: &str) -> VtxResult<Buffer> {
10    stream_io::open_file(uuid).map_err(VtxError::from_host_message)
11}
12
13/// 创建一个内存 Buffer(通常用于构造 `HttpResponse.body`)。
14pub fn memory_buffer(data: impl AsRef<[u8]>) -> Buffer {
15    stream_io::create_memory_buffer(data.as_ref())
16}
17
18/// `Buffer` 资源的便捷扩展方法。
19pub trait BufferExt {
20    /// 读取整个 Buffer。
21    ///
22    /// - 对于 file/memory:使用 `size()` 做分块读取。
23    /// - 对于 pipe:会持续读取直到 EOF(返回空数组)或到达 `max_total_bytes`。
24    fn read_all(&self) -> Vec<u8>;
25
26    /// 按 UTF-8 读取整个 Buffer。
27    fn read_to_string(&self) -> VtxResult<String>;
28
29    /// 将 Buffer 中的 JSON 反序列化为目标类型。
30    fn read_json<T: DeserializeOwned>(&self) -> VtxResult<T>;
31
32    /// 向 Buffer 追加写入(对文件:append;对 pipe:写入 stdin;对 memory:append)。
33    fn write_all(&self, data: impl AsRef<[u8]>) -> u64;
34}
35
36impl BufferExt for Buffer {
37    fn read_all(&self) -> Vec<u8> {
38        const CHUNK: u64 = 64 * 1024;
39        const MAX_TOTAL: usize = 64 * 1024 * 1024;
40
41        let mut out = Vec::new();
42
43        let total = self.size();
44        if total > 0 {
45            let mut offset = 0u64;
46            while offset < total && out.len() < MAX_TOTAL {
47                let to_read = std::cmp::min(CHUNK, total - offset);
48                let chunk = self.read(offset, to_read);
49                if chunk.is_empty() {
50                    break;
51                }
52                out.extend_from_slice(&chunk);
53                offset += chunk.len() as u64;
54            }
55            return out;
56        }
57
58        // Pipe 模式:不知道 size,读到空为止(EOF)。
59        while out.len() < MAX_TOTAL {
60            let chunk = self.read(0, CHUNK);
61            if chunk.is_empty() {
62                break;
63            }
64            out.extend_from_slice(&chunk);
65        }
66
67        out
68    }
69
70    fn read_to_string(&self) -> VtxResult<String> {
71        let bytes = self.read_all();
72        String::from_utf8(bytes).map_err(|e| VtxError::SerializationError(e.to_string()))
73    }
74
75    fn read_json<T: DeserializeOwned>(&self) -> VtxResult<T> {
76        let s = self.read_to_string()?;
77        serde_json::from_str(&s).map_err(|e| VtxError::SerializationError(e.to_string()))
78    }
79
80    fn write_all(&self, data: impl AsRef<[u8]>) -> u64 {
81        self.write(data.as_ref())
82    }
83}