diff --git a/Cargo.lock b/Cargo.lock index 42049da8e6ad..f78b610ec6c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1350,9 +1350,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.1" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f22b8f315b98f415780ddbe9163c7dbbc5a07225b6d102ace1d8aeef85775140" +checksum = "1010591b26bbfe835e9faeabeb11866061cc7dcebffd56ad7d0942d0e61aefd8" dependencies = [ "compiler_builtins", "libc", diff --git a/src/libpanic_unwind/hermit.rs b/src/libpanic_unwind/hermit.rs index 6bded4dd499b..69b9edb77c56 100644 --- a/src/libpanic_unwind/hermit.rs +++ b/src/libpanic_unwind/hermit.rs @@ -4,7 +4,6 @@ use alloc::boxed::Box; use core::any::Any; -use core::ptr; pub unsafe fn cleanup(_ptr: *mut u8) -> Box { extern "C" { diff --git a/src/libstd/os/mod.rs b/src/libstd/os/mod.rs index 91e37ed833a4..0fa4a1d2353c 100644 --- a/src/libstd/os/mod.rs +++ b/src/libstd/os/mod.rs @@ -24,7 +24,7 @@ cfg_if::cfg_if! { // If we're not documenting libstd then we just expose the main modules // as we otherwise would. - #[cfg(any(target_os = "redox", unix, target_os = "vxworks"))] + #[cfg(any(target_os = "redox", unix, target_os = "vxworks", target_os = "hermit"))] #[stable(feature = "rust1", since = "1.0.0")] pub use crate::sys::ext as unix; diff --git a/src/libstd/sys/hermit/ext/ffi.rs b/src/libstd/sys/hermit/ext/ffi.rs new file mode 100644 index 000000000000..07b59a02556d --- /dev/null +++ b/src/libstd/sys/hermit/ext/ffi.rs @@ -0,0 +1,38 @@ +//! HermitCore-specific extension to the primitives in the `std::ffi` module +//! +//! # Examples +//! +//! ``` +//! use std::ffi::OsString; +//! use std::os::hermit::ffi::OsStringExt; +//! +//! let bytes = b"foo".to_vec(); +//! +//! // OsStringExt::from_vec +//! let os_string = OsString::from_vec(bytes); +//! assert_eq!(os_string.to_str(), Some("foo")); +//! +//! // OsStringExt::into_vec +//! let bytes = os_string.into_vec(); +//! assert_eq!(bytes, b"foo"); +//! ``` +//! +//! ``` +//! use std::ffi::OsStr; +//! use std::os::hermit::ffi::OsStrExt; +//! +//! let bytes = b"foo"; +//! +//! // OsStrExt::from_bytes +//! let os_str = OsStr::from_bytes(bytes); +//! assert_eq!(os_str.to_str(), Some("foo")); +//! +//! // OsStrExt::as_bytes +//! let bytes = os_str.as_bytes(); +//! assert_eq!(bytes, b"foo"); +//! ``` + +#![stable(feature = "rust1", since = "1.0.0")] + +#[stable(feature = "rust1", since = "1.0.0")] +pub use crate::sys_common::os_str_bytes::*; diff --git a/src/libstd/sys/hermit/ext/mod.rs b/src/libstd/sys/hermit/ext/mod.rs new file mode 100644 index 000000000000..ea87d0ad2c94 --- /dev/null +++ b/src/libstd/sys/hermit/ext/mod.rs @@ -0,0 +1,14 @@ +#![stable(feature = "rust1", since = "1.0.0")] +#![allow(missing_docs)] + +pub mod ffi; + +/// A prelude for conveniently writing platform-specific code. +/// +/// Includes all extension traits, and some important type definitions. +#[stable(feature = "rust1", since = "1.0.0")] +pub mod prelude { + #[doc(no_inline)] + #[stable(feature = "rust1", since = "1.0.0")] + pub use super::ffi::{OsStrExt, OsStringExt}; +} diff --git a/src/libstd/sys/hermit/mod.rs b/src/libstd/sys/hermit/mod.rs index 1e4a53abdc7b..4983b1430b3e 100644 --- a/src/libstd/sys/hermit/mod.rs +++ b/src/libstd/sys/hermit/mod.rs @@ -21,6 +21,7 @@ pub mod args; pub mod cmath; pub mod condvar; pub mod env; +pub mod ext; pub mod fast_thread_local; pub mod fd; pub mod fs; @@ -93,9 +94,7 @@ pub unsafe extern "C" fn __rust_abort() { #[cfg(not(test))] pub fn init() { - unsafe { - let _ = net::init(); - } + let _ = net::init(); } #[cfg(not(test))] diff --git a/src/libstd/sys/hermit/net.rs b/src/libstd/sys/hermit/net.rs index 82917e71be1f..377c3132c5a3 100644 --- a/src/libstd/sys/hermit/net.rs +++ b/src/libstd/sys/hermit/net.rs @@ -1,291 +1,362 @@ use crate::convert::TryFrom; use crate::fmt; -use crate::io::{self, IoSlice, IoSliceMut}; +use crate::io::{self, ErrorKind, IoSlice, IoSliceMut}; use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; use crate::str; +use crate::sys::hermit::abi; use crate::sys::{unsupported, Void}; use crate::time::Duration; -//// Iinitializes HermitCore's network stack -pub unsafe fn init() -> io::Result<()> { +/// Checks whether the HermitCore's socket interface has been started already, and +/// if not, starts it. +pub fn init() -> io::Result<()> { + if abi::network_init() < 0 { + return Err(io::Error::new(ErrorKind::Other, "Unable to initialize network interface")); + } + Ok(()) } -pub struct TcpStream(Void); +pub struct TcpStream(abi::Handle); impl TcpStream { - pub fn connect(_: io::Result<&SocketAddr>) -> io::Result { - unsupported() + pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result { + let addr = addr?; + + match abi::tcpstream::connect(addr.ip().to_string().as_bytes(), addr.port(), None) { + Ok(handle) => Ok(TcpStream(handle)), + _ => { + Err(io::Error::new(ErrorKind::Other, "Unable to initiate a connection on a socket")) + } + } } - pub fn connect_timeout(_: &SocketAddr, _: Duration) -> io::Result { - unsupported() + pub fn connect_timeout(saddr: &SocketAddr, duration: Duration) -> io::Result { + match abi::tcpstream::connect( + saddr.ip().to_string().as_bytes(), + saddr.port(), + Some(duration.as_millis() as u64), + ) { + Ok(handle) => Ok(TcpStream(handle)), + _ => { + Err(io::Error::new(ErrorKind::Other, "Unable to initiate a connection on a socket")) + } + } } - pub fn set_read_timeout(&self, _: Option) -> io::Result<()> { - match self.0 {} + pub fn set_read_timeout(&self, duration: Option) -> io::Result<()> { + abi::tcpstream::set_read_timeout(self.0, duration.map(|d| d.as_millis() as u64)) + .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to set timeout value")) } - pub fn set_write_timeout(&self, _: Option) -> io::Result<()> { - match self.0 {} + pub fn set_write_timeout(&self, duration: Option) -> io::Result<()> { + abi::tcpstream::set_write_timeout(self.0, duration.map(|d| d.as_millis() as u64)) + .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to set timeout value")) } pub fn read_timeout(&self) -> io::Result> { - match self.0 {} + let duration = abi::tcpstream::get_read_timeout(self.0) + .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to determine timeout value"))?; + + Ok(duration.map(|d| Duration::from_millis(d))) } pub fn write_timeout(&self) -> io::Result> { - match self.0 {} + let duration = abi::tcpstream::get_write_timeout(self.0) + .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to determine timeout value"))?; + + Ok(duration.map(|d| Duration::from_millis(d))) } - pub fn peek(&self, _: &mut [u8]) -> io::Result { - match self.0 {} + pub fn peek(&self, buf: &mut [u8]) -> io::Result { + abi::tcpstream::peek(self.0, buf) + .map_err(|_| io::Error::new(ErrorKind::Other, "set_nodelay failed")) } - pub fn read(&self, _: &mut [u8]) -> io::Result { - match self.0 {} + pub fn read(&self, buffer: &mut [u8]) -> io::Result { + self.read_vectored(&mut [IoSliceMut::new(buffer)]) } - pub fn read_vectored(&self, _: &mut [IoSliceMut<'_>]) -> io::Result { - match self.0 {} + pub fn read_vectored(&self, ioslice: &mut [IoSliceMut<'_>]) -> io::Result { + let mut size: usize = 0; + + for i in ioslice.iter_mut() { + let mut pos: usize = 0; + + while pos < i.len() { + let ret = abi::tcpstream::read(self.0, &mut i[pos..]) + .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to read on socket"))?; + + if ret == 0 { + return Ok(size); + } else { + size += ret; + pos += ret; + } + } + } + + Ok(size) } - pub fn write(&self, _: &[u8]) -> io::Result { - match self.0 {} + pub fn write(&self, buffer: &[u8]) -> io::Result { + self.write_vectored(&[IoSlice::new(buffer)]) } - pub fn write_vectored(&self, _: &[IoSlice<'_>]) -> io::Result { - match self.0 {} + pub fn write_vectored(&self, ioslice: &[IoSlice<'_>]) -> io::Result { + let mut size: usize = 0; + + for i in ioslice.iter() { + size += abi::tcpstream::write(self.0, i) + .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to write on socket"))?; + } + + Ok(size) } pub fn peer_addr(&self) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "peer_addr isn't supported")) } pub fn socket_addr(&self) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "socket_addr isn't supported")) } - pub fn shutdown(&self, _: Shutdown) -> io::Result<()> { - match self.0 {} + pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { + abi::tcpstream::shutdown(self.0, how as i32) + .map_err(|_| io::Error::new(ErrorKind::Other, "unable to shutdown socket")) } pub fn duplicate(&self) -> io::Result { - match self.0 {} + let handle = abi::tcpstream::duplicate(self.0) + .map_err(|_| io::Error::new(ErrorKind::Other, "unable to duplicate stream"))?; + + Ok(TcpStream(handle)) } - pub fn set_nodelay(&self, _: bool) -> io::Result<()> { - match self.0 {} + pub fn set_nodelay(&self, mode: bool) -> io::Result<()> { + abi::tcpstream::set_nodelay(self.0, mode) + .map_err(|_| io::Error::new(ErrorKind::Other, "set_nodelay failed")) } pub fn nodelay(&self) -> io::Result { - match self.0 {} + abi::tcpstream::nodelay(self.0) + .map_err(|_| io::Error::new(ErrorKind::Other, "nodelay failed")) } - pub fn set_ttl(&self, _: u32) -> io::Result<()> { - match self.0 {} + pub fn set_ttl(&self, tll: u32) -> io::Result<()> { + abi::tcpstream::set_tll(self.0, tll) + .map_err(|_| io::Error::new(ErrorKind::Other, "unable to set TTL")) } pub fn ttl(&self) -> io::Result { - match self.0 {} + abi::tcpstream::get_tll(self.0) + .map_err(|_| io::Error::new(ErrorKind::Other, "unable to get TTL")) } pub fn take_error(&self) -> io::Result> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "take_error isn't supported")) } - pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { - match self.0 {} + pub fn set_nonblocking(&self, mode: bool) -> io::Result<()> { + abi::tcpstream::set_nonblocking(self.0, mode) + .map_err(|_| io::Error::new(ErrorKind::Other, "unable to set blocking mode")) + } +} + +impl Drop for TcpStream { + fn drop(&mut self) { + let _ = abi::tcpstream::close(self.0); } } impl fmt::Debug for TcpStream { fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 {} + Ok(()) } } -pub struct TcpListener(Void); +pub struct TcpListener(abi::Handle); impl TcpListener { pub fn bind(_: io::Result<&SocketAddr>) -> io::Result { - unsupported() + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn socket_addr(&self) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn duplicate(&self) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn set_ttl(&self, _: u32) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn ttl(&self) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn set_only_v6(&self, _: bool) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn only_v6(&self) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn take_error(&self) -> io::Result> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } } impl fmt::Debug for TcpListener { fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 {} + Ok(()) } } -pub struct UdpSocket(Void); +pub struct UdpSocket(abi::Handle); impl UdpSocket { pub fn bind(_: io::Result<&SocketAddr>) -> io::Result { - unsupported() + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn peer_addr(&self) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn socket_addr(&self) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn duplicate(&self) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn set_read_timeout(&self, _: Option) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn set_write_timeout(&self, _: Option) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn read_timeout(&self) -> io::Result> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn write_timeout(&self) -> io::Result> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn set_broadcast(&self, _: bool) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn broadcast(&self) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn multicast_loop_v4(&self) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn multicast_ttl_v4(&self) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn multicast_loop_v6(&self) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn set_ttl(&self, _: u32) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn ttl(&self) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn take_error(&self) -> io::Result> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn recv(&self, _: &mut [u8]) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn peek(&self, _: &mut [u8]) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn send(&self, _: &[u8]) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } } impl fmt::Debug for UdpSocket { fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 {} + Ok(()) } }