tvix_eval/builtins/
impure.rs1use builtin_macros::builtins;
2use genawaiter::rc::Gen;
3
4use std::{
5 env,
6 time::{SystemTime, UNIX_EPOCH},
7};
8
9use crate::{
10 self as tvix_eval, NixString, Value,
11 errors::ErrorKind,
12 value::NixAttrs,
13 vm::generators::{self, GenCo},
14};
15
16#[builtins]
17mod impure_builtins {
18 use std::ffi::OsStr;
19 use std::os::unix::ffi::OsStrExt;
20
21 use super::*;
22 use crate::builtins::{coerce_value_to_path, hash::hash_nix_string};
23
24 #[builtin("getEnv")]
25 async fn builtin_get_env(co: GenCo, var: Value) -> Result<Value, ErrorKind> {
26 Ok(env::var(OsStr::from_bytes(&var.to_str()?))
27 .unwrap_or_else(|_| "".into())
28 .into())
29 }
30
31 #[builtin("hashFile")]
32 async fn builtin_hash_file(co: GenCo, algo: Value, path: Value) -> Result<Value, ErrorKind> {
33 let path = match coerce_value_to_path(&co, path).await? {
34 Err(cek) => return Ok(Value::from(cek)),
35 Ok(p) => p,
36 };
37 let r = generators::request_open_file(&co, path).await;
38 hash_nix_string(algo.to_str()?, r).map(Value::from)
39 }
40
41 #[builtin("pathExists")]
42 async fn builtin_path_exists(co: GenCo, path: Value) -> Result<Value, ErrorKind> {
43 match coerce_value_to_path(&co, path).await? {
44 Err(cek) => Ok(Value::from(cek)),
45 Ok(path) => Ok(generators::request_path_exists(&co, path).await),
46 }
47 }
48
49 #[builtin("readDir")]
50 async fn builtin_read_dir(co: GenCo, path: Value) -> Result<Value, ErrorKind> {
51 match coerce_value_to_path(&co, path).await? {
52 Err(cek) => Ok(Value::from(cek)),
53 Ok(path) => {
54 let dir = generators::request_read_dir(&co, path).await;
55 let res = dir.into_iter().map(|(name, ftype)| {
56 (
57 NixString::from(
59 String::from_utf8(name.to_vec()).expect("parsing file name as string"),
60 ),
61 Value::from(ftype.to_string()),
62 )
63 });
64
65 Ok(Value::attrs(NixAttrs::from_iter(res)))
66 }
67 }
68 }
69
70 #[builtin("readFile")]
71 async fn builtin_read_file(co: GenCo, path: Value) -> Result<Value, ErrorKind> {
72 match coerce_value_to_path(&co, path).await? {
73 Err(cek) => Ok(Value::from(cek)),
74 Ok(path) => {
75 let mut buf = Vec::new();
76 generators::request_open_file(&co, path)
77 .await
78 .read_to_end(&mut buf)?;
79 Ok(Value::from(buf))
80 }
81 }
82 }
83
84 #[builtin("readFileType")]
85 async fn builtin_read_file_type(co: GenCo, path: Value) -> Result<Value, ErrorKind> {
86 match coerce_value_to_path(&co, path).await? {
87 Err(cek) => Ok(Value::from(cek)),
88 Ok(path) => Ok(Value::from(
89 generators::request_read_file_type(&co, path)
90 .await
91 .to_string(),
92 )),
93 }
94 }
95}
96
97pub fn impure_builtins() -> Vec<(&'static str, Value)> {
100 let mut result = impure_builtins::builtins();
101
102 {
104 let seconds = match SystemTime::now().duration_since(UNIX_EPOCH) {
105 Ok(dur) => dur.as_secs() as i64,
106
107 Err(err) => -(err.duration().as_secs() as i64),
109 };
110
111 result.push(("currentTime", Value::Integer(seconds)));
112 }
113
114 result
115}