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