1 | | | typedef Cast<T> = T Function(dynamic); |
2 | | |
|
3 | | | abstract base class Converter { |
4 | | 23 | const Converter(); |
5 | | |
|
6 | | 6 | static bool isIdentity<T>(Cast<T>? cast) => |
7 | | 6 | (cast == null) || (cast == identity<T>); |
8 | | |
|
9 | | 16 | static T identity<T>(dynamic x) => x as T; |
10 | | |
|
11 | | 3 | static List<dynamic> toList(dynamic x) => |
12 | | 4 | (x is List) ? x : (x as Iterable).toList(); |
13 | | |
|
14 | | 0 | static Set<dynamic> toSet(dynamic x) => |
15 | | 0 | (x is Set) ? x : (x as Iterable).toSet(); |
16 | | |
|
17 | | | // non-nullable value |
18 | | | Cast<T> value<T>(); |
19 | | |
|
20 | | | // nullable value |
21 | | 2 | Cast<T?> nullable<T>([Cast<T>? cast]) { |
22 | | 2 | final op = cast ?? value<T>(); |
23 | | 2 | return Converter.isIdentity<T>(op) |
24 | | 2 | ? value<T?>() |
25 | | 3 | : (($) => ($ == null) ? null : op($)); |
26 | | 1 | } |
27 | | |
|
28 | | | // list |
29 | | 3 | Cast<List<T>> list<T>([Cast<T>? cast]) { |
30 | | 3 | final op = cast ?? value<T>(); |
31 | | 3 | return Converter.isIdentity<T>(op) |
32 | | 7 | ? ((x) => Converter.toList(x).cast<T>()) |
33 | | 5 | : ((x) => Converter.toList(x).map<T>(op).toList()); |
34 | | 1 | } |
35 | | |
|
36 | | | // set |
37 | | 2 | Cast<Set<T>> set<T>([Cast<T>? cast]) { |
38 | | 2 | final op = list<T>(cast); |
39 | | 4 | return (x) => op(x).toSet(); |
40 | | 1 | } |
41 | | |
|
42 | | | // map |
43 | | 6 | Cast<Map<K, V>> map<K, V>({Cast<K>? kcast, Cast<V>? vcast}) { |
44 | | 9 | final kop = kcast ?? value<K>(), vop = vcast ?? value<V>(); |
45 | | 9 | if (Converter.isIdentity<K>(kop) && Converter.isIdentity<V>(vop)) { |
46 | | 9 | return ((x) => (x as Map).cast<K, V>()); |
47 | | | } else { |
48 | | 7 | return ((x) => (x as Map).map((k, v) => MapEntry(kop(k), vop(v)))); |
49 | | | } |
50 | | 3 | } |
51 | | | } |