From 687291cebcffca7cc0d2a480444b9e6559486c1a Mon Sep 17 00:00:00 2001 From: edef Date: Wed, 1 May 2024 11:49:51 +0000 Subject: feat(tvix/castore/path): more conversions Change-Id: I3ee510b444848316df520dc8ca445d0f3c7d607f Reviewed-on: https://cl.tvl.fyi/c/depot/+/11567 Tested-by: BuildkiteCI Reviewed-by: flokli --- tvix/castore/src/path.rs | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) (limited to 'tvix/castore') diff --git a/tvix/castore/src/path.rs b/tvix/castore/src/path.rs index d2b011947a87..7e0ad391c7ca 100644 --- a/tvix/castore/src/path.rs +++ b/tvix/castore/src/path.rs @@ -46,6 +46,11 @@ impl Path { Some(unsafe { Path::from_bytes_unchecked(bytes) }) } + pub fn into_boxed_bytes(self: Box) -> Box<[u8]> { + // SAFETY: Box and Box<[u8]> have the same representation. + unsafe { mem::transmute(self) } + } + /// Returns the path without its final component, if there is one. /// /// Note that the parent of a bare file name is [Path::ROOT]. @@ -100,7 +105,7 @@ impl Path { self.components().last() } - pub fn as_slice(&self) -> &[u8] { + pub fn as_bytes(&self) -> &[u8] { &self.inner } } @@ -156,6 +161,19 @@ impl Borrow for PathBuf { } } +impl From> for PathBuf { + fn from(value: Box) -> Self { + // SAFETY: Box is always a valid path. + unsafe { PathBuf::from_bytes_unchecked(value.into_boxed_bytes().into_vec()) } + } +} + +impl From<&Path> for PathBuf { + fn from(value: &Path) -> Self { + value.to_owned() + } +} + impl FromStr for PathBuf { type Err = std::io::Error; @@ -178,6 +196,23 @@ impl Display for PathBuf { } } +impl PathBuf { + /// Convert a byte vector to a PathBuf, without checking validity. + unsafe fn from_bytes_unchecked(bytes: Vec) -> PathBuf { + PathBuf { inner: bytes } + } + + pub fn into_boxed_path(self) -> Box { + // SAFETY: Box<[u8]> and Box have the same representation, + // and PathBuf always contains a valid Path. + unsafe { mem::transmute(self.inner.into_boxed_slice()) } + } + + pub fn into_bytes(self) -> Vec { + self.inner + } +} + #[cfg(test)] mod test { use super::{Path, PathBuf}; @@ -201,7 +236,7 @@ mod test { pub fn from_str(#[case] s: &str, #[case] num_components: usize) { let p: PathBuf = s.parse().expect("must parse"); - assert_eq!(s.as_bytes(), p.as_slice(), "inner bytes mismatch"); + assert_eq!(s.as_bytes(), p.as_bytes(), "inner bytes mismatch"); assert_eq!( num_components, p.components().count(), -- cgit 1.4.1