1use crate::{flow_type, Config, Dummy, Flow, TypeVisitor};
4
5macro_rules! impl_wrapper {
7 ($($t:tt)*) => {
8 $($t)* {
9 type WithoutGenerics = Self;
10 type OptionInnerType = Self;
11 fn name(cfg: &Config) -> String { <T as crate::Flow>::name(cfg) }
12 fn inline(cfg: &Config) -> String { <T as crate::Flow>::inline(cfg) }
13 fn inline_flattened(cfg: &Config) -> String { <T as crate::Flow>::inline_flattened(cfg) }
14 fn visit_dependencies(v: &mut impl TypeVisitor)
15 where
16 Self: 'static,
17 {
18 <T as crate::Flow>::visit_dependencies(v);
19 }
20 fn visit_generics(v: &mut impl TypeVisitor)
21 where
22 Self: 'static,
23 {
24 <T as crate::Flow>::visit_generics(v);
25 v.visit::<T>();
26 }
27 fn decl(_: &Config) -> String { panic!("wrapper type cannot be declared") }
28 fn decl_concrete(_: &Config) -> String { panic!("wrapper type cannot be declared") }
29 }
30 };
31}
32
33macro_rules! impl_shadow {
35 (as $s:ty: $($impl:tt)*) => {
36 $($impl)* {
37 type WithoutGenerics = <$s as crate::Flow>::WithoutGenerics;
38 type OptionInnerType = <$s as crate::Flow>::OptionInnerType;
39 fn ident(cfg: &Config) -> String { <$s as crate::Flow>::ident(cfg) }
40 fn name(cfg: &Config) -> String { <$s as crate::Flow>::name(cfg) }
41 fn inline(cfg: &Config) -> String { <$s as crate::Flow>::inline(cfg) }
42 fn inline_flattened(cfg: &Config) -> String { <$s as crate::Flow>::inline_flattened(cfg) }
43 fn visit_dependencies(v: &mut impl crate::TypeVisitor)
44 where
45 Self: 'static,
46 {
47 <$s as crate::Flow>::visit_dependencies(v);
48 }
49 fn visit_generics(v: &mut impl crate::TypeVisitor)
50 where
51 Self: 'static,
52 {
53 <$s as crate::Flow>::visit_generics(v);
54 }
55 fn decl(cfg: &Config) -> String { <$s as crate::Flow>::decl(cfg) }
56 fn decl_concrete(cfg: &Config) -> String { <$s as crate::Flow>::decl_concrete(cfg) }
57 fn output_path() -> Option<std::path::PathBuf> { <$s as crate::Flow>::output_path() }
58 }
59 };
60}
61
62macro_rules! impl_flow_primitive {
63 ($rust_ty:ty, $flow_ty:expr) => {
64 impl Flow for $rust_ty {
65 type WithoutGenerics = Self;
66 type OptionInnerType = Self;
67 fn name(_: &Config) -> String {
68 $flow_ty.to_owned()
69 }
70 fn inline(cfg: &Config) -> String {
71 <Self as crate::Flow>::name(cfg)
72 }
73 }
74 };
75}
76
77impl_flow_primitive!(bool, flow_type::BOOLEAN);
79impl_flow_primitive!(i8, flow_type::NUMBER);
80impl_flow_primitive!(i16, flow_type::NUMBER);
81impl_flow_primitive!(i32, flow_type::NUMBER);
82impl_flow_primitive!(u8, flow_type::NUMBER);
83impl_flow_primitive!(u16, flow_type::NUMBER);
84impl_flow_primitive!(u32, flow_type::NUMBER);
85impl_flow_primitive!(i64, flow_type::NUMBER);
86impl_flow_primitive!(u64, flow_type::NUMBER);
87impl_flow_primitive!(i128, flow_type::NUMBER);
88impl_flow_primitive!(u128, flow_type::NUMBER);
89impl_flow_primitive!(f32, flow_type::NUMBER);
90impl_flow_primitive!(f64, flow_type::NUMBER);
91impl_flow_primitive!(char, flow_type::STRING);
92impl_flow_primitive!(String, flow_type::STRING);
93impl_flow_primitive!(str, flow_type::STRING);
94impl_flow_primitive!((), flow_type::VOID);
95
96impl<T: Flow> Flow for Option<T> {
98 type WithoutGenerics = Self;
99 type OptionInnerType = T;
100 const IS_OPTION: bool = true;
101
102 fn name(cfg: &Config) -> String {
103 format!("?{}", T::name(cfg))
104 }
105 fn inline(cfg: &Config) -> String {
106 format!("?{}", T::inline(cfg))
107 }
108 fn visit_dependencies(v: &mut impl TypeVisitor)
109 where
110 Self: 'static,
111 {
112 <T as crate::Flow>::visit_dependencies(v);
113 }
114 fn visit_generics(v: &mut impl TypeVisitor)
115 where
116 Self: 'static,
117 {
118 <T as crate::Flow>::visit_generics(v);
119 v.visit::<T>();
120 }
121}
122
123impl<T: Flow> Flow for Vec<T> {
125 type WithoutGenerics = Vec<Dummy>;
126 type OptionInnerType = Self;
127
128 fn ident(_: &Config) -> String {
129 flow_type::READ_ONLY_ARRAY.to_owned()
130 }
131 fn name(cfg: &Config) -> String {
132 format!("{}<{}>", flow_type::READ_ONLY_ARRAY, T::name(cfg))
133 }
134 fn inline(cfg: &Config) -> String {
135 format!("{}<{}>", flow_type::READ_ONLY_ARRAY, T::inline(cfg))
136 }
137 fn visit_dependencies(v: &mut impl TypeVisitor)
138 where
139 Self: 'static,
140 {
141 <T as crate::Flow>::visit_dependencies(v);
142 }
143 fn visit_generics(v: &mut impl TypeVisitor)
144 where
145 Self: 'static,
146 {
147 <T as crate::Flow>::visit_generics(v);
148 v.visit::<T>();
149 }
150}
151
152impl_shadow!(as Vec<T>: impl<T: Flow> Flow for [T]);
154
155impl_wrapper!(impl<T: Flow + ?Sized> Flow for Box<T>);
157
158impl_wrapper!(impl<'a, T: Flow + ?Sized> Flow for &'a T);
160
161impl<K: Flow, V: Flow> Flow for std::collections::HashMap<K, V> {
163 type WithoutGenerics = std::collections::HashMap<Dummy, Dummy>;
164 type OptionInnerType = Self;
165
166 fn ident(_: &Config) -> String {
167 panic!()
168 }
169 fn name(cfg: &Config) -> String {
170 format!("{{ [key: {}]: {} }}", K::name(cfg), V::name(cfg))
171 }
172 fn inline(cfg: &Config) -> String {
173 format!("{{ [key: {}]: {} }}", K::inline(cfg), V::inline(cfg))
174 }
175 fn inline_flattened(cfg: &Config) -> String {
176 format!("({})", Self::inline(cfg))
177 }
178 fn visit_dependencies(v: &mut impl TypeVisitor)
179 where
180 Self: 'static,
181 {
182 K::visit_dependencies(v);
183 V::visit_dependencies(v);
184 }
185 fn visit_generics(v: &mut impl TypeVisitor)
186 where
187 Self: 'static,
188 {
189 K::visit_generics(v);
190 v.visit::<K>();
191 V::visit_generics(v);
192 v.visit::<V>();
193 }
194}
195
196impl_shadow!(as std::collections::HashMap<K, V>: impl<K: Flow, V: Flow> Flow for std::collections::BTreeMap<K, V>);
198
199impl_shadow!(as Vec<T>: impl<T: Flow> Flow for std::collections::HashSet<T>);
201
202impl_shadow!(as Vec<T>: impl<T: Flow> Flow for std::collections::BTreeSet<T>);
204
205impl_shadow!(as Vec<T>: impl<T: Flow> Flow for std::collections::VecDeque<T>);
207
208impl_shadow!(as Vec<T>: impl<T: Flow> Flow for std::collections::LinkedList<T>);
210
211macro_rules! impl_flow_tuples {
213 ( impl $($i:ident),* ) => {
214 impl<$($i: Flow),*> Flow for ($($i,)*) {
215 type WithoutGenerics = (Dummy, );
216 type OptionInnerType = Self;
217 fn name(cfg: &Config) -> String {
218 let parts: Vec<String> = vec![$($i::name(cfg)),*];
219 format!("[{}]", parts.join(", "))
220 }
221 fn inline(cfg: &Config) -> String {
222 let parts: Vec<String> = vec![$($i::inline(cfg)),*];
223 format!("[{}]", parts.join(", "))
224 }
225 fn inline_flattened(cfg: &Config) -> String {
226 format!("({})", Self::inline(cfg))
227 }
228 fn decl(_: &Config) -> String {
229 panic!("tuple cannot be declared")
230 }
231 fn decl_concrete(_: &Config) -> String {
232 panic!("tuple cannot be declared")
233 }
234 fn visit_generics(v: &mut impl TypeVisitor)
235 where
236 Self: 'static
237 {
238 $(
239 v.visit::<$i>();
240 <$i as crate::Flow>::visit_generics(v);
241 )*
242 }
243 }
244 };
245 ( $i2:ident $(, $i:ident)* ) => {
246 impl_flow_tuples!(impl $i2 $(, $i)* );
247 impl_flow_tuples!($($i),*);
248 };
249 () => {};
250}
251
252impl_flow_tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
253
254#[cfg(feature = "serde-json-impl")]
256impl Flow for serde_json::Value {
257 type WithoutGenerics = Self;
258 type OptionInnerType = Self;
259 fn name(_: &Config) -> String {
260 "JsonValue".to_owned()
261 }
262 fn inline(_: &Config) -> String {
263 flow_type::MIXED.to_owned()
264 }
265 fn decl(_: &Config) -> String {
266 format!("type JsonValue = {};", flow_type::MIXED)
267 }
268 fn decl_concrete(_: &Config) -> String {
269 format!("type JsonValue = {};", flow_type::MIXED)
270 }
271 fn output_path() -> Option<std::path::PathBuf> {
272 Some(std::path::PathBuf::from("JsonValue.js.flow"))
273 }
274}
275
276impl Flow for std::path::PathBuf {
278 type WithoutGenerics = Self;
279 type OptionInnerType = Self;
280 fn name(_: &Config) -> String {
281 flow_type::STRING.to_owned()
282 }
283 fn inline(_: &Config) -> String {
284 flow_type::STRING.to_owned()
285 }
286}
287
288impl Flow for std::path::Path {
289 type WithoutGenerics = Self;
290 type OptionInnerType = Self;
291 fn name(_: &Config) -> String {
292 flow_type::STRING.to_owned()
293 }
294 fn inline(_: &Config) -> String {
295 flow_type::STRING.to_owned()
296 }
297}
298
299impl_wrapper!(impl<'a, T: Flow + ToOwned + ?Sized> Flow for std::borrow::Cow<'a, T>);
301
302impl<T: Flow, E: Flow> Flow for Result<T, E> {
304 type WithoutGenerics = Result<Dummy, Dummy>;
305 type OptionInnerType = Self;
306
307 fn name(cfg: &Config) -> String {
308 format!(
309 "{{| +ok: {} |}} | {{| +err: {} |}}",
310 T::name(cfg),
311 E::name(cfg)
312 )
313 }
314 fn inline(cfg: &Config) -> String {
315 format!(
316 "{{| +ok: {} |}} | {{| +err: {} |}}",
317 T::inline(cfg),
318 E::inline(cfg)
319 )
320 }
321 fn visit_dependencies(v: &mut impl TypeVisitor)
322 where
323 Self: 'static,
324 {
325 <T as crate::Flow>::visit_dependencies(v);
326 <E as crate::Flow>::visit_dependencies(v);
327 }
328 fn visit_generics(v: &mut impl TypeVisitor)
329 where
330 Self: 'static,
331 {
332 <T as crate::Flow>::visit_generics(v);
333 v.visit::<T>();
334 <E as crate::Flow>::visit_generics(v);
335 v.visit::<E>();
336 }
337}
338
339impl<T: Flow, const N: usize> Flow for [T; N] {
341 type WithoutGenerics = [Dummy; N];
342 type OptionInnerType = Self;
343
344 fn name(cfg: &Config) -> String {
345 if N > cfg.array_tuple_limit() {
346 return <Vec<T> as crate::Flow>::name(cfg);
347 }
348 format!(
349 "[{}]",
350 (0..N).map(|_| T::name(cfg)).collect::<Vec<_>>().join(", ")
351 )
352 }
353 fn inline(cfg: &Config) -> String {
354 if N > cfg.array_tuple_limit() {
355 return <Vec<T> as crate::Flow>::inline(cfg);
356 }
357 format!(
358 "[{}]",
359 (0..N)
360 .map(|_| T::inline(cfg))
361 .collect::<Vec<_>>()
362 .join(", ")
363 )
364 }
365 fn visit_dependencies(v: &mut impl TypeVisitor)
366 where
367 Self: 'static,
368 {
369 <T as crate::Flow>::visit_dependencies(v);
370 }
371 fn visit_generics(v: &mut impl TypeVisitor)
372 where
373 Self: 'static,
374 {
375 <T as crate::Flow>::visit_generics(v);
376 v.visit::<T>();
377 }
378}
379
380impl_wrapper!(impl<T: Flow + ?Sized> Flow for std::sync::Arc<T>);
382
383impl_wrapper!(impl<T: Flow + ?Sized> Flow for std::rc::Rc<T>);
385
386impl_wrapper!(impl<T: Flow> Flow for std::cell::Cell<T>);
388
389impl_wrapper!(impl<T: Flow> Flow for std::cell::RefCell<T>);
391
392impl_wrapper!(impl<T: Flow> Flow for std::sync::Mutex<T>);
394
395impl_wrapper!(impl<T: Flow> Flow for std::sync::RwLock<T>);
397
398impl_flow_primitive!(usize, flow_type::NUMBER);
400impl_flow_primitive!(isize, flow_type::NUMBER);
401
402impl_shadow!(as u8: impl Flow for std::num::NonZeroU8);
404impl_shadow!(as u16: impl Flow for std::num::NonZeroU16);
405impl_shadow!(as u32: impl Flow for std::num::NonZeroU32);
406impl_shadow!(as u64: impl Flow for std::num::NonZeroU64);
407impl_shadow!(as u128: impl Flow for std::num::NonZeroU128);
408impl_shadow!(as usize: impl Flow for std::num::NonZeroUsize);
409impl_shadow!(as i8: impl Flow for std::num::NonZeroI8);
410impl_shadow!(as i16: impl Flow for std::num::NonZeroI16);
411impl_shadow!(as i32: impl Flow for std::num::NonZeroI32);
412impl_shadow!(as i64: impl Flow for std::num::NonZeroI64);
413impl_shadow!(as i128: impl Flow for std::num::NonZeroI128);
414impl_shadow!(as isize: impl Flow for std::num::NonZeroIsize);
415
416impl<T: ?Sized> Flow for std::marker::PhantomData<T> {
418 type WithoutGenerics = Self;
419 type OptionInnerType = Self;
420 fn name(_: &Config) -> String {
421 flow_type::VOID.to_owned()
422 }
423 fn inline(_: &Config) -> String {
424 flow_type::VOID.to_owned()
425 }
426}
427
428impl<T: Flow> Flow for std::ops::Range<T> {
430 type WithoutGenerics = std::ops::Range<Dummy>;
431 type OptionInnerType = Self;
432
433 fn ident(_: &Config) -> String {
434 panic!()
435 }
436 fn name(cfg: &Config) -> String {
437 format!("{{ +start: {}, +end: {} }}", T::name(cfg), T::name(cfg))
438 }
439 fn inline(cfg: &Config) -> String {
440 format!("{{ +start: {}, +end: {} }}", T::inline(cfg), T::inline(cfg))
441 }
442 fn inline_flattened(cfg: &Config) -> String {
443 format!("({})", Self::inline(cfg))
444 }
445 fn visit_dependencies(v: &mut impl TypeVisitor)
446 where
447 Self: 'static,
448 {
449 T::visit_dependencies(v);
450 }
451 fn visit_generics(v: &mut impl TypeVisitor)
452 where
453 Self: 'static,
454 {
455 T::visit_generics(v);
456 v.visit::<T>();
457 }
458}
459
460impl_shadow!(as std::ops::Range<T>: impl<T: Flow> Flow for std::ops::RangeInclusive<T>);
462
463impl Flow for std::time::Duration {
465 type WithoutGenerics = Self;
466 type OptionInnerType = Self;
467 fn name(_: &Config) -> String {
468 format!(
469 "{{| +secs: {}, +nanos: {} |}}",
470 flow_type::NUMBER,
471 flow_type::NUMBER
472 )
473 }
474 fn inline(cfg: &Config) -> String {
475 Self::name(cfg)
476 }
477}
478
479impl_flow_primitive!(std::time::SystemTime, flow_type::STRING);
481
482impl_flow_primitive!(std::net::IpAddr, flow_type::STRING);
484impl_flow_primitive!(std::net::Ipv4Addr, flow_type::STRING);
485impl_flow_primitive!(std::net::Ipv6Addr, flow_type::STRING);
486impl_flow_primitive!(std::net::SocketAddr, flow_type::STRING);
487impl_flow_primitive!(std::net::SocketAddrV4, flow_type::STRING);
488impl_flow_primitive!(std::net::SocketAddrV6, flow_type::STRING);
489
490#[cfg(feature = "chrono-impl")]
492impl_flow_primitive!(chrono::NaiveDate, flow_type::STRING);
493#[cfg(feature = "chrono-impl")]
494impl_flow_primitive!(chrono::NaiveTime, flow_type::STRING);
495#[cfg(feature = "chrono-impl")]
496impl_flow_primitive!(chrono::NaiveDateTime, flow_type::STRING);
497#[cfg(feature = "chrono-impl")]
498impl<T: chrono::TimeZone> Flow for chrono::DateTime<T> {
499 type WithoutGenerics = Self;
500 type OptionInnerType = Self;
501 fn name(_: &Config) -> String {
502 flow_type::STRING.to_owned()
503 }
504 fn inline(_: &Config) -> String {
505 flow_type::STRING.to_owned()
506 }
507}
508#[cfg(feature = "chrono-impl")]
509impl_flow_primitive!(chrono::Duration, flow_type::STRING);
510
511#[cfg(feature = "uuid-impl")]
513impl_flow_primitive!(uuid::Uuid, flow_type::STRING);
514
515#[cfg(feature = "url-impl")]
517impl_flow_primitive!(url::Url, flow_type::STRING);