From 45df4d0d9b577fecee798d672695fe24ff57fb1b Mon Sep 17 00:00:00 2001 From: mo khan Date: Tue, 15 Jul 2025 16:37:08 -0600 Subject: feat: migrate from Cedar to SpiceDB authorization system This is a major architectural change that replaces the Cedar policy-based authorization system with SpiceDB's relation-based authorization. Key changes: - Migrate from Rust to Go implementation - Replace Cedar policies with SpiceDB schema and relationships - Switch from envoy `ext_authz` with Cedar to SpiceDB permission checks - Update build system and dependencies for Go ecosystem - Maintain Envoy integration for external authorization This change enables more flexible permission modeling through SpiceDB's Google Zanzibar inspired relation-based system, supporting complex hierarchical permissions that were difficult to express in Cedar. Breaking change: Existing Cedar policies and Rust-based configuration will no longer work and need to be migrated to SpiceDB schema. --- vendor/rustix/src/path/arg.rs | 1097 ------------------------------------- vendor/rustix/src/path/dec_int.rs | 261 --------- vendor/rustix/src/path/mod.rs | 9 - 3 files changed, 1367 deletions(-) delete mode 100644 vendor/rustix/src/path/arg.rs delete mode 100644 vendor/rustix/src/path/dec_int.rs delete mode 100644 vendor/rustix/src/path/mod.rs (limited to 'vendor/rustix/src/path') diff --git a/vendor/rustix/src/path/arg.rs b/vendor/rustix/src/path/arg.rs deleted file mode 100644 index 9edeb57f..00000000 --- a/vendor/rustix/src/path/arg.rs +++ /dev/null @@ -1,1097 +0,0 @@ -//! Convenient and efficient string argument passing. -//! -//! This module defines the `Arg` trait and implements it for several common -//! string types. This allows users to pass any of these string types directly -//! to rustix APIs with string arguments, and it allows rustix to implement -//! NUL-termination without the need for copying or dynamic allocation where -//! possible. - -use crate::ffi::CStr; -use crate::io; -use crate::path::{DecInt, SMALL_PATH_BUFFER_SIZE}; -#[cfg(feature = "alloc")] -use alloc::borrow::ToOwned as _; -use core::mem::MaybeUninit; -use core::{ptr, slice, str}; -#[cfg(feature = "std")] -use std::ffi::{OsStr, OsString}; -#[cfg(all(feature = "std", target_os = "hermit"))] -use std::os::hermit::ext::ffi::{OsStrExt, OsStringExt}; -#[cfg(all(feature = "std", unix))] -use std::os::unix::ffi::{OsStrExt as _, OsStringExt as _}; -#[cfg(all(feature = "std", target_os = "vxworks"))] -use std::os::vxworks::ext::ffi::{OsStrExt, OsStringExt}; -#[cfg(all( - feature = "std", - target_os = "wasi", - any(not(target_env = "p2"), wasip2) -))] -use std::os::wasi::ffi::{OsStrExt, OsStringExt}; -#[cfg(feature = "std")] -use std::path::{Component, Components, Iter, Path, PathBuf}; -#[cfg(feature = "alloc")] -use {crate::ffi::CString, alloc::borrow::Cow}; -#[cfg(feature = "alloc")] -use {alloc::string::String, alloc::vec::Vec}; - -/// A trait for passing path arguments. -/// -/// This is similar to [`AsRef`]`<`[`Path`]`>`, but is implemented for more -/// kinds of strings and can convert into more kinds of strings. -/// -/// # Examples -/// -/// ``` -/// # #[cfg(any(feature = "fs", feature = "net"))] -/// use rustix::ffi::CStr; -/// use rustix::io; -/// # #[cfg(any(feature = "fs", feature = "net"))] -/// use rustix::path::Arg; -/// -/// # #[cfg(any(feature = "fs", feature = "net"))] -/// pub fn touch(path: P) -> io::Result<()> { -/// let path = path.into_c_str()?; -/// _touch(&path) -/// } -/// -/// # #[cfg(any(feature = "fs", feature = "net"))] -/// fn _touch(path: &CStr) -> io::Result<()> { -/// // implementation goes here -/// Ok(()) -/// } -/// ``` -/// -/// Users can then call `touch("foo")`, `touch(cstr!("foo"))`, -/// `touch(Path::new("foo"))`, or many other things. -/// -/// [`AsRef`]: std::convert::AsRef -pub trait Arg { - /// Returns a view of this string as a string slice. - fn as_str(&self) -> io::Result<&str>; - - /// Returns a potentially-lossy rendering of this string as a - /// `Cow<'_, str>`. - #[cfg(feature = "alloc")] - fn to_string_lossy(&self) -> Cow<'_, str>; - - /// Returns a view of this string as a maybe-owned [`CStr`]. - #[cfg(feature = "alloc")] - fn as_cow_c_str(&self) -> io::Result>; - - /// Consumes `self` and returns a view of this string as a maybe-owned - /// [`CStr`]. - #[cfg(feature = "alloc")] - fn into_c_str<'b>(self) -> io::Result> - where - Self: 'b; - - /// Runs a closure with `self` passed in as a `&CStr`. - fn into_with_c_str(self, f: F) -> io::Result - where - Self: Sized, - F: FnOnce(&CStr) -> io::Result; -} - -/// Runs a closure on `arg` where `A` is mapped to a `&CStr` -pub fn option_into_with_c_str(arg: Option, f: F) -> io::Result -where - A: Arg + Sized, - F: FnOnce(Option<&CStr>) -> io::Result, -{ - if let Some(arg) = arg { - arg.into_with_c_str(|p| f(Some(p))) - } else { - f(None) - } -} - -impl Arg for &str { - #[inline] - fn as_str(&self) -> io::Result<&str> { - Ok(self) - } - - #[cfg(feature = "alloc")] - #[inline] - fn to_string_lossy(&self) -> Cow<'_, str> { - Cow::Borrowed(self) - } - - #[cfg(feature = "alloc")] - #[inline] - fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Owned( - CString::new(*self).map_err(|_cstr_err| io::Errno::INVAL)?, - )) - } - - #[cfg(feature = "alloc")] - #[inline] - fn into_c_str<'b>(self) -> io::Result> - where - Self: 'b, - { - Ok(Cow::Owned( - CString::new(self).map_err(|_cstr_err| io::Errno::INVAL)?, - )) - } - - #[inline] - fn into_with_c_str(self, f: F) -> io::Result - where - Self: Sized, - F: FnOnce(&CStr) -> io::Result, - { - with_c_str(self.as_bytes(), f) - } -} - -#[cfg(feature = "alloc")] -impl Arg for &String { - #[inline] - fn as_str(&self) -> io::Result<&str> { - Ok(self) - } - - #[cfg(feature = "alloc")] - #[inline] - fn to_string_lossy(&self) -> Cow<'_, str> { - Cow::Borrowed(self) - } - - #[cfg(feature = "alloc")] - #[inline] - fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Owned( - CString::new(String::as_str(self)).map_err(|_cstr_err| io::Errno::INVAL)?, - )) - } - - #[cfg(feature = "alloc")] - #[inline] - fn into_c_str<'b>(self) -> io::Result> - where - Self: 'b, - { - self.as_str().into_c_str() - } - - #[inline] - fn into_with_c_str(self, f: F) -> io::Result - where - Self: Sized, - F: FnOnce(&CStr) -> io::Result, - { - with_c_str(self.as_bytes(), f) - } -} - -#[cfg(feature = "alloc")] -impl Arg for String { - #[inline] - fn as_str(&self) -> io::Result<&str> { - Ok(self) - } - - #[cfg(feature = "alloc")] - #[inline] - fn to_string_lossy(&self) -> Cow<'_, str> { - Cow::Borrowed(self) - } - - #[cfg(feature = "alloc")] - #[inline] - fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Owned( - CString::new(self.as_str()).map_err(|_cstr_err| io::Errno::INVAL)?, - )) - } - - #[cfg(feature = "alloc")] - #[inline] - fn into_c_str<'b>(self) -> io::Result> - where - Self: 'b, - { - Ok(Cow::Owned( - CString::new(self).map_err(|_cstr_err| io::Errno::INVAL)?, - )) - } - - #[inline] - fn into_with_c_str(self, f: F) -> io::Result - where - Self: Sized, - F: FnOnce(&CStr) -> io::Result, - { - f(&CString::new(self).map_err(|_cstr_err| io::Errno::INVAL)?) - } -} - -#[cfg(feature = "std")] -#[cfg(any(not(target_os = "wasi"), not(target_env = "p2"), wasip2))] -impl Arg for &OsStr { - #[inline] - fn as_str(&self) -> io::Result<&str> { - self.to_str().ok_or(io::Errno::INVAL) - } - - #[inline] - fn to_string_lossy(&self) -> Cow<'_, str> { - OsStr::to_string_lossy(self) - } - - #[inline] - fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Owned( - CString::new(self.as_bytes()).map_err(|_cstr_err| io::Errno::INVAL)?, - )) - } - - #[inline] - fn into_c_str<'b>(self) -> io::Result> - where - Self: 'b, - { - Ok(Cow::Owned( - CString::new(self.as_bytes()).map_err(|_cstr_err| io::Errno::INVAL)?, - )) - } - - #[inline] - fn into_with_c_str(self, f: F) -> io::Result - where - Self: Sized, - F: FnOnce(&CStr) -> io::Result, - { - with_c_str(self.as_bytes(), f) - } -} - -#[cfg(feature = "std")] -#[cfg(any(not(target_os = "wasi"), not(target_env = "p2"), wasip2))] -impl Arg for &OsString { - #[inline] - fn as_str(&self) -> io::Result<&str> { - OsString::as_os_str(self).to_str().ok_or(io::Errno::INVAL) - } - - #[inline] - fn to_string_lossy(&self) -> Cow<'_, str> { - self.as_os_str().to_string_lossy() - } - - #[inline] - fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Owned( - CString::new(OsString::as_os_str(self).as_bytes()) - .map_err(|_cstr_err| io::Errno::INVAL)?, - )) - } - - #[inline] - fn into_c_str<'b>(self) -> io::Result> - where - Self: 'b, - { - self.as_os_str().into_c_str() - } - - #[inline] - fn into_with_c_str(self, f: F) -> io::Result - where - Self: Sized, - F: FnOnce(&CStr) -> io::Result, - { - with_c_str(self.as_bytes(), f) - } -} - -#[cfg(feature = "std")] -#[cfg(any(not(target_os = "wasi"), not(target_env = "p2"), wasip2))] -impl Arg for OsString { - #[inline] - fn as_str(&self) -> io::Result<&str> { - self.as_os_str().to_str().ok_or(io::Errno::INVAL) - } - - #[inline] - fn to_string_lossy(&self) -> Cow<'_, str> { - self.as_os_str().to_string_lossy() - } - - #[inline] - fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Owned( - CString::new(self.as_bytes()).map_err(|_cstr_err| io::Errno::INVAL)?, - )) - } - - #[inline] - fn into_c_str<'b>(self) -> io::Result> - where - Self: 'b, - { - Ok(Cow::Owned( - CString::new(self.into_vec()).map_err(|_cstr_err| io::Errno::INVAL)?, - )) - } - - #[inline] - fn into_with_c_str(self, f: F) -> io::Result - where - Self: Sized, - F: FnOnce(&CStr) -> io::Result, - { - f(&CString::new(self.into_vec()).map_err(|_cstr_err| io::Errno::INVAL)?) - } -} - -#[cfg(feature = "std")] -#[cfg(any(not(target_os = "wasi"), not(target_env = "p2"), wasip2))] -impl Arg for &Path { - #[inline] - fn as_str(&self) -> io::Result<&str> { - self.as_os_str().to_str().ok_or(io::Errno::INVAL) - } - - #[inline] - fn to_string_lossy(&self) -> Cow<'_, str> { - Path::to_string_lossy(self) - } - - #[inline] - fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Owned( - CString::new(self.as_os_str().as_bytes()).map_err(|_cstr_err| io::Errno::INVAL)?, - )) - } - - #[inline] - fn into_c_str<'b>(self) -> io::Result> - where - Self: 'b, - { - Ok(Cow::Owned( - CString::new(self.as_os_str().as_bytes()).map_err(|_cstr_err| io::Errno::INVAL)?, - )) - } - - #[inline] - fn into_with_c_str(self, f: F) -> io::Result - where - Self: Sized, - F: FnOnce(&CStr) -> io::Result, - { - with_c_str(self.as_os_str().as_bytes(), f) - } -} - -#[cfg(feature = "std")] -#[cfg(any(not(target_os = "wasi"), not(target_env = "p2"), wasip2))] -impl Arg for &PathBuf { - #[inline] - fn as_str(&self) -> io::Result<&str> { - PathBuf::as_path(self) - .as_os_str() - .to_str() - .ok_or(io::Errno::INVAL) - } - - #[inline] - fn to_string_lossy(&self) -> Cow<'_, str> { - self.as_path().to_string_lossy() - } - - #[inline] - fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Owned( - CString::new(PathBuf::as_path(self).as_os_str().as_bytes()) - .map_err(|_cstr_err| io::Errno::INVAL)?, - )) - } - - #[inline] - fn into_c_str<'b>(self) -> io::Result> - where - Self: 'b, - { - self.as_path().into_c_str() - } - - #[inline] - fn into_with_c_str(self, f: F) -> io::Result - where - Self: Sized, - F: FnOnce(&CStr) -> io::Result, - { - with_c_str(self.as_os_str().as_bytes(), f) - } -} - -#[cfg(feature = "std")] -#[cfg(any(not(target_os = "wasi"), not(target_env = "p2"), wasip2))] -impl Arg for PathBuf { - #[inline] - fn as_str(&self) -> io::Result<&str> { - self.as_os_str().to_str().ok_or(io::Errno::INVAL) - } - - #[inline] - fn to_string_lossy(&self) -> Cow<'_, str> { - self.as_os_str().to_string_lossy() - } - - #[inline] - fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Owned( - CString::new(self.as_os_str().as_bytes()).map_err(|_cstr_err| io::Errno::INVAL)?, - )) - } - - #[inline] - fn into_c_str<'b>(self) -> io::Result> - where - Self: 'b, - { - Ok(Cow::Owned( - CString::new(self.into_os_string().into_vec()).map_err(|_cstr_err| io::Errno::INVAL)?, - )) - } - - #[inline] - fn into_with_c_str(self, f: F) -> io::Result - where - Self: Sized, - F: FnOnce(&CStr) -> io::Result, - { - f( - &CString::new(self.into_os_string().into_vec()) - .map_err(|_cstr_err| io::Errno::INVAL)?, - ) - } -} - -impl Arg for &CStr { - #[inline] - fn as_str(&self) -> io::Result<&str> { - self.to_str().map_err(|_utf8_err| io::Errno::INVAL) - } - - #[cfg(feature = "alloc")] - #[inline] - fn to_string_lossy(&self) -> Cow<'_, str> { - CStr::to_string_lossy(self) - } - - #[cfg(feature = "alloc")] - #[inline] - fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Borrowed(self)) - } - - #[cfg(feature = "alloc")] - #[inline] - fn into_c_str<'b>(self) -> io::Result> - where - Self: 'b, - { - Ok(Cow::Borrowed(self)) - } - - #[inline] - fn into_with_c_str(self, f: F) -> io::Result - where - Self: Sized, - F: FnOnce(&CStr) -> io::Result, - { - f(self) - } -} - -#[cfg(feature = "alloc")] -impl Arg for &CString { - #[inline] - fn as_str(&self) -> io::Result<&str> { - unimplemented!() - } - - #[inline] - fn to_string_lossy(&self) -> Cow<'_, str> { - unimplemented!() - } - - #[inline] - fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Borrowed(self)) - } - - #[inline] - fn into_c_str<'b>(self) -> io::Result> - where - Self: 'b, - { - Ok(Cow::Borrowed(self)) - } - - #[inline] - fn into_with_c_str(self, f: F) -> io::Result - where - Self: Sized, - F: FnOnce(&CStr) -> io::Result, - { - f(self) - } -} - -#[cfg(feature = "alloc")] -impl Arg for CString { - #[inline] - fn as_str(&self) -> io::Result<&str> { - self.to_str().map_err(|_utf8_err| io::Errno::INVAL) - } - - #[inline] - fn to_string_lossy(&self) -> Cow<'_, str> { - CStr::to_string_lossy(self) - } - - #[inline] - fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Borrowed(self)) - } - - #[inline] - fn into_c_str<'b>(self) -> io::Result> - where - Self: 'b, - { - Ok(Cow::Owned(self)) - } - - #[inline] - fn into_with_c_str(self, f: F) -> io::Result - where - Self: Sized, - F: FnOnce(&CStr) -> io::Result, - { - f(&self) - } -} - -#[cfg(feature = "alloc")] -impl<'a> Arg for Cow<'a, str> { - #[inline] - fn as_str(&self) -> io::Result<&str> { - Ok(self) - } - - #[inline] - fn to_string_lossy(&self) -> Cow<'_, str> { - Cow::Borrowed(self) - } - - #[inline] - fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Owned( - CString::new(self.as_ref()).map_err(|_cstr_err| io::Errno::INVAL)?, - )) - } - - #[inline] - fn into_c_str<'b>(self) -> io::Result> - where - Self: 'b, - { - Ok(Cow::Owned( - match self { - Cow::Owned(s) => CString::new(s), - Cow::Borrowed(s) => CString::new(s), - } - .map_err(|_cstr_err| io::Errno::INVAL)?, - )) - } - - #[inline] - fn into_with_c_str(self, f: F) -> io::Result - where - Self: Sized, - F: FnOnce(&CStr) -> io::Result, - { - with_c_str(self.as_bytes(), f) - } -} - -#[cfg(feature = "std")] -#[cfg(any(not(target_os = "wasi"), not(target_env = "p2"), wasip2))] -impl<'a> Arg for Cow<'a, OsStr> { - #[inline] - fn as_str(&self) -> io::Result<&str> { - (**self).to_str().ok_or(io::Errno::INVAL) - } - - #[inline] - fn to_string_lossy(&self) -> Cow<'_, str> { - (**self).to_string_lossy() - } - - #[inline] - fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Owned( - CString::new(self.as_bytes()).map_err(|_cstr_err| io::Errno::INVAL)?, - )) - } - - #[inline] - fn into_c_str<'b>(self) -> io::Result> - where - Self: 'b, - { - Ok(Cow::Owned( - match self { - Cow::Owned(os) => CString::new(os.into_vec()), - Cow::Borrowed(os) => CString::new(os.as_bytes()), - } - .map_err(|_cstr_err| io::Errno::INVAL)?, - )) - } - - #[inline] - fn into_with_c_str(self, f: F) -> io::Result - where - Self: Sized, - F: FnOnce(&CStr) -> io::Result, - { - with_c_str(self.as_bytes(), f) - } -} - -#[cfg(feature = "alloc")] -impl<'a> Arg for Cow<'a, CStr> { - #[inline] - fn as_str(&self) -> io::Result<&str> { - self.to_str().map_err(|_utf8_err| io::Errno::INVAL) - } - - #[inline] - fn to_string_lossy(&self) -> Cow<'_, str> { - let borrow: &CStr = core::borrow::Borrow::borrow(self); - borrow.to_string_lossy() - } - - #[inline] - fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Borrowed(self)) - } - - #[inline] - fn into_c_str<'b>(self) -> io::Result> - where - Self: 'b, - { - Ok(self) - } - - #[inline] - fn into_with_c_str(self, f: F) -> io::Result - where - Self: Sized, - F: FnOnce(&CStr) -> io::Result, - { - f(&self) - } -} - -#[cfg(feature = "std")] -#[cfg(any(not(target_os = "wasi"), not(target_env = "p2"), wasip2))] -impl<'a> Arg for Component<'a> { - #[inline] - fn as_str(&self) -> io::Result<&str> { - self.as_os_str().to_str().ok_or(io::Errno::INVAL) - } - - #[inline] - fn to_string_lossy(&self) -> Cow<'_, str> { - self.as_os_str().to_string_lossy() - } - - #[inline] - fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Owned( - CString::new(self.as_os_str().as_bytes()).map_err(|_cstr_err| io::Errno::INVAL)?, - )) - } - - #[inline] - fn into_c_str<'b>(self) -> io::Result> - where - Self: 'b, - { - Ok(Cow::Owned( - CString::new(self.as_os_str().as_bytes()).map_err(|_cstr_err| io::Errno::INVAL)?, - )) - } - - #[inline] - fn into_with_c_str(self, f: F) -> io::Result - where - Self: Sized, - F: FnOnce(&CStr) -> io::Result, - { - with_c_str(self.as_os_str().as_bytes(), f) - } -} - -#[cfg(feature = "std")] -#[cfg(any(not(target_os = "wasi"), not(target_env = "p2"), wasip2))] -impl<'a> Arg for Components<'a> { - #[inline] - fn as_str(&self) -> io::Result<&str> { - self.as_path().to_str().ok_or(io::Errno::INVAL) - } - - #[inline] - fn to_string_lossy(&self) -> Cow<'_, str> { - self.as_path().to_string_lossy() - } - - #[inline] - fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Owned( - CString::new(self.as_path().as_os_str().as_bytes()) - .map_err(|_cstr_err| io::Errno::INVAL)?, - )) - } - - #[inline] - fn into_c_str<'b>(self) -> io::Result> - where - Self: 'b, - { - Ok(Cow::Owned( - CString::new(self.as_path().as_os_str().as_bytes()) - .map_err(|_cstr_err| io::Errno::INVAL)?, - )) - } - - #[inline] - fn into_with_c_str(self, f: F) -> io::Result - where - Self: Sized, - F: FnOnce(&CStr) -> io::Result, - { - with_c_str(self.as_path().as_os_str().as_bytes(), f) - } -} - -#[cfg(feature = "std")] -#[cfg(any(not(target_os = "wasi"), not(target_env = "p2"), wasip2))] -impl<'a> Arg for Iter<'a> { - #[inline] - fn as_str(&self) -> io::Result<&str> { - self.as_path().to_str().ok_or(io::Errno::INVAL) - } - - #[inline] - fn to_string_lossy(&self) -> Cow<'_, str> { - self.as_path().to_string_lossy() - } - - #[inline] - fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Owned( - CString::new(self.as_path().as_os_str().as_bytes()) - .map_err(|_cstr_err| io::Errno::INVAL)?, - )) - } - - #[inline] - fn into_c_str<'b>(self) -> io::Result> - where - Self: 'b, - { - Ok(Cow::Owned( - CString::new(self.as_path().as_os_str().as_bytes()) - .map_err(|_cstr_err| io::Errno::INVAL)?, - )) - } - - #[inline] - fn into_with_c_str(self, f: F) -> io::Result - where - Self: Sized, - F: FnOnce(&CStr) -> io::Result, - { - with_c_str(self.as_path().as_os_str().as_bytes(), f) - } -} - -impl Arg for &[u8] { - #[inline] - fn as_str(&self) -> io::Result<&str> { - str::from_utf8(self).map_err(|_utf8_err| io::Errno::INVAL) - } - - #[cfg(feature = "alloc")] - #[inline] - fn to_string_lossy(&self) -> Cow<'_, str> { - String::from_utf8_lossy(self) - } - - #[cfg(feature = "alloc")] - #[inline] - fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Owned( - CString::new(*self).map_err(|_cstr_err| io::Errno::INVAL)?, - )) - } - - #[cfg(feature = "alloc")] - #[inline] - fn into_c_str<'b>(self) -> io::Result> - where - Self: 'b, - { - Ok(Cow::Owned( - CString::new(self).map_err(|_cstr_err| io::Errno::INVAL)?, - )) - } - - #[inline] - fn into_with_c_str(self, f: F) -> io::Result - where - Self: Sized, - F: FnOnce(&CStr) -> io::Result, - { - with_c_str(self, f) - } -} - -#[cfg(feature = "alloc")] -impl Arg for &Vec { - #[inline] - fn as_str(&self) -> io::Result<&str> { - str::from_utf8(self).map_err(|_utf8_err| io::Errno::INVAL) - } - - #[cfg(feature = "alloc")] - #[inline] - fn to_string_lossy(&self) -> Cow<'_, str> { - String::from_utf8_lossy(self) - } - - #[cfg(feature = "alloc")] - #[inline] - fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Owned( - CString::new(self.as_slice()).map_err(|_cstr_err| io::Errno::INVAL)?, - )) - } - - #[cfg(feature = "alloc")] - #[inline] - fn into_c_str<'b>(self) -> io::Result> - where - Self: 'b, - { - Ok(Cow::Owned( - CString::new(self.as_slice()).map_err(|_cstr_err| io::Errno::INVAL)?, - )) - } - - #[inline] - fn into_with_c_str(self, f: F) -> io::Result - where - Self: Sized, - F: FnOnce(&CStr) -> io::Result, - { - with_c_str(self, f) - } -} - -#[cfg(feature = "alloc")] -#[cfg(any(not(target_os = "wasi"), not(target_env = "p2"), wasip2))] -impl Arg for Vec { - #[inline] - fn as_str(&self) -> io::Result<&str> { - str::from_utf8(self).map_err(|_utf8_err| io::Errno::INVAL) - } - - #[cfg(feature = "alloc")] - #[inline] - fn to_string_lossy(&self) -> Cow<'_, str> { - String::from_utf8_lossy(self) - } - - #[cfg(feature = "alloc")] - #[inline] - fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Owned( - CString::new(self.as_slice()).map_err(|_cstr_err| io::Errno::INVAL)?, - )) - } - - #[cfg(feature = "alloc")] - #[inline] - fn into_c_str<'b>(self) -> io::Result> - where - Self: 'b, - { - Ok(Cow::Owned( - CString::new(self).map_err(|_cstr_err| io::Errno::INVAL)?, - )) - } - - #[inline] - fn into_with_c_str(self, f: F) -> io::Result - where - Self: Sized, - F: FnOnce(&CStr) -> io::Result, - { - f(&CString::new(self).map_err(|_cstr_err| io::Errno::INVAL)?) - } -} - -impl Arg for DecInt { - #[inline] - fn as_str(&self) -> io::Result<&str> { - Ok(self.as_str()) - } - - #[cfg(feature = "alloc")] - #[inline] - fn to_string_lossy(&self) -> Cow<'_, str> { - Cow::Borrowed(self.as_str()) - } - - #[cfg(feature = "alloc")] - #[inline] - fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Borrowed(self.as_c_str())) - } - - #[cfg(feature = "alloc")] - #[inline] - fn into_c_str<'b>(self) -> io::Result> - where - Self: 'b, - { - Ok(Cow::Owned(self.as_c_str().to_owned())) - } - - #[inline] - fn into_with_c_str(self, f: F) -> io::Result - where - Self: Sized, - F: FnOnce(&CStr) -> io::Result, - { - f(self.as_c_str()) - } -} - -/// Runs a closure with `bytes` passed in as a `&CStr`. -#[allow(unsafe_code, clippy::int_plus_one)] -#[inline] -fn with_c_str(bytes: &[u8], f: F) -> io::Result -where - F: FnOnce(&CStr) -> io::Result, -{ - // Most paths are less than `SMALL_PATH_BUFFER_SIZE` long. The rest can go - // through the dynamic allocation path. If you're opening many files in a - // directory with a long path, consider opening the directory and using - // `openat` to open the files under it, which will avoid this, and is often - // faster in the OS as well. - - // Test with `>=` so that we have room for the trailing NUL. - if bytes.len() >= SMALL_PATH_BUFFER_SIZE { - return with_c_str_slow_path(bytes, f); - } - - // Taken from - // - let mut buf = MaybeUninit::<[u8; SMALL_PATH_BUFFER_SIZE]>::uninit(); - let buf_ptr = buf.as_mut_ptr().cast::(); - - // This helps test our safety condition below. - debug_assert!(bytes.len() + 1 <= SMALL_PATH_BUFFER_SIZE); - - // SAFETY: `bytes.len() < SMALL_PATH_BUFFER_SIZE` which means we have space - // for `bytes.len() + 1` `u8`s: - unsafe { - ptr::copy_nonoverlapping(bytes.as_ptr(), buf_ptr, bytes.len()); - buf_ptr.add(bytes.len()).write(b'\0'); - } - - // SAFETY: We just wrote the bytes above and they will remain valid for the - // duration of `f` because `buf` doesn't get dropped until the end of the - // function. - match CStr::from_bytes_with_nul(unsafe { slice::from_raw_parts(buf_ptr, bytes.len() + 1) }) { - Ok(s) => f(s), - Err(_) => Err(io::Errno::INVAL), - } -} - -/// The slow path which handles any length. In theory OS's only support up to -/// `PATH_MAX`, but we let the OS enforce that. -#[allow(unsafe_code, clippy::int_plus_one)] -#[cold] -fn with_c_str_slow_path(bytes: &[u8], f: F) -> io::Result -where - F: FnOnce(&CStr) -> io::Result, -{ - #[cfg(feature = "alloc")] - { - f(&CString::new(bytes).map_err(|_cstr_err| io::Errno::INVAL)?) - } - - #[cfg(not(feature = "alloc"))] - { - #[cfg(all( - libc, - not(any( - target_os = "espidf", - target_os = "horizon", - target_os = "hurd", - target_os = "vita", - target_os = "wasi" - )) - ))] - const LARGE_PATH_BUFFER_SIZE: usize = libc::PATH_MAX as usize; - #[cfg(linux_raw)] - const LARGE_PATH_BUFFER_SIZE: usize = linux_raw_sys::general::PATH_MAX as usize; - #[cfg(any( - target_os = "espidf", - target_os = "horizon", - target_os = "hurd", - target_os = "vita", - target_os = "wasi" - ))] - const LARGE_PATH_BUFFER_SIZE: usize = 4096 as usize; // TODO: upstream this - - // Taken from - // - let mut buf = MaybeUninit::<[u8; LARGE_PATH_BUFFER_SIZE]>::uninit(); - let buf_ptr = buf.as_mut_ptr().cast::(); - - // This helps test our safety condition below. - if bytes.len() + 1 > LARGE_PATH_BUFFER_SIZE { - return Err(io::Errno::NAMETOOLONG); - } - - // SAFETY: `bytes.len() < LARGE_PATH_BUFFER_SIZE` which means we have - // space for `bytes.len() + 1` `u8`s: - unsafe { - ptr::copy_nonoverlapping(bytes.as_ptr(), buf_ptr, bytes.len()); - buf_ptr.add(bytes.len()).write(b'\0'); - } - - // SAFETY: We just wrote the bytes above and they will remain valid for - // the duration of `f` because `buf` doesn't get dropped until the end - // of the function. - match CStr::from_bytes_with_nul(unsafe { slice::from_raw_parts(buf_ptr, bytes.len() + 1) }) - { - Ok(s) => f(s), - Err(_) => Err(io::Errno::INVAL), - } - } -} diff --git a/vendor/rustix/src/path/dec_int.rs b/vendor/rustix/src/path/dec_int.rs deleted file mode 100644 index 5b6e2f81..00000000 --- a/vendor/rustix/src/path/dec_int.rs +++ /dev/null @@ -1,261 +0,0 @@ -//! Efficient decimal integer formatting. -//! -//! # Safety -//! -//! This uses `CStr::from_bytes_with_nul_unchecked` and -//! `str::from_utf8_unchecked`on the buffer that it filled itself. -#![allow(unsafe_code)] - -use crate::backend::fd::{AsFd, AsRawFd as _}; -use crate::ffi::CStr; -use core::fmt; -use core::hint::unreachable_unchecked; -use core::mem::{self, MaybeUninit}; -use core::num::{NonZeroU8, NonZeroUsize}; -#[cfg(all(feature = "std", unix))] -use std::os::unix::ffi::OsStrExt; -#[cfg(all( - feature = "std", - target_os = "wasi", - any(not(target_env = "p2"), wasip2) -))] -use std::os::wasi::ffi::OsStrExt; -#[cfg(feature = "std")] -use {std::ffi::OsStr, std::path::Path}; - -/// Format an integer into a decimal `Path` component, without constructing a -/// temporary `PathBuf` or `String`. -/// -/// This is used for opening paths such as `/proc/self/fd/` on Linux. -/// -/// # Examples -/// -/// ``` -/// # #[cfg(any(feature = "fs", feature = "net"))] -/// use rustix::path::DecInt; -/// -/// # #[cfg(any(feature = "fs", feature = "net"))] -/// assert_eq!( -/// format!("hello {}", DecInt::new(9876).as_ref().display()), -/// "hello 9876" -/// ); -/// ``` -#[derive(Clone)] -pub struct DecInt { - buf: [MaybeUninit; BUF_LEN], - len: NonZeroU8, -} - -/// Enough to hold an {u,i}64 and NUL terminator. -const BUF_LEN: usize = U64_MAX_STR_LEN + 1; - -/// Maximum length of a formatted [`u64`]. -const U64_MAX_STR_LEN: usize = "18446744073709551615".len(); - -/// Maximum length of a formatted [`i64`]. -#[allow(dead_code)] -const I64_MAX_STR_LEN: usize = "-9223372036854775808".len(); - -const _: () = assert!(U64_MAX_STR_LEN == I64_MAX_STR_LEN); - -mod private { - pub trait Sealed: Copy { - type Unsigned: super::Integer; - - fn as_unsigned(self) -> (bool, Self::Unsigned); - fn eq_zero(self) -> bool; - fn div_mod_10(&mut self) -> u8; - } - - macro_rules! impl_unsigned { - ($($ty:ty)+) => { $( - impl Sealed for $ty { - type Unsigned = $ty; - - #[inline] - fn as_unsigned(self) -> (bool, $ty) { - (false, self) - } - - #[inline] - fn eq_zero(self) -> bool { - self == 0 - } - - #[inline] - fn div_mod_10(&mut self) -> u8 { - let result = (*self % 10) as u8; - *self /= 10; - result - } - } - )+ } - } - - macro_rules! impl_signed { - ($($signed:ty : $unsigned:ty)+) => { $( - impl Sealed for $signed { - type Unsigned = $unsigned; - - #[inline] - fn as_unsigned(self) -> (bool, $unsigned) { - if self >= 0 { - (false, self as $unsigned) - } else { - (true, !(self as $unsigned) + 1) - } - } - - #[inline] - fn eq_zero(self) -> bool { - unimplemented!() - } - - #[inline] - fn div_mod_10(&mut self) -> u8 { - unimplemented!() - } - } - )+ } - } - - impl_unsigned!(u8 u16 u32 u64); - impl_signed!(i8:u8 i16:u16 i32:u32 i64:u64); - - #[cfg(any( - target_pointer_width = "16", - target_pointer_width = "32", - target_pointer_width = "64" - ))] - const _: () = { - impl_unsigned!(usize); - impl_signed!(isize:usize); - }; -} - -/// An integer that can be used by [`DecInt::new`]. -pub trait Integer: private::Sealed {} - -impl Integer for i8 {} -impl Integer for i16 {} -impl Integer for i32 {} -impl Integer for i64 {} -impl Integer for u8 {} -impl Integer for u16 {} -impl Integer for u32 {} -impl Integer for u64 {} - -#[cfg(any( - target_pointer_width = "16", - target_pointer_width = "32", - target_pointer_width = "64" -))] -const _: () = { - impl Integer for isize {} - impl Integer for usize {} -}; - -impl DecInt { - /// Construct a new path component from an integer. - pub fn new(i: Int) -> Self { - use private::Sealed as _; - - let (is_neg, mut i) = i.as_unsigned(); - let mut len = 1; - let mut buf = [MaybeUninit::uninit(); BUF_LEN]; - buf[BUF_LEN - 1] = MaybeUninit::new(b'\0'); - - // We use `loop { …; if cond { break } }` instead of - // `while !cond { … }` so the loop is entered at least once. This way - // `0` does not need a special handling. - loop { - len += 1; - if len > BUF_LEN { - // SAFETY: A stringified `i64`/`u64` cannot be longer than - // `U64_MAX_STR_LEN` bytes. - unsafe { unreachable_unchecked() }; - } - buf[BUF_LEN - len] = MaybeUninit::new(b'0' + i.div_mod_10()); - if i.eq_zero() { - break; - } - } - - if is_neg { - len += 1; - if len > BUF_LEN { - // SAFETY: A stringified `i64`/`u64` cannot be longer than - // `U64_MAX_STR_LEN` bytes. - unsafe { unreachable_unchecked() }; - } - buf[BUF_LEN - len] = MaybeUninit::new(b'-'); - } - - Self { - buf, - len: NonZeroU8::new(len as u8).unwrap(), - } - } - - /// Construct a new path component from a file descriptor. - #[inline] - pub fn from_fd(fd: Fd) -> Self { - Self::new(fd.as_fd().as_raw_fd()) - } - - /// Return the raw byte buffer as a `&str`. - #[inline] - pub fn as_str(&self) -> &str { - // SAFETY: `DecInt` always holds a formatted decimal number, so it's - // always valid UTF-8. - unsafe { core::str::from_utf8_unchecked(self.as_bytes()) } - } - - /// Return the raw byte buffer as a `&CStr`. - #[inline] - pub fn as_c_str(&self) -> &CStr { - let bytes_with_nul = self.as_bytes_with_nul(); - debug_assert!(CStr::from_bytes_with_nul(bytes_with_nul).is_ok()); - - // SAFETY: `self.buf` holds a single decimal ASCII representation and - // at least one extra NUL byte. - unsafe { CStr::from_bytes_with_nul_unchecked(bytes_with_nul) } - } - - /// Return the raw byte buffer including the NUL byte. - #[inline] - pub fn as_bytes_with_nul(&self) -> &[u8] { - let len = NonZeroUsize::from(self.len).get(); - if len > BUF_LEN { - // SAFETY: A stringified `i64`/`u64` cannot be longer than - // `U64_MAX_STR_LEN` bytes. - unsafe { unreachable_unchecked() }; - } - let init = &self.buf[(self.buf.len() - len)..]; - // SAFETY: We're guaranteed to have initialized `len + 1` bytes. - unsafe { mem::transmute::<&[MaybeUninit], &[u8]>(init) } - } - - /// Return the raw byte buffer. - #[inline] - pub fn as_bytes(&self) -> &[u8] { - let bytes = self.as_bytes_with_nul(); - &bytes[..bytes.len() - 1] - } -} - -#[cfg(feature = "std")] -#[cfg(any(not(target_os = "wasi"), not(target_env = "p2"), wasip2))] -impl AsRef for DecInt { - #[inline] - fn as_ref(&self) -> &Path { - let as_os_str: &OsStr = OsStrExt::from_bytes(self.as_bytes()); - Path::new(as_os_str) - } -} - -impl fmt::Debug for DecInt { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.as_str().fmt(f) - } -} diff --git a/vendor/rustix/src/path/mod.rs b/vendor/rustix/src/path/mod.rs deleted file mode 100644 index 627716d8..00000000 --- a/vendor/rustix/src/path/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -//! Filesystem path operations. - -mod arg; -mod dec_int; - -pub use arg::{option_into_with_c_str, Arg}; -pub use dec_int::{DecInt, Integer}; - -pub(crate) const SMALL_PATH_BUFFER_SIZE: usize = 256; -- cgit v1.2.3