#![allow(unused_unsafe)]
use crate::{syscall_hint_len, syscall_hint_read, syscall_write};
use serde::{de::DeserializeOwned, Serialize};
use std::{
alloc::Layout,
io::{Result, Write},
};
pub const FD_PUBLIC_VALUES: u32 = 3;
pub const FD_HINT: u32 = 4;
pub const FD_ECRECOVER_HOOK: u32 = 5;
struct SyscallWriter {
fd: u32,
}
impl Write for SyscallWriter {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
let nbytes = buf.len();
let write_buf = buf.as_ptr();
unsafe {
syscall_write(self.fd, write_buf, nbytes);
}
Ok(nbytes)
}
fn flush(&mut self) -> Result<()> {
Ok(())
}
}
pub fn read_vec() -> Vec<u8> {
let len = unsafe { syscall_hint_len() };
let capacity = (len + 3) / 4 * 4;
let layout = Layout::from_size_align(capacity, 4).expect("vec is too large");
let ptr = unsafe { std::alloc::alloc(layout) };
let mut vec = unsafe { Vec::from_raw_parts(ptr, 0, capacity) };
unsafe {
syscall_hint_read(ptr, len);
vec.set_len(len);
}
vec
}
pub fn read<T: DeserializeOwned>() -> T {
let vec = read_vec();
bincode::deserialize(&vec).expect("deserialization failed")
}
pub fn commit<T: Serialize>(value: &T) {
let writer = SyscallWriter { fd: FD_PUBLIC_VALUES };
bincode::serialize_into(writer, value).expect("serialization failed");
}
pub fn commit_slice(buf: &[u8]) {
let mut my_writer = SyscallWriter { fd: FD_PUBLIC_VALUES };
my_writer.write_all(buf).unwrap();
}
pub fn hint<T: Serialize>(value: &T) {
let writer = SyscallWriter { fd: FD_HINT };
bincode::serialize_into(writer, value).expect("serialization failed");
}
pub fn hint_slice(buf: &[u8]) {
let mut my_reader = SyscallWriter { fd: FD_HINT };
my_reader.write_all(buf).unwrap();
}
pub fn write(fd: u32, buf: &[u8]) {
SyscallWriter { fd }.write_all(buf).unwrap();
}