OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
| 5 /// This library exists so that pub can retain backwards-compatibility with |
| 6 /// versions of barback prior to 0.13.1. |
| 7 /// |
| 8 /// In 0.13.1, `lib/src/internal_asset.dart` was moved to |
| 9 /// `lib/src/asset/internal_asset.dart. Pub needs to support all versions of |
| 10 /// barback back through 0.13.0, though. In order for this to work, it needs to |
| 11 /// be able to import "package:barback/src/internal_asset.dart" on all available |
| 12 /// barback versions, hence the existence of this library. |
5 library barback.internal_asset; | 13 library barback.internal_asset; |
6 | 14 |
7 import 'dart:async'; | 15 export 'asset/internal_asset.dart'; |
8 import 'dart:convert'; | |
9 import 'dart:typed_data'; | |
10 | |
11 import 'asset.dart'; | |
12 import 'asset_id.dart'; | |
13 import 'file_pool.dart'; | |
14 import 'serialize.dart'; | |
15 import 'stream_replayer.dart'; | |
16 import 'utils.dart'; | |
17 | |
18 /// Serialize an asset to a form that's safe to send across isolates. | |
19 Map serializeAsset(Asset asset) { | |
20 var id = serializeId(asset.id); | |
21 if (asset is BinaryAsset) { | |
22 return { | |
23 'type': 'binary', | |
24 'id': id, | |
25 'contents': asset._contents | |
26 }; | |
27 } else if (asset is FileAsset) { | |
28 return { | |
29 'type': 'file', | |
30 'id': id, | |
31 'path': asset._path | |
32 }; | |
33 } else if (asset is StringAsset) { | |
34 return { | |
35 'type': 'string', | |
36 'id': id, | |
37 'contents': asset._contents | |
38 }; | |
39 } else { | |
40 // [asset] is probably a [StreamAsset], but it's possible that the user has | |
41 // created a custom subclass, in which case we just serialize the stream | |
42 // anyway. | |
43 return { | |
44 'type': 'stream', | |
45 'id': id, | |
46 'stream': serializeStream(asset.read()) | |
47 }; | |
48 } | |
49 } | |
50 | |
51 /// Deserialize an asset from the form returned by [serialize]. | |
52 Asset deserializeAsset(Map asset) { | |
53 var id = deserializeId(asset['id']); | |
54 switch (asset['type']) { | |
55 case 'binary': return new BinaryAsset(id, asset['contents']); | |
56 case 'file': return new FileAsset(id, asset['path']); | |
57 case 'string': return new StringAsset(id, asset['contents']); | |
58 case 'stream': | |
59 return new StreamAsset(id, deserializeStream(asset['stream'])); | |
60 default: | |
61 throw new FormatException('Unknown asset type "${asset['type']}".'); | |
62 } | |
63 } | |
64 | |
65 /// An asset whose data is stored in a list of bytes. | |
66 class BinaryAsset implements Asset { | |
67 final AssetId id; | |
68 | |
69 final Uint8List _contents; | |
70 | |
71 BinaryAsset(this.id, List<int> contents) | |
72 : _contents = toUint8List(contents); | |
73 | |
74 Future<String> readAsString({Encoding encoding}) { | |
75 if (encoding == null) encoding = UTF8; | |
76 | |
77 return new Future.value(encoding.decode(_contents)); | |
78 } | |
79 | |
80 Stream<List<int>> read() => new Future<List<int>>.value(_contents).asStream(); | |
81 | |
82 String toString() { | |
83 var buffer = new StringBuffer(); | |
84 buffer.write("Bytes ["); | |
85 | |
86 // Don't show the whole list if it's long. | |
87 if (_contents.length > 11) { | |
88 for (var i = 0; i < 5; i++) { | |
89 buffer.write(byteToHex(_contents[i])); | |
90 buffer.write(" "); | |
91 } | |
92 | |
93 buffer.write("..."); | |
94 | |
95 for (var i = _contents.length - 5; i < _contents.length; i++) { | |
96 buffer.write(" "); | |
97 buffer.write(byteToHex(_contents[i])); | |
98 } | |
99 } else { | |
100 for (var i = 0; i < _contents.length; i++) { | |
101 if (i > 0) buffer.write(" "); | |
102 buffer.write(byteToHex(_contents[i])); | |
103 } | |
104 } | |
105 | |
106 buffer.write("]"); | |
107 return buffer.toString(); | |
108 } | |
109 } | |
110 | |
111 /// An asset backed by a file on the local file system. | |
112 class FileAsset implements Asset { | |
113 final AssetId id; | |
114 | |
115 /// Use a [FilePool] to handle reads so we can try to cope with running out | |
116 /// of file descriptors more gracefully. | |
117 static final _pool = new FilePool(); | |
118 | |
119 final String _path; | |
120 FileAsset(this.id, this._path); | |
121 | |
122 Future<String> readAsString({Encoding encoding}) { | |
123 if (encoding == null) encoding = UTF8; | |
124 return _pool.readAsString(_path, encoding); | |
125 } | |
126 | |
127 Stream<List<int>> read() => _pool.openRead(_path); | |
128 | |
129 String toString() => 'File "${_path}"'; | |
130 } | |
131 | |
132 /// An asset whose data is stored in a string. | |
133 class StringAsset implements Asset { | |
134 final AssetId id; | |
135 | |
136 final String _contents; | |
137 | |
138 StringAsset(this.id, this._contents); | |
139 | |
140 Future<String> readAsString({Encoding encoding}) => | |
141 new Future.value(_contents); | |
142 | |
143 Stream<List<int>> read() => | |
144 new Future<List<int>>.value(UTF8.encode(_contents)).asStream(); | |
145 | |
146 String toString() { | |
147 // Don't show the whole string if it's long. | |
148 var contents = _contents; | |
149 if (contents.length > 40) { | |
150 contents = contents.substring(0, 20) + " ... " + | |
151 contents.substring(contents.length - 20); | |
152 } | |
153 | |
154 contents = _escape(contents); | |
155 return 'String "$contents"'; | |
156 } | |
157 | |
158 String _escape(String string) { | |
159 return string | |
160 .replaceAll("\"", r'\"') | |
161 .replaceAll("\n", r"\n") | |
162 .replaceAll("\r", r"\r") | |
163 .replaceAll("\t", r"\t"); | |
164 } | |
165 } | |
166 | |
167 /// An asset whose data is available from a stream. | |
168 class StreamAsset implements Asset { | |
169 final AssetId id; | |
170 | |
171 /// A stream replayer that records and replays the contents of the input | |
172 /// stream. | |
173 final StreamReplayer<List<int>> _replayer; | |
174 | |
175 StreamAsset(this.id, Stream<List<int>> stream) | |
176 : _replayer = new StreamReplayer(stream); | |
177 | |
178 Future<String> readAsString({Encoding encoding}) { | |
179 if (encoding == null) encoding = UTF8; | |
180 return _replayer.getReplay().toList() | |
181 .then((chunks) => encoding.decode(flatten(chunks))); | |
182 } | |
183 | |
184 Stream<List<int>> read() => _replayer.getReplay(); | |
185 | |
186 String toString() => "Stream"; | |
187 } | |
OLD | NEW |