wry_bindgen/convert/
traits.rs1use crate::encode::{
2 Anchored, BinaryDecode, BinaryEncode, BorrowScope, CallScoped, EncodeTypeDef, JsRef,
3 ThrowingResult,
4};
5use crate::ipc::EncodedData;
6use crate::{JsCast, JsValue};
7use core::mem::ManuallyDrop;
8use core::ops::Deref;
9
10pub trait IntoWasmAbi: BinaryEncode + EncodeTypeDef {
18 #[inline]
19 fn into_abi(self) -> u32
20 where
21 Self: Sized + IntoAbiId,
22 {
23 self.into_abi_id()
24 }
25}
26
27pub trait FromWasmAbi: BinaryDecode + EncodeTypeDef {
30 #[inline]
41 unsafe fn from_abi(js: u32) -> Self
42 where
43 Self: Sized + FromAbiId,
44 {
45 unsafe { Self::from_abi_id(js) }
46 }
47}
48
49pub trait OptionIntoWasmAbi: IntoWasmAbi {}
51
52pub trait OptionFromWasmAbi: FromWasmAbi {}
54
55pub trait WasmAbi {}
57
58pub trait RefFromWasmAbi {
60 #[inline]
67 unsafe fn ref_from_abi(js: u32) -> AbiRef<Self>
68 where
69 Self: Sized + FromAbiId,
70 {
71 AbiRef(ManuallyDrop::new(unsafe { Self::from_abi_id(js) }))
72 }
73}
74
75pub struct AbiRef<T>(ManuallyDrop<T>);
77
78impl<T> Deref for AbiRef<T> {
79 type Target = T;
80
81 #[inline]
82 fn deref(&self) -> &Self::Target {
83 &self.0
84 }
85}
86
87impl<T> AsRef<T> for AbiRef<T> {
88 #[inline]
89 fn as_ref(&self) -> &T {
90 self
91 }
92}
93
94#[doc(hidden)]
95pub trait IntoAbiId {
96 fn into_abi_id(self) -> u32;
97}
98
99#[doc(hidden)]
100pub trait FromAbiId {
101 unsafe fn from_abi_id(js: u32) -> Self;
102}
103
104impl<T> IntoAbiId for T
105where
106 T: AsRef<JsValue>,
107{
108 #[inline]
109 fn into_abi_id(self) -> u32 {
110 let id = self.as_ref().js_ref().into_abi();
111 core::mem::forget(self);
112 id
113 }
114}
115
116impl<T> FromAbiId for T
117where
118 T: JsCast,
119{
120 #[inline]
121 unsafe fn from_abi_id(js: u32) -> Self {
122 T::unchecked_from_js(JsValue::from_ref(JsRef::from_abi(js)))
123 }
124}
125
126pub trait ReturnAbi<S: BorrowScope> {
134 type Wire: EncodeTypeDef;
136}
137
138pub trait ReturnSync: ReturnAbi<CallScoped> {
143 fn return_abi(self, encoder: &mut EncodedData);
145}
146
147impl<T: IntoWasmAbi> ReturnAbi<CallScoped> for T {
148 type Wire = T;
149}
150impl<T: IntoWasmAbi> ReturnSync for T {
151 #[inline]
152 fn return_abi(self, encoder: &mut EncodedData) {
153 self.encode(encoder);
154 }
155}
156
157impl<T, E> ReturnAbi<CallScoped> for Result<T, E>
158where
159 T: BinaryEncode + EncodeTypeDef,
160 E: Into<JsValue>,
161{
162 type Wire = ThrowingResult<T, JsValue>;
163}
164impl<T, E> ReturnSync for Result<T, E>
165where
166 T: BinaryEncode + EncodeTypeDef,
167 E: Into<JsValue>,
168{
169 #[inline]
170 fn return_abi(self, encoder: &mut EncodedData) {
171 ThrowingResult(self.map_err(Into::into)).encode(encoder);
172 }
173}
174
175impl ReturnAbi<CallScoped> for crate::__rt::object_store::ObjectHandle {
179 type Wire = Self;
180}
181impl ReturnSync for crate::__rt::object_store::ObjectHandle {
182 #[inline]
183 fn return_abi(self, encoder: &mut EncodedData) {
184 self.encode(encoder);
185 }
186}
187
188pub trait TryFromJsValue: Sized {
190 fn try_from_js_value(value: JsValue) -> Result<Self, JsValue> {
191 Self::try_from_js_value_ref(&value).ok_or(value)
192 }
193
194 fn try_from_js_value_ref(value: &JsValue) -> Option<Self>;
195}
196
197pub trait ReturnAsync: ReturnAbi<Anchored> {
203 fn into_js_result(self) -> Result<JsValue, JsValue>;
204}
205
206impl<T> ReturnAbi<Anchored> for T
207where
208 T: Into<JsValue> + crate::sys::Promising,
209 <T as crate::sys::Promising>::Resolution: EncodeTypeDef,
210{
211 type Wire = <T as crate::sys::Promising>::Resolution;
212}
213impl<T> ReturnAsync for T
214where
215 T: Into<JsValue> + crate::sys::Promising,
216 <T as crate::sys::Promising>::Resolution: EncodeTypeDef,
217{
218 #[inline]
219 fn into_js_result(self) -> Result<JsValue, JsValue> {
220 Ok(self.into())
221 }
222}
223
224impl<T, E> ReturnAbi<Anchored> for Result<T, E>
225where
226 T: Into<JsValue> + crate::sys::Promising,
227 <T as crate::sys::Promising>::Resolution: EncodeTypeDef,
228 E: Into<JsValue>,
229{
230 type Wire = <T as crate::sys::Promising>::Resolution;
231}
232impl<T, E> ReturnAsync for Result<T, E>
233where
234 T: Into<JsValue> + crate::sys::Promising,
235 <T as crate::sys::Promising>::Resolution: EncodeTypeDef,
236 E: Into<JsValue>,
237{
238 #[inline]
239 fn into_js_result(self) -> Result<JsValue, JsValue> {
240 match self {
241 Ok(value) => Ok(value.into()),
242 Err(error) => Err(error.into()),
243 }
244 }
245}
246
247pub trait FromJsFuture: Sized {
252 fn from_js_future(result: Result<JsValue, JsValue>) -> Self;
253}
254
255impl<T: TryFromJsValue> FromJsFuture for T {
256 #[inline]
257 fn from_js_future(result: Result<JsValue, JsValue>) -> Self {
258 let value = result.expect("async function failed");
259 T::try_from_js_value(value).expect("async function returned incompatible value")
260 }
261}
262
263impl<T: TryFromJsValue, E: From<JsValue>> FromJsFuture for Result<T, E> {
264 #[inline]
265 fn from_js_future(result: Result<JsValue, JsValue>) -> Self {
266 match result {
267 Ok(value) => Ok(
268 T::try_from_js_value(value).expect("async function returned incompatible value")
269 ),
270 Err(error) => Err(E::from(error)),
271 }
272 }
273}
274
275pub trait UpcastFrom<S: ?Sized> {}
314
315pub trait Upcast<T: ?Sized> {
317 #[inline]
318 fn upcast(&self) -> &T
319 where
320 Self: crate::__rt::marker::ErasableGeneric,
321 T: Sized
322 + crate::__rt::marker::ErasableGeneric<
323 Repr = <Self as crate::__rt::marker::ErasableGeneric>::Repr,
324 >,
325 {
326 unsafe { &*(self as *const Self as *const T) }
327 }
328
329 #[inline]
330 fn upcast_into(self) -> T
331 where
332 Self: Sized + crate::__rt::marker::ErasableGeneric,
333 T: Sized
334 + crate::__rt::marker::ErasableGeneric<
335 Repr = <Self as crate::__rt::marker::ErasableGeneric>::Repr,
336 >,
337 {
338 unsafe { core::mem::transmute_copy(&core::mem::ManuallyDrop::new(self)) }
339 }
340}
341
342impl<S, T> Upcast<T> for S
343where
344 T: UpcastFrom<S> + ?Sized,
345 S: ?Sized,
346{
347}
348
349impl<'a, T: ?Sized, Target: ?Sized> UpcastFrom<&'a mut T> for &'a mut Target
350where
351 Target: UpcastFrom<T>,
352 T: UpcastFrom<Target>,
353{
354}
355impl<'a, T, Target> UpcastFrom<&'a T> for &'a Target where Target: UpcastFrom<T> {}
356
357macro_rules! impl_tuple_upcast {
358 ([$($ty:ident)+] [$($target:ident)+]) => {
359 impl<$($ty,)+ $($target,)+> UpcastFrom<($($ty,)+)> for ($($target,)+)
360 where
361 $($ty: JsGeneric,)+
362 $($target: JsGeneric + UpcastFrom<$ty>,)+
363 {
364 }
365
366 impl<$($ty,)+ $($target,)+> UpcastFrom<($($ty,)+)> for crate::sys::JsOption<($($target,)+)>
367 where
368 $($ty: JsGeneric,)+
369 $($target: JsGeneric + UpcastFrom<$ty>,)+
370 {
371 }
372 };
373}
374
375impl_tuple_upcast!([T1][Target1]);
376impl_tuple_upcast!([T1 T2] [Target1 Target2]);
377impl_tuple_upcast!([T1 T2 T3] [Target1 Target2 Target3]);
378impl_tuple_upcast!([T1 T2 T3 T4] [Target1 Target2 Target3 Target4]);
379impl_tuple_upcast!([T1 T2 T3 T4 T5] [Target1 Target2 Target3 Target4 Target5]);
380impl_tuple_upcast!([T1 T2 T3 T4 T5 T6] [Target1 Target2 Target3 Target4 Target5 Target6]);
381impl_tuple_upcast!([T1 T2 T3 T4 T5 T6 T7] [Target1 Target2 Target3 Target4 Target5 Target6 Target7]);
382impl_tuple_upcast!([T1 T2 T3 T4 T5 T6 T7 T8] [Target1 Target2 Target3 Target4 Target5 Target6 Target7 Target8]);
383
384pub trait JsGeneric:
386 crate::__rt::marker::ErasableGeneric<Repr = JsValue>
387 + UpcastFrom<Self>
388 + Upcast<Self>
389 + Upcast<JsValue>
390 + JsCast
391 + crate::__rt::JsRefEncode
392 + crate::__rt::EncodeTypeDef
393 + crate::__rt::BinaryEncode
394 + crate::__rt::BinaryDecode
395 + crate::__rt::BatchableResult
396 + 'static
397{
398}
399
400impl<T> JsGeneric for T where
401 T: crate::__rt::marker::ErasableGeneric<Repr = JsValue>
402 + UpcastFrom<T>
403 + Upcast<JsValue>
404 + JsCast
405 + crate::__rt::JsRefEncode
406 + crate::__rt::EncodeTypeDef
407 + crate::__rt::BinaryEncode
408 + crate::__rt::BinaryDecode
409 + crate::__rt::BatchableResult
410 + 'static
411{
412}
413
414pub trait IntoJsGeneric {
416 type JsCanon: JsGeneric;
417
418 fn to_js(self) -> Self::JsCanon;
419}
420
421impl IntoJsGeneric for JsValue {
422 type JsCanon = JsValue;
423
424 #[inline]
425 fn to_js(self) -> JsValue {
426 self
427 }
428}
429
430impl<T: IntoJsGeneric + Clone> IntoJsGeneric for &T {
431 type JsCanon = T::JsCanon;
432
433 #[inline]
434 fn to_js(self) -> T::JsCanon {
435 self.clone().to_js()
436 }
437}