flashdb_rs/kvdb/
reader.rs

1use crate::{fdb_blob_make_by, fdb_blob_read, Error, RawHandle};
2use embedded_storage::nor_flash::NorFlash;
3
4use super::{KVEntry, KVDB};
5
6/// KV值读取器
7///
8/// 实现了embedded-io的Read和Seek trait,用于流式读取KV值,适合处理大型数据
9/// 生命周期`'a`确保读取器不会超过其关联的KVDB实例的生命周期
10pub struct KVReader<'a, S: NorFlash> {
11    position: usize,        // 当前读取位置
12    inner: &'a mut KVDB<S>, // 指向KVDB实例的指针
13    pub entry: KVEntry,     // KV对象元数据
14}
15
16impl<'a, S: NorFlash> KVReader<'a, S> {
17    pub fn new(kvdb: &'a mut KVDB<S>, entry: KVEntry) -> Self {
18        return Self {
19            inner: kvdb,
20            entry: entry,
21            position: 0,
22        };
23    }
24}
25
26impl<'a, S: NorFlash> embedded_io::ErrorType for KVReader<'a, S> {
27    type Error = Error;
28}
29
30impl<'a, S: NorFlash> embedded_io::Read for KVReader<'a, S> {
31    /// 从KV值中读取数据到缓冲区
32    ///
33    /// # 参数
34    /// - `buf`: 接收数据的缓冲区
35    ///
36    /// # 返回值
37    /// 成功时返回读取的字节数,失败时返回Error
38    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
39        if self.position >= self.entry.value_len() {
40            return Ok(0); // EOF
41        }
42        let mut blob = fdb_blob_make_by(buf, &self.entry, self.position);
43        let read_len = unsafe { fdb_blob_read(self.inner.handle() as *mut _, &mut blob) };
44        self.position += read_len;
45        Ok(read_len)
46    }
47}
48
49impl<'a, S: NorFlash> embedded_io::Seek for KVReader<'a, S> {
50    /// 调整读取位置
51    ///
52    /// # 参数
53    /// - `pos`: 要定位的位置,支持从开始、当前位置或末尾偏移
54    ///
55    /// # 返回值
56    /// 成功时返回新的位置,失败时返回Error
57    fn seek(&mut self, pos: embedded_io::SeekFrom) -> Result<u64, Self::Error> {
58        let total_len = self.entry.value_len();
59        // 根据SeekFrom计算新位置
60        let new_pos = match pos {
61            embedded_io::SeekFrom::Start(offset) => offset as usize,
62            embedded_io::SeekFrom::End(offset) => (total_len as i64 + offset) as usize,
63            embedded_io::SeekFrom::Current(offset) => (self.position as i64 + offset) as usize,
64        };
65
66        // 检查新位置是否有效
67        if new_pos > total_len {
68            return Err(Error::InvalidArgument);
69        }
70
71        self.position = new_pos;
72        Ok(new_pos as u64)
73    }
74}