OLD | NEW |
| (Empty) |
1 library googleapis.common; | |
2 | |
3 import 'dart:async' as async; | |
4 import 'dart:core' as core; | |
5 import 'dart:collection' as collection; | |
6 /** | |
7 * Represents a media consisting of a stream of bytes, a content type and a | |
8 * length. | |
9 */ | |
10 class Media { | |
11 final async.Stream<core.List<core.int>> stream; | |
12 final core.String contentType; | |
13 final core.int length; | |
14 | |
15 /** | |
16 * Creates a new [Media] with a byte [stream] of length [length] with a | |
17 * [contentType]. | |
18 * | |
19 * When uploading media, [length] can only be null if [ResumableUploadOptions] | |
20 * is used. | |
21 */ | |
22 Media(this.stream, this.length, | |
23 {this.contentType: "application/octet-stream"}) { | |
24 if (stream == null || contentType == null) { | |
25 throw new core.ArgumentError( | |
26 'Arguments stream, contentType and length must not be null.'); | |
27 } | |
28 if (length != null && length < 0) { | |
29 throw new core.ArgumentError('A negative content length is not allowed'); | |
30 } | |
31 } | |
32 } | |
33 | |
34 | |
35 /** | |
36 * Represents options for uploading a [Media]. | |
37 */ | |
38 class UploadOptions { | |
39 /** Use either simple uploads (only media) or multipart for media+metadata */ | |
40 static const UploadOptions Default = const UploadOptions(); | |
41 | |
42 /** Make resumable uploads */ | |
43 static final ResumableUploadOptions Resumable = new ResumableUploadOptions(); | |
44 | |
45 const UploadOptions(); | |
46 } | |
47 | |
48 | |
49 /** | |
50 * Specifies options for resumable uploads. | |
51 */ | |
52 class ResumableUploadOptions extends UploadOptions { | |
53 static final core.Function ExponentialBackoff = (core.int failedAttempts) { | |
54 // Do not retry more than 5 times. | |
55 if (failedAttempts > 5) return null; | |
56 | |
57 // Wait for 2^(failedAttempts-1) seconds, before retrying. | |
58 // i.e. 1 second, 2 seconds, 4 seconds, ... | |
59 return new core.Duration(seconds: 1 << (failedAttempts - 1)); | |
60 }; | |
61 | |
62 /** | |
63 * Maximum number of upload attempts per chunk. | |
64 */ | |
65 final core.int numberOfAttempts; | |
66 | |
67 /** | |
68 * Preferred size (in bytes) of a uploaded chunk. | |
69 * Must be a multiple of 256 KB. | |
70 * | |
71 * The default is 1 MB. | |
72 */ | |
73 final core.int chunkSize; | |
74 | |
75 /** | |
76 * Function for determining the [core.Duration] to wait before making the | |
77 * next attempt. See [ExponentialBackoff] for an example. | |
78 */ | |
79 final core.Function backoffFunction; | |
80 | |
81 ResumableUploadOptions({this.numberOfAttempts: 3, | |
82 this.chunkSize: 1024 * 1024, | |
83 core.Function backoffFunction}) | |
84 : backoffFunction = backoffFunction == null ? | |
85 ExponentialBackoff : backoffFunction { | |
86 // See e.g. here: | |
87 // https://developers.google.com/maps-engine/documentation/resumable-upload | |
88 // | |
89 // Chunk size restriction: | |
90 // There are some chunk size restrictions based on the size of the file you | |
91 // are uploading. Files larger than 256 KB (256 x 1024 bytes) must have | |
92 // chunk sizes that are multiples of 256 KB. For files smaller than 256 KB, | |
93 // there are no restrictions. In either case, the final chunk has no | |
94 // limitations; you can simply transfer the remaining bytes. If you use | |
95 // chunking, it is important to keep the chunk size as large as possible | |
96 // to keep the upload efficient. | |
97 // | |
98 if (numberOfAttempts < 1 || (chunkSize % (256 * 1024)) != 0) { | |
99 throw new core.ArgumentError('Invalid arguments.'); | |
100 } | |
101 } | |
102 } | |
103 | |
104 | |
105 /** | |
106 * Represents options for downloading media. | |
107 * | |
108 * For partial downloads, see [PartialDownloadOptions]. | |
109 */ | |
110 class DownloadOptions { | |
111 /** Download only metadata. */ | |
112 static const DownloadOptions Metadata = const DownloadOptions(); | |
113 | |
114 /** Download full media. */ | |
115 static final PartialDownloadOptions FullMedia = | |
116 new PartialDownloadOptions(new ByteRange(0, -1)); | |
117 | |
118 const DownloadOptions(); | |
119 | |
120 /** Indicates whether metadata should be downloaded. */ | |
121 core.bool get isMetadataDownload => true; | |
122 } | |
123 | |
124 | |
125 /** | |
126 * Options for downloading a [Media]. | |
127 */ | |
128 class PartialDownloadOptions extends DownloadOptions { | |
129 /** The range of bytes to be downloaded */ | |
130 final ByteRange range; | |
131 | |
132 PartialDownloadOptions(this.range); | |
133 | |
134 core.bool get isMetadataDownload => false; | |
135 | |
136 /** | |
137 * `true` if this is a full download and `false` if this is a partial | |
138 * download. | |
139 */ | |
140 core.bool get isFullDownload => range.start == 0 && range.end == -1; | |
141 } | |
142 | |
143 | |
144 /** | |
145 * Specifies a range of media. | |
146 */ | |
147 class ByteRange { | |
148 /** First byte of media. */ | |
149 final core.int start; | |
150 | |
151 /** Last byte of media (inclusive) */ | |
152 final core.int end; | |
153 | |
154 /** Length of this range (i.e. number of bytes) */ | |
155 core.int get length => end - start + 1; | |
156 | |
157 ByteRange(this.start, this.end) { | |
158 if (!(start == 0 && end == -1 || start >= 0 && end > start)) { | |
159 throw new core.ArgumentError('Invalid media range [$start, $end]'); | |
160 } | |
161 } | |
162 } | |
163 | |
164 | |
165 /** | |
166 * Represents a general error reported by the API endpoint. | |
167 */ | |
168 class ApiRequestError extends core.Error { | |
169 final core.String message; | |
170 | |
171 ApiRequestError(this.message); | |
172 | |
173 core.String toString() => 'ApiRequestError(message: $message)'; | |
174 } | |
175 | |
176 /** | |
177 * Represents a specific error reported by the API endpoint. | |
178 */ | |
179 class DetailedApiRequestError extends ApiRequestError { | |
180 final core.int status; | |
181 | |
182 DetailedApiRequestError(this.status, core.String message) : super(message); | |
183 | |
184 core.String toString() | |
185 => 'DetailedApiRequestError(status: $status, message: $message)'; | |
186 } | |
OLD | NEW |