diff --git a/.cargo/config.toml b/.cargo/config.toml
index f072b50..41f20d6 100644
--- a/.cargo/config.toml
+++ b/.cargo/config.toml
@@ -3,10 +3,9 @@ target = "riscv64.json"
[unstable]
json-target-spec = true
-build-std = ["core", "compiler_builtins", "alloc"]
-build-std-features = ["compiler-builtins-mem"]
[target.riscv64]
rustflags = [
"-C", "link-arg=-Tilm.ld",
+ "--sysroot", "sysroot"
]
diff --git a/.gitignore b/.gitignore
index 55983a2..6ea937b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,5 @@
disk.img
**/*.mem
mnt
+
+sysroot/lib/rustlib/riscv64
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..22a9e10
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "library/backtrace"]
+ path = library/backtrace
+ url = https://github.com/rust-lang/backtrace-rs.git
diff --git a/Cargo.toml b/Cargo.toml
index 6895294..3840326 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,7 @@
[workspace]
resolver = "3"
-members = ["crates/bytes-struct","crates/io","crates/std", "crates/shared", "user/*"]
+members = [ "user/*"]
+exclude = ["library"]
[package]
name = "kernel-rust"
diff --git a/crates/bffs/src/lib.rs b/crates/bffs/src/lib.rs
index ba52fb0..1bd1a59 100644
--- a/crates/bffs/src/lib.rs
+++ b/crates/bffs/src/lib.rs
@@ -1,4 +1,5 @@
#![feature(iterator_try_collect, iter_order_by)]
+#![allow(unused_features)]
#![cfg_attr(any(not(feature = "std"), target_arch = "riscv64"), no_std)]
use core::cell::RefCell;
diff --git a/crates/kernel-macros/Cargo.toml b/crates/kernel-macros/Cargo.toml
index 5832c35..ae9e488 100644
--- a/crates/kernel-macros/Cargo.toml
+++ b/crates/kernel-macros/Cargo.toml
@@ -7,6 +7,6 @@ edition = "2024"
proc-macro = true
[dependencies]
-image = "0.25"
+image = { version = "0.25", default-features = false, features = ["png"] }
syn = { version = "2", features = ["full"] }
zyn = "0.5"
diff --git a/crates/os-std-macros/Cargo.toml b/crates/os-std-macros/Cargo.toml
deleted file mode 100644
index 77bc004..0000000
--- a/crates/os-std-macros/Cargo.toml
+++ /dev/null
@@ -1,12 +0,0 @@
-[package]
-name = "os-std-macros"
-version = "0.1.0"
-edition = "2024"
-
-[lib]
-proc-macro = true
-
-[dependencies]
-proc-macro2 = "1"
-quote = "1"
-syn = { version = "2", features = ["full"] }
diff --git a/crates/os-std-macros/src/lib.rs b/crates/os-std-macros/src/lib.rs
deleted file mode 100644
index 8b13789..0000000
--- a/crates/os-std-macros/src/lib.rs
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/crates/std/Cargo.toml b/crates/std/Cargo.toml
deleted file mode 100644
index 9d12f40..0000000
--- a/crates/std/Cargo.toml
+++ /dev/null
@@ -1,9 +0,0 @@
-[package]
-name = "std"
-version = "0.1.0"
-edition = "2024"
-
-[dependencies]
-os-std-macros = { path = "../os-std-macros" }
-shared = { path = "../shared", features = ["user"] }
-io = { path = "../io", features = ["alloc"] }
diff --git a/crates/std/src/ffi/c_str.rs b/crates/std/src/ffi/c_str.rs
deleted file mode 100644
index a7d1de4..0000000
--- a/crates/std/src/ffi/c_str.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//! [`CStr`], [`CString`], and related types.
-pub use alloc::ffi::c_str::FromVecWithNulError;
-pub use alloc::ffi::c_str::IntoStringError;
-pub use alloc::ffi::c_str::{CString, NulError};
-pub use core::ffi::c_str::CStr;
-pub use core::ffi::c_str::FromBytesUntilNulError;
-pub use core::ffi::c_str::FromBytesWithNulError;
diff --git a/crates/std/src/ffi/mod.rs b/crates/std/src/ffi/mod.rs
deleted file mode 100644
index 7f24b7b..0000000
--- a/crates/std/src/ffi/mod.rs
+++ /dev/null
@@ -1,184 +0,0 @@
-//! Utilities related to FFI bindings.
-//!
-//! This module provides utilities to handle data across non-Rust
-//! interfaces, like other programming languages and the underlying
-//! operating system. It is mainly of use for FFI (Foreign Function
-//! Interface) bindings and code that needs to exchange C-like strings
-//! with other languages.
-//!
-//! # Overview
-//!
-//! Rust represents owned strings with the [`String`] type, and
-//! borrowed slices of strings with the [`str`] primitive. Both are
-//! always in UTF-8 encoding, and may contain nul bytes in the middle,
-//! i.e., if you look at the bytes that make up the string, there may
-//! be a `\0` among them. Both `String` and `str` store their length
-//! explicitly; there are no nul terminators at the end of strings
-//! like in C.
-//!
-//! C strings are different from Rust strings:
-//!
-//! * **Encodings** - Rust strings are UTF-8, but C strings may use
-//! other encodings. If you are using a string from C, you should
-//! check its encoding explicitly, rather than just assuming that it
-//! is UTF-8 like you can do in Rust.
-//!
-//! * **Character size** - C strings may use `char` or `wchar_t`-sized
-//! characters; please **note** that C's `char` is different from Rust's.
-//! The C standard leaves the actual sizes of those types open to
-//! interpretation, but defines different APIs for strings made up of
-//! each character type. Rust strings are always UTF-8, so different
-//! Unicode characters will be encoded in a variable number of bytes
-//! each. The Rust type [`char`] represents a '[Unicode scalar
-//! value]', which is similar to, but not the same as, a '[Unicode
-//! code point]'.
-//!
-//! * **Nul terminators and implicit string lengths** - Often, C
-//! strings are nul-terminated, i.e., they have a `\0` character at the
-//! end. The length of a string buffer is not stored, but has to be
-//! calculated; to compute the length of a string, C code must
-//! manually call a function like `strlen()` for `char`-based strings,
-//! or `wcslen()` for `wchar_t`-based ones. Those functions return
-//! the number of characters in the string excluding the nul
-//! terminator, so the buffer length is really `len+1` characters.
-//! Rust strings don't have a nul terminator; their length is always
-//! stored and does not need to be calculated. While in Rust
-//! accessing a string's length is an *O*(1) operation (because the
-//! length is stored); in C it is an *O*(*n*) operation because the
-//! length needs to be computed by scanning the string for the nul
-//! terminator.
-//!
-//! * **Internal nul characters** - When C strings have a nul
-//! terminator character, this usually means that they cannot have nul
-//! characters in the middle — a nul character would essentially
-//! truncate the string. Rust strings *can* have nul characters in
-//! the middle, because nul does not have to mark the end of the
-//! string in Rust.
-//!
-//! # Representations of non-Rust strings
-//!
-//! [`CString`] and [`CStr`] are useful when you need to transfer
-//! UTF-8 strings to and from languages with a C ABI, like Python.
-//!
-//! * **From Rust to C:** [`CString`] represents an owned, C-friendly
-//! string: it is nul-terminated, and has no internal nul characters.
-//! Rust code can create a [`CString`] out of a normal string (provided
-//! that the string doesn't have nul characters in the middle), and
-//! then use a variety of methods to obtain a raw \*mut [u8] that can
-//! then be passed as an argument to functions which use the C
-//! conventions for strings.
-//!
-//! * **From C to Rust:** [`CStr`] represents a borrowed C string; it
-//! is what you would use to wrap a raw \*const [u8] that you got from
-//! a C function. A [`CStr`] is guaranteed to be a nul-terminated array
-//! of bytes. Once you have a [`CStr`], you can convert it to a Rust
-//! &[str] if it's valid UTF-8, or lossily convert it by adding
-//! replacement characters.
-//!
-//! [`OsString`] and [`OsStr`] are useful when you need to transfer
-//! strings to and from the operating system itself, or when capturing
-//! the output of external commands. Conversions between [`OsString`],
-//! [`OsStr`] and Rust strings work similarly to those for [`CString`]
-//! and [`CStr`].
-//!
-//! * [`OsString`] losslessly represents an owned platform string. However, this
-//! representation is not necessarily in a form native to the platform.
-//! In the Rust standard library, various APIs that transfer strings to/from the operating
-//! system use [`OsString`] instead of plain strings. For example,
-//! [`env::var_os()`] is used to query environment variables; it
-//! returns an [Option]<[OsString]>. If the environment variable
-//! exists you will get a [Some]\(os_string), which you can
-//! *then* try to convert to a Rust string. This yields a [`Result`], so that
-//! your code can detect errors in case the environment variable did
-//! not in fact contain valid Unicode data.
-//!
-//! * [`OsStr`] losslessly represents a borrowed reference to a platform string.
-//! However, this representation is not necessarily in a form native to the platform.
-//! It can be converted into a UTF-8 Rust string slice in a similar way to
-//! [`OsString`].
-//!
-//! # Conversions
-//!
-//! ## On Unix
-//!
-//! On Unix, [`OsStr`] implements the
-//! std::os::unix::ffi::[OsStrExt][unix.OsStrExt] trait, which
-//! augments it with two methods, [`from_bytes`] and [`as_bytes`].
-//! These do inexpensive conversions from and to byte slices.
-//!
-//! Additionally, on Unix [`OsString`] implements the
-//! std::os::unix::ffi::[OsStringExt][unix.OsStringExt] trait,
-//! which provides [`from_vec`] and [`into_vec`] methods that consume
-//! their arguments, and take or produce vectors of [`u8`].
-//!
-//! ## On Windows
-//!
-//! An [`OsStr`] can be losslessly converted to a native Windows string. And
-//! a native Windows string can be losslessly converted to an [`OsString`].
-//!
-//! On Windows, [`OsStr`] implements the
-//! std::os::windows::ffi::[OsStrExt][windows.OsStrExt] trait,
-//! which provides an [`encode_wide`] method. This provides an
-//! iterator that can be [`collect`]ed into a vector of [`u16`]. After a nul
-//! characters is appended, this is the same as a native Windows string.
-//!
-//! Additionally, on Windows [`OsString`] implements the
-//! std::os::windows:ffi::[OsStringExt][windows.OsStringExt]
-//! trait, which provides a [`from_wide`] method to convert a native Windows
-//! string (without the terminating nul character) to an [`OsString`].
-//!
-//! ## Other platforms
-//!
-//! Many other platforms provide their own extension traits in a
-//! `std::os::*::ffi` module.
-//!
-//! ## On all platforms
-//!
-//! On all platforms, [`OsStr`] consists of a sequence of bytes that is encoded as a superset of
-//! UTF-8; see [`OsString`] for more details on its encoding on different platforms.
-//!
-//! For limited, inexpensive conversions from and to bytes, see [`OsStr::as_encoded_bytes`] and
-//! [`OsStr::from_encoded_bytes_unchecked`].
-//!
-//! For basic string processing, see [`OsStr::slice_encoded_bytes`].
-//!
-//! [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value
-//! [Unicode code point]: https://www.unicode.org/glossary/#code_point
-//! [`env::set_var()`]: crate::env::set_var "env::set_var"
-//! [`env::var_os()`]: crate::env::var_os "env::var_os"
-//! [unix.OsStringExt]: crate::os::unix::ffi::OsStringExt "os::unix::ffi::OsStringExt"
-//! [`from_vec`]: crate::os::unix::ffi::OsStringExt::from_vec "os::unix::ffi::OsStringExt::from_vec"
-//! [`into_vec`]: crate::os::unix::ffi::OsStringExt::into_vec "os::unix::ffi::OsStringExt::into_vec"
-//! [unix.OsStrExt]: crate::os::unix::ffi::OsStrExt "os::unix::ffi::OsStrExt"
-//! [`from_bytes`]: crate::os::unix::ffi::OsStrExt::from_bytes "os::unix::ffi::OsStrExt::from_bytes"
-//! [`as_bytes`]: crate::os::unix::ffi::OsStrExt::as_bytes "os::unix::ffi::OsStrExt::as_bytes"
-//! [`OsStrExt`]: crate::os::unix::ffi::OsStrExt "os::unix::ffi::OsStrExt"
-//! [windows.OsStrExt]: crate::os::windows::ffi::OsStrExt "os::windows::ffi::OsStrExt"
-//! [`encode_wide`]: crate::os::windows::ffi::OsStrExt::encode_wide "os::windows::ffi::OsStrExt::encode_wide"
-//! [`collect`]: crate::iter::Iterator::collect "iter::Iterator::collect"
-//! [windows.OsStringExt]: crate::os::windows::ffi::OsStringExt "os::windows::ffi::OsStringExt"
-//! [`from_wide`]: crate::os::windows::ffi::OsStringExt::from_wide "os::windows::ffi::OsStringExt::from_wide"
-pub mod c_str;
-pub use core::ffi::c_void;
-pub use core::ffi::{VaArgSafe, VaList};
-pub use core::ffi::{
- c_char, c_double, c_float, c_int, c_long, c_longlong, c_schar, c_short, c_uchar, c_uint,
- c_ulong, c_ulonglong, c_ushort,
-};
-pub use core::ffi::{c_ptrdiff_t, c_size_t, c_ssize_t};
-
-#[doc(inline)]
-pub use self::c_str::FromBytesUntilNulError;
-#[doc(inline)]
-pub use self::c_str::FromBytesWithNulError;
-#[doc(inline)]
-pub use self::c_str::FromVecWithNulError;
-#[doc(inline)]
-pub use self::c_str::IntoStringError;
-#[doc(inline)]
-pub use self::c_str::NulError;
-#[doc(inline)]
-pub use self::c_str::{CStr, CString};
-// #[doc(inline)]
-// pub use self::os_str::{OsStr, OsString};
-pub mod os_str;
diff --git a/crates/std/src/ffi/os_str.rs b/crates/std/src/ffi/os_str.rs
deleted file mode 100644
index 2862f4f..0000000
--- a/crates/std/src/ffi/os_str.rs
+++ /dev/null
@@ -1,1661 +0,0 @@
-// //! The [`OsStr`] and [`OsString`] types and associated utilities.
-
-// #[cfg(test)]
-// mod tests;
-
-// use core::clone::CloneToUninit;
-
-// use crate::borrow::{Borrow, Cow};
-// use crate::collections::TryReserveError;
-// use crate::hash::{Hash, Hasher};
-// use crate::ops::{self, Range};
-// use crate::rc::Rc;
-// use crate::str::FromStr;
-// use crate::sync::Arc;
-// use crate::sys::os_str::{Buf, Slice};
-// use crate::sys::{AsInner, FromInner, IntoInner};
-// use crate::{cmp, fmt, slice};
-
-// /// A type that can represent owned, mutable platform-native strings, but is
-// /// cheaply inter-convertible with Rust strings.
-// ///
-// /// The need for this type arises from the fact that:
-// ///
-// /// * On Unix systems, strings are often arbitrary sequences of non-zero
-// /// bytes, in many cases interpreted as UTF-8.
-// ///
-// /// * On Windows, strings are often arbitrary sequences of non-zero 16-bit
-// /// values, interpreted as UTF-16 when it is valid to do so.
-// ///
-// /// * In Rust, strings are always valid UTF-8, which may contain zeros.
-// ///
-// /// `OsString` and [`OsStr`] bridge this gap by simultaneously representing Rust
-// /// and platform-native string values, and in particular allowing a Rust string
-// /// to be converted into an "OS" string with no cost if possible. A consequence
-// /// of this is that `OsString` instances are *not* `NUL` terminated; in order
-// /// to pass to e.g., Unix system call, you should create a [`CStr`].
-// ///
-// /// `OsString` is to &[OsStr] as [`String`] is to &[str]: the former
-// /// in each pair are owned strings; the latter are borrowed
-// /// references.
-// ///
-// /// Note, `OsString` and [`OsStr`] internally do not necessarily hold strings in
-// /// the form native to the platform; While on Unix, strings are stored as a
-// /// sequence of 8-bit values, on Windows, where strings are 16-bit value based
-// /// as just discussed, strings are also actually stored as a sequence of 8-bit
-// /// values, encoded in a less-strict variant of UTF-8. This is useful to
-// /// understand when handling capacity and length values.
-// ///
-// /// # Capacity of `OsString`
-// ///
-// /// Capacity uses units of UTF-8 bytes for OS strings which were created from valid unicode, and
-// /// uses units of bytes in an unspecified encoding for other contents. On a given target, all
-// /// `OsString` and `OsStr` values use the same units for capacity, so the following will work:
-// /// ```
-// /// use std::ffi::{OsStr, OsString};
-// ///
-// /// fn concat_os_strings(a: &OsStr, b: &OsStr) -> OsString {
-// /// let mut ret = OsString::with_capacity(a.len() + b.len()); // This will allocate
-// /// ret.push(a); // This will not allocate further
-// /// ret.push(b); // This will not allocate further
-// /// ret
-// /// }
-// /// ```
-// ///
-// /// # Creating an `OsString`
-// ///
-// /// **From a Rust string**: `OsString` implements
-// /// [From]<[String]>, so you can use my_string.[into]\() to
-// /// create an `OsString` from a normal Rust string.
-// ///
-// /// **From slices:** Just like you can start with an empty Rust
-// /// [`String`] and then [`String::push_str`] some &[str]
-// /// sub-string slices into it, you can create an empty `OsString` with
-// /// the [`OsString::new`] method and then push string slices into it with the
-// /// [`OsString::push`] method.
-// ///
-// /// # Extracting a borrowed reference to the whole OS string
-// ///
-// /// You can use the [`OsString::as_os_str`] method to get an &[OsStr] from
-// /// an `OsString`; this is effectively a borrowed reference to the
-// /// whole string.
-// ///
-// /// # Conversions
-// ///
-// /// See the [module's toplevel documentation about conversions][conversions] for a discussion on
-// /// the traits which `OsString` implements for [conversions] from/to native representations.
-// ///
-// /// [`CStr`]: crate::ffi::CStr
-// /// [conversions]: super#conversions
-// /// [into]: Into::into
-// #[cfg_attr(not(test), rustc_diagnostic_item = "OsString")]
-// pub struct OsString {
-// inner: Buf,
-// }
-
-// /// Allows extension traits within `std`.
-// impl crate::sealed::Sealed for OsString {}
-
-// /// Borrowed reference to an OS string (see [`OsString`]).
-// ///
-// /// This type represents a borrowed reference to a string in the operating system's preferred
-// /// representation.
-// ///
-// /// `&OsStr` is to [`OsString`] as &[str] is to [`String`]: the
-// /// former in each pair are borrowed references; the latter are owned strings.
-// ///
-// /// See the [module's toplevel documentation about conversions][conversions] for a discussion on
-// /// the traits which `OsStr` implements for [conversions] from/to native representations.
-// ///
-// /// [conversions]: super#conversions
-// #[cfg_attr(not(test), rustc_diagnostic_item = "OsStr")]
-// // `OsStr::from_inner` and `impl CloneToUninit for OsStr` current implementation relies
-// // on `OsStr` being layout-compatible with `Slice`.
-// // However, `OsStr` layout is considered an implementation detail and must not be relied upon.
-// #[repr(transparent)]
-// pub struct OsStr {
-// inner: Slice,
-// }
-
-// /// Allows extension traits within `std`.
-// impl crate::sealed::Sealed for OsStr {}
-
-// impl OsString {
-// /// Constructs a new empty `OsString`.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// ///
-// /// let os_string = OsString::new();
-// /// ```
-// #[must_use]
-// #[inline]
-// pub const fn new() -> OsString {
-// OsString { inner: Buf::from_string(String::new()) }
-// }
-
-// /// Converts bytes to an `OsString` without checking that the bytes contains
-// /// valid [`OsStr`]-encoded data.
-// ///
-// /// The byte encoding is an unspecified, platform-specific, self-synchronizing superset of UTF-8.
-// /// By being a self-synchronizing superset of UTF-8, this encoding is also a superset of 7-bit
-// /// ASCII.
-// ///
-// /// See the [module's toplevel documentation about conversions][conversions] for safe,
-// /// cross-platform [conversions] from/to native representations.
-// ///
-// /// # Safety
-// ///
-// /// As the encoding is unspecified, callers must pass in bytes that originated as a mixture of
-// /// validated UTF-8 and bytes from [`OsStr::as_encoded_bytes`] from within the same Rust version
-// /// built for the same target platform. For example, reconstructing an `OsString` from bytes sent
-// /// over the network or stored in a file will likely violate these safety rules.
-// ///
-// /// Due to the encoding being self-synchronizing, the bytes from [`OsStr::as_encoded_bytes`] can be
-// /// split either immediately before or immediately after any valid non-empty UTF-8 substring.
-// ///
-// /// # Example
-// ///
-// /// ```
-// /// use std::ffi::OsStr;
-// ///
-// /// let os_str = OsStr::new("Mary had a little lamb");
-// /// let bytes = os_str.as_encoded_bytes();
-// /// let words = bytes.split(|b| *b == b' ');
-// /// let words: Vec<&OsStr> = words.map(|word| {
-// /// // SAFETY:
-// /// // - Each `word` only contains content that originated from `OsStr::as_encoded_bytes`
-// /// // - Only split with ASCII whitespace which is a non-empty UTF-8 substring
-// /// unsafe { OsStr::from_encoded_bytes_unchecked(word) }
-// /// }).collect();
-// /// ```
-// ///
-// /// [conversions]: super#conversions
-// #[inline]
-// pub unsafe fn from_encoded_bytes_unchecked(bytes: Vec) -> Self {
-// OsString { inner: unsafe { Buf::from_encoded_bytes_unchecked(bytes) } }
-// }
-
-// /// Converts to an [`OsStr`] slice.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::{OsString, OsStr};
-// ///
-// /// let os_string = OsString::from("foo");
-// /// let os_str = OsStr::new("foo");
-// /// assert_eq!(os_string.as_os_str(), os_str);
-// /// ```
-// #[cfg_attr(not(test), rustc_diagnostic_item = "os_string_as_os_str")]
-// #[must_use]
-// #[inline]
-// pub fn as_os_str(&self) -> &OsStr {
-// self
-// }
-
-// /// Converts the `OsString` into a byte vector. To convert the byte vector back into an
-// /// `OsString`, use the [`OsString::from_encoded_bytes_unchecked`] function.
-// ///
-// /// The byte encoding is an unspecified, platform-specific, self-synchronizing superset of UTF-8.
-// /// By being a self-synchronizing superset of UTF-8, this encoding is also a superset of 7-bit
-// /// ASCII.
-// ///
-// /// Note: As the encoding is unspecified, any sub-slice of bytes that is not valid UTF-8 should
-// /// be treated as opaque and only comparable within the same Rust version built for the same
-// /// target platform. For example, sending the bytes over the network or storing it in a file
-// /// will likely result in incompatible data. See [`OsString`] for more encoding details
-// /// and [`std::ffi`] for platform-specific, specified conversions.
-// ///
-// /// [`std::ffi`]: crate::ffi
-// #[inline]
-// pub fn into_encoded_bytes(self) -> Vec {
-// self.inner.into_encoded_bytes()
-// }
-
-// /// Converts the `OsString` into a [`String`] if it contains valid Unicode data.
-// ///
-// /// On failure, ownership of the original `OsString` is returned.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// ///
-// /// let os_string = OsString::from("foo");
-// /// let string = os_string.into_string();
-// /// assert_eq!(string, Ok(String::from("foo")));
-// /// ```
-// #[inline]
-// pub fn into_string(self) -> Result {
-// self.inner.into_string().map_err(|buf| OsString { inner: buf })
-// }
-
-// /// Extends the string with the given &[OsStr] slice.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// ///
-// /// let mut os_string = OsString::from("foo");
-// /// os_string.push("bar");
-// /// assert_eq!(&os_string, "foobar");
-// /// ```
-// #[inline]
-// pub fn push>(&mut self, s: T) {
-// trait SpecPushTo {
-// fn spec_push_to(&self, buf: &mut OsString);
-// }
-
-// impl> SpecPushTo for T {
-// #[inline]
-// default fn spec_push_to(&self, buf: &mut OsString) {
-// buf.inner.push_slice(&self.as_ref().inner);
-// }
-// }
-
-// // Use a more efficient implementation when the string is UTF-8.
-// macro spec_str($T:ty) {
-// impl SpecPushTo for $T {
-// #[inline]
-// fn spec_push_to(&self, buf: &mut OsString) {
-// buf.inner.push_str(self);
-// }
-// }
-// }
-// spec_str!(str);
-// spec_str!(String);
-
-// s.spec_push_to(self)
-// }
-
-// /// Creates a new `OsString` with at least the given capacity.
-// ///
-// /// The string will be able to hold at least `capacity` length units of other
-// /// OS strings without reallocating. This method is allowed to allocate for
-// /// more units than `capacity`. If `capacity` is 0, the string will not
-// /// allocate.
-// ///
-// /// See the main `OsString` documentation information about encoding and capacity units.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// ///
-// /// let mut os_string = OsString::with_capacity(10);
-// /// let capacity = os_string.capacity();
-// ///
-// /// // This push is done without reallocating
-// /// os_string.push("foo");
-// ///
-// /// assert_eq!(capacity, os_string.capacity());
-// /// ```
-// #[must_use]
-// #[inline]
-// pub fn with_capacity(capacity: usize) -> OsString {
-// OsString { inner: Buf::with_capacity(capacity) }
-// }
-
-// /// Truncates the `OsString` to zero length.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// ///
-// /// let mut os_string = OsString::from("foo");
-// /// assert_eq!(&os_string, "foo");
-// ///
-// /// os_string.clear();
-// /// assert_eq!(&os_string, "");
-// /// ```
-// #[inline]
-// pub fn clear(&mut self) {
-// self.inner.clear()
-// }
-
-// /// Returns the capacity this `OsString` can hold without reallocating.
-// ///
-// /// See the main `OsString` documentation information about encoding and capacity units.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// ///
-// /// let os_string = OsString::with_capacity(10);
-// /// assert!(os_string.capacity() >= 10);
-// /// ```
-// #[must_use]
-// #[inline]
-// pub fn capacity(&self) -> usize {
-// self.inner.capacity()
-// }
-
-// /// Reserves capacity for at least `additional` more capacity to be inserted
-// /// in the given `OsString`. Does nothing if the capacity is
-// /// already sufficient.
-// ///
-// /// The collection may reserve more space to speculatively avoid frequent reallocations.
-// ///
-// /// See the main `OsString` documentation information about encoding and capacity units.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// ///
-// /// let mut s = OsString::new();
-// /// s.reserve(10);
-// /// assert!(s.capacity() >= 10);
-// /// ```
-// #[inline]
-// pub fn reserve(&mut self, additional: usize) {
-// self.inner.reserve(additional)
-// }
-
-// /// Tries to reserve capacity for at least `additional` more length units
-// /// in the given `OsString`. The string may reserve more space to speculatively avoid
-// /// frequent reallocations. After calling `try_reserve`, capacity will be
-// /// greater than or equal to `self.len() + additional` if it returns `Ok(())`.
-// /// Does nothing if capacity is already sufficient. This method preserves
-// /// the contents even if an error occurs.
-// ///
-// /// See the main `OsString` documentation information about encoding and capacity units.
-// ///
-// /// # Errors
-// ///
-// /// If the capacity overflows, or the allocator reports a failure, then an error
-// /// is returned.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::{OsStr, OsString};
-// /// use std::collections::TryReserveError;
-// ///
-// /// fn process_data(data: &str) -> Result {
-// /// let mut s = OsString::new();
-// ///
-// /// // Pre-reserve the memory, exiting if we can't
-// /// s.try_reserve(OsStr::new(data).len())?;
-// ///
-// /// // Now we know this can't OOM in the middle of our complex work
-// /// s.push(data);
-// ///
-// /// Ok(s)
-// /// }
-// /// # process_data("123").expect("why is the test harness OOMing on 3 bytes?");
-// /// ```
-// #[inline]
-// pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
-// self.inner.try_reserve(additional)
-// }
-
-// /// Reserves the minimum capacity for at least `additional` more capacity to
-// /// be inserted in the given `OsString`. Does nothing if the capacity is
-// /// already sufficient.
-// ///
-// /// Note that the allocator may give the collection more space than it
-// /// requests. Therefore, capacity can not be relied upon to be precisely
-// /// minimal. Prefer [`reserve`] if future insertions are expected.
-// ///
-// /// [`reserve`]: OsString::reserve
-// ///
-// /// See the main `OsString` documentation information about encoding and capacity units.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// ///
-// /// let mut s = OsString::new();
-// /// s.reserve_exact(10);
-// /// assert!(s.capacity() >= 10);
-// /// ```
-// #[inline]
-// pub fn reserve_exact(&mut self, additional: usize) {
-// self.inner.reserve_exact(additional)
-// }
-
-// /// Tries to reserve the minimum capacity for at least `additional`
-// /// more length units in the given `OsString`. After calling
-// /// `try_reserve_exact`, capacity will be greater than or equal to
-// /// `self.len() + additional` if it returns `Ok(())`.
-// /// Does nothing if the capacity is already sufficient.
-// ///
-// /// Note that the allocator may give the `OsString` more space than it
-// /// requests. Therefore, capacity can not be relied upon to be precisely
-// /// minimal. Prefer [`try_reserve`] if future insertions are expected.
-// ///
-// /// [`try_reserve`]: OsString::try_reserve
-// ///
-// /// See the main `OsString` documentation information about encoding and capacity units.
-// ///
-// /// # Errors
-// ///
-// /// If the capacity overflows, or the allocator reports a failure, then an error
-// /// is returned.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::{OsStr, OsString};
-// /// use std::collections::TryReserveError;
-// ///
-// /// fn process_data(data: &str) -> Result {
-// /// let mut s = OsString::new();
-// ///
-// /// // Pre-reserve the memory, exiting if we can't
-// /// s.try_reserve_exact(OsStr::new(data).len())?;
-// ///
-// /// // Now we know this can't OOM in the middle of our complex work
-// /// s.push(data);
-// ///
-// /// Ok(s)
-// /// }
-// /// # process_data("123").expect("why is the test harness OOMing on 3 bytes?");
-// /// ```
-// #[inline]
-// pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
-// self.inner.try_reserve_exact(additional)
-// }
-
-// /// Shrinks the capacity of the `OsString` to match its length.
-// ///
-// /// See the main `OsString` documentation information about encoding and capacity units.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// ///
-// /// let mut s = OsString::from("foo");
-// ///
-// /// s.reserve(100);
-// /// assert!(s.capacity() >= 100);
-// ///
-// /// s.shrink_to_fit();
-// /// assert_eq!(3, s.capacity());
-// /// ```
-// #[inline]
-// pub fn shrink_to_fit(&mut self) {
-// self.inner.shrink_to_fit()
-// }
-
-// /// Shrinks the capacity of the `OsString` with a lower bound.
-// ///
-// /// The capacity will remain at least as large as both the length
-// /// and the supplied value.
-// ///
-// /// If the current capacity is less than the lower limit, this is a no-op.
-// ///
-// /// See the main `OsString` documentation information about encoding and capacity units.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// ///
-// /// let mut s = OsString::from("foo");
-// ///
-// /// s.reserve(100);
-// /// assert!(s.capacity() >= 100);
-// ///
-// /// s.shrink_to(10);
-// /// assert!(s.capacity() >= 10);
-// /// s.shrink_to(0);
-// /// assert!(s.capacity() >= 3);
-// /// ```
-// #[inline]
-// pub fn shrink_to(&mut self, min_capacity: usize) {
-// self.inner.shrink_to(min_capacity)
-// }
-
-// /// Converts this `OsString` into a boxed [`OsStr`].
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::{OsString, OsStr};
-// ///
-// /// let s = OsString::from("hello");
-// ///
-// /// let b: Box = s.into_boxed_os_str();
-// /// ```
-// #[must_use = "`self` will be dropped if the result is not used"]
-// pub fn into_boxed_os_str(self) -> Box {
-// let rw = Box::into_raw(self.inner.into_box()) as *mut OsStr;
-// unsafe { Box::from_raw(rw) }
-// }
-
-// /// Consumes and leaks the `OsString`, returning a mutable reference to the contents,
-// /// `&'a mut OsStr`.
-// ///
-// /// The caller has free choice over the returned lifetime, including 'static.
-// /// Indeed, this function is ideally used for data that lives for the remainder of
-// /// the program’s life, as dropping the returned reference will cause a memory leak.
-// ///
-// /// It does not reallocate or shrink the `OsString`, so the leaked allocation may include
-// /// unused capacity that is not part of the returned slice. If you want to discard excess
-// /// capacity, call [`into_boxed_os_str`], and then [`Box::leak`] instead.
-// /// However, keep in mind that trimming the capacity may result in a reallocation and copy.
-// ///
-// /// [`into_boxed_os_str`]: Self::into_boxed_os_str
-// #[inline]
-// pub fn leak<'a>(self) -> &'a mut OsStr {
-// OsStr::from_inner_mut(self.inner.leak())
-// }
-
-// /// Truncate the `OsString` to the specified length.
-// ///
-// /// # Panics
-// /// Panics if `len` does not lie on a valid `OsStr` boundary
-// /// (as described in [`OsStr::slice_encoded_bytes`]).
-// #[inline]
-// pub fn truncate(&mut self, len: usize) {
-// self.as_os_str().inner.check_public_boundary(len);
-// // SAFETY: The length was just checked to be at a valid boundary.
-// unsafe { self.inner.truncate_unchecked(len) };
-// }
-
-// /// Provides plumbing to `Vec::extend_from_slice` without giving full
-// /// mutable access to the `Vec`.
-// ///
-// /// # Safety
-// ///
-// /// The slice must be valid for the platform encoding (as described in
-// /// [`OsStr::from_encoded_bytes_unchecked`]).
-// ///
-// /// This bypasses the encoding-dependent surrogate joining, so either
-// /// `self` must not end with a leading surrogate half, or `other` must not
-// /// start with a trailing surrogate half.
-// #[inline]
-// pub(crate) unsafe fn extend_from_slice_unchecked(&mut self, other: &[u8]) {
-// // SAFETY: Guaranteed by caller.
-// unsafe { self.inner.extend_from_slice_unchecked(other) };
-// }
-// }
-// impl From for OsString {
-// /// Converts a [`String`] into an [`OsString`].
-// ///
-// /// This conversion does not allocate or copy memory.
-// #[inline]
-// fn from(s: String) -> OsString {
-// OsString { inner: Buf::from_string(s) }
-// }
-// }
-// impl> From<&T> for OsString {
-// /// Copies any value implementing [AsRef]<[OsStr]>
-// /// into a newly allocated [`OsString`].
-// fn from(s: &T) -> OsString {
-// trait SpecToOsString {
-// fn spec_to_os_string(&self) -> OsString;
-// }
-
-// impl> SpecToOsString for T {
-// #[inline]
-// default fn spec_to_os_string(&self) -> OsString {
-// self.as_ref().to_os_string()
-// }
-// }
-
-// // Preserve the known-UTF-8 property for strings.
-// macro spec_str($T:ty) {
-// impl SpecToOsString for $T {
-// #[inline]
-// fn spec_to_os_string(&self) -> OsString {
-// OsString::from(String::from(self))
-// }
-// }
-// }
-// spec_str!(str);
-// spec_str!(String);
-
-// s.spec_to_os_string()
-// }
-// }
-// impl ops::Index for OsString {
-// type Output = OsStr;
-
-// #[inline]
-// fn index(&self, _index: ops::RangeFull) -> &OsStr {
-// OsStr::from_inner(self.inner.as_slice())
-// }
-// }
-// impl ops::IndexMut for OsString {
-// #[inline]
-// fn index_mut(&mut self, _index: ops::RangeFull) -> &mut OsStr {
-// OsStr::from_inner_mut(self.inner.as_mut_slice())
-// }
-// }
-// impl ops::Deref for OsString {
-// type Target = OsStr;
-
-// #[inline]
-// fn deref(&self) -> &OsStr {
-// &self[..]
-// }
-// }
-// impl ops::DerefMut for OsString {
-// #[inline]
-// fn deref_mut(&mut self) -> &mut OsStr {
-// &mut self[..]
-// }
-// }
-// impl Default for OsString {
-// /// Constructs an empty `OsString`.
-// #[inline]
-// fn default() -> OsString {
-// OsString::new()
-// }
-// }
-// impl Clone for OsString {
-// #[inline]
-// fn clone(&self) -> Self {
-// OsString { inner: self.inner.clone() }
-// }
-
-// /// Clones the contents of `source` into `self`.
-// ///
-// /// This method is preferred over simply assigning `source.clone()` to `self`,
-// /// as it avoids reallocation if possible.
-// #[inline]
-// fn clone_from(&mut self, source: &Self) {
-// self.inner.clone_from(&source.inner)
-// }
-// }
-// impl fmt::Debug for OsString {
-// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-// fmt::Debug::fmt(&**self, formatter)
-// }
-// }
-// impl PartialEq for OsString {
-// #[inline]
-// fn eq(&self, other: &OsString) -> bool {
-// &**self == &**other
-// }
-// }
-// impl PartialEq for OsString {
-// #[inline]
-// fn eq(&self, other: &str) -> bool {
-// &**self == other
-// }
-// }
-// impl PartialEq for str {
-// #[inline]
-// fn eq(&self, other: &OsString) -> bool {
-// &**other == self
-// }
-// }
-// impl PartialEq<&str> for OsString {
-// #[inline]
-// fn eq(&self, other: &&str) -> bool {
-// **self == **other
-// }
-// }
-// impl<'a> PartialEq for &'a str {
-// #[inline]
-// fn eq(&self, other: &OsString) -> bool {
-// **other == **self
-// }
-// }
-// impl Eq for OsString {}
-// impl PartialOrd for OsString {
-// #[inline]
-// fn partial_cmp(&self, other: &OsString) -> Option {
-// (&**self).partial_cmp(&**other)
-// }
-// #[inline]
-// fn lt(&self, other: &OsString) -> bool {
-// &**self < &**other
-// }
-// #[inline]
-// fn le(&self, other: &OsString) -> bool {
-// &**self <= &**other
-// }
-// #[inline]
-// fn gt(&self, other: &OsString) -> bool {
-// &**self > &**other
-// }
-// #[inline]
-// fn ge(&self, other: &OsString) -> bool {
-// &**self >= &**other
-// }
-// }
-// impl PartialOrd for OsString {
-// #[inline]
-// fn partial_cmp(&self, other: &str) -> Option {
-// (&**self).partial_cmp(other)
-// }
-// }
-// impl Ord for OsString {
-// #[inline]
-// fn cmp(&self, other: &OsString) -> cmp::Ordering {
-// (&**self).cmp(&**other)
-// }
-// }
-// impl Hash for OsString {
-// #[inline]
-// fn hash(&self, state: &mut H) {
-// (&**self).hash(state)
-// }
-// }
-// impl fmt::Write for OsString {
-// fn write_str(&mut self, s: &str) -> fmt::Result {
-// self.push(s);
-// Ok(())
-// }
-// }
-
-// impl OsStr {
-// /// Coerces into an `OsStr` slice.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsStr;
-// ///
-// /// let os_str = OsStr::new("foo");
-// /// ```
-// #[inline]
-// pub const fn new + ?Sized>(s: &S) -> &OsStr {
-// s.as_ref()
-// }
-
-// /// Converts a slice of bytes to an OS string slice without checking that the string contains
-// /// valid `OsStr`-encoded data.
-// ///
-// /// The byte encoding is an unspecified, platform-specific, self-synchronizing superset of UTF-8.
-// /// By being a self-synchronizing superset of UTF-8, this encoding is also a superset of 7-bit
-// /// ASCII.
-// ///
-// /// See the [module's toplevel documentation about conversions][conversions] for safe,
-// /// cross-platform [conversions] from/to native representations.
-// ///
-// /// # Safety
-// ///
-// /// As the encoding is unspecified, callers must pass in bytes that originated as a mixture of
-// /// validated UTF-8 and bytes from [`OsStr::as_encoded_bytes`] from within the same Rust version
-// /// built for the same target platform. For example, reconstructing an `OsStr` from bytes sent
-// /// over the network or stored in a file will likely violate these safety rules.
-// ///
-// /// Due to the encoding being self-synchronizing, the bytes from [`OsStr::as_encoded_bytes`] can be
-// /// split either immediately before or immediately after any valid non-empty UTF-8 substring.
-// ///
-// /// # Example
-// ///
-// /// ```
-// /// use std::ffi::OsStr;
-// ///
-// /// let os_str = OsStr::new("Mary had a little lamb");
-// /// let bytes = os_str.as_encoded_bytes();
-// /// let words = bytes.split(|b| *b == b' ');
-// /// let words: Vec<&OsStr> = words.map(|word| {
-// /// // SAFETY:
-// /// // - Each `word` only contains content that originated from `OsStr::as_encoded_bytes`
-// /// // - Only split with ASCII whitespace which is a non-empty UTF-8 substring
-// /// unsafe { OsStr::from_encoded_bytes_unchecked(word) }
-// /// }).collect();
-// /// ```
-// ///
-// /// [conversions]: super#conversions
-// #[inline]
-// pub unsafe fn from_encoded_bytes_unchecked(bytes: &[u8]) -> &Self {
-// Self::from_inner(unsafe { Slice::from_encoded_bytes_unchecked(bytes) })
-// }
-
-// #[inline]
-// const fn from_inner(inner: &Slice) -> &OsStr {
-// // SAFETY: OsStr is just a wrapper of Slice,
-// // therefore converting &Slice to &OsStr is safe.
-// unsafe { &*(inner as *const Slice as *const OsStr) }
-// }
-
-// #[inline]
-// const fn from_inner_mut(inner: &mut Slice) -> &mut OsStr {
-// // SAFETY: OsStr is just a wrapper of Slice,
-// // therefore converting &mut Slice to &mut OsStr is safe.
-// // Any method that mutates OsStr must be careful not to
-// // break platform-specific encoding, in particular Wtf8 on Windows.
-// unsafe { &mut *(inner as *mut Slice as *mut OsStr) }
-// }
-
-// /// Yields a &[str] slice if the `OsStr` is valid Unicode.
-// ///
-// /// This conversion may entail doing a check for UTF-8 validity.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsStr;
-// ///
-// /// let os_str = OsStr::new("foo");
-// /// assert_eq!(os_str.to_str(), Some("foo"));
-// /// ```
-// #[must_use = "this returns the result of the operation, \
-// without modifying the original"]
-// #[inline]
-// pub fn to_str(&self) -> Option<&str> {
-// self.inner.to_str().ok()
-// }
-
-// /// Converts an `OsStr` to a [Cow]<[str]>.
-// ///
-// /// Any non-UTF-8 sequences are replaced with
-// /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD].
-// ///
-// /// [U+FFFD]: crate::char::REPLACEMENT_CHARACTER
-// ///
-// /// # Examples
-// ///
-// /// Calling `to_string_lossy` on an `OsStr` with invalid unicode:
-// ///
-// /// ```
-// /// // Note, due to differences in how Unix and Windows represent strings,
-// /// // we are forced to complicate this example, setting up example `OsStr`s
-// /// // with different source data and via different platform extensions.
-// /// // Understand that in reality you could end up with such example invalid
-// /// // sequences simply through collecting user command line arguments, for
-// /// // example.
-// ///
-// /// #[cfg(unix)] {
-// /// use std::ffi::OsStr;
-// /// use std::os::unix::ffi::OsStrExt;
-// ///
-// /// // Here, the values 0x66 and 0x6f correspond to 'f' and 'o'
-// /// // respectively. The value 0x80 is a lone continuation byte, invalid
-// /// // in a UTF-8 sequence.
-// /// let source = [0x66, 0x6f, 0x80, 0x6f];
-// /// let os_str = OsStr::from_bytes(&source[..]);
-// ///
-// /// assert_eq!(os_str.to_string_lossy(), "fo�o");
-// /// }
-// /// #[cfg(windows)] {
-// /// use std::ffi::OsString;
-// /// use std::os::windows::prelude::*;
-// ///
-// /// // Here the values 0x0066 and 0x006f correspond to 'f' and 'o'
-// /// // respectively. The value 0xD800 is a lone surrogate half, invalid
-// /// // in a UTF-16 sequence.
-// /// let source = [0x0066, 0x006f, 0xD800, 0x006f];
-// /// let os_string = OsString::from_wide(&source[..]);
-// /// let os_str = os_string.as_os_str();
-// ///
-// /// assert_eq!(os_str.to_string_lossy(), "fo�o");
-// /// }
-// /// ```
-// #[must_use = "this returns the result of the operation, \
-// without modifying the original"]
-// #[inline]
-// pub fn to_string_lossy(&self) -> Cow<'_, str> {
-// self.inner.to_string_lossy()
-// }
-
-// /// Copies the slice into an owned [`OsString`].
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::{OsStr, OsString};
-// ///
-// /// let os_str = OsStr::new("foo");
-// /// let os_string = os_str.to_os_string();
-// /// assert_eq!(os_string, OsString::from("foo"));
-// /// ```
-// #[must_use = "this returns the result of the operation, \
-// without modifying the original"]
-// #[inline]
-// #[cfg_attr(not(test), rustc_diagnostic_item = "os_str_to_os_string")]
-// pub fn to_os_string(&self) -> OsString {
-// OsString { inner: self.inner.to_owned() }
-// }
-
-// /// Checks whether the `OsStr` is empty.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsStr;
-// ///
-// /// let os_str = OsStr::new("");
-// /// assert!(os_str.is_empty());
-// ///
-// /// let os_str = OsStr::new("foo");
-// /// assert!(!os_str.is_empty());
-// /// ```
-// #[must_use]
-// #[inline]
-// pub fn is_empty(&self) -> bool {
-// self.inner.inner.is_empty()
-// }
-
-// /// Returns the length of this `OsStr`.
-// ///
-// /// Note that this does **not** return the number of bytes in the string in
-// /// OS string form.
-// ///
-// /// The length returned is that of the underlying storage used by `OsStr`.
-// /// As discussed in the [`OsString`] introduction, [`OsString`] and `OsStr`
-// /// store strings in a form best suited for cheap inter-conversion between
-// /// native-platform and Rust string forms, which may differ significantly
-// /// from both of them, including in storage size and encoding.
-// ///
-// /// This number is simply useful for passing to other methods, like
-// /// [`OsString::with_capacity`] to avoid reallocations.
-// ///
-// /// See the main `OsString` documentation information about encoding and capacity units.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsStr;
-// ///
-// /// let os_str = OsStr::new("");
-// /// assert_eq!(os_str.len(), 0);
-// ///
-// /// let os_str = OsStr::new("foo");
-// /// assert_eq!(os_str.len(), 3);
-// /// ```
-// #[must_use]
-// #[inline]
-// pub fn len(&self) -> usize {
-// self.inner.inner.len()
-// }
-
-// /// Converts a [Box]<[OsStr]> into an [`OsString`] without copying or allocating.
-// #[must_use = "`self` will be dropped if the result is not used"]
-// pub fn into_os_string(self: Box) -> OsString {
-// let boxed = unsafe { Box::from_raw(Box::into_raw(self) as *mut Slice) };
-// OsString { inner: Buf::from_box(boxed) }
-// }
-
-// /// Converts an OS string slice to a byte slice. To convert the byte slice back into an OS
-// /// string slice, use the [`OsStr::from_encoded_bytes_unchecked`] function.
-// ///
-// /// The byte encoding is an unspecified, platform-specific, self-synchronizing superset of UTF-8.
-// /// By being a self-synchronizing superset of UTF-8, this encoding is also a superset of 7-bit
-// /// ASCII.
-// ///
-// /// Note: As the encoding is unspecified, any sub-slice of bytes that is not valid UTF-8 should
-// /// be treated as opaque and only comparable within the same Rust version built for the same
-// /// target platform. For example, sending the slice over the network or storing it in a file
-// /// will likely result in incompatible byte slices. See [`OsString`] for more encoding details
-// /// and [`std::ffi`] for platform-specific, specified conversions.
-// ///
-// /// [`std::ffi`]: crate::ffi
-// #[inline]
-// pub fn as_encoded_bytes(&self) -> &[u8] {
-// self.inner.as_encoded_bytes()
-// }
-
-// /// Takes a substring based on a range that corresponds to the return value of
-// /// [`OsStr::as_encoded_bytes`].
-// ///
-// /// The range's start and end must lie on valid `OsStr` boundaries.
-// /// A valid `OsStr` boundary is one of:
-// /// - The start of the string
-// /// - The end of the string
-// /// - Immediately before a valid non-empty UTF-8 substring
-// /// - Immediately after a valid non-empty UTF-8 substring
-// ///
-// /// # Panics
-// ///
-// /// Panics if `range` does not lie on valid `OsStr` boundaries or if it
-// /// exceeds the end of the string.
-// ///
-// /// # Example
-// ///
-// /// ```
-// /// #![feature(os_str_slice)]
-// ///
-// /// use std::ffi::OsStr;
-// ///
-// /// let os_str = OsStr::new("foo=bar");
-// /// let bytes = os_str.as_encoded_bytes();
-// /// if let Some(index) = bytes.iter().position(|b| *b == b'=') {
-// /// let key = os_str.slice_encoded_bytes(..index);
-// /// let value = os_str.slice_encoded_bytes(index + 1..);
-// /// assert_eq!(key, "foo");
-// /// assert_eq!(value, "bar");
-// /// }
-// /// ```
-// pub fn slice_encoded_bytes>(&self, range: R) -> &Self {
-// let encoded_bytes = self.as_encoded_bytes();
-// let Range { start, end } = slice::range(range, ..encoded_bytes.len());
-
-// // `check_public_boundary` should panic if the index does not lie on an
-// // `OsStr` boundary as described above. It's possible to do this in an
-// // encoding-agnostic way, but details of the internal encoding might
-// // permit a more efficient implementation.
-// self.inner.check_public_boundary(start);
-// self.inner.check_public_boundary(end);
-
-// // SAFETY: `slice::range` ensures that `start` and `end` are valid
-// let slice = unsafe { encoded_bytes.get_unchecked(start..end) };
-
-// // SAFETY: `slice` comes from `self` and we validated the boundaries
-// unsafe { Self::from_encoded_bytes_unchecked(slice) }
-// }
-
-// /// Converts this string to its ASCII lower case equivalent in-place.
-// ///
-// /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
-// /// but non-ASCII letters are unchanged.
-// ///
-// /// To return a new lowercased value without modifying the existing one, use
-// /// [`OsStr::to_ascii_lowercase`].
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// ///
-// /// let mut s = OsString::from("GRÜßE, JÜRGEN ❤");
-// ///
-// /// s.make_ascii_lowercase();
-// ///
-// /// assert_eq!("grÜße, jÜrgen ❤", s);
-// /// ```
-// #[inline]
-// pub fn make_ascii_lowercase(&mut self) {
-// self.inner.make_ascii_lowercase()
-// }
-
-// /// Converts this string to its ASCII upper case equivalent in-place.
-// ///
-// /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
-// /// but non-ASCII letters are unchanged.
-// ///
-// /// To return a new uppercased value without modifying the existing one, use
-// /// [`OsStr::to_ascii_uppercase`].
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// ///
-// /// let mut s = OsString::from("Grüße, Jürgen ❤");
-// ///
-// /// s.make_ascii_uppercase();
-// ///
-// /// assert_eq!("GRüßE, JüRGEN ❤", s);
-// /// ```
-// #[inline]
-// pub fn make_ascii_uppercase(&mut self) {
-// self.inner.make_ascii_uppercase()
-// }
-
-// /// Returns a copy of this string where each character is mapped to its
-// /// ASCII lower case equivalent.
-// ///
-// /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
-// /// but non-ASCII letters are unchanged.
-// ///
-// /// To lowercase the value in-place, use [`OsStr::make_ascii_lowercase`].
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// /// let s = OsString::from("Grüße, Jürgen ❤");
-// ///
-// /// assert_eq!("grüße, jürgen ❤", s.to_ascii_lowercase());
-// /// ```
-// #[must_use = "to lowercase the value in-place, use `make_ascii_lowercase`"]
-// pub fn to_ascii_lowercase(&self) -> OsString {
-// OsString::from_inner(self.inner.to_ascii_lowercase())
-// }
-
-// /// Returns a copy of this string where each character is mapped to its
-// /// ASCII upper case equivalent.
-// ///
-// /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
-// /// but non-ASCII letters are unchanged.
-// ///
-// /// To uppercase the value in-place, use [`OsStr::make_ascii_uppercase`].
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// /// let s = OsString::from("Grüße, Jürgen ❤");
-// ///
-// /// assert_eq!("GRüßE, JüRGEN ❤", s.to_ascii_uppercase());
-// /// ```
-// #[must_use = "to uppercase the value in-place, use `make_ascii_uppercase`"]
-// pub fn to_ascii_uppercase(&self) -> OsString {
-// OsString::from_inner(self.inner.to_ascii_uppercase())
-// }
-
-// /// Checks if all characters in this string are within the ASCII range.
-// ///
-// /// An empty string returns `true`.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// ///
-// /// let ascii = OsString::from("hello!\n");
-// /// let non_ascii = OsString::from("Grüße, Jürgen ❤");
-// ///
-// /// assert!(ascii.is_ascii());
-// /// assert!(!non_ascii.is_ascii());
-// /// ```
-// #[must_use]
-// #[inline]
-// pub fn is_ascii(&self) -> bool {
-// self.inner.is_ascii()
-// }
-
-// /// Checks that two strings are an ASCII case-insensitive match.
-// ///
-// /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
-// /// but without allocating and copying temporaries.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// ///
-// /// assert!(OsString::from("Ferris").eq_ignore_ascii_case("FERRIS"));
-// /// assert!(OsString::from("Ferrös").eq_ignore_ascii_case("FERRöS"));
-// /// assert!(!OsString::from("Ferrös").eq_ignore_ascii_case("FERRÖS"));
-// /// ```
-// pub fn eq_ignore_ascii_case>(&self, other: S) -> bool {
-// self.inner.eq_ignore_ascii_case(&other.as_ref().inner)
-// }
-
-// /// Returns an object that implements [`Display`] for safely printing an
-// /// [`OsStr`] that may contain non-Unicode data. This may perform lossy
-// /// conversion, depending on the platform. If you would like an
-// /// implementation which escapes the [`OsStr`] please use [`Debug`]
-// /// instead.
-// ///
-// /// [`Display`]: fmt::Display
-// /// [`Debug`]: fmt::Debug
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsStr;
-// ///
-// /// let s = OsStr::new("Hello, world!");
-// /// println!("{}", s.display());
-// /// ```
-// #[must_use = "this does not display the `OsStr`; \
-// it returns an object that can be displayed"]
-// #[inline]
-// pub fn display(&self) -> Display<'_> {
-// Display { os_str: self }
-// }
-
-// /// Returns the same string as a string slice `&OsStr`.
-// ///
-// /// This method is redundant when used directly on `&OsStr`, but
-// /// it helps dereferencing other string-like types to string slices,
-// /// for example references to `Box` or `Arc`.
-// #[inline]
-// pub const fn as_os_str(&self) -> &OsStr {
-// self
-// }
-// }
-// impl From<&OsStr> for Box {
-// /// Copies the string into a newly allocated [Box]<[OsStr]>.
-// #[inline]
-// fn from(s: &OsStr) -> Box {
-// Box::clone_from_ref(s)
-// }
-// }
-// impl From<&mut OsStr> for Box {
-// /// Copies the string into a newly allocated [Box]<[OsStr]>.
-// #[inline]
-// fn from(s: &mut OsStr) -> Box {
-// Self::from(&*s)
-// }
-// }
-// impl From> for Box {
-// /// Converts a `Cow<'a, OsStr>` into a [Box]<[OsStr]>,
-// /// by copying the contents if they are borrowed.
-// #[inline]
-// fn from(cow: Cow<'_, OsStr>) -> Box {
-// match cow {
-// Cow::Borrowed(s) => Box::from(s),
-// Cow::Owned(s) => Box::from(s),
-// }
-// }
-// }
-// impl From> for OsString {
-// /// Converts a [Box]<[OsStr]> into an [`OsString`] without copying or
-// /// allocating.
-// #[inline]
-// fn from(boxed: Box) -> OsString {
-// boxed.into_os_string()
-// }
-// }
-// impl From for Box {
-// /// Converts an [`OsString`] into a [Box]<[OsStr]> without copying or allocating.
-// #[inline]
-// fn from(s: OsString) -> Box {
-// s.into_boxed_os_str()
-// }
-// }
-// impl Clone for Box {
-// #[inline]
-// fn clone(&self) -> Self {
-// self.to_os_string().into_boxed_os_str()
-// }
-// }
-// unsafe impl CloneToUninit for OsStr {
-// #[inline]
-// #[cfg_attr(debug_assertions, track_caller)]
-// unsafe fn clone_to_uninit(&self, dst: *mut u8) {
-// // SAFETY: we're just a transparent wrapper around a platform-specific Slice
-// unsafe { self.inner.clone_to_uninit(dst) }
-// }
-// }
-// impl From for Arc {
-// /// Converts an [`OsString`] into an [Arc]<[OsStr]> by moving the [`OsString`]
-// /// data into a new [`Arc`] buffer.
-// #[inline]
-// fn from(s: OsString) -> Arc {
-// let arc = s.inner.into_arc();
-// unsafe { Arc::from_raw(Arc::into_raw(arc) as *const OsStr) }
-// }
-// }
-// impl From<&OsStr> for Arc {
-// /// Copies the string into a newly allocated [Arc]<[OsStr]>.
-// #[inline]
-// fn from(s: &OsStr) -> Arc {
-// let arc = s.inner.into_arc();
-// unsafe { Arc::from_raw(Arc::into_raw(arc) as *const OsStr) }
-// }
-// }
-// impl From<&mut OsStr> for Arc {
-// /// Copies the string into a newly allocated [Arc]<[OsStr]>.
-// #[inline]
-// fn from(s: &mut OsStr) -> Arc {
-// Arc::from(&*s)
-// }
-// }
-// impl From for Rc {
-// /// Converts an [`OsString`] into an [Rc]<[OsStr]> by moving the [`OsString`]
-// /// data into a new [`Rc`] buffer.
-// #[inline]
-// fn from(s: OsString) -> Rc {
-// let rc = s.inner.into_rc();
-// unsafe { Rc::from_raw(Rc::into_raw(rc) as *const OsStr) }
-// }
-// }
-// impl From<&OsStr> for Rc {
-// /// Copies the string into a newly allocated [Rc]<[OsStr]>.
-// #[inline]
-// fn from(s: &OsStr) -> Rc {
-// let rc = s.inner.into_rc();
-// unsafe { Rc::from_raw(Rc::into_raw(rc) as *const OsStr) }
-// }
-// }
-// impl From<&mut OsStr> for Rc {
-// /// Copies the string into a newly allocated [Rc]<[OsStr]>.
-// #[inline]
-// fn from(s: &mut OsStr) -> Rc {
-// Rc::from(&*s)
-// }
-// }
-// impl<'a> From for Cow<'a, OsStr> {
-// /// Moves the string into a [`Cow::Owned`].
-// #[inline]
-// fn from(s: OsString) -> Cow<'a, OsStr> {
-// Cow::Owned(s)
-// }
-// }
-// impl<'a> From<&'a OsStr> for Cow<'a, OsStr> {
-// /// Converts the string reference into a [`Cow::Borrowed`].
-// #[inline]
-// fn from(s: &'a OsStr) -> Cow<'a, OsStr> {
-// Cow::Borrowed(s)
-// }
-// }
-// impl<'a> From<&'a OsString> for Cow<'a, OsStr> {
-// /// Converts the string reference into a [`Cow::Borrowed`].
-// #[inline]
-// fn from(s: &'a OsString) -> Cow<'a, OsStr> {
-// Cow::Borrowed(s.as_os_str())
-// }
-// }
-// impl<'a> From> for OsString {
-// /// Converts a `Cow<'a, OsStr>` into an [`OsString`],
-// /// by copying the contents if they are borrowed.
-// #[inline]
-// fn from(s: Cow<'a, OsStr>) -> Self {
-// s.into_owned()
-// }
-// }
-// impl<'a> TryFrom<&'a OsStr> for &'a str {
-// type Error = crate::str::Utf8Error;
-
-// /// Tries to convert an `&OsStr` to a `&str`.
-// ///
-// /// ```
-// /// use std::ffi::OsStr;
-// ///
-// /// let os_str = OsStr::new("foo");
-// /// let as_str = <&str>::try_from(os_str).unwrap();
-// /// assert_eq!(as_str, "foo");
-// /// ```
-// fn try_from(value: &'a OsStr) -> Result {
-// value.inner.to_str()
-// }
-// }
-// impl Default for Box {
-// #[inline]
-// fn default() -> Box {
-// let rw = Box::into_raw(Slice::empty_box()) as *mut OsStr;
-// unsafe { Box::from_raw(rw) }
-// }
-// }
-// impl Default for &OsStr {
-// /// Creates an empty `OsStr`.
-// #[inline]
-// fn default() -> Self {
-// OsStr::new("")
-// }
-// }
-// impl PartialEq for OsStr {
-// #[inline]
-// fn eq(&self, other: &OsStr) -> bool {
-// self.as_encoded_bytes().eq(other.as_encoded_bytes())
-// }
-// }
-// impl PartialEq for OsStr {
-// #[inline]
-// fn eq(&self, other: &str) -> bool {
-// *self == *OsStr::new(other)
-// }
-// }
-// impl PartialEq for str {
-// #[inline]
-// fn eq(&self, other: &OsStr) -> bool {
-// *other == *OsStr::new(self)
-// }
-// }
-// impl Eq for OsStr {}
-// impl PartialOrd for OsStr {
-// #[inline]
-// fn partial_cmp(&self, other: &OsStr) -> Option {
-// self.as_encoded_bytes().partial_cmp(other.as_encoded_bytes())
-// }
-// #[inline]
-// fn lt(&self, other: &OsStr) -> bool {
-// self.as_encoded_bytes().lt(other.as_encoded_bytes())
-// }
-// #[inline]
-// fn le(&self, other: &OsStr) -> bool {
-// self.as_encoded_bytes().le(other.as_encoded_bytes())
-// }
-// #[inline]
-// fn gt(&self, other: &OsStr) -> bool {
-// self.as_encoded_bytes().gt(other.as_encoded_bytes())
-// }
-// #[inline]
-// fn ge(&self, other: &OsStr) -> bool {
-// self.as_encoded_bytes().ge(other.as_encoded_bytes())
-// }
-// }
-// impl PartialOrd for OsStr {
-// #[inline]
-// fn partial_cmp(&self, other: &str) -> Option {
-// self.partial_cmp(OsStr::new(other))
-// }
-// }
-
-// // FIXME (#19470): cannot provide PartialOrd for str until we
-// // have more flexible coherence rules.
-// impl Ord for OsStr {
-// #[inline]
-// fn cmp(&self, other: &OsStr) -> cmp::Ordering {
-// self.as_encoded_bytes().cmp(other.as_encoded_bytes())
-// }
-// }
-
-// macro_rules! impl_cmp {
-// ($lhs:ty, $rhs: ty) => {
-// impl PartialEq<$rhs> for $lhs {
-// #[inline]
-// fn eq(&self, other: &$rhs) -> bool {
-// ::eq(self, other)
-// }
-// }
-// impl PartialEq<$lhs> for $rhs {
-// #[inline]
-// fn eq(&self, other: &$lhs) -> bool {
-// ::eq(self, other)
-// }
-// }
-// impl PartialOrd<$rhs> for $lhs {
-// #[inline]
-// fn partial_cmp(&self, other: &$rhs) -> Option {
-// ::partial_cmp(self, other)
-// }
-// }
-// impl PartialOrd<$lhs> for $rhs {
-// #[inline]
-// fn partial_cmp(&self, other: &$lhs) -> Option {
-// ::partial_cmp(self, other)
-// }
-// }
-// };
-// }
-
-// impl_cmp!(OsString, OsStr);
-// impl_cmp!(OsString, &OsStr);
-// impl_cmp!(Cow<'_, OsStr>, OsStr);
-// impl_cmp!(Cow<'_, OsStr>, &OsStr);
-// impl_cmp!(Cow<'_, OsStr>, OsString);
-// impl Hash for OsStr {
-// #[inline]
-// fn hash(&self, state: &mut H) {
-// self.as_encoded_bytes().hash(state)
-// }
-// }
-// impl fmt::Debug for OsStr {
-// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-// fmt::Debug::fmt(&self.inner, formatter)
-// }
-// }
-
-// /// Helper struct for safely printing an [`OsStr`] with [`format!`] and `{}`.
-// ///
-// /// An [`OsStr`] might contain non-Unicode data. This `struct` implements the
-// /// [`Display`] trait in a way that mitigates that. It is created by the
-// /// [`display`](OsStr::display) method on [`OsStr`]. This may perform lossy
-// /// conversion, depending on the platform. If you would like an implementation
-// /// which escapes the [`OsStr`] please use [`Debug`] instead.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsStr;
-// ///
-// /// let s = OsStr::new("Hello, world!");
-// /// println!("{}", s.display());
-// /// ```
-// ///
-// /// [`Display`]: fmt::Display
-// /// [`format!`]: crate::format
-// pub struct Display<'a> {
-// os_str: &'a OsStr,
-// }
-// impl fmt::Debug for Display<'_> {
-// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-// fmt::Debug::fmt(&self.os_str, f)
-// }
-// }
-// impl fmt::Display for Display<'_> {
-// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-// fmt::Display::fmt(&self.os_str.inner, f)
-// }
-// }
-// impl> alloc::slice::Join<&OsStr> for [S] {
-// type Output = OsString;
-
-// fn join(slice: &Self, sep: &OsStr) -> OsString {
-// let Some((first, suffix)) = slice.split_first() else {
-// return OsString::new();
-// };
-// let first_owned = first.borrow().to_owned();
-// suffix.iter().fold(first_owned, |mut a, b| {
-// a.push(sep);
-// a.push(b.borrow());
-// a
-// })
-// }
-// }
-// impl Borrow for OsString {
-// #[inline]
-// fn borrow(&self) -> &OsStr {
-// &self[..]
-// }
-// }
-// impl ToOwned for OsStr {
-// type Owned = OsString;
-// #[inline]
-// fn to_owned(&self) -> OsString {
-// self.to_os_string()
-// }
-// #[inline]
-// fn clone_into(&self, target: &mut OsString) {
-// self.inner.clone_into(&mut target.inner)
-// }
-// }
-// impl const AsRef for OsStr {
-// #[inline]
-// fn as_ref(&self) -> &OsStr {
-// self
-// }
-// }
-// impl AsRef for OsString {
-// #[inline]
-// fn as_ref(&self) -> &OsStr {
-// self
-// }
-// }
-// impl AsRef for str {
-// #[inline]
-// fn as_ref(&self) -> &OsStr {
-// OsStr::from_inner(Slice::from_str(self))
-// }
-// }
-// impl AsRef for String {
-// #[inline]
-// fn as_ref(&self) -> &OsStr {
-// (&**self).as_ref()
-// }
-// }
-
-// impl FromInner for OsString {
-// #[inline]
-// fn from_inner(buf: Buf) -> OsString {
-// OsString { inner: buf }
-// }
-// }
-
-// impl IntoInner for OsString {
-// #[inline]
-// fn into_inner(self) -> Buf {
-// self.inner
-// }
-// }
-
-// impl AsInner for OsStr {
-// #[inline]
-// fn as_inner(&self) -> &Slice {
-// &self.inner
-// }
-// }
-// impl FromStr for OsString {
-// type Err = core::convert::Infallible;
-
-// #[inline]
-// fn from_str(s: &str) -> Result {
-// Ok(OsString::from(s))
-// }
-// }
-// impl Extend for OsString {
-// #[inline]
-// fn extend>(&mut self, iter: T) {
-// for s in iter {
-// self.push(&s);
-// }
-// }
-// }
-// impl<'a> Extend<&'a OsStr> for OsString {
-// #[inline]
-// fn extend>(&mut self, iter: T) {
-// for s in iter {
-// self.push(s);
-// }
-// }
-// }
-// impl<'a> Extend> for OsString {
-// #[inline]
-// fn extend>>(&mut self, iter: T) {
-// for s in iter {
-// self.push(&s);
-// }
-// }
-// }
-// impl FromIterator for OsString {
-// #[inline]
-// fn from_iter>(iter: I) -> Self {
-// let mut iterator = iter.into_iter();
-
-// // Because we're iterating over `OsString`s, we can avoid at least
-// // one allocation by getting the first string from the iterator
-// // and appending to it all the subsequent strings.
-// match iterator.next() {
-// None => OsString::new(),
-// Some(mut buf) => {
-// buf.extend(iterator);
-// buf
-// }
-// }
-// }
-// }
-// impl<'a> FromIterator<&'a OsStr> for OsString {
-// #[inline]
-// fn from_iter>(iter: I) -> Self {
-// let mut buf = Self::new();
-// for s in iter {
-// buf.push(s);
-// }
-// buf
-// }
-// }
-// impl<'a> FromIterator> for OsString {
-// #[inline]
-// fn from_iter>>(iter: I) -> Self {
-// let mut iterator = iter.into_iter();
-
-// // Because we're iterating over `OsString`s, we can avoid at least
-// // one allocation by getting the first owned string from the iterator
-// // and appending to it all the subsequent strings.
-// match iterator.next() {
-// None => OsString::new(),
-// Some(Cow::Owned(mut buf)) => {
-// buf.extend(iterator);
-// buf
-// }
-// Some(Cow::Borrowed(buf)) => {
-// let mut buf = OsString::from(buf);
-// buf.extend(iterator);
-// buf
-// }
-// }
-// }
-// }
diff --git a/crates/std/src/io.rs b/crates/std/src/io.rs
deleted file mode 100644
index 709f22d..0000000
--- a/crates/std/src/io.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-use crate::fs::File;
-use io::IoBase;
-pub use io::Read;
-pub use io::Seek;
-pub use io::SeekFrom;
-pub use io::Write;
-
-pub struct Stdin;
-
-impl IoBase for Stdin {
- type Error = ();
-}
-
-impl Read for Stdin {
- fn read(&mut self, buf: &mut [u8]) -> Result {
- unsafe { File::from_raw_fd(0).read(buf) }
- }
-}
-
-pub fn stdin() -> Stdin {
- Stdin
-}
diff --git a/crates/std/src/lib.rs b/crates/std/src/lib.rs
deleted file mode 100644
index 871b601..0000000
--- a/crates/std/src/lib.rs
+++ /dev/null
@@ -1,242 +0,0 @@
-#![no_std]
-#![allow(internal_features)]
-//
-// Language features:
-// tidy-alphabetical-start
-#![feature(alloc_error_handler)]
-#![feature(allocator_internals)]
-#![feature(allow_internal_unsafe)]
-#![feature(allow_internal_unstable)]
-#![feature(asm_experimental_arch)]
-#![feature(autodiff)]
-#![feature(cfg_sanitizer_cfi)]
-#![feature(cfg_target_thread_local)]
-#![feature(cfi_encoding)]
-#![feature(const_default)]
-#![feature(const_trait_impl)]
-#![feature(core_float_math)]
-#![feature(decl_macro)]
-#![feature(deprecated_suggestion)]
-#![feature(doc_cfg)]
-#![feature(doc_masked)]
-#![feature(doc_notable_trait)]
-#![feature(dropck_eyepatch)]
-#![feature(f16)]
-#![feature(f128)]
-#![feature(ffi_const)]
-#![feature(formatting_options)]
-#![feature(funnel_shifts)]
-#![feature(if_let_guard)]
-#![feature(intra_doc_pointers)]
-#![feature(iter_advance_by)]
-#![feature(iter_next_chunk)]
-#![feature(lang_items)]
-#![feature(link_cfg)]
-#![feature(linkage)]
-#![feature(macro_metavar_expr_concat)]
-#![feature(maybe_uninit_fill)]
-#![feature(min_specialization)]
-#![feature(must_not_suspend)]
-#![feature(needs_panic_runtime)]
-#![feature(negative_impls)]
-#![feature(never_type)]
-#![feature(optimize_attribute)]
-#![feature(prelude_import)]
-#![feature(rustc_attrs)]
-#![feature(rustdoc_internals)]
-// #![feature(staged_api)]
-#![feature(stmt_expr_attributes)]
-#![feature(strict_provenance_lints)]
-#![feature(thread_local)]
-#![feature(try_blocks)]
-#![feature(try_trait_v2)]
-#![feature(type_alias_impl_trait)]
-// tidy-alphabetical-end
-//
-// Library features (core):
-// tidy-alphabetical-start
-#![feature(bstr)]
-#![feature(bstr_internals)]
-#![feature(cast_maybe_uninit)]
-#![feature(cfg_select)]
-#![feature(char_internals)]
-#![feature(clone_to_uninit)]
-#![feature(const_convert)]
-#![feature(core_intrinsics)]
-#![feature(core_io_borrowed_buf)]
-#![feature(drop_guard)]
-#![feature(duration_constants)]
-#![feature(error_generic_member_access)]
-#![feature(error_iter)]
-#![feature(exact_size_is_empty)]
-#![feature(exclusive_wrapper)]
-#![feature(extend_one)]
-#![feature(float_algebraic)]
-// #![feature(float_gamma)]
-#![feature(float_minimum_maximum)]
-#![feature(fmt_internals)]
-#![feature(fn_ptr_trait)]
-#![feature(generic_atomic)]
-#![feature(hasher_prefixfree_extras)]
-#![feature(hashmap_internals)]
-#![feature(hint_must_use)]
-#![feature(int_from_ascii)]
-#![feature(ip)]
-#![feature(maybe_uninit_array_assume_init)]
-#![feature(panic_can_unwind)]
-#![feature(panic_internals)]
-#![feature(pin_coerce_unsized_trait)]
-#![feature(pointer_is_aligned_to)]
-#![feature(portable_simd)]
-#![feature(ptr_as_uninit)]
-#![feature(ptr_mask)]
-#![feature(random)]
-#![feature(slice_internals)]
-#![feature(slice_ptr_get)]
-#![feature(slice_range)]
-#![feature(slice_split_once)]
-#![feature(std_internals)]
-#![feature(str_internals)]
-#![feature(sync_unsafe_cell)]
-#![feature(temporary_niche_types)]
-#![feature(ub_checks)]
-#![feature(used_with_arg)]
-// tidy-alphabetical-end
-//
-// Library features (alloc):
-// tidy-alphabetical-start
-#![feature(alloc_layout_extra)]
-#![feature(allocator_api)]
-#![feature(clone_from_ref)]
-#![feature(get_mut_unchecked)]
-#![feature(map_try_insert)]
-#![feature(slice_concat_trait)]
-#![feature(thin_box)]
-#![feature(try_reserve_kind)]
-#![feature(try_with_capacity)]
-#![feature(unique_rc_arc)]
-#![feature(wtf8_internals)]
-// tidy-alphabetical-end
-//
-// Library features (unwind):
-// tidy-alphabetical-start
-// #![feature(panic_unwind)]
-// tidy-alphabetical-end
-//
-// Library features (std_detect):
-// tidy-alphabetical-start
-// #![feature(stdarch_internal)]
-// tidy-alphabetical-end
-//
-// Only for re-exporting:
-// tidy-alphabetical-start
-#![feature(assert_matches)]
-#![feature(async_iterator)]
-#![feature(c_variadic)]
-#![feature(cfg_accessible)]
-#![feature(cfg_eval)]
-#![feature(concat_bytes)]
-#![feature(const_format_args)]
-#![feature(custom_test_frameworks)]
-#![feature(edition_panic)]
-#![feature(format_args_nl)]
-#![feature(log_syntax)]
-#![feature(test)]
-#![feature(trace_macros)]
-// tidy-alphabetical-end
-//
-// Only used in tests/benchmarks:
-//
-// Only for const-ness:
-// tidy-alphabetical-start
-// #![feature(io_const_error)]
-// tidy-alphabetical-end
-//
-#![feature(c_size_t, unsafe_binders)]
-#![allow(clippy::doc_lazy_continuation, clippy::legacy_numeric_constants)]
-#![allow(stable_features, incomplete_features)]
-
-extern crate alloc;
-
-pub use core::any;
-pub use core::array;
-pub use core::async_iter;
-pub use core::cell;
-pub use core::char;
-pub use core::clone;
-pub use core::cmp;
-pub use core::convert;
-pub use core::default;
-pub use core::future;
-pub use core::hint;
-#[allow(deprecated, deprecated_in_future)]
-pub use core::i8;
-#[allow(deprecated, deprecated_in_future)]
-pub use core::i16;
-#[allow(deprecated, deprecated_in_future)]
-pub use core::i32;
-#[allow(deprecated, deprecated_in_future)]
-pub use core::i64;
-#[allow(deprecated, deprecated_in_future)]
-pub use core::i128;
-pub use core::intrinsics;
-#[allow(deprecated, deprecated_in_future)]
-pub use core::isize;
-pub use core::iter;
-pub use core::marker;
-pub use core::mem;
-pub use core::ops;
-pub use core::option;
-pub use core::pin;
-pub use core::ptr;
-pub use core::range;
-pub use core::result;
-#[allow(deprecated, deprecated_in_future)]
-pub use core::u8;
-#[allow(deprecated, deprecated_in_future)]
-pub use core::u16;
-#[allow(deprecated, deprecated_in_future)]
-pub use core::u32;
-#[allow(deprecated, deprecated_in_future)]
-pub use core::u64;
-#[allow(deprecated, deprecated_in_future)]
-pub use core::u128;
-pub use core::unsafe_binder;
-#[allow(deprecated, deprecated_in_future)]
-pub use core::usize;
-
-pub use alloc::borrow;
-pub use alloc::boxed;
-pub use alloc::fmt;
-pub use alloc::format;
-pub use alloc::rc;
-pub use alloc::slice;
-pub use alloc::str;
-pub use alloc::string;
-pub use alloc::vec;
-
-pub mod ffi;
-pub mod io;
-pub mod prelude;
-pub mod process;
-
-pub use shared::fs;
-pub use shared::syscall;
-
-#[macro_export]
-macro_rules! print {
- ($($args:expr),*) => {
- $crate::syscall::write_string_temp(&format!($($args),*))
- };
-}
-#[macro_export]
-macro_rules! println {
- () => {
- $crate::print!("");
- // $crate::print!("\n\r");
- };
- ($($args:expr),*) => {
- $crate::print!($($args),*);
- // $crate::println!();
- };
-}
diff --git a/crates/std/src/prelude.rs b/crates/std/src/prelude.rs
deleted file mode 100644
index 895a601..0000000
--- a/crates/std/src/prelude.rs
+++ /dev/null
@@ -1,54 +0,0 @@
-pub mod rust_2024 {
- pub use crate::print;
- pub use crate::println;
- pub use alloc::borrow::ToOwned;
- pub use alloc::format;
- pub use alloc::string::String;
- pub use alloc::vec;
-
- extern crate alloc;
-
- struct GlobalAllocator;
-
- #[core::prelude::v1::global_allocator]
- static GLOBAL_ALLOCATOR: GlobalAllocator = GlobalAllocator;
-
- unsafe impl core::alloc::GlobalAlloc for GlobalAllocator {
- unsafe fn alloc(&self, layout: core::alloc::Layout) -> *mut u8 {
- crate::syscall::alloc(layout)
- }
-
- unsafe fn dealloc(&self, ptr: *mut u8, layout: core::alloc::Layout) {
- crate::syscall::dealloc(ptr, layout)
- }
- }
-
- #[panic_handler]
- fn panic(_panic_info: &core::panic::PanicInfo) -> ! {
- // TODO print
- loop {}
- }
-
- /// # Safety
- /// `argc` and `argv` are passed by the kernel
- #[unsafe(no_mangle)]
- pub unsafe extern "C" fn _start(argc: isize, argv: *const *const u8) -> isize {
- unsafe extern "Rust" {
- fn main(argc: isize, argv: *const *const u8) -> isize;
- }
-
- unsafe { main(argc, argv) }
- }
-
- #[lang = "start"]
- pub fn lang_start(
- main: fn() -> T,
- argc: isize,
- argv: *const *const u8,
- _sigpipe: u8,
- ) -> isize {
- println!("{}", argc);
- println!("{:?}", argv);
- main().report().to_isize()
- }
-}
diff --git a/crates/std/src/process.rs b/crates/std/src/process.rs
deleted file mode 100644
index 11e4ff4..0000000
--- a/crates/std/src/process.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-pub struct ExitCode(isize);
-
-impl ExitCode {
- pub const SUCCESS: ExitCode = ExitCode(0);
-
- pub fn to_isize(self) -> isize {
- self.0
- }
-}
-
-#[lang = "termination"]
-pub trait Termination {
- /// Is called to get the representation of the value as status code.
- /// This status code is returned to the operating system.
- fn report(self) -> ExitCode;
-}
-
-impl Termination for () {
- #[inline]
- fn report(self) -> ExitCode {
- ExitCode::SUCCESS
- }
-}
-impl Termination for isize {
- #[inline]
- fn report(self) -> ExitCode {
- ExitCode(self)
- }
-}
diff --git a/justfile b/justfile
index d8c779b..c2753dc 100644
--- a/justfile
+++ b/justfile
@@ -2,7 +2,6 @@ release := ""
qemu_flags := ""
cargo_flags := "" + if release != "" { "--release" } else { "" }
bin_path := if release != "" { "target/riscv64/release" } else { "target/riscv64/debug" }
-rust_src := `rustc --print sysroot` / "lib/rustlib/src/rust/library/std/src"
default: run
@@ -13,25 +12,19 @@ mount_filesystem:
sync_filesystem:
sync
-cp_std path:
- @echo "Copying {{ path }}"
- @mkdir {{ "crates/std/src" / parent_directory(path) }} -p
- @cp {{ rust_src / path }} {{ "crates/std/src" / path }}
- @perl -i -0777 -pe 's/^\s*#!?\[(un)?stable\(.*?\)\s*\]\n//gsm' {{ "crates/std/src" / path }}
- @perl -i -0777 -pe 's/^\s*#!?\[rustc_.*?\]\n//gsm' {{ "crates/std/src" / path }}
+update-std:
+ @cd library/std && just update-std
-update_std:
- @just cp_std "ffi/c_str.rs"
- @just cp_std "ffi/mod.rs"
- @just cp_std "ffi/os_str.rs"
+build-sysroot:
+ @cd library/std && just build-sysroot
build_user_prog prog:
- RUSTFLAGS="-C relocation-model=pic -C link-arg=-Tuser.ld -C link-arg=-pie" cargo b {{ cargo_flags }} --package {{ prog }}
+ RUSTFLAGS="-C relocation-model=pic -C link-arg=-pie --sysroot {{ justfile_directory() / "sysroot" }}" cargo b {{ cargo_flags }} --package {{ prog }}
riscv64-elf-strip {{ bin_path / prog }}
cp {{ bin_path / prog }} {{ "mnt/usr/bin" / prog }}
build: mount_filesystem (map_dir "user" f"just release=\"{{release}}\" cargo_flags=\"{{cargo_flags}}\" build_user_prog")
- cargo b {{ cargo_flags }}
+ RUSTFLAGS="-Clink-arg=-Tilm.ld --sysroot {{ justfile_directory() / "sysroot" }}" cargo b {{ cargo_flags }}
just sync_filesystem
run: build (runner f"{{bin_path / "kernel-rust"}}")
@@ -66,4 +59,5 @@ runner args:
{{ qemu }} -kernel {{ args }}
clean:
+ cd library && just clean
cargo clean
diff --git a/library/.gitignore b/library/.gitignore
new file mode 100644
index 0000000..efc0ca5
--- /dev/null
+++ b/library/.gitignore
@@ -0,0 +1,17 @@
+portable-simd
+core_arch
+core
+compiler-builtins
+alloc
+stdarch
+unwind
+std_detect
+panic_abort
+panic_unwind
+rustc-std-workspace-alloc
+rustc-std-workspace-core
+rustc-std-workspace-std
+windows_link
+profiler_builtins
+test
+proc_macro
diff --git a/library/Cargo.toml b/library/Cargo.toml
new file mode 100644
index 0000000..ab037e8
--- /dev/null
+++ b/library/Cargo.toml
@@ -0,0 +1,88 @@
+
+cargo-features = ["profile-rustflags"]
+
+[workspace]
+resolver = "1"
+members = [
+ "std",
+ # "sysroot",
+ # "coretests",
+ # "alloctests",
+]
+
+exclude = [
+ # stdarch has its own Cargo workspace
+ "stdarch",
+ "windows_link"
+]
+
+[profile.release.package.compiler_builtins]
+# For compiler-builtins we always use a high number of codegen units.
+# The goal here is to place every single intrinsic into its own object
+# file to avoid symbol clashes with the system libgcc if possible. Note
+# that this number doesn't actually produce this many object files, we
+# just don't create more than this number of object files.
+#
+# It's a bit of a bummer that we have to pass this here, unfortunately.
+# Ideally this would be specified through an env var to Cargo so Cargo
+# knows how many CGUs are for this specific crate, but for now
+# per-crate configuration isn't specifiable in the environment.
+codegen-units = 10000
+
+# These dependencies of the standard library implement symbolication for
+# backtraces on most platforms. Their debuginfo causes both linking to be slower
+# (more data to chew through) and binaries to be larger without really all that
+# much benefit. This section turns them all to down to have no debuginfo which
+# helps to improve link times a little bit.
+[profile.release.package]
+addr2line.debug = 0
+addr2line.opt-level = "s"
+adler2.debug = 0
+gimli.debug = 0
+gimli.opt-level = "s"
+miniz_oxide.debug = 0
+miniz_oxide.opt-level = "s"
+# `opt-level = "s"` for `object` led to a size regression when tried previously
+object.debug = 0
+rustc-demangle.debug = 0
+rustc-demangle.opt-level = "s"
+
+# panic_abort must always be compiled with panic=abort, even when the rest of the
+# sysroot is panic=unwind.
+[profile.dev.package.panic_abort]
+rustflags = ["-Cpanic=abort"]
+
+[profile.release.package.panic_abort]
+rustflags = ["-Cpanic=abort"]
+
+# The "dist" profile is used by bootstrap for prebuilt libstd artifacts
+# These settings ensure that the prebuilt artifacts support a variety of features
+# in the user's profile.
+[profile.dist]
+inherits = "release"
+codegen-units = 1
+debug = 1 # "limited"
+rustflags = [
+ # `profile.lto=off` implies `-Cembed-bitcode=no`, but unconditionally embedding
+ # bitcode is necessary for when users enable LTO.
+ # Required until Cargo can re-build the standard library based on the value
+ # of `profile.lto` in the user's profile.
+ "-Cembed-bitcode=yes",
+ # Enable frame pointers
+ "-Zunstable-options",
+ "-Cforce-frame-pointers=non-leaf",
+]
+
+[profile.dist.package.panic_abort]
+rustflags = [
+ "-Cpanic=abort",
+ "-Cembed-bitcode=yes",
+ "-Zunstable-options",
+ "-Cforce-frame-pointers=non-leaf",
+]
+
+[patch.crates-io]
+# See comments in `library/rustc-std-workspace-core/README.md` for what's going on here
+rustc-std-workspace-core = { path = 'rustc-std-workspace-core' }
+rustc-std-workspace-alloc = { path = 'rustc-std-workspace-alloc' }
+# rustc-std-workspace-std = { path = 'rustc-std-workspace-std' }
diff --git a/library/backtrace b/library/backtrace
new file mode 160000
index 0000000..28ec93b
--- /dev/null
+++ b/library/backtrace
@@ -0,0 +1 @@
+Subproject commit 28ec93b503bf0410745bc3d571bf3dc1caac3019
diff --git a/library/justfile b/library/justfile
new file mode 100644
index 0000000..c0d1165
--- /dev/null
+++ b/library/justfile
@@ -0,0 +1,319 @@
+SRC_DIR := "std/src"
+PATCH_DIR := "std/patches"
+RUST_SRC := `rustc --print sysroot` / "lib/rustlib/src/rust/library"
+
+patch-std:
+ @echo "Start patching the std..."
+ @find {{ PATCH_DIR }} -type f | while read -r patch_file; do \
+ relative_path="${patch_file#{{ PATCH_DIR }}/}"; \
+ target_file="${relative_path%.sed}.rs"; \
+ if [ -f "{{ SRC_DIR }}/$target_file" ]; then \
+ echo " [SED] $target_file"; \
+ sed -i -f "$patch_file" "{{ SRC_DIR }}/$target_file"; \
+ else \
+ echo "⚠ [WARN] target doesn't exist: $target_file"; \
+ fi; \
+ done
+ @echo "✅ Patching done."
+
+update-std:
+ @just setup-std
+ @just patch-std
+
+cp_std path:
+ @echo "Linking {{ path }}"
+ @mkdir {{ "std/src" / parent_directory(path) }} -p
+ @ln -fs {{ RUST_SRC / "std/src" / path }} {{ "std/src" / parent_directory(path) }}
+
+real_cp_std path:
+ @echo "Copying {{ path }}"
+ @mkdir {{ "std/src" / parent_directory(path) }} -p
+ @cp {{ RUST_SRC / "std/src" / path }} {{ "std/src" / path }}
+
+setup-std:
+ ln -fs {{ RUST_SRC / "std_detect" }} "."
+ ln -fs {{ RUST_SRC / "panic_abort" }} "."
+ ln -fs {{ RUST_SRC / "panic_unwind" }} "."
+ ln -fs {{ RUST_SRC / "windows_link" }} "."
+ ln -fs {{ RUST_SRC / "unwind" }} "."
+ ln -fs {{ RUST_SRC / "alloc" }} "."
+ ln -fs {{ RUST_SRC / "rustc-std-workspace-alloc" }} "."
+ ln -fs {{ RUST_SRC / "rustc-std-workspace-core" }} "."
+ ln -fs {{ RUST_SRC / "rustc-std-workspace-std" }} "."
+ ln -fs {{ RUST_SRC / "compiler-builtins" }} "."
+ ln -fs {{ RUST_SRC / "core" }} "."
+ ln -fs {{ RUST_SRC / "stdarch" }} "."
+ ln -fs {{ RUST_SRC / "portable-simd" }} "."
+ ln -fs {{ RUST_SRC / "proc_macro" }} "."
+ ln -fs {{ RUST_SRC / "profiler_builtins" }} "."
+ ln -fs {{ RUST_SRC / "test" }} "."
+
+ @just cp_std "../build.rs"
+ @sed -i "59a\ || target_os == \"survos\"" std/build.rs
+
+ @just cp_std "alloc.rs"
+ @just cp_std "ascii.rs"
+ @just cp_std "backtrace.rs"
+ @just cp_std "bstr.rs"
+ @just cp_std "env.rs"
+ @just cp_std "error.rs"
+ @just cp_std "fs.rs"
+ @just cp_std "keyword_docs.rs"
+ @just cp_std "lib.rs"
+ @just cp_std "macros.rs"
+ @just cp_std "panic.rs"
+ @just cp_std "panicking.rs"
+ @just cp_std "pat.rs"
+ @just cp_std "path.rs"
+ @just cp_std "process.rs"
+ @just cp_std "random.rs"
+ @just cp_std "rt.rs"
+ @just cp_std "tests_helpers.rs"
+ @just cp_std "time.rs"
+
+ @just cp_std "backtrace"
+
+ @just cp_std "collections"
+
+ @just cp_std "ffi"
+
+ @just cp_std "fs"
+
+ @just cp_std "hash"
+
+ @just cp_std "io"
+
+ @just cp_std "net"
+
+ @just cp_std "num"
+
+ @just cp_std "os/raw/mod.rs"
+ @just cp_std "os/raw/tests.rs"
+ @just cp_std "os/mod.rs"
+
+ @just cp_std "prelude"
+
+ @just cp_std "process"
+
+ @just cp_std "sync"
+
+ @just cp_std "sys/alloc/mod.rs"
+
+ @just real_cp_std "sys/args/mod.rs"
+ @just cp_std "sys/args/unsupported.rs"
+
+ @just cp_std "sys/env/mod.rs"
+ @just cp_std "sys/env/common.rs"
+ @just cp_std "sys/env/unsupported.rs"
+
+ @just cp_std "sys/fd/mod.rs"
+
+ @just cp_std "sys/fs/mod.rs"
+ @just cp_std "sys/fs/common.rs"
+ @just cp_std "sys/fs/unsupported.rs"
+
+ @just cp_std "sys/helpers/mod.rs"
+ @just cp_std "sys/helpers/small_c_string.rs"
+ @just cp_std "sys/helpers/tests.rs"
+ @just cp_std "sys/helpers/wstr.rs"
+
+ @just cp_std "sys/io/error/generic.rs"
+ @just real_cp_std "sys/io/error/mod.rs"
+ @just cp_std "sys/io/io_slice/unsupported.rs"
+ @just cp_std "sys/io/is_terminal/unsupported.rs"
+ @just cp_std "sys/io/kernel_copy/mod.rs"
+ @just cp_std "sys/io/mod.rs"
+
+ @just cp_std "sys/net/connection/mod.rs"
+ @just cp_std "sys/net/connection/unsupported.rs"
+ @just cp_std "sys/net/hostname/mod.rs"
+ @just cp_std "sys/net/hostname/unsupported.rs"
+ @just cp_std "sys/net/mod.rs"
+
+ @just cp_std "sys/os_str/bytes/tests.rs"
+ @just cp_std "sys/os_str/bytes.rs"
+ @just cp_std "sys/os_str/mod.rs"
+
+ @just real_cp_std "sys/pal/mod.rs"
+ @just cp_std "sys/pal/unsupported/mod.rs"
+ @just cp_std "sys/pal/unsupported/common.rs"
+ @just cp_std "sys/pal/unsupported/os.rs"
+
+ @just cp_std "sys/path/mod.rs"
+ @just cp_std "sys/path/unix.rs"
+
+ @just cp_std "sys/personality/dwarf/eh.rs"
+ @just cp_std "sys/personality/dwarf/mod.rs"
+ @just cp_std "sys/personality/dwarf/tests.rs"
+ @just cp_std "sys/personality/mod.rs"
+
+ @just cp_std "sys/pipe/mod.rs"
+ @just cp_std "sys/pipe/unsupported.rs"
+
+ @just cp_std "sys/platform_version/mod.rs"
+
+ @just cp_std "sys/process/mod.rs"
+ @just cp_std "sys/process/env.rs"
+ @just cp_std "sys/process/unsupported.rs"
+
+ @just real_cp_std "sys/random/mod.rs"
+ @just cp_std "sys/random/unsupported.rs"
+
+ @just cp_std "sys/stdio/mod.rs"
+ @just cp_std "sys/stdio/unsupported.rs"
+
+ @just cp_std "sys/sync/condvar/mod.rs"
+ @just cp_std "sys/sync/condvar/no_threads.rs"
+ @just cp_std "sys/sync/mutex/mod.rs"
+ @just cp_std "sys/sync/mutex/no_threads.rs"
+ @just cp_std "sys/sync/once/mod.rs"
+ @just cp_std "sys/sync/once/no_threads.rs"
+ @just cp_std "sys/sync/rwlock/mod.rs"
+ @just cp_std "sys/sync/rwlock/no_threads.rs"
+ @just cp_std "sys/sync/thread_parking/mod.rs"
+ @just cp_std "sys/sync/thread_parking/unsupported.rs"
+ @just cp_std "sys/sync/mod.rs"
+ @just cp_std "sys/sync/once_box.rs"
+
+ @just cp_std "sys/thread/mod.rs"
+ @just cp_std "sys/thread/unsupported.rs"
+
+ @just real_cp_std "sys/thread_local/mod.rs"
+ @just cp_std "sys/thread_local/no_threads.rs"
+ @just cp_std "sys/thread_local/os.rs"
+
+ @just cp_std "sys/time/mod.rs"
+ @just cp_std "sys/time/unsupported.rs"
+
+ @just cp_std "sys/backtrace.rs"
+ @just cp_std "sys/cmath.rs"
+ @just cp_std "sys/configure_builtins.rs"
+ @just cp_std "sys/env_consts.rs"
+ @just cp_std "sys/exit.rs"
+ @just cp_std "sys/mod.rs"
+
+ @just cp_std "thread"
+
+STD_FILES := "alloc.rs \
+ascii.rs \
+backtrace.rs \
+bstr.rs \
+env.rs \
+error.rs \
+fs.rs \
+keyword_docs.rs \
+lib.rs \
+macros.rs \
+panic.rs \
+panicking.rs \
+pat.rs \
+path.rs \
+process.rs \
+random.rs \
+rt.rs \
+tests_helpers.rs \
+time.rs \
+backtrace \
+collections \
+ffi \
+fs \
+hash \
+io \
+net \
+num \
+os/raw/mod.rs \
+os/raw/tests.rs \
+os/mod.rs \
+prelude \
+process \
+sync \
+sys/alloc/mod.rs \
+sys/args/mod.rs \
+sys/args/unsupported.rs \
+sys/env/mod.rs \
+sys/env/common.rs \
+sys/env/unsupported.rs \
+sys/fd/mod.rs \
+sys/fs/mod.rs \
+sys/fs/common.rs \
+sys/fs/unsupported.rs \
+sys/helpers/mod.rs \
+sys/helpers/small_c_string.rs \
+sys/helpers/tests.rs \
+sys/helpers/wstr.rs \
+sys/io/error/generic.rs \
+sys/io/error/mod.rs \
+sys/io/io_slice/unsupported.rs \
+sys/io/is_terminal/unsupported.rs \
+sys/io/kernel_copy/mod.rs \
+sys/io/mod.rs \
+sys/net/connection/mod.rs \
+sys/net/connection/unsupported.rs \
+sys/net/hostname/mod.rs \
+sys/net/hostname/unsupported.rs \
+sys/net/mod.rs \
+sys/os_str/bytes/tests.rs \
+sys/os_str/bytes.rs \
+sys/os_str/mod.rs \
+sys/pal/mod.rs \
+sys/pal/unsupported/mod.rs \
+sys/pal/unsupported/common.rs \
+sys/pal/unsupported/os.rs \
+sys/path/mod.rs \
+sys/path/unix.rs \
+sys/personality/dwarf/eh.rs \
+sys/personality/dwarf/mod.rs \
+sys/personality/dwarf/tests.rs \
+sys/personality/mod.rs \
+sys/pipe/mod.rs \
+sys/pipe/unsupported.rs \
+sys/platform_version/mod.rs \
+sys/process/mod.rs \
+sys/process/env.rs \
+sys/process/unsupported.rs \
+sys/random/mod.rs \
+sys/random/unsupported.rs \
+sys/stdio/mod.rs \
+sys/stdio/unsupported.rs \
+sys/sync/condvar/mod.rs \
+sys/sync/condvar/no_threads.rs \
+sys/sync/mutex/mod.rs \
+sys/sync/mutex/no_threads.rs \
+sys/sync/once/mod.rs \
+sys/sync/once/no_threads.rs \
+sys/sync/rwlock/mod.rs \
+sys/sync/rwlock/no_threads.rs \
+sys/sync/thread_parking/mod.rs \
+sys/sync/thread_parking/unsupported.rs \
+sys/sync/mod.rs \
+sys/sync/once_box.rs \
+sys/thread/mod.rs \
+sys/thread/unsupported.rs \
+sys/thread_local/mod.rs \
+sys/thread_local/no_threads.rs \
+sys/thread_local/os.rs \
+sys/time/mod.rs \
+sys/time/unsupported.rs \
+sys/backtrace.rs \
+sys/cmath.rs \
+sys/configure_builtins.rs \
+sys/env_consts.rs \
+sys/exit.rs \
+sys/mod.rs \
+thread"
+
+build-sysroot: update-std
+ RUSTFLAGS="-Zforce-unstable-if-unmarked -C relocation-model=pic -C link-arg=-pie" cargo build --target ../riscv64.json
+ mkdir ../sysroot/lib/rustlib/riscv64/lib -p
+ rm ../sysroot/lib/rustlib/riscv64/lib/* -rf
+ cp target/riscv64/debug/deps/*.rlib ../sysroot/lib/rustlib/riscv64/lib
+
+clean:
+ # cargo clean
+ rm ../sysroot/lib/rustlib/riscv64/lib/* -rf
+
+ for file in {{ STD_FILES }}; do \
+ rm -rf std/src/$file; \
+ done
+
+ rm -rf std/build.rs
diff --git a/library/std/.gitignore b/library/std/.gitignore
new file mode 100644
index 0000000..6abdf1c
--- /dev/null
+++ b/library/std/.gitignore
@@ -0,0 +1,109 @@
+build.rs
+
+src/alloc.rs
+src/ascii.rs
+src/backtrace.rs
+src/bstr.rs
+src/env.rs
+src/error.rs
+src/fs.rs
+src/keyword_docs.rs
+src/lib.rs
+src/macros.rs
+src/panic.rs
+src/panicking.rs
+src/pat.rs
+src/path.rs
+src/process.rs
+src/random.rs
+src/rt.rs
+src/tests_helpers.rs
+src/time.rs
+src/backtrace
+src/collections
+src/ffi
+src/fs
+src/hash
+src/io
+src/net
+src/num
+src/os/raw/mod.rs
+src/os/raw/tests.rs
+src/os/mod.rs
+src/prelude
+src/process
+src/sync
+src/sys/alloc/mod.rs
+src/sys/args/mod.rs
+src/sys/args/unsupported.rs
+src/sys/env/mod.rs
+src/sys/env/common.rs
+src/sys/env/unsupported.rs
+src/sys/fd/mod.rs
+src/sys/fs/mod.rs
+src/sys/fs/common.rs
+src/sys/fs/unsupported.rs
+src/sys/helpers/mod.rs
+src/sys/helpers/small_c_string.rs
+src/sys/helpers/tests.rs
+src/sys/helpers/wstr.rs
+src/sys/io/error/generic.rs
+src/sys/io/error/mod.rs
+src/sys/io/io_slice/unsupported.rs
+src/sys/io/is_terminal/unsupported.rs
+src/sys/io/kernel_copy/mod.rs
+src/sys/io/mod.rs
+src/sys/net/connection/mod.rs
+src/sys/net/connection/unsupported.rs
+src/sys/net/hostname/mod.rs
+src/sys/net/hostname/unsupported.rs
+src/sys/net/mod.rs
+src/sys/os_str/bytes/tests.rs
+src/sys/os_str/bytes.rs
+src/sys/os_str/mod.rs
+src/sys/pal/mod.rs
+src/sys/pal/unsupported/mod.rs
+src/sys/pal/unsupported/common.rs
+src/sys/pal/unsupported/os.rs
+src/sys/path/mod.rs
+src/sys/path/unix.rs
+src/sys/personality/dwarf/eh.rs
+src/sys/personality/dwarf/mod.rs
+src/sys/personality/dwarf/tests.rs
+src/sys/personality/mod.rs
+src/sys/pipe/mod.rs
+src/sys/pipe/unsupported.rs
+src/sys/platform_version/mod.rs
+src/sys/process/mod.rs
+src/sys/process/env.rs
+src/sys/process/unsupported.rs
+src/sys/random/mod.rs
+src/sys/random/unsupported.rs
+src/sys/stdio/mod.rs
+src/sys/stdio/unsupported.rs
+src/sys/sync/condvar/mod.rs
+src/sys/sync/condvar/no_threads.rs
+src/sys/sync/mutex/mod.rs
+src/sys/sync/mutex/no_threads.rs
+src/sys/sync/once/mod.rs
+src/sys/sync/once/no_threads.rs
+src/sys/sync/rwlock/mod.rs
+src/sys/sync/rwlock/no_threads.rs
+src/sys/sync/thread_parking/mod.rs
+src/sys/sync/thread_parking/unsupported.rs
+src/sys/sync/mod.rs
+src/sys/sync/once_box.rs
+src/sys/thread/mod.rs
+src/sys/thread/unsupported.rs
+src/sys/thread_local/mod.rs
+src/sys/thread_local/no_threads.rs
+src/sys/thread_local/os.rs
+src/sys/time/mod.rs
+src/sys/time/unsupported.rs
+src/sys/backtrace.rs
+src/sys/cmath.rs
+src/sys/configure_builtins.rs
+src/sys/env_consts.rs
+src/sys/exit.rs
+src/sys/mod.rs
+src/thread
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
new file mode 100644
index 0000000..388d917
--- /dev/null
+++ b/library/std/Cargo.toml
@@ -0,0 +1,177 @@
+cargo-features = ["public-dependency"]
+
+[package]
+name = "std"
+version = "0.0.0"
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/rust-lang/rust.git"
+description = "The Rust Standard Library"
+edition = "2024"
+autobenches = false
+
+[lib]
+crate-type = ["dylib", "rlib"]
+
+[dependencies]
+alloc = { path = "../alloc", public = true }
+# std no longer uses cfg-if directly, but the included copy of backtrace does.
+cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
+panic_unwind = { path = "../panic_unwind", optional = true }
+panic_abort = { path = "../panic_abort" }
+core = { path = "../core", public = true }
+unwind = { path = "../unwind" }
+hashbrown = { version = "0.16.1", default-features = false, features = [
+ 'rustc-dep-of-std',
+] }
+std_detect = { path = "../std_detect", public = true }
+
+# Dependencies of the `backtrace` crate
+rustc-demangle = { version = "0.1.27", features = ['rustc-dep-of-std'] }
+
+[target.'cfg(not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))))'.dependencies]
+miniz_oxide = { version = "0.8.0", optional = true, default-features = false }
+addr2line = { version = "0.25.0", optional = true, default-features = false }
+
+[target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies]
+libc = { version = "0.2.178", default-features = false, features = [
+ 'rustc-dep-of-std',
+], public = true }
+
+[target.'cfg(all(not(target_os = "aix"), not(all(windows, target_env = "msvc", not(target_vendor = "uwp")))))'.dependencies]
+object = { version = "0.37.1", default-features = false, optional = true, features = [
+ 'read_core',
+ 'elf',
+ 'macho',
+ 'pe',
+ 'unaligned',
+ 'archive',
+] }
+
+[target.'cfg(target_os = "aix")'.dependencies]
+object = { version = "0.37.1", default-features = false, optional = true, features = [
+ 'read_core',
+ 'xcoff',
+ 'unaligned',
+ 'archive',
+] }
+
+[target.'cfg(any(windows, target_os = "cygwin"))'.dependencies.windows-link]
+path = "../windows_link"
+
+[dev-dependencies]
+rand = { version = "0.9.0", default-features = false, features = ["alloc"] }
+rand_xorshift = "0.4.0"
+
+[target.'cfg(any(all(target_family = "wasm", target_os = "unknown"), target_os = "xous", target_os = "vexos", all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies]
+dlmalloc = { version = "0.2.10", features = ['rustc-dep-of-std'] }
+
+[target.x86_64-fortanix-unknown-sgx.dependencies]
+fortanix-sgx-abi = { version = "0.6.1", features = [
+ 'rustc-dep-of-std',
+], public = true }
+
+[target.'cfg(target_os = "motor")'.dependencies]
+moto-rt = { version = "0.16", features = ['rustc-dep-of-std'], public = true }
+
+[target.'cfg(target_os = "hermit")'.dependencies]
+hermit-abi = { version = "0.5.0", features = [
+ 'rustc-dep-of-std',
+], public = true }
+
+[target.'cfg(all(target_os = "wasi", target_env = "p1"))'.dependencies]
+wasi = { version = "0.11.0", features = [
+ 'rustc-dep-of-std',
+], default-features = false }
+
+[target.'cfg(all(target_os = "wasi", target_env = "p2"))'.dependencies]
+wasip2 = { version = '0.14.4', features = [
+ 'rustc-dep-of-std',
+], default-features = false, package = 'wasi' }
+
+[target.'cfg(all(target_os = "wasi", target_env = "p3"))'.dependencies]
+wasip2 = { version = '0.14.4', features = [
+ 'rustc-dep-of-std',
+], default-features = false, package = 'wasi' }
+
+[target.'cfg(target_os = "uefi")'.dependencies]
+r-efi = { version = "5.2.0", features = ['rustc-dep-of-std'] }
+r-efi-alloc = { version = "2.0.0", features = ['rustc-dep-of-std'] }
+
+[target.'cfg(target_os = "vexos")'.dependencies]
+vex-sdk = { version = "0.27.0", features = [
+ 'rustc-dep-of-std',
+], default-features = false }
+
+[features]
+default = ["compiler-builtins-mem"]
+backtrace = [
+ 'addr2line/rustc-dep-of-std',
+ 'object/rustc-dep-of-std',
+ 'miniz_oxide/rustc-dep-of-std',
+]
+# Disable symbolization in backtraces. For use with -Zbuild-std.
+# FIXME: Ideally this should be an additive backtrace-symbolization feature
+backtrace-trace-only = []
+
+panic-unwind = ["dep:panic_unwind"]
+compiler-builtins-c = ["alloc/compiler-builtins-c"]
+compiler-builtins-mem = ["alloc/compiler-builtins-mem"]
+llvm-libunwind = ["unwind/llvm-libunwind"]
+system-llvm-libunwind = ["unwind/system-llvm-libunwind"]
+
+# Choose algorithms that are optimized for binary size instead of runtime performance
+optimize_for_size = ["core/optimize_for_size", "alloc/optimize_for_size"]
+
+# Make `RefCell` store additional debugging information, which is printed out when
+# a borrow error occurs
+debug_refcell = ["core/debug_refcell"]
+
+llvm_enzyme = ["core/llvm_enzyme"]
+
+# Enable using raw-dylib for Windows imports.
+# This will eventually be the default.
+windows_raw_dylib = ["windows-link/windows_raw_dylib"]
+
+[package.metadata.fortanix-sgx]
+# Maximum possible number of threads when testing
+threads = 125
+# Maximum heap size
+heap_size = 0x8000000
+
+[[test]]
+name = "pipe-subprocess"
+path = "tests/pipe_subprocess.rs"
+harness = false
+
+[[test]]
+name = "sync"
+path = "tests/sync/lib.rs"
+
+[[test]]
+name = "thread_local"
+path = "tests/thread_local/lib.rs"
+
+[[bench]]
+name = "stdbenches"
+path = "benches/lib.rs"
+test = true
+
+[lints.rust.unexpected_cfgs]
+level = "warn"
+check-cfg = [
+ # std use #[path] imports to portable-simd `std_float` crate
+ # and to the `backtrace` crate which messes-up with Cargo list
+ # of declared features, we therefor expect any feature cfg
+ 'cfg(feature, values(any()))',
+ # Internal features aren't marked known config by default, we use these to
+ # gate tests.
+ 'cfg(target_has_reliable_f16)',
+ 'cfg(target_has_reliable_f16_math)',
+ 'cfg(target_has_reliable_f128)',
+ 'cfg(target_has_reliable_f128_math)',
+]
+
+
+
+# shared = { path = "../shared", features = ["user"] }
+# io_crate = { package = "io", path = "../io", features = ["alloc_crate"] }
diff --git a/library/std/patches/sys/args/mod.sed b/library/std/patches/sys/args/mod.sed
new file mode 100644
index 0000000..cd70d7a
--- /dev/null
+++ b/library/std/patches/sys/args/mod.sed
@@ -0,0 +1,4 @@
+# 55a \ target_os = "survos" => { \
+# mod survos; \
+# pub use survos::*; \
+# }
diff --git a/library/std/patches/sys/io/error/mod.sed b/library/std/patches/sys/io/error/mod.sed
new file mode 100644
index 0000000..3c6f879
--- /dev/null
+++ b/library/std/patches/sys/io/error/mod.sed
@@ -0,0 +1 @@
+45a \ target_os = "survos",
diff --git a/library/std/patches/sys/pal/mod.sed b/library/std/patches/sys/pal/mod.sed
new file mode 100644
index 0000000..acd2d76
--- /dev/null
+++ b/library/std/patches/sys/pal/mod.sed
@@ -0,0 +1,6 @@
+62a \ target_os = "survos" => { \
+ mod unsupported; \
+ pub use self::unsupported::*; \
+ mod survos; \
+ pub use self::survos::*; \
+ }
diff --git a/library/std/patches/sys/random/mod.sed b/library/std/patches/sys/random/mod.sed
new file mode 100644
index 0000000..32c4012
--- /dev/null
+++ b/library/std/patches/sys/random/mod.sed
@@ -0,0 +1,2 @@
+108a \target_os = "survos",
+124a \target_os = "survos",
diff --git a/library/std/patches/sys/thread_local/mod.sed b/library/std/patches/sys/thread_local/mod.sed
new file mode 100644
index 0000000..d436d18
--- /dev/null
+++ b/library/std/patches/sys/thread_local/mod.sed
@@ -0,0 +1,6 @@
+32a \ target_os = "survos",
+
+129a \ target_os = "survos" => { \
+ // todo \
+ pub(crate) fn enable() {} \
+ }
diff --git a/library/std/riscv64.json b/library/std/riscv64.json
new file mode 100644
index 0000000..1801bfe
--- /dev/null
+++ b/library/std/riscv64.json
@@ -0,0 +1,22 @@
+{
+ "llvm-target": "riscv64",
+ "llvm-abiname": "lp64",
+ "abi": "lp64",
+ "data-layout": "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
+ "target-endian": "little",
+ "target-pointer-width": 64,
+ "arch": "riscv64",
+ "os": "survos",
+ "vendor": "unknown",
+ "env": "",
+ "features": "+i,+m,+a,+zicsr",
+ "linker": "ld.lld",
+ "linker-flavor": "ld",
+ "executables": true,
+ "panic-strategy": "abort",
+ "relocation-model": "static",
+ "disable-redzone": true,
+ "emit-debug-gdb-scripts": false,
+ "eh-frame-header": false,
+ "code-model": "medium"
+}
diff --git a/library/std/src/sys/pal/survos.rs b/library/std/src/sys/pal/survos.rs
new file mode 100644
index 0000000..e68ea1d
--- /dev/null
+++ b/library/std/src/sys/pal/survos.rs
@@ -0,0 +1,11 @@
+/// # Safety
+/// `argc` and `argv` are passed by the kernel
+#[unsafe(no_mangle)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub unsafe extern "C" fn _start(argc: isize, argv: *const *const u8) -> isize {
+ unsafe extern "C" {
+ fn main(argc: isize, argv: *const *const u8) -> isize;
+ }
+
+ unsafe { main(argc, argv) }
+}
diff --git a/riscv64.json b/riscv64.json
index 7d21f3a..1801bfe 100644
--- a/riscv64.json
+++ b/riscv64.json
@@ -6,7 +6,7 @@
"target-endian": "little",
"target-pointer-width": 64,
"arch": "riscv64",
- "os": "none",
+ "os": "survos",
"vendor": "unknown",
"env": "",
"features": "+i,+m,+a,+zicsr",
diff --git a/sysroot/lib/rustlib/src/rust/library/library b/sysroot/lib/rustlib/src/rust/library/library
new file mode 120000
index 0000000..7036b83
--- /dev/null
+++ b/sysroot/lib/rustlib/src/rust/library/library
@@ -0,0 +1 @@
+../../../../../../library
\ No newline at end of file
diff --git a/user.ld b/user.ld
deleted file mode 100644
index f1e4581..0000000
--- a/user.ld
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * ld directives the for barmetal RISCV
- */
-OUTPUT_ARCH(riscv)
-ENTRY(_start)
-
-MEMORY {
- RAM (wxa) : ORIGIN = 0x0, LENGTH = 128M
-}
-
-SECTIONS {
- . = 0x0;
- .text : {
- KEEP(*(.text._start))
-
- *(.text .text.*)
- } > RAM
-
- .rodata : {
- *(.rodata .rodata.*)
- } > RAM
-
- .data : {
- *(.data .data.*)
- } > RAM
-
- .bss : ALIGN(8) {
- __bss_start = .;
- *(.bss .bss.*)
- __bss_end = .;
- } > RAM
-
- _heap_start = ALIGN(8);
- _heap_end = ORIGIN(RAM) + LENGTH(RAM);
-}
diff --git a/user/shell/Cargo.toml b/user/shell/Cargo.toml
index a973d7f..6b3a444 100644
--- a/user/shell/Cargo.toml
+++ b/user/shell/Cargo.toml
@@ -4,4 +4,6 @@ version = "0.1.0"
edition = "2024"
[dependencies]
-std = { path = "../../crates/std" }
+# std = { path = "../../crates/std" }
+# shared = { path = "../../crates/shared", features = ["user"] }
+# core = { path = "../../crates/std/crates/core" }
diff --git a/user/shell/src/main.rs b/user/shell/src/main.rs
index c531d7a..f0784f1 100644
--- a/user/shell/src/main.rs
+++ b/user/shell/src/main.rs
@@ -1,6 +1,9 @@
-fn main() -> isize {
+fn main() {
+ let a = std::env::args();
+ for a in a {
+ println!("Argument: {}", a);
+ }
println!(
"Hello from PIC program loaded dynamically with custom std and a better justfile, and syscalls ! "
);
- 0
}
diff --git a/user/test_pic/Cargo.toml b/user/test_pic/Cargo.toml
index 6a9b6ac..4ccb322 100644
--- a/user/test_pic/Cargo.toml
+++ b/user/test_pic/Cargo.toml
@@ -4,4 +4,7 @@ version = "0.1.0"
edition = "2024"
[dependencies]
-std = { path = "../../crates/std" }
+# std = { path = "../../crates/std" }
+shared = { path = "../../crates/shared", features = ["user"] }
+io = { path = "../../crates/io" }
+bffs = { path = "../../crates/bffs" }
diff --git a/user/test_pic/src/main.rs b/user/test_pic/src/main.rs
index a1c2f43..e7f321c 100644
--- a/user/test_pic/src/main.rs
+++ b/user/test_pic/src/main.rs
@@ -1,23 +1,24 @@
#![allow(unused)]
-use std::{
- io::{Read, Write, stdin},
- syscall,
-};
+use io::{Read, Write};
+use std::io::{Stdin, stdin};
+use shared::syscall;
fn main() {
- // let mut input = String::new();
+ let mut input = String::new();
+ input.push('a');
// let mut file = syscall::open("/dev/fb0");
// syscall::seek(&mut file, SeekFrom::End(-3));
// syscall::write(&mut file, &[255; 6400 * 50]);
// syscall::sleep(Duration::from_secs_f64(2.0));
syscall::close(0);
let mut tty = syscall::open("/dev/tty0");
+ tty.write(input.as_bytes()).unwrap();
syscall::spawn("/usr/bin/shell");
loop {
let mut test = [0; 2];
- let len = stdin().read(&mut test).unwrap();
- tty.write_all(str::from_utf8(&test[..len as usize]).unwrap().as_bytes())
+ let len = tty.read(&mut test).unwrap();
+ tty.write(str::from_utf8(&test[..len as usize]).unwrap().as_bytes())
.unwrap();
}
}