about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Kolloch <info@eigenvalue.net>2024-02-17T06·55+0700
committerclbot <clbot@tvl.fyi>2024-02-17T08·11+0000
commite87f2a2b3a5912387d89ef1229d4826b557bb8dc (patch)
tree5dd54f638270ce6f738628b87b7fb3969c2254e4
parentd29330466726ae7263598fd8051894e18745461b (diff)
feat(tvix/nix-compat): serde for StorePath[Ref]s r/7544
Necessary, if we want to use it inside of `Derivation` etc.

Change-Id: I8888060417b2ee83ac52d7ec3e7b27c393271d8b
Reviewed-on: https://cl.tvl.fyi/c/depot/+/10947
Reviewed-by: tazjin <tazjin@tvl.su>
Autosubmit: Peter Kolloch <info@eigenvalue.net>
Tested-by: BuildkiteCI
Reviewed-by: flokli <flokli@flokli.de>
-rw-r--r--tvix/nix-compat/src/store_path/mod.rs94
1 files changed, 94 insertions, 0 deletions
diff --git a/tvix/nix-compat/src/store_path/mod.rs b/tvix/nix-compat/src/store_path/mod.rs
index e23002bfb97e..ecf8ec8fa653 100644
--- a/tvix/nix-compat/src/store_path/mod.rs
+++ b/tvix/nix-compat/src/store_path/mod.rs
@@ -1,5 +1,6 @@
 use crate::nixbase32;
 use data_encoding::{DecodeError, BASE64};
+use serde::{Deserialize, Serialize};
 use std::{
     fmt,
     path::PathBuf,
@@ -135,6 +136,26 @@ impl StorePath {
     }
 }
 
+impl<'de> Deserialize<'de> for StorePath {
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+    where
+        D: serde::Deserializer<'de>,
+    {
+        let r = <StorePathRef<'de> as Deserialize<'de>>::deserialize(deserializer)?;
+        Ok(r.to_owned())
+    }
+}
+
+impl Serialize for StorePath {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: serde::Serializer,
+    {
+        let r: StorePathRef = self.into();
+        r.serialize(serializer)
+    }
+}
+
 /// Like [StorePath], but without a heap allocation for the name.
 /// Used by [StorePath] for parsing.
 ///
@@ -220,6 +241,35 @@ impl<'a> StorePathRef<'a> {
     }
 }
 
+impl<'de> Deserialize<'de> for StorePathRef<'de> {
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+    where
+        D: serde::Deserializer<'de>,
+    {
+        let string: &'de str = Deserialize::deserialize(deserializer)?;
+        let stripped: Option<&str> = string.strip_prefix(STORE_DIR_WITH_SLASH);
+        let stripped: &str = stripped.ok_or_else(|| {
+            serde::de::Error::invalid_value(
+                serde::de::Unexpected::Str(string),
+                &"store path prefix",
+            )
+        })?;
+        StorePathRef::from_bytes(stripped.as_bytes()).map_err(|_| {
+            serde::de::Error::invalid_value(serde::de::Unexpected::Str(string), &"StorePath")
+        })
+    }
+}
+
+impl Serialize for StorePathRef<'_> {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: serde::Serializer,
+    {
+        let string: String = self.to_absolute_path();
+        string.serialize(serializer)
+    }
+}
+
 /// NAME_CHARS contains `true` for bytes that are valid in store path names,
 /// not accounting for '.' being permitted only past the first character.
 static NAME_CHARS: [bool; 256] = {
@@ -388,6 +438,50 @@ mod tests {
         );
     }
 
+    #[test]
+    fn serialize_ref() {
+        let store_path_str =
+            "/nix/store/00bgd045z0d4icpbc2yyz4gx48ak44la-net-tools-1.60_p20170221182432";
+        let nixpath_actual =
+            StorePathRef::from_absolute_path(store_path_str.as_bytes()).expect("can parse");
+
+        let serialized = serde_json::to_string(&nixpath_actual).expect("can serialize");
+
+        assert_eq!(
+            "\"/nix/store/00bgd045z0d4icpbc2yyz4gx48ak44la-net-tools-1.60_p20170221182432\"",
+            &serialized
+        );
+    }
+
+    #[test]
+    fn serialize_owned() {
+        let store_path_str =
+            "/nix/store/00bgd045z0d4icpbc2yyz4gx48ak44la-net-tools-1.60_p20170221182432";
+        let nixpath_actual = StorePathRef::from_absolute_path(store_path_str.as_bytes())
+            .expect("can parse")
+            .to_owned();
+
+        let serialized = serde_json::to_string(&nixpath_actual).expect("can serialize");
+
+        assert_eq!(
+            "\"/nix/store/00bgd045z0d4icpbc2yyz4gx48ak44la-net-tools-1.60_p20170221182432\"",
+            &serialized
+        );
+    }
+
+    #[test]
+    fn deserialize_ref() {
+        let store_path_str_json =
+            "\"/nix/store/00bgd045z0d4icpbc2yyz4gx48ak44la-net-tools-1.60_p20170221182432\"";
+
+        let store_path: StorePath = serde_json::from_str(store_path_str_json).expect("valid json");
+
+        assert_eq!(
+            "/nix/store/00bgd045z0d4icpbc2yyz4gx48ak44la-net-tools-1.60_p20170221182432",
+            store_path.to_absolute_path()
+        );
+    }
+
     #[test_case(
         "/nix/store/00bgd045z0d4icpbc2yyz4gx48ak44la-net-tools-1.60_p20170221182432",
         (StorePath::from_bytes(b"00bgd045z0d4icpbc2yyz4gx48ak44la-net-tools-1.60_p20170221182432").unwrap(), PathBuf::new())