mirror of
https://github.com/github/codeql-action.git
synced 2025-12-27 01:30:10 +08:00
Co-authored-by: Andrew Eisenberg <aeisenberg@github.com> Co-authored-by: Henry Mercer <henrymercer@github.com>
228 lines
6.6 KiB
JavaScript
228 lines
6.6 KiB
JavaScript
import { PbLong, PbULong } from "./pb-long";
|
|
import { varint32write, varint64write } from "./goog-varint";
|
|
import { assertFloat32, assertInt32, assertUInt32 } from "./assert";
|
|
const defaultsWrite = {
|
|
writeUnknownFields: true,
|
|
writerFactory: () => new BinaryWriter(),
|
|
};
|
|
/**
|
|
* Make options for writing binary data form partial options.
|
|
*/
|
|
export function binaryWriteOptions(options) {
|
|
return options ? Object.assign(Object.assign({}, defaultsWrite), options) : defaultsWrite;
|
|
}
|
|
export class BinaryWriter {
|
|
constructor(textEncoder) {
|
|
/**
|
|
* Previous fork states.
|
|
*/
|
|
this.stack = [];
|
|
this.textEncoder = textEncoder !== null && textEncoder !== void 0 ? textEncoder : new TextEncoder();
|
|
this.chunks = [];
|
|
this.buf = [];
|
|
}
|
|
/**
|
|
* Return all bytes written and reset this writer.
|
|
*/
|
|
finish() {
|
|
this.chunks.push(new Uint8Array(this.buf)); // flush the buffer
|
|
let len = 0;
|
|
for (let i = 0; i < this.chunks.length; i++)
|
|
len += this.chunks[i].length;
|
|
let bytes = new Uint8Array(len);
|
|
let offset = 0;
|
|
for (let i = 0; i < this.chunks.length; i++) {
|
|
bytes.set(this.chunks[i], offset);
|
|
offset += this.chunks[i].length;
|
|
}
|
|
this.chunks = [];
|
|
return bytes;
|
|
}
|
|
/**
|
|
* Start a new fork for length-delimited data like a message
|
|
* or a packed repeated field.
|
|
*
|
|
* Must be joined later with `join()`.
|
|
*/
|
|
fork() {
|
|
this.stack.push({ chunks: this.chunks, buf: this.buf });
|
|
this.chunks = [];
|
|
this.buf = [];
|
|
return this;
|
|
}
|
|
/**
|
|
* Join the last fork. Write its length and bytes, then
|
|
* return to the previous state.
|
|
*/
|
|
join() {
|
|
// get chunk of fork
|
|
let chunk = this.finish();
|
|
// restore previous state
|
|
let prev = this.stack.pop();
|
|
if (!prev)
|
|
throw new Error('invalid state, fork stack empty');
|
|
this.chunks = prev.chunks;
|
|
this.buf = prev.buf;
|
|
// write length of chunk as varint
|
|
this.uint32(chunk.byteLength);
|
|
return this.raw(chunk);
|
|
}
|
|
/**
|
|
* Writes a tag (field number and wire type).
|
|
*
|
|
* Equivalent to `uint32( (fieldNo << 3 | type) >>> 0 )`.
|
|
*
|
|
* Generated code should compute the tag ahead of time and call `uint32()`.
|
|
*/
|
|
tag(fieldNo, type) {
|
|
return this.uint32((fieldNo << 3 | type) >>> 0);
|
|
}
|
|
/**
|
|
* Write a chunk of raw bytes.
|
|
*/
|
|
raw(chunk) {
|
|
if (this.buf.length) {
|
|
this.chunks.push(new Uint8Array(this.buf));
|
|
this.buf = [];
|
|
}
|
|
this.chunks.push(chunk);
|
|
return this;
|
|
}
|
|
/**
|
|
* Write a `uint32` value, an unsigned 32 bit varint.
|
|
*/
|
|
uint32(value) {
|
|
assertUInt32(value);
|
|
// write value as varint 32, inlined for speed
|
|
while (value > 0x7f) {
|
|
this.buf.push((value & 0x7f) | 0x80);
|
|
value = value >>> 7;
|
|
}
|
|
this.buf.push(value);
|
|
return this;
|
|
}
|
|
/**
|
|
* Write a `int32` value, a signed 32 bit varint.
|
|
*/
|
|
int32(value) {
|
|
assertInt32(value);
|
|
varint32write(value, this.buf);
|
|
return this;
|
|
}
|
|
/**
|
|
* Write a `bool` value, a variant.
|
|
*/
|
|
bool(value) {
|
|
this.buf.push(value ? 1 : 0);
|
|
return this;
|
|
}
|
|
/**
|
|
* Write a `bytes` value, length-delimited arbitrary data.
|
|
*/
|
|
bytes(value) {
|
|
this.uint32(value.byteLength); // write length of chunk as varint
|
|
return this.raw(value);
|
|
}
|
|
/**
|
|
* Write a `string` value, length-delimited data converted to UTF-8 text.
|
|
*/
|
|
string(value) {
|
|
let chunk = this.textEncoder.encode(value);
|
|
this.uint32(chunk.byteLength); // write length of chunk as varint
|
|
return this.raw(chunk);
|
|
}
|
|
/**
|
|
* Write a `float` value, 32-bit floating point number.
|
|
*/
|
|
float(value) {
|
|
assertFloat32(value);
|
|
let chunk = new Uint8Array(4);
|
|
new DataView(chunk.buffer).setFloat32(0, value, true);
|
|
return this.raw(chunk);
|
|
}
|
|
/**
|
|
* Write a `double` value, a 64-bit floating point number.
|
|
*/
|
|
double(value) {
|
|
let chunk = new Uint8Array(8);
|
|
new DataView(chunk.buffer).setFloat64(0, value, true);
|
|
return this.raw(chunk);
|
|
}
|
|
/**
|
|
* Write a `fixed32` value, an unsigned, fixed-length 32-bit integer.
|
|
*/
|
|
fixed32(value) {
|
|
assertUInt32(value);
|
|
let chunk = new Uint8Array(4);
|
|
new DataView(chunk.buffer).setUint32(0, value, true);
|
|
return this.raw(chunk);
|
|
}
|
|
/**
|
|
* Write a `sfixed32` value, a signed, fixed-length 32-bit integer.
|
|
*/
|
|
sfixed32(value) {
|
|
assertInt32(value);
|
|
let chunk = new Uint8Array(4);
|
|
new DataView(chunk.buffer).setInt32(0, value, true);
|
|
return this.raw(chunk);
|
|
}
|
|
/**
|
|
* Write a `sint32` value, a signed, zigzag-encoded 32-bit varint.
|
|
*/
|
|
sint32(value) {
|
|
assertInt32(value);
|
|
// zigzag encode
|
|
value = ((value << 1) ^ (value >> 31)) >>> 0;
|
|
varint32write(value, this.buf);
|
|
return this;
|
|
}
|
|
/**
|
|
* Write a `fixed64` value, a signed, fixed-length 64-bit integer.
|
|
*/
|
|
sfixed64(value) {
|
|
let chunk = new Uint8Array(8);
|
|
let view = new DataView(chunk.buffer);
|
|
let long = PbLong.from(value);
|
|
view.setInt32(0, long.lo, true);
|
|
view.setInt32(4, long.hi, true);
|
|
return this.raw(chunk);
|
|
}
|
|
/**
|
|
* Write a `fixed64` value, an unsigned, fixed-length 64 bit integer.
|
|
*/
|
|
fixed64(value) {
|
|
let chunk = new Uint8Array(8);
|
|
let view = new DataView(chunk.buffer);
|
|
let long = PbULong.from(value);
|
|
view.setInt32(0, long.lo, true);
|
|
view.setInt32(4, long.hi, true);
|
|
return this.raw(chunk);
|
|
}
|
|
/**
|
|
* Write a `int64` value, a signed 64-bit varint.
|
|
*/
|
|
int64(value) {
|
|
let long = PbLong.from(value);
|
|
varint64write(long.lo, long.hi, this.buf);
|
|
return this;
|
|
}
|
|
/**
|
|
* Write a `sint64` value, a signed, zig-zag-encoded 64-bit varint.
|
|
*/
|
|
sint64(value) {
|
|
let long = PbLong.from(value),
|
|
// zigzag encode
|
|
sign = long.hi >> 31, lo = (long.lo << 1) ^ sign, hi = ((long.hi << 1) | (long.lo >>> 31)) ^ sign;
|
|
varint64write(lo, hi, this.buf);
|
|
return this;
|
|
}
|
|
/**
|
|
* Write a `uint64` value, an unsigned 64-bit varint.
|
|
*/
|
|
uint64(value) {
|
|
let long = PbULong.from(value);
|
|
varint64write(long.lo, long.hi, this.buf);
|
|
return this;
|
|
}
|
|
}
|