Dactyloidae/netwerk/dns/mdns/libmdns/fallback/DataReader.jsm

133 lines
2.8 KiB
JavaScript

/* -*- Mode: js; js-indent-level: 2; indent-tabs-mode: nil; tab-width: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
/* jshint esnext: true, moz: true */
'use strict';
this.EXPORTED_SYMBOLS = ['DataReader'];
class DataReader {
// `data` is `Uint8Array`
constructor(data, startByte = 0) {
this._data = data;
this._cursor = startByte;
}
get buffer() {
return this._data.buffer;
}
get data() {
return this._data;
}
get eof() {
return this._cursor >= this._data.length;
}
getBytes(length = 1) {
if (!length) {
return new Uint8Array();
}
let end = this._cursor + length;
if (end > this._data.length) {
return new Uint8Array();
}
let uint8Array = new Uint8Array(this.buffer.slice(this._cursor, end));
this._cursor += length;
return uint8Array;
}
getString(length) {
let uint8Array = this.getBytes(length);
return _uint8ArrayToString(uint8Array);
}
getValue(length) {
let uint8Array = this.getBytes(length);
return _uint8ArrayToValue(uint8Array);
}
getLabel(decompressData) {
let parts = [];
let partLength;
while ((partLength = this.getValue(1))) {
// If a length has been specified instead of a pointer,
// read the string of the specified length.
if (partLength !== 0xc0) {
parts.push(this.getString(partLength));
continue;
}
// TODO: Handle case where we have a pointer to the label
parts.push(String.fromCharCode(0xc0) + this.getString(1));
break;
}
let label = parts.join('.');
return _decompressLabel(label, decompressData || this._data);
}
}
/**
* @private
*/
function _uint8ArrayToValue(uint8Array) {
let length = uint8Array.length;
if (length === 0) {
return null;
}
let value = 0;
for (let i = 0; i < length; i++) {
value = value << 8;
value += uint8Array[i];
}
return value;
}
/**
* @private
*/
function _uint8ArrayToString(uint8Array) {
let length = uint8Array.length;
if (length === 0) {
return '';
}
let results = [];
for (let i = 0; i < length; i += 1024) {
results.push(String.fromCharCode.apply(null, uint8Array.subarray(i, i + 1024)));
}
return results.join('');
}
/**
* @private
*/
function _decompressLabel(label, decompressData) {
let result = '';
for (let i = 0, length = label.length; i < length; i++) {
if (label.charCodeAt(i) !== 0xc0) {
result += label.charAt(i);
continue;
}
i++;
let reader = new DataReader(decompressData, label.charCodeAt(i));
result += _decompressLabel(reader.getLabel(), decompressData);
}
return result;
}