Skip to main content

bitwarden_ffi/
wire_macros.rs

1//! The `impl_wire_*` macros, which implement the wire traits.
2//!
3//! Defined outside that module so they exist without this crate's `wasm` feature. Like the
4//! attribute macros, each one gates what it generates on the calling crate's `wasm` feature, so a
5//! call site needs no `cfg` of its own.
6
7/// Implements both traits for a type that crosses as itself: a `#[wasm_bindgen]` handle, an
8/// `extern "C"` type, or a primitive wasm_bindgen already understands.
9///
10/// `#[wasm_object]` and `#[wasm_import]` call this for the types they declare.
11#[macro_export]
12macro_rules! impl_wire_object {
13    ($($ty:ty),* $(,)?) => {
14        $(
15            #[cfg(feature = "wasm")]
16            impl $crate::FromWasm for $ty {
17                type Wire = $ty;
18
19                fn from_wire(wire: Self::Wire) -> ::core::result::Result<Self, $crate::WireError> {
20                    ::core::result::Result::Ok(wire)
21                }
22            }
23
24            #[cfg(feature = "wasm")]
25            impl $crate::ToWasm for $ty {
26                type Wire = $ty;
27
28                fn to_wire(self) -> ::core::result::Result<Self::Wire, $crate::WireError> {
29                    ::core::result::Result::Ok(self)
30                }
31            }
32        )*
33    };
34}
35
36/// Implements the traits for a type that crosses as a `String`, so a malformed string is a
37/// [`WireError::Parse`](crate::WireError::Parse) rather than a throw from inside `FromWasmAbi`.
38///
39/// - `impl_wire_string!(T)` parses with `FromStr` and formats with `Display`.
40/// - `impl_wire_string!(T, parse = f, format = g)` takes `f: FnOnce(String) -> Result<T, E>` and
41///   `g: FnOnce(T) -> String`.
42/// - `impl_wire_string!(T, parse = f)` implements only [`FromWasm`](crate::FromWasm), for a type
43///   JavaScript never receives.
44///
45/// Also implements wasm_bindgen's ABI traits through the same conversion, so the type needs no
46/// hand-written `WasmDescribe` / `FromWasmAbi` / `IntoWasmAbi`. `from_abi` cannot fail, so it
47/// throws on a malformed string.
48#[macro_export]
49macro_rules! impl_wire_string {
50    ($ty:ty $(,)?) => {
51        $crate::impl_wire_string!(
52            $ty,
53            parse = |wire: ::std::string::String| wire.parse::<$ty>(),
54            format = |value: $ty| ::std::string::ToString::to_string(&value),
55        );
56    };
57    ($ty:ty, parse = $parse:expr, format = $format:expr $(,)?) => {
58        $crate::impl_wire_string!($ty, parse = $parse);
59
60        #[cfg(feature = "wasm")]
61        impl $crate::ToWasm for $ty {
62            type Wire = ::std::string::String;
63
64            fn to_wire(self) -> ::core::result::Result<Self::Wire, $crate::WireError> {
65                ::core::result::Result::Ok($crate::format_wire_string(self, $format))
66            }
67        }
68
69        #[cfg(feature = "wasm")]
70        impl $crate::_macro::wasm_bindgen::convert::IntoWasmAbi for $ty {
71            type Abi =
72                <::std::string::String as $crate::_macro::wasm_bindgen::convert::IntoWasmAbi>::Abi;
73
74            fn into_abi(self) -> Self::Abi {
75                let wire = $crate::_macro::wasm_bindgen::UnwrapThrowExt::unwrap_throw(
76                    <$ty as $crate::ToWasm>::to_wire(self),
77                );
78                $crate::_macro::wasm_bindgen::convert::IntoWasmAbi::into_abi(wire)
79            }
80        }
81
82        #[cfg(feature = "wasm")]
83        impl $crate::_macro::wasm_bindgen::convert::OptionIntoWasmAbi for $ty {
84            fn none() -> Self::Abi {
85                <::std::string::String as $crate::_macro::wasm_bindgen::convert::OptionIntoWasmAbi>::none()
86            }
87        }
88    };
89    ($ty:ty, parse = $parse:expr $(,)?) => {
90        #[cfg(feature = "wasm")]
91        impl $crate::FromWasm for $ty {
92            type Wire = ::std::string::String;
93
94            fn from_wire(wire: Self::Wire) -> ::core::result::Result<Self, $crate::WireError> {
95                $crate::parse_wire_string(stringify!($ty), wire, $parse)
96            }
97        }
98
99        #[cfg(feature = "wasm")]
100        impl $crate::_macro::wasm_bindgen::describe::WasmDescribe for $ty {
101            fn describe() {
102                <::std::string::String as $crate::_macro::wasm_bindgen::describe::WasmDescribe>::describe();
103            }
104        }
105
106        #[cfg(feature = "wasm")]
107        impl $crate::_macro::wasm_bindgen::convert::FromWasmAbi for $ty {
108            type Abi =
109                <::std::string::String as $crate::_macro::wasm_bindgen::convert::FromWasmAbi>::Abi;
110
111            unsafe fn from_abi(abi: Self::Abi) -> Self {
112                // SAFETY: `abi` came from wasm_bindgen as a `String` ABI value, per `Self::Abi`.
113                let wire = unsafe {
114                    <::std::string::String as $crate::_macro::wasm_bindgen::convert::FromWasmAbi>::from_abi(abi)
115                };
116                $crate::_macro::wasm_bindgen::UnwrapThrowExt::unwrap_throw(
117                    <$ty as $crate::FromWasm>::from_wire(wire),
118                )
119            }
120        }
121
122        #[cfg(feature = "wasm")]
123        impl $crate::_macro::wasm_bindgen::convert::OptionFromWasmAbi for $ty {
124            fn is_none(abi: &Self::Abi) -> bool {
125                <::std::string::String as $crate::_macro::wasm_bindgen::convert::OptionFromWasmAbi>::is_none(abi)
126            }
127        }
128    };
129}