1use js_sys::{Map, Object, Reflect};
2use wasm_bindgen::prelude::*;
3use wasm_bindgen_futures::JsFuture;
4
5use crate::{Fetcher, Result};
6
7#[derive(Debug)]
8pub struct Container {
9 pub(super) inner: worker_sys::Container,
10}
11
12impl Container {
13 pub fn running(&self) -> bool {
14 self.inner.running()
15 }
16
17 pub fn start(&self, options: Option<ContainerStartupOptions>) -> Result<()> {
18 let options = match options {
19 Some(o) => o.into(),
20 None => JsValue::undefined(),
21 };
22 self.inner.start(&options).map_err(|e| e.into())
23 }
24
25 pub async fn wait_for_exit(&self) -> Result<()> {
26 let promise = self.inner.monitor();
27 JsFuture::from(promise).await?;
28 Ok(())
29 }
30
31 pub async fn destroy(&self, error: Option<&str>) -> Result<()> {
32 let promise = self.inner.destroy(error);
33 JsFuture::from(promise).await?;
34 Ok(())
35 }
36
37 pub fn signal(&self, signo: i32) -> Result<()> {
38 self.inner.signal(signo).map_err(|e| e.into())
39 }
40
41 pub fn get_tcp_port(&self, port: u16) -> Result<Fetcher> {
42 self.inner
43 .get_tcp_port(port)
44 .map(|f| f.into())
45 .map_err(|e| e.into())
46 }
47}
48
49unsafe impl Sync for Container {}
50unsafe impl Send for Container {}
51
52impl From<worker_sys::Container> for Container {
53 fn from(inner: worker_sys::Container) -> Self {
54 Self { inner }
55 }
56}
57
58impl AsRef<JsValue> for Container {
59 fn as_ref(&self) -> &JsValue {
60 &self.inner
61 }
62}
63
64impl From<Container> for JsValue {
65 fn from(container: Container) -> Self {
66 JsValue::from(container.inner)
67 }
68}
69
70impl JsCast for Container {
71 fn instanceof(val: &JsValue) -> bool {
72 val.is_instance_of::<worker_sys::Container>()
73 }
74
75 fn unchecked_from_js(val: JsValue) -> Self {
76 Self { inner: val.into() }
77 }
78
79 fn unchecked_from_js_ref(val: &JsValue) -> &Self {
80 unsafe { &*(val as *const JsValue as *const Self) }
81 }
82}
83
84#[wasm_bindgen(getter_with_clone)]
85#[derive(Debug, Clone)]
86pub struct ContainerStartupOptions {
87 pub entrypoint: Vec<String>,
88 #[wasm_bindgen(js_name = "enableInternet")]
89 pub enable_internet: Option<bool>,
90 pub env: Map,
91}
92
93impl ContainerStartupOptions {
94 pub fn new() -> ContainerStartupOptions {
95 ContainerStartupOptions {
96 entrypoint: Vec::new(),
97 enable_internet: None,
98 env: Map::new(),
99 }
100 }
101
102 pub fn set_entrypoint(&mut self, entrypoint: &[&str]) {
103 self.entrypoint = entrypoint.iter().map(|s| s.to_string()).collect();
104 }
105
106 pub fn enable_internet(&mut self, enable_internet: bool) {
107 self.enable_internet = Some(enable_internet);
108 }
109
110 pub fn add_env(&mut self, key: &str, value: &str) {
111 self.env
112 .set(&JsValue::from_str(key), &JsValue::from_str(value));
113 }
114}
115
116impl From<ContainerStartupOptions> for Object {
117 fn from(options: ContainerStartupOptions) -> Self {
118 let obj = options.clone().into();
119 if !options.entrypoint.is_empty() {
120 Reflect::delete_property(&obj, &JsValue::from_str("entrypoint")).unwrap();
121 }
122 if options.enable_internet.is_some() {
123 Reflect::delete_property(&obj, &JsValue::from_str("enableInternet")).unwrap();
124 }
125 if options.env.size() != 0 {
126 Reflect::delete_property(&obj, &JsValue::from_str("env")).unwrap();
127 }
128 obj
129 }
130}