about summary refs log tree commit diff
path: root/tvix/castore/src/proto
diff options
context:
space:
mode:
authorFlorian Klink <flokli@flokli.de>2024-08-16T14·32+0300
committerclbot <clbot@tvl.fyi>2024-08-17T15·59+0000
commit5ec93b57e6a263eef91ee583aba9f04581e4a66b (patch)
tree896407c00900d630a38ee82176ff12e0870f7a20 /tvix/castore/src/proto
parent8ea7d2b60eb4052d934820078c31ff25786376a4 (diff)
refactor(tvix/castore): add PathComponent type for checked components r/8506
This encodes a verified component on the type level. Internally, it
contains a bytes::Bytes.

The castore Path/PathBuf component() and file_name() methods now
return this type, the old ones returning bytes were renamed to
component_bytes() and component_file_name() respectively.

We can drop the directory_reject_invalid_name test - it's not possible
anymore to pass an invalid name to Directories::add.
Invalid names in the Directory proto are still being tested to be
rejected in the validate_invalid_names tests.

Change-Id: Ide4d16415dfd50b7e2d7e0c36d42a3bbeeb9b6c5
Reviewed-on: https://cl.tvl.fyi/c/depot/+/12217
Autosubmit: flokli <flokli@flokli.de>
Reviewed-by: Connor Brewster <cbrewster@hey.com>
Tested-by: BuildkiteCI
Diffstat (limited to 'tvix/castore/src/proto')
-rw-r--r--tvix/castore/src/proto/mod.rs27
-rw-r--r--tvix/castore/src/proto/tests/directory.rs2
2 files changed, 17 insertions, 12 deletions
diff --git a/tvix/castore/src/proto/mod.rs b/tvix/castore/src/proto/mod.rs
index c12eb4ee3c91..f32f3a0687a7 100644
--- a/tvix/castore/src/proto/mod.rs
+++ b/tvix/castore/src/proto/mod.rs
@@ -5,7 +5,7 @@ use prost::Message;
 mod grpc_blobservice_wrapper;
 mod grpc_directoryservice_wrapper;
 
-use crate::{B3Digest, DirectoryError};
+use crate::{path::PathComponent, B3Digest, DirectoryError};
 pub use grpc_blobservice_wrapper::GRPCBlobServiceWrapper;
 pub use grpc_directoryservice_wrapper::GRPCDirectoryServiceWrapper;
 
@@ -162,19 +162,19 @@ impl From<&crate::Directory> for Directory {
                     size,
                     executable,
                 } => files.push(FileNode {
-                    name: name.clone(),
+                    name: name.to_owned().into(),
                     digest: digest.to_owned().into(),
                     size: *size,
                     executable: *executable,
                 }),
                 crate::Node::Directory { digest, size } => directories.push(DirectoryNode {
-                    name: name.clone(),
+                    name: name.to_owned().into(),
                     digest: digest.to_owned().into(),
                     size: *size,
                 }),
                 crate::Node::Symlink { target } => {
                     symlinks.push(SymlinkNode {
-                        name: name.clone(),
+                        name: name.to_owned().into(),
                         target: target.to_owned().into(),
                     });
                 }
@@ -190,22 +190,24 @@ impl From<&crate::Directory> for Directory {
 
 impl Node {
     /// Converts a proto [Node] to a [crate::Node], and splits off the name.
-    pub fn into_name_and_node(self) -> Result<(bytes::Bytes, crate::Node), DirectoryError> {
+    pub fn into_name_and_node(self) -> Result<(PathComponent, crate::Node), DirectoryError> {
         match self.node.ok_or_else(|| DirectoryError::NoNodeSet)? {
             node::Node::Directory(n) => {
+                let name: PathComponent = n.name.try_into()?;
                 let digest = B3Digest::try_from(n.digest)
-                    .map_err(|e| DirectoryError::InvalidNode(n.name.to_owned(), e.into()))?;
+                    .map_err(|e| DirectoryError::InvalidNode(name.clone(), e.into()))?;
 
                 let node = crate::Node::Directory {
                     digest,
                     size: n.size,
                 };
 
-                Ok((n.name, node))
+                Ok((name, node))
             }
             node::Node::File(n) => {
+                let name: PathComponent = n.name.try_into()?;
                 let digest = B3Digest::try_from(n.digest)
-                    .map_err(|e| DirectoryError::InvalidNode(n.name.to_owned(), e.into()))?;
+                    .map_err(|e| DirectoryError::InvalidNode(name.clone(), e.into()))?;
 
                 let node = crate::Node::File {
                     digest,
@@ -213,23 +215,26 @@ impl Node {
                     executable: n.executable,
                 };
 
-                Ok((n.name, node))
+                Ok((name, node))
             }
 
             node::Node::Symlink(n) => {
+                let name: PathComponent = n.name.try_into()?;
                 let node = crate::Node::Symlink {
                     target: n
                         .target
                         .try_into()
-                        .map_err(|e| DirectoryError::InvalidNode(n.name.to_owned(), e))?,
+                        .map_err(|e| DirectoryError::InvalidNode(name.clone(), e))?,
                 };
 
-                Ok((n.name, node))
+                Ok((name, node))
             }
         }
     }
 
     /// Construsts a [Node] from a name and [crate::Node].
+    /// The name is a [bytes::Bytes], not a [PathComponent], as we have use an
+    /// empty name in some places.
     pub fn from_name_and_node(name: bytes::Bytes, n: crate::Node) -> Self {
         match n {
             crate::Node::Directory { digest, size } => Self {
diff --git a/tvix/castore/src/proto/tests/directory.rs b/tvix/castore/src/proto/tests/directory.rs
index 215bce7275dd..1e7cdb89c118 100644
--- a/tvix/castore/src/proto/tests/directory.rs
+++ b/tvix/castore/src/proto/tests/directory.rs
@@ -301,7 +301,7 @@ fn validate_sorting() {
         };
         match crate::Directory::try_from(d).expect_err("must fail") {
             DirectoryError::DuplicateName(s) => {
-                assert_eq!(s, b"a");
+                assert_eq!(s.as_ref(), b"a");
             }
             _ => panic!("unexpected error"),
         }