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!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15);
119impl_tuple!(
120    T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16
121);
122
123impl<T, const N: usize> TypeDef for [T; N]
124where
125    T: TypeDef,
126{
127    const INFO: TypeInfo = TypeInfo::Native(NativeTypeInfo {
128        r#ref: TypeExpr::Tuple(TypeTuple {
129            docs: None,
130            elements: &[TypeExpr::Ref(&T::INFO); N],
131        }),
132    });
133}
134
135impl<T> TypeDef for Option<T>
136where
137    T: TypeDef,
138{
139    const INFO: TypeInfo = TypeInfo::Native(NativeTypeInfo {
140        r#ref: TypeExpr::Union(TypeUnion {
141            docs: None,
142            members: &[TypeExpr::Ref(&T::INFO), TypeExpr::ident(Ident("null"))],
143        }),
144    });
145}
146
147macro_rules! list_type_info {
148    ($item:ty) => {
149        TypeInfo::Native(NativeTypeInfo {
150            r#ref: TypeExpr::Array(TypeArray {
151                docs: None,
152                item: &TypeExpr::Ref(&<$item>::INFO),
153            }),
154        })
155    };
156}
157
158impl<T> TypeDef for Vec<T>
159where
160    T: TypeDef,
161{
162    const INFO: TypeInfo = list_type_info!(T);
163}
164
165impl<T> TypeDef for [T]
166where
167    T: TypeDef,
168{
169    const INFO: TypeInfo = list_type_info!(T);
170}
171
172macro_rules! set_type_info {
173    ($item:ty) => {
174        TypeInfo::Native(NativeTypeInfo {
175            r#ref: TypeExpr::Array(TypeArray {
176                docs: None,
177                item: &TypeExpr::Ref(&<$item>::INFO),
178            }),
179        })
180    };
181}
182
183impl<T, S> TypeDef for std::collections::HashSet<T, S>
184where
185    T: TypeDef,
186    S: 'static,
187{
188    const INFO: TypeInfo = set_type_info!(T);
189}
190
191impl<T> TypeDef for std::collections::BTreeSet<T>
192where
193    T: TypeDef,
194{
195    const INFO: TypeInfo = set_type_info!(T);
196}
197
198macro_rules! map_type_info {
199    ($key:ty, $value:ty) => {
200        TypeInfo::Native(NativeTypeInfo {
201            r#ref: TypeExpr::Name(TypeName {
202                path: &[],
203                name: Ident("Record"),
204                generic_args: &[
205                    TypeExpr::Ref(&<$key>::INFO),
206                    TypeExpr::Ref(&<$value>::INFO),
207                ],
208            }),
209        })
210    };
211}
212
213impl<K, V, S> TypeDef for std::collections::HashMap<K, V, S>
214where
215    K: TypeDef,
216    V: TypeDef,
217    S: 'static,
218{
219    const INFO: TypeInfo = map_type_info!(K, V);
220}
221
222impl<K, V> TypeDef for std::collections::BTreeMap<K, V>
223where
224    K: TypeDef,
225    V: TypeDef,
226{
227    const INFO: TypeInfo = map_type_info!(K, V);
228}
229
230#[cfg(feature = "json_value")]
231impl<K, V> TypeDef for serde_json::Map<K, V>
232where
233    K: TypeDef,
234    V: TypeDef,
235{
236    const INFO: TypeInfo = map_type_info!(K, V);
237}
238
239impl<T> TypeDef for &'static T
240where
241    T: TypeDef + ?Sized,
242{
243    const INFO: TypeInfo = TypeInfo::Native(NativeTypeInfo {
244        r#ref: TypeExpr::Ref(&T::INFO),
245    });
246}
247
248impl<T> TypeDef for Box<T>
249where
250    T: TypeDef + ?Sized,
251{
252    const INFO: TypeInfo = TypeInfo::Native(NativeTypeInfo {
253        r#ref: TypeExpr::Ref(&T::INFO),
254    });
255}
256
257impl<T> TypeDef for std::borrow::Cow<'static, T>
258where
259    T: Clone + TypeDef + ?Sized,
260{
261    const INFO: TypeInfo = TypeInfo::Native(NativeTypeInfo {
262        r#ref: TypeExpr::Ref(&T::INFO),
263    });
264}
265
266impl<T> TypeDef for std::marker::PhantomData<T>
267where
268    T: TypeDef + ?Sized,
269{
270    const INFO: TypeInfo = TypeInfo::Native(NativeTypeInfo {
271        r#ref: TypeExpr::Ref(&T::INFO),
272    });
273}
274
275impl<T, E> TypeDef for std::result::Result<T, E>
276where
277    T: TypeDef,
278    E: TypeDef,
279{
280    const INFO: TypeInfo = TypeInfo::Native(NativeTypeInfo {
281        r#ref: TypeExpr::Union(TypeUnion {
282            docs: None,
283            members: &[
284                TypeExpr::Object(TypeObject {
285                    docs: None,
286                    index_signature: None,
287                    fields: &[ObjectField {
288                        docs: None,
289                        name: TypeString {
290                            docs: None,
291                            value: "Ok",
292                        },
293                        optional: false,
294                        r#type: TypeExpr::Ref(&T::INFO),
295                    }],
296                }),
297                TypeExpr::Object(TypeObject {
298                    docs: None,
299                    index_signature: None,
300                    fields: &[ObjectField {
301                        docs: None,
302                        name: TypeString {
303                            docs: None,
304                            value: "Err",
305                        },
306                        optional: false,
307                        r#type: TypeExpr::Ref(&E::INFO),
308                    }],
309                }),
310            ],
311        }),
312    });
313}
314
315#[cfg(feature = "json_value")]
316impl TypeDef for serde_json::Value {
317    const INFO: TypeInfo = TypeInfo::Defined(DefinedTypeInfo {
318        def: TypeDefinition {
319            docs: None,
320            path: &[],
321            name: Ident("JSONValue"),
322            generic_vars: &[],
323            def: TypeExpr::Union(TypeUnion {
324                docs: None,
325                members: &[
326                    TypeExpr::ident(Ident("null")),
327                    TypeExpr::ident(Ident("boolean")),
328                    TypeExpr::ident(Ident("number")),
329                    TypeExpr::ident(Ident("string")),
330                    TypeExpr::Array(TypeArray {
331                        docs: None,
332                        item: &TypeExpr::ident(Ident("JSONValue")),
333                    }),
334                    TypeExpr::Object(TypeObject {
335                        docs: None,
336                        index_signature: Some(
337                            crate::type_expr::IndexSignature {
338                                docs: None,
339                                name: Ident("key"),
340                                value: &TypeExpr::ident(Ident("JSONValue")),
341                            },
342                        ),
343                        fields: &[],
344                    }),
345                ],
346            }),
347        },
348        generic_args: &[],
349    });
350}