Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 library barback.asset; | 5 library barback.asset; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:io'; | 8 import 'dart:io'; |
| 9 import 'dart:utf'; | |
| 9 | 10 |
| 10 import 'asset_id.dart'; | 11 import 'asset_id.dart'; |
| 11 | 12 |
| 12 /// A blob of content. | 13 /// A blob of content. |
| 13 /// | 14 /// |
| 14 /// Assets may come from the file system, or as the output of a [Transformer]. | 15 /// Assets may come from the file system, or as the output of a [Transformer]. |
| 15 /// They are identified by [AssetId]. | 16 /// They are identified by [AssetId]. |
| 16 abstract class Asset { | 17 abstract class Asset { |
| 17 /// The ID for this asset. | 18 /// The ID for this asset. |
| 18 final AssetId id; | 19 final AssetId id; |
| 19 | 20 |
| 20 Asset(this.id); | 21 Asset(this.id); |
| 21 | 22 |
| 22 factory Asset.fromFile(AssetId id, File file) { | 23 factory Asset.fromBytes(AssetId id, List<int> bytes) => |
| 23 return new _FileAsset(id, file); | 24 new _BinaryAsset(id, bytes); |
| 25 | |
| 26 factory Asset.fromFile(AssetId id, File file) => | |
| 27 new _FileAsset(id, file); | |
| 28 | |
| 29 factory Asset.fromString(AssetId id, String content) => | |
| 30 new _StringAsset(id, content); | |
| 31 | |
| 32 factory Asset.fromPath(AssetId id, String path) => | |
| 33 new _FileAsset(id, new File(path)); | |
| 34 | |
| 35 /// Returns the contents of the asset as a string. | |
| 36 /// | |
| 37 /// If the asset was created from a [String] the original string is always | |
| 38 /// returned and [encoding] is ignored. Otherwise, the binary data of the | |
| 39 /// asset is decoded using [encoding], which defaults to [Encoding.UTF_8]. | |
| 40 Future<String> readAsString({Encoding encoding}); | |
| 41 | |
| 42 /// Streams the binary contents of the asset. | |
| 43 /// | |
| 44 /// If the asset was created from a [String], this returns its UTF-8 encoding. | |
| 45 Stream<List<int>> read(); | |
| 46 } | |
| 47 | |
| 48 /// An asset whose data is stored in a list of bytes. | |
| 49 class _BinaryAsset extends Asset { | |
| 50 final List<int> _contents; | |
| 51 | |
| 52 _BinaryAsset(AssetId id, this._contents) | |
| 53 : super(id); | |
| 54 | |
| 55 Future<String> readAsString({Encoding encoding}) { | |
| 56 if (encoding == null) encoding = Encoding.UTF_8; | |
| 57 | |
| 58 // TODO(rnystrom): When #6284 is fixed, just use that. Until then, only | |
| 59 // UTF-8 is supported. :( | |
| 60 if (encoding != Encoding.UTF_8) { | |
| 61 throw new UnsupportedError( | |
| 62 "${encoding.name} is not a supported encoding."); | |
| 63 } | |
| 64 | |
| 65 return new Future.value(decodeUtf8(_contents)); | |
| 24 } | 66 } |
| 25 | 67 |
| 26 factory Asset.fromString(AssetId id, String content) { | 68 Stream<List<int>> read() => new Future<List<int>>.value(_contents).asStream(); |
| 27 return new _StringAsset(id, content); | 69 |
| 70 String toString() { | |
| 71 var buffer = new StringBuffer(); | |
| 72 buffer.write("Bytes ["); | |
| 73 | |
| 74 writeByte(int i) { | |
| 75 var byte = _contents[i]; | |
| 76 var digits = "0123456789abcdef"; | |
| 77 buffer.write(digits[(byte ~/ 16) % 16]); | |
| 78 buffer.write(digits[byte % 16]); | |
|
nweiz
2013/07/08 22:50:46
Add an intToHex function in utils.
Bob Nystrom
2013/07/08 23:26:04
Done.
| |
| 79 } | |
| 80 | |
| 81 // Don't show the whole list if it's long. | |
| 82 if (_contents.length > 10) { | |
|
nweiz
2013/07/08 22:50:46
It's weird that an 11-byte buffer is abbreviated t
Bob Nystrom
2013/07/08 23:26:04
I suppose so, but I think this is tolerable balanc
nweiz
2013/07/09 02:00:01
All you have to do is change "> 10" to "> 11".
Bob Nystrom
2013/07/09 16:26:03
Done.
| |
| 83 for (var i = 0; i < 5; i++) { | |
| 84 writeByte(i); | |
| 85 buffer.write(" "); | |
| 86 } | |
| 87 | |
| 88 buffer.write("..."); | |
| 89 | |
| 90 for (var i = _contents.length - 5; i < _contents.length; i++) { | |
| 91 buffer.write(" "); | |
| 92 writeByte(i); | |
| 93 } | |
| 94 } else { | |
| 95 for (var i = 0; i < _contents.length; i++) { | |
| 96 if (i > 0) buffer.write(" "); | |
| 97 writeByte(i); | |
| 98 } | |
| 99 } | |
| 100 | |
| 101 buffer.write("]"); | |
| 102 return buffer.toString(); | |
| 28 } | 103 } |
| 29 | |
| 30 factory Asset.fromPath(AssetId id, String path) { | |
| 31 return new _FileAsset(id, new File(path)); | |
| 32 } | |
| 33 | |
| 34 // TODO(rnystrom): This prevents users from defining their own | |
| 35 // implementations of Asset. Use serialization package instead. | |
| 36 factory Asset.deserialize(data) { | |
| 37 // TODO(rnystrom): Handle errors. | |
| 38 var id = new AssetId.parse(data[1]); | |
| 39 switch (data[0]) { | |
| 40 case "file": return new _FileAsset(id, new File(data[2])); break; | |
| 41 case "string": return new _StringAsset(id, data[2]); break; | |
| 42 } | |
| 43 } | |
| 44 | |
| 45 /// Returns the contents of the asset as a string. | |
| 46 // TODO(rnystrom): Figure out how binary assets should be handled. | |
| 47 Future<String> readAsString(); | |
| 48 | |
| 49 /// Streams the contents of the asset. | |
| 50 Stream<List<int>> read(); | |
| 51 | |
| 52 /// Serializes this [Asset] to an object that can be sent across isolates | |
| 53 /// and passed to [deserialize]. | |
| 54 Object serialize(); | |
| 55 } | 104 } |
| 56 | 105 |
| 57 /// An asset backed by a file on the local file system. | 106 /// An asset backed by a file on the local file system. |
| 58 class _FileAsset extends Asset { | 107 class _FileAsset extends Asset { |
| 59 final File _file; | 108 final File _file; |
| 60 _FileAsset(AssetId id, this._file) | 109 _FileAsset(AssetId id, this._file) |
| 61 : super(id); | 110 : super(id); |
| 62 | 111 |
| 63 Future<String> readAsString() => _file.readAsString(); | 112 Future<String> readAsString({Encoding encoding}) { |
| 113 if (encoding == null) encoding = Encoding.UTF_8; | |
| 114 return _file.readAsString(encoding: encoding); | |
| 115 } | |
| 116 | |
| 64 Stream<List<int>> read() => _file.openRead(); | 117 Stream<List<int>> read() => _file.openRead(); |
| 65 | 118 |
| 66 String toString() => 'File "${_file.path}"'; | 119 String toString() => 'File "${_file.path}"'; |
| 67 | |
| 68 Object serialize() => ["file", id.serialize(), _file.path]; | |
| 69 } | 120 } |
| 70 | 121 |
| 71 /// An asset whose data is stored in a string. | 122 /// An asset whose data is stored in a string. |
| 72 // TODO(rnystrom): Have something similar for in-memory binary assets. | |
| 73 class _StringAsset extends Asset { | 123 class _StringAsset extends Asset { |
| 74 final String _contents; | 124 final String _contents; |
| 75 | 125 |
| 76 _StringAsset(AssetId id, this._contents) | 126 _StringAsset(AssetId id, this._contents) |
| 77 : super(id); | 127 : super(id); |
| 78 | 128 |
| 79 Future<String> readAsString() => new Future.value(_contents); | 129 Future<String> readAsString({Encoding encoding}) => |
| 130 new Future.value(_contents); | |
| 80 | 131 |
| 81 // TODO(rnystrom): Implement this and handle encoding. | 132 Stream<List<int>> read() => |
| 82 Stream<List<int>> read() => throw new UnimplementedError(); | 133 new Future<List<int>>.value(encodeUtf8(_contents)).asStream(); |
| 83 | 134 |
| 84 String toString() { | 135 String toString() { |
| 85 // Don't show the whole string if it's long. | 136 // Don't show the whole string if it's long. |
| 86 var contents = _contents; | 137 var contents = _contents; |
| 87 if (contents.length > 40) { | 138 if (contents.length > 40) { |
| 88 contents = contents.substring(0, 20) + " ... " + | 139 contents = contents.substring(0, 20) + " ... " + |
| 89 contents.substring(contents.length - 20); | 140 contents.substring(contents.length - 20); |
| 90 } | 141 } |
| 91 | 142 |
| 92 contents = _escape(contents); | 143 contents = _escape(contents); |
| 93 return 'String "$contents"'; | 144 return 'String "$contents"'; |
| 94 } | 145 } |
| 95 | 146 |
| 96 Object serialize() => ["string", id.serialize(), _contents]; | |
| 97 | |
| 98 String _escape(String string) { | 147 String _escape(String string) { |
| 99 return string | 148 return string |
| 100 .replaceAll("\"", r'\"') | 149 .replaceAll("\"", r'\"') |
| 101 .replaceAll("\n", r"\n") | 150 .replaceAll("\n", r"\n") |
| 102 .replaceAll("\r", r"\r") | 151 .replaceAll("\r", r"\r") |
| 103 .replaceAll("\t", r"\t"); | 152 .replaceAll("\t", r"\t"); |
| 104 } | 153 } |
| 105 } | 154 } |
| OLD | NEW |