ic_stable_structures/
reader.rs1use crate::{Memory, WASM_PAGE_SIZE};
2use std::io;
3
4#[cfg(test)]
5mod tests;
6
7pub struct Reader<'a, M> {
11 offset: u64,
13
14 memory: &'a M,
16}
17
18#[derive(Debug)]
19pub struct OutOfBounds {
20 pub max_address: u64,
21 pub attempted_read_address: u64,
22}
23
24impl<'a, M: Memory> Reader<'a, M> {
25 pub fn new(memory: &'a M, offset: u64) -> Self {
27 Self { offset, memory }
28 }
29
30 pub fn read(&mut self, buf: &mut [u8]) -> Result<usize, OutOfBounds> {
32 let memory_end_addr = self.memory.size() * WASM_PAGE_SIZE;
33
34 let read_buf = if buf.len() as u64 + self.offset > memory_end_addr {
35 if self.offset < memory_end_addr {
36 let available_bytes = (memory_end_addr - self.offset) as usize;
38 &mut buf[..available_bytes]
39 } else {
40 return Err(OutOfBounds {
41 max_address: memory_end_addr,
42 attempted_read_address: self.offset,
43 });
44 }
45 } else {
46 buf
47 };
48
49 self.memory.read(self.offset, read_buf);
50 self.offset += read_buf.len() as u64;
51 Ok(read_buf.len())
52 }
53}
54
55impl<M: Memory> io::Read for Reader<'_, M> {
56 fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
57 self.read(buf).or(Ok(0)) }
59}
60
61pub struct BufferedReader<'a, M> {
63 inner: io::BufReader<Reader<'a, M>>,
64}
65
66impl<M: Memory> BufferedReader<'_, M> {
67 pub fn new(buffer_size: usize, reader: Reader<M>) -> BufferedReader<M> {
69 BufferedReader {
70 inner: io::BufReader::with_capacity(buffer_size, reader),
71 }
72 }
73}
74
75impl<M: Memory> io::Read for BufferedReader<'_, M> {
76 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
77 self.inner.read(buf)
78 }
79}