1 | | | import 'converter.dart'; |
2 | | |
|
3 | | | /// This converter converts items in lists and maps **in place**. It avoids |
4 | | | /// creating a copy of the data to hold the conversion result. All items in |
5 | | | /// the list/map are converted at the time the list/map is processed. |
6 | | | final class InPlaceConverter extends Converter { |
7 | | 3 | const InPlaceConverter(this.converter) : super(); |
8 | | |
|
9 | | | final Converter converter; |
10 | | |
|
11 | | 1 | @override |
12 | | 3 | Cast<T> value<T>() => converter.value<T>(); |
13 | | |
|
14 | | 1 | @override |
15 | | 1 | Cast<List<T>> list<T>([Cast<T>? cast]) { |
16 | | 2 | final op = cast ?? value<T>(); |
17 | | 5 | return Converter.isIdentity<T>(op) ? converter.list<T>(op) : _toList(op); |
18 | | 1 | } |
19 | | |
|
20 | | 1 | @override |
21 | | 1 | Cast<Map<K, V>> map<K, V>({Cast<K>? kcast, Cast<V>? vcast}) { |
22 | | 3 | final kop = kcast ?? value<K>(), vop = vcast ?? value<V>(); |
23 | | 3 | return (!Converter.isIdentity<K>(kop) || Converter.isIdentity<V>(vop)) |
24 | | 3 | ? converter.map<K, V>(kcast: kop, vcast: vop) |
25 | | 2 | : _toMap(vop); |
26 | | 1 | } |
27 | | |
|
28 | | 2 | static Cast<List<T>> _toList<T>(Cast<T> cast) { |
29 | | 2 | return (x) { |
30 | | 2 | final y = Converter.toList(x); |
31 | | 5 | for (var i = y.length - 1; i >= 0; i--) { |
32 | | 2 | final v = y[i]; |
33 | | 3 | y[i] = (v == null) ? v : cast(v); |
34 | | | } |
35 | | 2 | return y.cast<T>(); |
36 | | 1 | }; |
37 | | 1 | } |
38 | | |
|
39 | | 2 | Cast<Map<K, V>> _toMap<K, V>(Cast<V> vcast) { |
40 | | 2 | return (x) { |
41 | | | x as Map; |
42 | | 2 | final keys = x.keys.toList(); |
43 | | 5 | for (var i = keys.length - 1; i >= 0; i--) { |
44 | | 3 | final k = keys[i], v = x[k]; |
45 | | 1 | if (v != null) { |
46 | | 3 | x[k] = vcast(v); |
47 | | | } |
48 | | | } |
49 | | 2 | return x.cast<K, V>(); |
50 | | 1 | }; |
51 | | 1 | } |
52 | | | } |