1use std::env;
5
6use rquickjs::{
7 Ctx, Exception, Result,
8 module::{Declarations, Exports, ModuleDef},
9 prelude::Func,
10};
11use rquickjs_extra_utils::{
12 module::export_default,
13 sysinfo::{get_arch, get_platform},
14};
15
16#[cfg(unix)]
17use self::unix::{EOL, get_release, get_type, get_version};
18#[cfg(windows)]
19use self::windows::{EOL, get_release, get_type, get_version};
20
21#[cfg(unix)]
22mod unix;
23#[cfg(windows)]
24mod windows;
25
26fn get_home_dir(ctx: Ctx<'_>) -> Result<String> {
27 home::home_dir()
28 .map(|val| val.to_string_lossy().into_owned())
29 .ok_or_else(|| Exception::throw_message(&ctx, "Could not determine home directory"))
30}
31
32fn get_tmp_dir() -> String {
33 env::temp_dir().to_string_lossy().to_string()
34}
35
36fn get_available_parallelism() -> usize {
37 num_cpus::get()
38}
39
40pub struct OsModule;
41
42impl ModuleDef for OsModule {
43 fn declare(declare: &Declarations) -> Result<()> {
44 declare.declare("arch")?;
45 declare.declare("availableParallelism")?;
46 declare.declare("EOL")?;
47 declare.declare("platform")?;
48 declare.declare("homedir")?;
49 declare.declare("release")?;
50 declare.declare("tmpdir")?;
51 declare.declare("type")?;
52 declare.declare("version")?;
53
54 declare.declare("default")?;
55
56 Ok(())
57 }
58
59 fn evaluate<'js>(ctx: &Ctx<'js>, exports: &Exports<'js>) -> Result<()> {
60 export_default(ctx, exports, |default| {
61 default.set("arch", Func::from(get_arch))?;
62 default.set(
63 "availableParallelism",
64 Func::from(get_available_parallelism),
65 )?;
66 default.set("EOL", EOL)?;
67 default.set("homedir", Func::from(get_home_dir))?;
68 default.set("platform", Func::from(get_platform))?;
69 default.set("release", Func::from(get_release))?;
70 default.set("tmpdir", Func::from(get_tmp_dir))?;
71 default.set("type", Func::from(get_type))?;
72 default.set("version", Func::from(get_version))?;
73
74 Ok(())
75 })
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use rquickjs_extra_test::{ModuleEvaluator, call_test, test_async_with};
82
83 use super::*;
84
85 #[tokio::test]
86 async fn test_type() {
87 test_async_with(|ctx| {
88 Box::pin(async move {
89 ModuleEvaluator::eval_rust::<OsModule>(ctx.clone(), "os")
90 .await
91 .unwrap();
92
93 let module = ModuleEvaluator::eval_js(
94 ctx.clone(),
95 "test",
96 r#"
97 import { type } from 'os';
98
99 export async function test() {
100 return type()
101 }
102 "#,
103 )
104 .await
105 .unwrap();
106
107 let result = call_test::<String, _>(&ctx, &module, ()).await;
108
109 assert!(result == "Linux" || result == "Windows_NT" || result == "Darwin");
110 })
111 })
112 .await;
113 }
114
115 #[tokio::test]
116 async fn test_release() {
117 test_async_with(|ctx| {
118 Box::pin(async move {
119 ModuleEvaluator::eval_rust::<OsModule>(ctx.clone(), "os")
120 .await
121 .unwrap();
122
123 let module = ModuleEvaluator::eval_js(
124 ctx.clone(),
125 "test",
126 r#"
127 import { release } from 'os';
128
129 export async function test() {
130 return release()
131 }
132 "#,
133 )
134 .await
135 .unwrap();
136
137 let result = call_test::<String, _>(&ctx, &module, ()).await;
138
139 assert!(!result.is_empty()); })
141 })
142 .await;
143 }
144
145 #[tokio::test]
146 async fn test_version() {
147 test_async_with(|ctx| {
148 Box::pin(async move {
149 ModuleEvaluator::eval_rust::<OsModule>(ctx.clone(), "os")
150 .await
151 .unwrap();
152
153 let module = ModuleEvaluator::eval_js(
154 ctx.clone(),
155 "test",
156 r#"
157 import { version } from 'os';
158
159 export async function test() {
160 return version()
161 }
162 "#,
163 )
164 .await
165 .unwrap();
166
167 let result = call_test::<String, _>(&ctx, &module, ()).await;
168
169 assert!(!result.is_empty()); })
171 })
172 .await;
173 }
174
175 #[tokio::test]
176 async fn test_available_parallelism() {
177 test_async_with(|ctx| {
178 Box::pin(async move {
179 ModuleEvaluator::eval_rust::<OsModule>(ctx.clone(), "os")
180 .await
181 .unwrap();
182
183 let module = ModuleEvaluator::eval_js(
184 ctx.clone(),
185 "test",
186 r#"
187 import { availableParallelism } from 'os';
188
189 export async function test() {
190 return availableParallelism()
191 }
192 "#,
193 )
194 .await
195 .unwrap();
196
197 let result = call_test::<usize, _>(&ctx, &module, ()).await;
198
199 assert!(result > 0);
200 })
201 })
202 .await;
203 }
204
205 #[tokio::test]
206 async fn test_eol() {
207 test_async_with(|ctx| {
208 Box::pin(async move {
209 ModuleEvaluator::eval_rust::<OsModule>(ctx.clone(), "os")
210 .await
211 .unwrap();
212
213 let module = ModuleEvaluator::eval_js(
214 ctx.clone(),
215 "test",
216 r#"
217 import { EOL } from 'os';
218
219 export async function test() {
220 return EOL
221 }
222 "#,
223 )
224 .await
225 .unwrap();
226
227 let result = call_test::<String, _>(&ctx, &module, ()).await;
228 assert!(result == EOL);
229 })
230 })
231 .await;
232 }
233
234 #[tokio::test]
235 async fn test_arch() {
236 test_async_with(|ctx| {
237 Box::pin(async move {
238 ModuleEvaluator::eval_rust::<OsModule>(ctx.clone(), "os")
239 .await
240 .unwrap();
241
242 let module = ModuleEvaluator::eval_js(
243 ctx.clone(),
244 "test",
245 r#"
246 import { arch } from 'os';
247
248 export async function test() {
249 return arch()
250 }
251 "#,
252 )
253 .await
254 .unwrap();
255
256 let result = call_test::<String, _>(&ctx, &module, ()).await;
257
258 assert!(!result.is_empty()); })
260 })
261 .await;
262 }
263}