about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--tvix/eval/src/builtins/mod.rs25
1 files changed, 25 insertions, 0 deletions
diff --git a/tvix/eval/src/builtins/mod.rs b/tvix/eval/src/builtins/mod.rs
index 05c5eceeffda..a3aaf33bf4af 100644
--- a/tvix/eval/src/builtins/mod.rs
+++ b/tvix/eval/src/builtins/mod.rs
@@ -381,6 +381,31 @@ fn pure_builtins() -> Vec<Builtin> {
                 Ok(Value::attrs(NixAttrs::from_map(res)))
             },
         ),
+        Builtin::new("parseDrvName", &[true], |args: Vec<Value>, vm: &mut VM| {
+            // This replicates cppnix's (mis?)handling of codepoints
+            // above U+007f following 0x2d ('-')
+            let s = args[0].coerce_to_string(CoercionKind::Weak, vm)?;
+            let slice: &[u8] = s.as_str().as_ref();
+            let (name, dash_and_version) = slice.split_at(
+                slice
+                    .windows(2)
+                    .enumerate()
+                    .find_map(|x| match x {
+                        (idx, [b'-', c1]) if !c1.is_ascii_alphabetic() => Some(idx),
+                        _ => None,
+                    })
+                    .unwrap_or(slice.len()),
+            );
+            let version = dash_and_version
+                .split_first()
+                .map(|x| core::str::from_utf8(x.1))
+                .unwrap_or(Ok(""))?
+                .into();
+            Ok(Value::attrs(NixAttrs::from_map(BTreeMap::from([
+                (NixString::NAME, core::str::from_utf8(name)?.into()),
+                ("version".into(), version),
+            ]))))
+        }),
         Builtin::new("splitVersion", &[true], |args: Vec<Value>, _: &mut VM| {
             let s = args[0].to_str()?;
             let s = VersionPartsIter::new(s.as_str());