blob: a882c3554e33b3286681cf4fa1476aa9770b56e5 [file] [log] [blame]
// Copyright (C) 2024 The Android Open Source Project
//
// 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.
import {assertTrue} from './logging';
/**
* A dynamically resizable array buffer implementation for efficient
* storage and manipulation of binary data. It starts with a specified
* initial size and grows as needed to accommodate appended data.
* Efficiently grows the buffer using an exponential strategy up to 32MB,
* and then linearly in 32MB increments to minimize reallocation overhead.
* Provides methods to append data, shrink the size, clear the buffer,
* and retrieve the stored data as a `Uint8Array`.
*/
export class ResizableArrayBuffer {
private buf: Uint8Array;
private _size = 0;
constructor(private readonly initialSize = 128) {
this.buf = new Uint8Array(initialSize);
}
append(data: ArrayLike<number>) {
const capacityNeeded = this._size + data.length;
if (this.capacity < capacityNeeded) {
this.grow(capacityNeeded);
}
this.buf.set(data, this._size);
this._size = capacityNeeded;
}
shrink(newSize: number) {
assertTrue(newSize <= this._size);
this._size = newSize;
}
clear() {
this.buf = new Uint8Array(this.initialSize);
this._size = 0;
}
get(): Uint8Array {
return this.buf.subarray(0, this._size);
}
get size(): number {
return this._size;
}
get capacity(): number {
return this.buf.length;
}
private grow(capacityNeeded: number) {
let newSize = this.buf.length;
const MB32 = 32 * 1024 * 1024;
do {
newSize = newSize < MB32 ? newSize * 2 : newSize + MB32;
} while (newSize < capacityNeeded);
const newBuf = new Uint8Array(newSize);
assertTrue(newBuf.length >= capacityNeeded);
newBuf.set(this.buf);
this.buf = newBuf;
}
}