use ckb_vm::{
Error, Memory, Register, SupportMachine, Syscalls,
registers::{A0, A1, A7},
};
#[derive(Clone)]
pub struct FileStream {
content: Vec<u8>,
offset: usize,
}
impl Default for FileStream {
fn default() -> Self {
Self { content: Default::default(), offset: 0 }
}
}
impl FileStream {
pub fn new(file_name: &str) -> Self {
let content = crate::arch::file_read(file_name).unwrap();
FileStream { content, offset: 0 }
}
fn read(&mut self, buf: &mut [u8]) -> isize {
if self.offset >= self.content.len() {
return -1;
}
let remaining_size = self.content.len() - self.offset;
let read_size = std::cmp::min(buf.len(), remaining_size);
buf[0..read_size].copy_from_slice(&self.content[self.offset..self.offset + read_size]);
self.offset += read_size;
read_size as isize
}
}
impl<Mac: SupportMachine> Syscalls<Mac> for FileStream {
fn initialize(&mut self, _machine: &mut Mac) -> Result<(), Error> {
Ok(())
}
fn ecall(&mut self, machine: &mut Mac) -> Result<bool, Error> {
let id = machine.registers()[A7].to_u64();
if id != 9000 {
return Ok(false);
}
let arg_buf = machine.registers()[A0].to_u64();
let arg_count = machine.registers()[A1].to_u64();
let mut buf = vec![0u8; arg_count as usize];
let read_size = self.read(&mut buf);
if read_size > 0 {
machine.memory_mut().store_bytes(arg_buf, &buf[0..read_size as usize])?;
machine.set_register(A0, Mac::REG::from_u64(read_size as u64));
} else {
machine.set_register(A0, Mac::REG::from_i64(-1));
}
return Ok(true);
}
}