1use crate::send::SendFuture;
2use crate::{env::EnvBinding, Error, Result};
3use serde::de::DeserializeOwned;
4use serde::Serialize;
5use wasm_bindgen::{JsCast, JsValue};
6use wasm_bindgen_futures::JsFuture;
7use worker_sys::{
8 ImageTransformationResult as ImageTransformationResultSys, ImageTransformer as ImageTransformerSys,
9 ImagesBinding as ImagesBindingSys,
10};
11
12#[derive(Debug, Clone)]
13pub struct ImagesBinding(ImagesBindingSys);
14
15#[derive(Debug, Clone)]
16pub struct ImageTransformer(ImageTransformerSys);
17
18#[derive(Debug, Clone)]
19pub struct ImageTransformationResult(ImageTransformationResultSys);
20
21unsafe impl Send for ImagesBinding {}
22unsafe impl Sync for ImagesBinding {}
23unsafe impl Send for ImageTransformer {}
24unsafe impl Sync for ImageTransformer {}
25unsafe impl Send for ImageTransformationResult {}
26unsafe impl Sync for ImageTransformationResult {}
27
28impl ImagesBinding {
29 pub async fn transform(&self, input: JsValue) -> Result<JsValue> {
30 let promise = self.0.transform(input)?;
31 let output = SendFuture::new(JsFuture::from(promise)).await;
32 output.map_err(Error::from)
33 }
34
35 pub async fn transform_json<T: Serialize, U: DeserializeOwned>(&self, input: T) -> Result<U> {
36 let value = self.transform(serde_wasm_bindgen::to_value(&input)?).await?;
37 Ok(serde_wasm_bindgen::from_value(value)?)
38 }
39
40 pub async fn info(&self, input: JsValue, options: Option<JsValue>) -> Result<JsValue> {
41 let promise = self
42 .0
43 .info(input, options.unwrap_or(JsValue::UNDEFINED))?;
44 let output = SendFuture::new(JsFuture::from(promise)).await;
45 output.map_err(Error::from)
46 }
47
48 pub async fn info_json<T: Serialize, U: DeserializeOwned>(
49 &self,
50 input: T,
51 options: Option<serde_json::Value>,
52 ) -> Result<U> {
53 let input = serde_wasm_bindgen::to_value(&input)?;
54 let options = options
55 .map(|opt| serde_wasm_bindgen::to_value(&opt))
56 .transpose()?;
57 let value = self.info(input, options).await?;
58 Ok(serde_wasm_bindgen::from_value(value)?)
59 }
60
61 pub fn input(&self, input: JsValue, options: Option<JsValue>) -> Result<ImageTransformer> {
62 let transformer = self
63 .0
64 .input(input, options.unwrap_or(JsValue::UNDEFINED))?;
65 Ok(ImageTransformer(transformer))
66 }
67
68 pub fn input_json<T: Serialize>(
69 &self,
70 input: T,
71 options: Option<serde_json::Value>,
72 ) -> Result<ImageTransformer> {
73 let input = serde_wasm_bindgen::to_value(&input)?;
74 let options = options
75 .map(|opt| serde_wasm_bindgen::to_value(&opt))
76 .transpose()?;
77 self.input(input, options)
78 }
79}
80
81impl ImageTransformer {
82 pub fn transform(self, options: JsValue) -> Result<Self> {
83 Ok(Self(self.0.transform_step(options)?))
84 }
85
86 pub fn transform_json(self, options: serde_json::Value) -> Result<Self> {
87 self.transform(serde_wasm_bindgen::to_value(&options)?)
88 }
89
90 pub fn draw(self, image: JsValue) -> Result<Self> {
91 Ok(Self(self.0.draw(image)?))
92 }
93
94 pub async fn output(self, options: Option<JsValue>) -> Result<ImageTransformationResult> {
95 let promise = self.0.output(options.unwrap_or(JsValue::UNDEFINED))?;
96 let output = SendFuture::new(JsFuture::from(promise)).await;
97 let value = output.map_err(Error::from)?;
98 Ok(ImageTransformationResult(value.unchecked_into()))
99 }
100
101 pub async fn output_json(self, options: Option<serde_json::Value>) -> Result<ImageTransformationResult> {
102 let options = options
103 .map(|opt| serde_wasm_bindgen::to_value(&opt))
104 .transpose()?;
105 self.output(options).await
106 }
107}
108
109impl ImageTransformationResult {
110 pub fn response_raw(&self) -> JsValue {
111 self.0.response()
112 }
113
114 pub fn content_type(&self) -> Option<String> {
115 self.0.content_type()
116 }
117
118 pub fn image_raw(&self) -> JsValue {
119 self.0.image()
120 }
121
122 pub fn image_json<U: DeserializeOwned>(&self) -> Result<U> {
123 Ok(serde_wasm_bindgen::from_value(self.0.image())?)
124 }
125}
126
127impl EnvBinding for ImagesBinding {
128 const TYPE_NAME: &'static str = "Object";
129
130 fn get(val: JsValue) -> Result<Self> {
131 if !val.is_object() {
132 return Err("Binding cannot be cast to ImagesBinding from non-object value".into());
133 }
134
135 let has_transform = js_sys::Reflect::has(&val, &JsValue::from("transform"))?;
136 if !has_transform {
137 return Err("Binding cannot be cast to ImagesBinding: missing `transform` method".into());
138 }
139
140 Ok(Self(val.unchecked_into()))
141 }
142}
143
144impl JsCast for ImagesBinding {
145 fn instanceof(val: &JsValue) -> bool {
146 val.is_object()
147 }
148
149 fn unchecked_from_js(val: JsValue) -> Self {
150 Self(val.unchecked_into())
151 }
152
153 fn unchecked_from_js_ref(val: &JsValue) -> &Self {
154 unsafe { &*(val as *const JsValue as *const Self) }
155 }
156}
157
158impl AsRef<JsValue> for ImagesBinding {
159 fn as_ref(&self) -> &JsValue {
160 &self.0
161 }
162}
163
164impl From<JsValue> for ImagesBinding {
165 fn from(val: JsValue) -> Self {
166 Self(val.unchecked_into())
167 }
168}
169
170impl From<ImagesBinding> for JsValue {
171 fn from(value: ImagesBinding) -> Self {
172 value.0.into()
173 }
174}