about summary refs log tree commit diff
path: root/library/std/src/sys/stdio
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-09-25 14:03:21 +0000
committerbors <bors@rust-lang.org>2025-09-25 14:03:21 +0000
commit6f34f4ee074ce0affc7bbf4e2c835f66cd576f13 (patch)
treeaede93bdb1c46b7be634690e6fe75c8160e124a2 /library/std/src/sys/stdio
parent7cfd7d328b14b936c7ffede92cacebe8557c6388 (diff)
parent59866ef3058654a81a44e2869d6647d8ba39c0fe (diff)
downloadrust-6f34f4ee074ce0affc7bbf4e2c835f66cd576f13.tar.gz
rust-6f34f4ee074ce0affc7bbf4e2c835f66cd576f13.zip
Auto merge of #147019 - Zalathar:rollup-boxzbmo, r=Zalathar
Rollup of 14 pull requests

Successful merges:

 - rust-lang/rust#145067 (RawVecInner: add missing `unsafe` to unsafe fns)
 - rust-lang/rust#145277 (Do not materialise X in [X; 0] when X is unsizing a const)
 - rust-lang/rust#145973 (Add `std` support for `armv7a-vex-v5`)
 - rust-lang/rust#146667 (Add an attribute to check the number of lanes in a SIMD vector after monomorphization)
 - rust-lang/rust#146735 (unstably constify float mul_add methods)
 - rust-lang/rust#146737 (f16_f128: enable some more tests in Miri)
 - rust-lang/rust#146766 (Add attributes for #[global_allocator] functions)
 - rust-lang/rust#146905 (llvm: update remarks support on LLVM 22)
 - rust-lang/rust#146982 (Remove erroneous normalization step in `tests/run-make/linker-warning`)
 - rust-lang/rust#147005 (Small string formatting cleanup)
 - rust-lang/rust#147007 (Explicitly note `&[SocketAddr]` impl of `ToSocketAddrs`)
 - rust-lang/rust#147008 (bootstrap.py: Respect build.jobs while building bootstrap tool)
 - rust-lang/rust#147013 (rustdoc: Fix documentation for `--doctest-build-arg`)
 - rust-lang/rust#147015 (Use `LLVMDisposeTargetMachine`)

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'library/std/src/sys/stdio')
-rw-r--r--library/std/src/sys/stdio/mod.rs4
-rw-r--r--library/std/src/sys/stdio/vexos.rs100
2 files changed, 104 insertions, 0 deletions
diff --git a/library/std/src/sys/stdio/mod.rs b/library/std/src/sys/stdio/mod.rs
index 7436e4d9de4..404ac877926 100644
--- a/library/std/src/sys/stdio/mod.rs
+++ b/library/std/src/sys/stdio/mod.rs
@@ -29,6 +29,10 @@ cfg_select! {
         mod uefi;
         pub use uefi::*;
     }
+    target_os = "vexos" => {
+        mod vexos;
+        pub use vexos::*;
+    }
     all(target_os = "wasi", target_env = "p1") => {
         mod wasip1;
         pub use wasip1::*;
diff --git a/library/std/src/sys/stdio/vexos.rs b/library/std/src/sys/stdio/vexos.rs
new file mode 100644
index 00000000000..1f2251c6421
--- /dev/null
+++ b/library/std/src/sys/stdio/vexos.rs
@@ -0,0 +1,100 @@
+use crate::io;
+
+pub struct Stdin;
+pub struct Stdout;
+pub type Stderr = Stdout;
+
+pub const STDIO_CHANNEL: u32 = 1;
+
+impl Stdin {
+    pub const fn new() -> Stdin {
+        Stdin
+    }
+}
+
+impl io::Read for Stdin {
+    fn read(&mut self, mut buf: &mut [u8]) -> io::Result<usize> {
+        let mut count = 0;
+
+        for out_byte in buf.iter_mut() {
+            let byte = unsafe { vex_sdk::vexSerialReadChar(STDIO_CHANNEL) };
+            if byte < 0 {
+                break;
+            }
+
+            *out_byte = byte as u8;
+            count += 1;
+        }
+
+        Ok(count)
+    }
+}
+
+impl Stdout {
+    pub const fn new() -> Stdout {
+        Stdout
+    }
+}
+
+impl io::Write for Stdout {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        let mut written = 0;
+
+        // HACK: VEXos holds an internal ringbuffer for serial writes that is flushed to USB1
+        // roughly every millisecond by `vexTasksRun`. For writes larger than 2048 bytes, we
+        // must block until that buffer is flushed to USB1 before writing the rest of `buf`.
+        //
+        // This is fairly nonstandard for a `write` implementation, but it avoids a guaranteed
+        // recursive panic when using macros such as `print!` to write large amounts of data
+        // (buf.len() > 2048) to stdout at once.
+        for chunk in buf.chunks(STDOUT_BUF_SIZE) {
+            if unsafe { vex_sdk::vexSerialWriteFree(STDIO_CHANNEL) as usize } < chunk.len() {
+                self.flush().unwrap();
+            }
+
+            let count: usize = unsafe {
+                vex_sdk::vexSerialWriteBuffer(STDIO_CHANNEL, chunk.as_ptr(), chunk.len() as u32)
+            }
+            .try_into()
+            .map_err(|_| {
+                io::const_error!(io::ErrorKind::Uncategorized, "internal write error occurred")
+            })?;
+
+            written += count;
+
+            // This is a sanity check to ensure that we don't end up with non-contiguous
+            // buffer writes. e.g. a chunk gets only partially written, but we continue
+            // attempting to write the remaining chunks.
+            //
+            // In practice, this should never really occur since the previous flush ensures
+            // enough space in FIFO to write the entire chunk to vexSerialWriteBuffer.
+            if count != chunk.len() {
+                break;
+            }
+        }
+
+        Ok(written)
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        // This may block for up to a millisecond.
+        unsafe {
+            while (vex_sdk::vexSerialWriteFree(STDIO_CHANNEL) as usize) != STDOUT_BUF_SIZE {
+                vex_sdk::vexTasksRun();
+            }
+        }
+
+        Ok(())
+    }
+}
+
+pub const STDIN_BUF_SIZE: usize = 4096;
+pub const STDOUT_BUF_SIZE: usize = 2048;
+
+pub fn is_ebadf(_err: &io::Error) -> bool {
+    false
+}
+
+pub fn panic_output() -> Option<impl io::Write> {
+    Some(Stdout::new())
+}