From 82cfeff7e13f54c6a24aa74f4d04cbe4323e1302 Mon Sep 17 00:00:00 2001 From: Mark Poliakov Date: Mon, 6 Jan 2025 10:13:30 +0200 Subject: [PATCH] alnyan/yggdrasil: implement join_paths()/split_paths() --- library/std/src/sys/pal/yggdrasil/os.rs | 67 +++++++++++++++++++------ 1 file changed, 52 insertions(+), 15 deletions(-) diff --git a/library/std/src/sys/pal/yggdrasil/os.rs b/library/std/src/sys/pal/yggdrasil/os.rs index 01a31957269..1f835ce4396 100644 --- a/library/std/src/sys/pal/yggdrasil/os.rs +++ b/library/std/src/sys/pal/yggdrasil/os.rs @@ -32,6 +32,7 @@ mod env { use super::env_imp; use crate::collections::hash_map; use crate::ffi::{OsStr, OsString}; + use crate::sys_common::AsInner; use crate::{fmt, io}; pub struct Env { @@ -71,21 +72,27 @@ mod env { Env { iter } } - // TODO check for = in name pub fn getenv(name: &OsStr) -> Option { + if name.as_inner().as_encoded_bytes().contains(&b'=') { + return None; + } let env = env_imp::read(); env.get(name).cloned() } - // TODO check for = in name pub unsafe fn setenv(name: &OsStr, value: &OsStr) -> io::Result<()> { + if name.as_inner().as_encoded_bytes().contains(&b'=') { + return Err(io::Error::new(io::ErrorKind::Uncategorized, "Invalid env var name")); + } let mut env = env_imp::write(); env.insert(name.to_owned(), value.to_owned()); Ok(()) } - // TODO check for = in name pub unsafe fn unsetenv(name: &OsStr) -> io::Result<()> { + if name.as_inner().as_encoded_bytes().contains(&b'=') { + return Err(io::Error::new(io::ErrorKind::Uncategorized, "Invalid env var name")); + } let mut env = env_imp::write(); env.remove(name); Ok(()) @@ -97,10 +104,13 @@ mod paths { use crate::ffi::{OsStr, OsString}; use crate::marker::PhantomData; use crate::path::{Path, PathBuf}; - use crate::sys::{cvt_io, run_with_path_str}; - use crate::{fmt, io}; + use crate::sys::{cvt_io, os_str, run_with_path_str}; + use crate::sys_common::{AsInner, FromInner}; + use crate::{fmt, io, iter, mem, slice}; - pub struct SplitPaths<'a>(!, PhantomData<&'a ()>); + pub struct SplitPaths<'a> { + iter: iter::Map bool>, fn(&'a [u8]) -> PathBuf>, + } #[derive(Debug)] pub struct JoinPathsError; @@ -108,34 +118,61 @@ mod paths { impl<'a> Iterator for SplitPaths<'a> { type Item = PathBuf; - fn next(&mut self) -> Option { - todo!() + fn next(&mut self) -> Option { + self.iter.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() } } impl fmt::Display for JoinPathsError { - fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - todo!() + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "path segment contains separator `/`") } } impl StdError for JoinPathsError { #[allow(deprecated)] fn description(&self) -> &str { - todo!() + "failed to join paths" } } - pub fn split_paths(_path: &OsStr) -> SplitPaths<'_> { - todo!() + pub fn split_paths(unparsed: &OsStr) -> SplitPaths<'_> { + fn bytes_to_path(b: &[u8]) -> PathBuf { + PathBuf::from(unsafe { mem::transmute::<_, &OsStr>(b) }) + } + fn is_separator(b: &u8) -> bool { + *b == b'/' + } + let unparsed = &unparsed.as_inner().inner; + SplitPaths { + iter: unparsed + .split(is_separator as fn(&u8) -> bool) + .map(bytes_to_path as fn(&[u8]) -> PathBuf), + } } - pub fn join_paths(_paths: I) -> Result + pub fn join_paths(paths: I) -> Result where I: Iterator, T: AsRef, { - todo!() + let mut joined = Vec::new(); + + for (i, path) in paths.enumerate() { + let path = &path.as_ref().as_inner().inner; + if i > 0 { + joined.push(b'/') + } + if path.contains(&b'/') { + return Err(JoinPathsError); + } + joined.extend_from_slice(path); + } + Ok(FromInner::from_inner(os_str::Buf { inner: joined })) } pub fn current_exe() -> io::Result {