corevm_guest/rust.rs
1//! Rust wrappers around C API.
2
3#![allow(clippy::missing_safety_doc)]
4
5use crate::c;
6use core::mem::size_of_val;
7
8/// Get the current amount of gas.
9#[inline]
10pub fn gas() -> u64 {
11 unsafe { c::gas() }
12}
13
14/// Allocate memory block of the specified size.
15///
16/// - The size is rounded up to the next multiple of page size.
17/// - The returned address is aligned at a page boundary.
18///
19/// Returns the pointer to the allocated memory region or [`null_mut()`](core::ptr::null_mut) if the
20/// allocation was unsuccessful.
21#[inline]
22pub unsafe fn alloc(size: u64) -> *mut u8 {
23 c::alloc(size) as *mut u8
24}
25
26/// Deallocate the memory block of the specified size starting at `address`.
27///
28/// Deallocates *all* the pages that overlap the memory block.
29#[inline]
30pub unsafe fn free(address: *mut u8, size: u64) {
31 c::free(address as u64, size)
32}
33
34/// Console stream type.
35#[derive(Debug, Clone, Copy, PartialEq, Eq)]
36pub enum ConsoleStream {
37 /// Standard output stream.
38 Stdout = 1,
39 /// Standard error stream.
40 Stderr = 2,
41}
42
43/// Append `text` to the specified _console_ output stream.
44pub fn yield_console_data(stream: ConsoleStream, text: &str) {
45 let bytes = text.as_bytes();
46 let len = bytes.len() as u64;
47 // Automatically retry host-call on reaching the output limit.
48 loop {
49 let ret = unsafe { c::yield_console_data(stream as u64, bytes.as_ptr() as u64, len) };
50 if ret == 0 {
51 break;
52 }
53 }
54}
55
56/// Append video frame to the _video_ output stream.
57///
58/// Frame format is defined by [`video_mode`](crate::video_mode).
59pub fn yield_video_frame<S: AsRef<[T]>, T: Sized>(frame: S) {
60 let frame = frame.as_ref();
61 let address = frame.as_ptr() as u64;
62 let len = size_of_val(frame) as u64;
63 // Automatically retry host-call on reaching the output limit.
64 loop {
65 let ret = unsafe { c::yield_video_frame(address, len) };
66 if ret == 0 {
67 break;
68 }
69 }
70}
71
72/// Set video monitor output mode to `mode`.
73#[inline]
74pub fn video_mode(mode: &VideoMode) {
75 unsafe {
76 c::video_mode(
77 mode.width as u64,
78 mode.height as u64,
79 mode.refresh_rate as u64,
80 mode.format as u64,
81 )
82 }
83}
84
85/// Video monitor output mode.
86pub struct VideoMode {
87 /// Frame width.
88 pub width: u32,
89 /// Frame height.
90 pub height: u32,
91 /// Monitor refresh rate (frames per second).
92 pub refresh_rate: u16,
93 /// Frame encoding.
94 pub format: VideoFrameFormat,
95}
96
97/// The format of the frames emitted via [`yield_video_frame`].
98#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
99pub enum VideoFrameFormat {
100 /// Indexed RGB colors.
101 ///
102 /// Format: `[ has_palette(1) | palette(256*3) | frame(width*height) ]`.
103 ///
104 /// Each frame starts with `has_palette` flag that defines whether the pallete is present or
105 /// not. `0` means the palette is not present and one should use the palette from the previous
106 /// frames. It is an error to transmit the first frame without a palette. `1` means the palette
107 /// is present.
108 ///
109 /// The pallete has 256 colors and each color has 3 components. Each color in the
110 /// palette is encoded as a sequence of red, green, blue components, each component occupies 8
111 /// bits.
112 ///
113 /// The frame itself goes after the pallete. It is encoded as a sequence of 8-bit indices into
114 /// the palette in row-major order, there are `width * height` indices in total.
115 Rgb888Indexed8 = 1,
116}