From f97c4b233ab4c2b38d2e483adf318295977cd557 Mon Sep 17 00:00:00 2001 From: Julien THILLARD Date: Tue, 17 Mar 2026 20:13:39 +0100 Subject: [PATCH] Add the rust std as a custom sysroot --- .cargo/config.toml | 3 +- .gitignore | 2 + .gitmodules | 3 + Cargo.toml | 3 +- crates/bffs/src/lib.rs | 1 + crates/kernel-macros/Cargo.toml | 2 +- crates/os-std-macros/Cargo.toml | 12 - crates/os-std-macros/src/lib.rs | 1 - crates/std/Cargo.toml | 9 - crates/std/src/ffi/c_str.rs | 7 - crates/std/src/ffi/mod.rs | 184 -- crates/std/src/ffi/os_str.rs | 1661 ------------------ crates/std/src/io.rs | 22 - crates/std/src/lib.rs | 242 --- crates/std/src/prelude.rs | 54 - crates/std/src/process.rs | 29 - justfile | 20 +- library/.gitignore | 17 + library/Cargo.toml | 88 + library/backtrace | 1 + library/justfile | 319 ++++ library/std/.gitignore | 109 ++ library/std/Cargo.toml | 177 ++ library/std/patches/sys/args/mod.sed | 4 + library/std/patches/sys/io/error/mod.sed | 1 + library/std/patches/sys/pal/mod.sed | 6 + library/std/patches/sys/random/mod.sed | 2 + library/std/patches/sys/thread_local/mod.sed | 6 + library/std/riscv64.json | 22 + library/std/src/sys/pal/survos.rs | 11 + riscv64.json | 2 +- sysroot/lib/rustlib/src/rust/library/library | 1 + user.ld | 35 - user/shell/Cargo.toml | 4 +- user/shell/src/main.rs | 7 +- user/test_pic/Cargo.toml | 5 +- user/test_pic/src/main.rs | 15 +- 37 files changed, 802 insertions(+), 2285 deletions(-) create mode 100644 .gitmodules delete mode 100644 crates/os-std-macros/Cargo.toml delete mode 100644 crates/os-std-macros/src/lib.rs delete mode 100644 crates/std/Cargo.toml delete mode 100644 crates/std/src/ffi/c_str.rs delete mode 100644 crates/std/src/ffi/mod.rs delete mode 100644 crates/std/src/ffi/os_str.rs delete mode 100644 crates/std/src/io.rs delete mode 100644 crates/std/src/lib.rs delete mode 100644 crates/std/src/prelude.rs delete mode 100644 crates/std/src/process.rs create mode 100644 library/.gitignore create mode 100644 library/Cargo.toml create mode 160000 library/backtrace create mode 100644 library/justfile create mode 100644 library/std/.gitignore create mode 100644 library/std/Cargo.toml create mode 100644 library/std/patches/sys/args/mod.sed create mode 100644 library/std/patches/sys/io/error/mod.sed create mode 100644 library/std/patches/sys/pal/mod.sed create mode 100644 library/std/patches/sys/random/mod.sed create mode 100644 library/std/patches/sys/thread_local/mod.sed create mode 100644 library/std/riscv64.json create mode 100644 library/std/src/sys/pal/survos.rs create mode 120000 sysroot/lib/rustlib/src/rust/library/library delete mode 100644 user.ld 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(); } }