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