/**
* Copyright 2017 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file Provides a Blob-like wrapper for various binary types (including the
* native Blob type). This makes it possible to upload types like ArrayBuffers,
* making uploads possible in environments without the native Blob type.
*/
import * as fs from './fs';
import * as string from './string';
import { StringFormat } from './string';
import * as type from './type';
/**
* @param opt_elideCopy If true, doesn't copy mutable input data
* (e.g. Uint8Arrays). Pass true only if you know the objects will not be
* modified after this blob's construction.
*/
export class FbsBlob {
private data_: Blob | Uint8Array;
private size_: number;
private type_: string;
constructor(data: Blob | Uint8Array | ArrayBuffer, opt_elideCopy?: boolean) {
let size: number = 0;
let blobType: string = '';
if (type.isNativeBlob(data)) {
this.data_ = data as Blob;
size = (data as Blob).size;
blobType = (data as Blob).type;
} else if (data instanceof ArrayBuffer) {
Iif (opt_elideCopy) {
this.data_ = new Uint8Array(data);
} else {
this.data_ = new Uint8Array(data.byteLength);
this.data_.set(new Uint8Array(data));
}
size = this.data_.length;
} else Eif (data instanceof Uint8Array) {
if (opt_elideCopy) {
this.data_ = data as Uint8Array;
} else {
this.data_ = new Uint8Array(data.length);
this.data_.set(data as Uint8Array);
}
size = data.length;
}
this.size_ = size;
this.type_ = blobType;
}
size(): number {
return this.size_;
}
type(): string {
return this.type_;
}
slice(startByte: number, endByte: number): FbsBlob | null {
if (type.isNativeBlob(this.data_)) {
let realBlob = this.data_ as Blob;
let sliced = fs.sliceBlob(realBlob, startByte, endByte);
Iif (sliced === null) {
return null;
}
return new FbsBlob(sliced);
} else {
let slice = new Uint8Array(
(this.data_ as Uint8Array).buffer,
startByte,
endByte - startByte
);
return new FbsBlob(slice, true);
}
}
static getBlob(...var_args: (string | FbsBlob)[]): FbsBlob | null {
if (type.isNativeBlobDefined()) {
var blobby: (Blob | Uint8Array | string)[] = var_args.map(function(
val: string | FbsBlob
): Blob | Uint8Array | string {
if (val instanceof FbsBlob) {
return val.data_;
} else {
return val;
}
});
return new FbsBlob(fs.getBlob.apply(null, blobby));
} else {
let uint8Arrays: Uint8Array[] = var_args.map(function(
val: string | FbsBlob
): Uint8Array {
if (type.isString(val)) {
return string.dataFromString(StringFormat.RAW, val as string).data;
} else {
// Blobs don't exist, so this has to be a Uint8Array.
return (val as FbsBlob).data_ as Uint8Array;
}
});
let finalLength = 0;
uint8Arrays.forEach(function(array: Uint8Array): void {
finalLength += array.byteLength;
});
let merged = new Uint8Array(finalLength);
let index = 0;
uint8Arrays.forEach(function(array: Uint8Array) {
for (let i = 0; i < array.length; i++) {
merged[index++] = array[i];
}
});
return new FbsBlob(merged, true);
}
}
uploadData(): Blob | Uint8Array {
return this.data_;
}
}
|