Skip to main content

typescript_type_def/
impls.rs

1use crate::{
2    emit::TypeDef,
3    type_expr::{
4        DefinedTypeInfo, Ident, NativeTypeInfo, ObjectField, TypeArray,
5        TypeDefinition, TypeExpr, TypeInfo, TypeName, TypeObject, TypeString,
6        TypeTuple, TypeUnion,
7    },
8};
9
10macro_rules! impl_native {
11    ($ty:ty, $ts_ty:literal) => {
12        impl TypeDef for $ty {
13            const INFO: TypeInfo = TypeInfo::Native(NativeTypeInfo {
14                r#ref: TypeExpr::ident(Ident($ts_ty)),
15            });
16        }
17    };
18}
19
20/// A Rust equivalent to the JavaScript
21/// [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) object.
22#[derive(Debug, Clone)]
23pub struct Blob(pub Vec<u8>);
24
25impl_native!(Blob, "Blob");
26impl_native!(bool, "boolean");
27impl_native!(String, "string");
28impl_native!(str, "string");
29impl_native!(char, "string");
30impl_native!(std::path::PathBuf, "string");
31impl_native!(std::path::Path, "string");
32impl_native!(std::ffi::CString, "string");
33impl_native!(std::ffi::CStr, "string");
34impl_native!(std::ffi::OsString, "string");
35impl_native!(std::ffi::OsStr, "string");
36#[cfg(feature = "json_value")]
37impl_native!(serde_json::Number, "number");
38impl_native!(std::net::IpAddr, "string");
39impl_native!(std::net::Ipv4Addr, "string");
40impl_native!(std::net::Ipv6Addr, "string");
41
42macro_rules! impl_number {
43    ($ty:ty, $name:ident) => {
44        impl TypeDef for $ty {
45            const INFO: TypeInfo = TypeInfo::Defined(DefinedTypeInfo {
46                def: TypeDefinition {
47                    docs: None,
48                    path: &[],
49                    name: Ident(stringify!($name)),
50                    generic_vars: &[],
51                    def: TypeExpr::ident(Ident("number")),
52                },
53                generic_args: &[],
54            });
55        }
56    };
57}
58
59impl_number!(u8, U8);
60impl_number!(u16, U16);
61impl_number!(u32, U32);
62impl_number!(u64, U64);
63impl_number!(usize, Usize);
64impl_number!(i8, I8);
65impl_number!(i16, I16);
66impl_number!(i32, I32);
67impl_number!(i64, I64);
68impl_number!(isize, Isize);
69impl_number!(std::num::NonZeroU8, NonZeroU8);
70impl_number!(std::num::NonZeroU16, NonZeroU16);
71impl_number!(std::num::NonZeroU32, NonZeroU32);
72impl_number!(std::num::NonZeroU64, NonZeroU64);
73impl_number!(std::num::NonZeroUsize, NonZeroUsize);
74impl_number!(std::num::NonZeroI8, NonZeroI8);
75impl_number!(std::num::NonZeroI16, NonZeroI16);
76impl_number!(std::num::NonZeroI32, NonZeroI32);
77impl_number!(std::num::NonZeroI64, NonZeroI64);
78impl_number!(std::num::NonZeroIsize, NonZeroIsize);
79impl_number!(f32, F32);
80impl_number!(f64, F64);
81
82impl TypeDef for () {
83    const INFO: TypeInfo = TypeInfo::Native(NativeTypeInfo {
84        r#ref: TypeExpr::ident(Ident("null")),
85    });
86}
87
88macro_rules! impl_tuple {
89    ($($var:ident),+) => {
90        impl<$($var),+> TypeDef for ($($var,)+)
91        where
92            $($var: TypeDef,)+
93        {
94            const INFO: TypeInfo = TypeInfo::Native(NativeTypeInfo {
95                r#ref: TypeExpr::Tuple(TypeTuple {
96                    docs: None,
97                    elements: &[$(TypeExpr::Ref(&$var::INFO),)+],
98                }),
99            });
100        }
101    };
102}
103
104impl_tuple!(T1);
105impl_tuple!(T1, T2);
106impl_tuple!(T1, T2, T3);
107impl_tuple!(T1, T2, T3, T4);
108impl_tuple!(T1, T2, T3, T4, T5);
109impl_tuple!(T1, T2, T3, T4, T5, T6);
110impl_tuple!(T1, T2, T3, T4, T5, T6, T7);
111impl_tuple!(T1, T2, T3, T4, T5, T6, T7, T8);
112impl_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9);
113impl_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
114impl_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
115impl_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
116impl_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13);
117impl_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14);
118impl_tuple!(
119    T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15
120);
121impl_tuple!(
122    T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16
123);
124
125impl<T, const N: usize> TypeDef for [T; N]
126where
127    T: TypeDef,
128{
129    const INFO: TypeInfo = TypeInfo::Native(NativeTypeInfo {
130        r#ref: TypeExpr::Tuple(TypeTuple {
131            docs: None,
132            elements: &[TypeExpr::Ref(&T::INFO); N],
133        }),
134    });
135}
136
137impl<T> TypeDef for Option<T>
138where
139    T: TypeDef,
140{
141    const INFO: TypeInfo = TypeInfo::Native(NativeTypeInfo {
142        r#ref: TypeExpr::Union(TypeUnion {
143            docs: None,
144            members: &[TypeExpr::Ref(&T::INFO), TypeExpr::ident(Ident("null"))],
145        }),
146    });
147}
148
149macro_rules! list_type_info {
150    ($item:ty) => {
151        TypeInfo::Native(NativeTypeInfo {
152            r#ref: TypeExpr::Array(TypeArray {
153                docs: None,
154                item: &TypeExpr::Ref(&<$item>::INFO),
155            }),
156        })
157    };
158}
159
160impl<T> TypeDef for Vec<T>
161where
162    T: TypeDef,
163{
164    const INFO: TypeInfo = list_type_info!(T);
165}
166
167impl<T> TypeDef for [T]
168where
169    T: TypeDef,
170{
171    const INFO: TypeInfo = list_type_info!(T);
172}
173
174macro_rules! set_type_info {
175    ($item:ty) => {
176        TypeInfo::Native(NativeTypeInfo {
177            r#ref: TypeExpr::Array(TypeArray {
178                docs: None,
179                item: &TypeExpr::Ref(&<$item>::INFO),
180            }),
181        })
182    };
183}
184
185impl<T, S> TypeDef for std::collections::HashSet<T, S>
186where
187    T: TypeDef,
188    S: 'static,
189{
190    const INFO: TypeInfo = set_type_info!(T);
191}
192
193impl<T> TypeDef for std::collections::BTreeSet<T>
194where
195    T: TypeDef,
196{
197    const INFO: TypeInfo = set_type_info!(T);
198}
199
200macro_rules! map_type_info {
201    ($key:ty, $value:ty) => {
202        TypeInfo::Native(NativeTypeInfo {
203            r#ref: TypeExpr::Name(TypeName {
204                path: &[],
205                name: Ident("Record"),
206                generic_args: &[
207                    TypeExpr::Ref(&<$key>::INFO),
208                    TypeExpr::Ref(&<$value>::INFO),
209                ],
210            }),
211        })
212    };
213}
214
215impl<K, V, S> TypeDef for std::collections::HashMap<K, V, S>
216where
217    K: TypeDef,
218    V: TypeDef,
219    S: 'static,
220{
221    const INFO: TypeInfo = map_type_info!(K, V);
222}
223
224impl<K, V> TypeDef for std::collections::BTreeMap<K, V>
225where
226    K: TypeDef,
227    V: TypeDef,
228{
229    const INFO: TypeInfo = map_type_info!(K, V);
230}
231
232#[cfg(feature = "json_value")]
233impl<K, V> TypeDef for serde_json::Map<K, V>
234where
235    K: TypeDef,
236    V: TypeDef,
237{
238    const INFO: TypeInfo = map_type_info!(K, V);
239}
240
241impl<T> TypeDef for &'static T
242where
243    T: TypeDef + ?Sized,
244{
245    const INFO: TypeInfo = TypeInfo::Native(NativeTypeInfo {
246        r#ref: TypeExpr::Ref(&T::INFO),
247    });
248}
249
250impl<T> TypeDef for Box<T>
251where
252    T: TypeDef + ?Sized,
253{
254    const INFO: TypeInfo = TypeInfo::Native(NativeTypeInfo {
255        r#ref: TypeExpr::Ref(&T::INFO),
256    });
257}
258
259impl<T> TypeDef for std::borrow::Cow<'static, T>
260where
261    T: ToOwned + TypeDef + ?Sized,
262{
263    const INFO: TypeInfo = TypeInfo::Native(NativeTypeInfo {
264        r#ref: TypeExpr::Ref(&T::INFO),
265    });
266}
267
268impl<T> TypeDef for std::marker::PhantomData<T>
269where
270    T: TypeDef + ?Sized,
271{
272    const INFO: TypeInfo = TypeInfo::Native(NativeTypeInfo {
273        r#ref: TypeExpr::Ref(&T::INFO),
274    });
275}
276
277impl<T, E> TypeDef for std::result::Result<T, E>
278where
279    T: TypeDef,
280    E: TypeDef,
281{
282    const INFO: TypeInfo = TypeInfo::Native(NativeTypeInfo {
283        r#ref: TypeExpr::Union(TypeUnion {
284            docs: None,
285            members: &[
286                TypeExpr::Object(TypeObject {
287                    docs: None,
288                    index_signature: None,
289                    fields: &[ObjectField {
290                        docs: None,
291                        name: TypeString {
292                            docs: None,
293                            value: "Ok",
294                        },
295                        optional: false,
296                        r#type: TypeExpr::Ref(&T::INFO),
297                    }],
298                }),
299                TypeExpr::Object(TypeObject {
300                    docs: None,
301                    index_signature: None,
302                    fields: &[ObjectField {
303                        docs: None,
304                        name: TypeString {
305                            docs: None,
306                            value: "Err",
307                        },
308                        optional: false,
309                        r#type: TypeExpr::Ref(&E::INFO),
310                    }],
311                }),
312            ],
313        }),
314    });
315}
316
317#[cfg(feature = "json_value")]
318impl TypeDef for serde_json::Value {
319    const INFO: TypeInfo = TypeInfo::Defined(DefinedTypeInfo {
320        def: TypeDefinition {
321            docs: None,
322            path: &[],
323            name: Ident("JSONValue"),
324            generic_vars: &[],
325            def: TypeExpr::Union(TypeUnion {
326                docs: None,
327                members: &[
328                    TypeExpr::ident(Ident("null")),
329                    TypeExpr::ident(Ident("boolean")),
330                    TypeExpr::ident(Ident("number")),
331                    TypeExpr::ident(Ident("string")),
332                    TypeExpr::Array(TypeArray {
333                        docs: None,
334                        item: &TypeExpr::ident(Ident("JSONValue")),
335                    }),
336                    TypeExpr::Object(TypeObject {
337                        docs: None,
338                        index_signature: Some(
339                            crate::type_expr::IndexSignature {
340                                docs: None,
341                                name: Ident("key"),
342                                value: &TypeExpr::ident(Ident("JSONValue")),
343                            },
344                        ),
345                        fields: &[],
346                    }),
347                ],
348            }),
349        },
350        generic_args: &[],
351    });
352}