use alloc::vec::Vec;
#[cfg(target_os = "zkvm")]
use core::alloc::Layout;
use core::fmt::Write;
#[cfg(target_os = "zkvm")]
use openvm_rv32im_guest::{hint_buffer_chunked, hint_input, hint_store_u32};
use serde::de::DeserializeOwned;
#[cfg(not(target_os = "zkvm"))]
use crate::host::{hint_input, read_n_bytes, read_u32};
use crate::serde::Deserializer;
mod read;
pub use openvm_platform::print::{print, println};
pub fn read_vec() -> Vec<u8> {
hint_input();
read_vec_by_len(read_u32() as usize)
}
pub fn read<T: DeserializeOwned>() -> T {
let reader = read::Reader::new();
let mut deserializer = Deserializer::new(reader);
T::deserialize(&mut deserializer).unwrap()
}
#[cfg(target_os = "zkvm")]
#[inline(always)]
#[allow(asm_sub_register)]
pub fn read_u32() -> u32 {
let ptr = unsafe { alloc::alloc::alloc(Layout::from_size_align(4, 4).unwrap()) };
let addr = ptr as u32;
hint_store_u32!(addr);
let result: u32;
unsafe {
core::arch::asm!("lw {rd}, ({rs1})", rd = out(reg) result, rs1 = in(reg) addr);
}
result
}
fn hint_store_word(ptr: *mut u32) {
#[cfg(target_os = "zkvm")]
hint_store_u32!(ptr);
#[cfg(not(target_os = "zkvm"))]
unsafe {
*ptr = crate::host::read_u32();
}
}
pub(crate) fn read_vec_by_len(len: usize) -> Vec<u8> {
let num_words = len.div_ceil(4);
let capacity = num_words.checked_mul(4).expect("hint length overflow");
#[cfg(target_os = "zkvm")]
{
let mut bytes = Vec::with_capacity(capacity);
hint_buffer_chunked(bytes.as_mut_ptr(), num_words as usize);
unsafe {
bytes.set_len(len);
}
bytes
}
#[cfg(not(target_os = "zkvm"))]
{
let mut buffer = Vec::with_capacity(capacity);
buffer.append(&mut read_n_bytes(len));
buffer
}
}
pub fn reveal_bytes32(bytes: [u8; 32]) {
for (i_u32, chunk) in bytes.chunks_exact(4).enumerate() {
let x = u32::from_le_bytes(chunk.try_into().unwrap());
reveal_u32(x, i_u32);
}
}
#[allow(unused_variables)]
#[inline(always)]
pub fn reveal_u32(x: u32, index: usize) {
let byte_index = (index * 4) as u32;
#[cfg(target_os = "zkvm")]
openvm_rv32im_guest::reveal!(byte_index, x, 0);
#[cfg(all(not(target_os = "zkvm"), feature = "std"))]
println!("reveal {} at byte location {}", x, index * 4);
}
pub struct Writer;
impl Write for Writer {
fn write_str(&mut self, s: &str) -> core::fmt::Result {
print(s);
Ok(())
}
}