OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 import "dart:core" hide Resource; |
5 import "dart:async" show Future, Stream; | 6 import "dart:async" show Future, Stream; |
6 import "dart:convert" show Encoding; | 7 import "dart:convert" show Encoding; |
7 import "dart:isolate" show Isolate; | |
8 import "loader.dart"; | |
9 | 8 |
10 /// A resource that can be read into the program. | 9 import "resource_loader.dart"; |
11 /// | 10 import "resolve.dart"; |
12 /// A resource is data that can be located using a URI and read into | 11 |
13 /// the program at runtime. | 12 /// Base resource implementation. |
14 /// The URI may use the `package` scheme to read resources provided | 13 class Resource { |
15 /// along with package sources. | 14 // Default implementation of a generic `Resource` class. |
16 abstract class Resource { | 15 // |
17 /// Creates a resource object with the given [uri] as location. | 16 // Actually exposed `Resource` interfaces uses this as implementation, |
18 /// | 17 // but expose a different `Resource` class with plaform-dependent statics. |
19 /// The [uri] must be either a [Uri] or a string containing a valid URI. | 18 // Requires a loader to be provided. |
20 /// If the string is not a valid URI, using any of the functions on | 19 |
21 /// the resource object will fail. | 20 /// Loading strategy for the resource. |
22 /// | 21 final ResourceLoader _loader; |
23 /// The URI may be relative, in which case it will be resolved | 22 |
24 /// against [Uri.base] before being used. | 23 /// The URI of the resource. |
25 /// | 24 final _uri; |
26 /// The URI may use the `package` scheme, which is always supported. | 25 |
27 /// Other schemes may also be supported where possible. | 26 const Resource(uri, ResourceLoader loader) |
28 /// | 27 : _uri = uri, _loader = loader; |
29 /// If [loader] is provided, it is used to load absolute non-package URIs. | |
30 /// Package: URIs are resolved to a non-package URI before being loaded, so | |
31 /// the loader doesn't have to support package: URIs, nor does it need to | |
32 /// support relative URI references. | |
33 /// If [loader] is omitted, a default implementation is used which supports | |
34 /// as many of `http`, `https`, `file` and `data` as are available on the | |
35 /// current platform. | |
36 const factory Resource(uri, {ResourceLoader loader}) = _Resource; | |
37 | 28 |
38 /// The location URI of this resource. | 29 /// The location URI of this resource. |
39 /// | 30 /// |
40 /// This is a [Uri] of the `uri` parameter given to the constructor. | 31 /// This is a [Uri] of the `uri` parameter given to the constructor. |
41 /// If the parameter was a string that did not contain a valid URI, | 32 /// If the parameter was a string that did not contain a valid URI, |
42 /// reading `uri` will fail. | 33 /// reading `uri` will fail. |
43 Uri get uri; | 34 Uri get uri => (_uri is String) ? Uri.parse(_uri) : (_uri as Uri); |
44 | 35 |
45 /// Reads the resource content as a stream of bytes. | 36 /// Reads the resource content as a stream of bytes. |
46 Stream<List<int>> openRead(); | 37 Stream<List<int>> openRead() async* { |
| 38 Uri uri = await resolveUri(this.uri); |
| 39 yield* _loader.openRead(uri); |
| 40 } |
47 | 41 |
48 /// Reads the resource content as a single list of bytes. | 42 /// Reads the resource content as a single list of bytes. |
49 Future<List<int>> readAsBytes(); | 43 Future<List<int>> readAsBytes() async { |
| 44 Uri uri = await resolveUri(this.uri); |
| 45 return _loader.readAsBytes(uri); |
| 46 } |
50 | 47 |
51 /// Reads the resource content as a string. | 48 /// Reads the resource content as a string. |
52 /// | 49 /// |
53 /// The content is decoded into a string using an [Encoding]. | 50 /// The content is decoded into a string using an [Encoding]. |
54 /// If no other encoding is provided, it defaults to UTF-8. | 51 /// If no encoding is provided, an encoding is chosen depending on the |
55 Future<String> readAsString({Encoding encoding}); | 52 /// protocol and/or available metadata. |
56 } | |
57 | |
58 class _Resource implements Resource { | |
59 /// Loading strategy for the resource. | |
60 final ResourceLoader _loader; | |
61 | |
62 /// The URI of the resource. | |
63 final _uri; | |
64 | |
65 const _Resource(uri, {ResourceLoader loader}) | |
66 : _uri = uri, _loader = (loader != null) ? loader : const DefaultLoader(); | |
67 // TODO: Make this `loader ?? const DefaultLoader()` when ?? is const. | |
68 | |
69 Uri get uri => (_uri is String) ? Uri.parse(_uri) : (_uri as Uri); | |
70 | |
71 Stream<List<int>> openRead() async* { | |
72 Uri uri = await _resolvedUri; | |
73 yield* _loader.openRead(uri); | |
74 } | |
75 | |
76 Future<List<int>> readAsBytes() async { | |
77 Uri uri = await _resolvedUri; | |
78 return _loader.readAsBytes(uri); | |
79 } | |
80 | |
81 Future<String> readAsString({Encoding encoding}) async { | 53 Future<String> readAsString({Encoding encoding}) async { |
82 Uri uri = await _resolvedUri; | 54 Uri uri = await resolveUri(this.uri); |
83 return _loader.readAsString(uri, encoding: encoding); | 55 return _loader.readAsString(uri, encoding: encoding); |
84 } | 56 } |
85 | |
86 Future<Uri> get _resolvedUri => resolveUri(uri); | |
87 } | 57 } |
OLD | NEW |