1#![feature(arbitrary_self_types)]
2#![feature(arbitrary_self_types_pointers)]
3
4mod command_line;
5mod custom;
6mod dotenv;
7mod filter;
8
9use std::{env, sync::Mutex};
10
11use anyhow::Result;
12use turbo_rcstr::RcStr;
13use turbo_tasks::{FxIndexMap, Vc};
14
15pub use self::{
16 command_line::CommandLineProcessEnv, custom::CustomProcessEnv, dotenv::DotenvProcessEnv,
17 filter::FilterProcessEnv,
18};
19
20#[turbo_tasks::value(transparent)]
21pub struct EnvMap(
22 #[turbo_tasks(trace_ignore)]
23 #[bincode(with = "turbo_bincode::indexmap")]
24 FxIndexMap<RcStr, RcStr>,
25);
26
27#[turbo_tasks::value_impl]
28impl EnvMap {
29 #[turbo_tasks::function]
30 pub fn empty() -> Vc<Self> {
31 EnvMap(FxIndexMap::default()).cell()
32 }
33}
34
35#[turbo_tasks::value_impl]
36impl ProcessEnv for EnvMap {
37 #[turbo_tasks::function]
38 fn read_all(self: Vc<Self>) -> Vc<EnvMap> {
39 self
40 }
41
42 #[turbo_tasks::function]
43 fn read(self: Vc<Self>, name: RcStr) -> Vc<Option<RcStr>> {
44 case_insensitive_read(self, name)
45 }
46}
47
48#[turbo_tasks::value_trait]
49pub trait ProcessEnv {
50 #[turbo_tasks::function]
57 fn read_all(self: Vc<Self>) -> Vc<EnvMap>;
58
59 #[turbo_tasks::function]
61 fn read(self: Vc<Self>, name: RcStr) -> Vc<Option<RcStr>> {
62 case_insensitive_read(self.read_all(), name)
63 }
64}
65
66pub fn sorted_env_vars() -> FxIndexMap<RcStr, RcStr> {
67 let mut vars = env::vars()
68 .map(|(k, v)| (k.into(), v.into()))
69 .collect::<FxIndexMap<_, _>>();
70 vars.sort_keys();
71 vars
72}
73
74#[turbo_tasks::function]
75pub async fn case_insensitive_read(map: Vc<EnvMap>, name: RcStr) -> Result<Vc<Option<RcStr>>> {
76 Ok(Vc::cell(
77 to_uppercase_map(map)
78 .await?
79 .get(&RcStr::from(name.to_uppercase()))
80 .cloned(),
81 ))
82}
83
84#[turbo_tasks::function]
85async fn to_uppercase_map(map: Vc<EnvMap>) -> Result<Vc<EnvMap>> {
86 let map = &*map.await?;
87 let mut new = FxIndexMap::with_capacity_and_hasher(map.len(), Default::default());
88 for (k, v) in map {
89 new.insert(k.to_uppercase().into(), v.clone());
90 }
91 Ok(Vc::cell(new))
92}
93
94pub static GLOBAL_ENV_LOCK: Mutex<()> = Mutex::new(());