diff options
author | edef <edef@edef.eu> | 2024-05-01T11·49+0000 |
---|---|---|
committer | edef <edef@edef.eu> | 2024-05-01T13·40+0000 |
commit | 687291cebcffca7cc0d2a480444b9e6559486c1a (patch) | |
tree | 75db298263f8425fae62b366c0e9780145e2ee4f /tvix/castore/src/path.rs | |
parent | 1bb023df91640268fad1e74571b5dc94822a79b3 (diff) |
feat(tvix/castore/path): more conversions r/8059
Change-Id: I3ee510b444848316df520dc8ca445d0f3c7d607f Reviewed-on: https://cl.tvl.fyi/c/depot/+/11567 Tested-by: BuildkiteCI Reviewed-by: flokli <flokli@flokli.de>
Diffstat (limited to 'tvix/castore/src/path.rs')
-rw-r--r-- | tvix/castore/src/path.rs | 39 |
1 files changed, 37 insertions, 2 deletions
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<Path>) -> Box<[u8]> { + // SAFETY: Box<Path> 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<Path> for PathBuf { } } +impl From<Box<Path>> for PathBuf { + fn from(value: Box<Path>) -> Self { + // SAFETY: Box<Path> 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<u8>) -> PathBuf { + PathBuf { inner: bytes } + } + + pub fn into_boxed_path(self) -> Box<Path> { + // SAFETY: Box<[u8]> and Box<Path> 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<u8> { + 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(), |