rx-player
Version:
Canal+ HTML5 Video Player
163 lines (154 loc) • 4.92 kB
text/typescript
/**
* Copyright 2015 CANAL+ Group
*
* 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 areArraysOfNumbersEqual from "../../../utils/are_arrays_of_numbers_equal";
import SerializableBytes from "./serializable_bytes";
/**
* Returns `true` if both values are compatible initialization data, which
* means that one is completely contained in the other.
*
* Both values given should be sorted by systemId the same way.
* @param {Array.<Object>} stored
* @param {Array.<Object>} newElts
* @returns {boolean}
*/
export default function areInitializationValuesCompatible(
stored: Array<{
systemId: string | undefined;
hash: number;
data: Uint8Array | SerializableBytes | string;
}>,
newElts: Array<{
systemId: string | undefined;
hash: number;
data: Uint8Array | SerializableBytes | string;
}>,
): boolean {
return _isAInB(stored, newElts) ?? _isAInB(newElts, stored) ?? false;
}
/**
* Take two arrays of initialization data values, `a` and `b`, sorted by
* their `systemId` property in the same order.
*
* Returns `true` if `a` is not empty and is completely contained in the `b`
* array.
* This is equivalent to: "`a` is contained in `b`".
*
* Returns `false` either if `a` is empty or if `b` has different initialization
* data than it for equivalent system ids.
* This is equivalent to: "`a` represents different data than `b`".
*
* Returns `null` if `a` is not fully contained in `b` but can still be
* compatible with it.
* This is equivalent to: "`a` is not contained in `b`, but `b` could be
* contained in `a`".
* @param {Array.<Object>} a
* @param {Array.<Object>} b
* @returns {boolean}
*/
function _isAInB(
a: Array<{
systemId: string | undefined;
hash: number;
data: Uint8Array | SerializableBytes | string;
}>,
b: Array<{
systemId: string | undefined;
hash: number;
data: Uint8Array | SerializableBytes | string;
}>,
): boolean | null {
if (a.length === 0) {
return false;
}
if (b.length < a.length) {
return null;
}
const firstAElt = a[0];
let aIdx = 0;
let bIdx = 0;
for (; bIdx < b.length; bIdx++) {
const bElt = b[bIdx];
if (bElt.systemId !== firstAElt.systemId) {
continue;
}
if (bElt.hash !== firstAElt.hash) {
return false;
}
let aData: Uint8Array;
if (firstAElt.data instanceof Uint8Array) {
aData = firstAElt.data;
} else if (typeof firstAElt.data === "string") {
aData = SerializableBytes.decode(firstAElt.data);
} else {
aData = firstAElt.data.initData;
}
let bData: Uint8Array;
if (bElt.data instanceof Uint8Array) {
bData = bElt.data;
} else if (typeof bElt.data === "string") {
bData = SerializableBytes.decode(bElt.data);
} else {
bData = bElt.data.initData;
}
if (!areArraysOfNumbersEqual(aData, bData)) {
return false;
}
if (b.length - bIdx < a.length) {
// not enough place to store `a`'s initialization data.
return null;
}
// first `a` value was found. Check if all `a` values are found in `b`
for (aIdx = 1; aIdx < a.length; aIdx++) {
const aElt = a[aIdx];
for (bIdx += 1; bIdx < b.length; bIdx++) {
const bNewElt = b[bIdx];
if (aElt.systemId !== bNewElt.systemId) {
continue;
}
if (aElt.hash !== bNewElt.hash) {
return false;
}
let aNewData: Uint8Array;
if (aElt.data instanceof Uint8Array) {
aNewData = aElt.data;
} else if (typeof aElt.data === "string") {
aNewData = SerializableBytes.decode(aElt.data);
} else {
aNewData = aElt.data.initData;
}
let bNewData: Uint8Array;
if (bNewElt.data instanceof Uint8Array) {
bNewData = bNewElt.data;
} else if (typeof bNewElt.data === "string") {
bNewData = SerializableBytes.decode(bNewElt.data);
} else {
bNewData = bNewElt.data.initData;
}
if (!areArraysOfNumbersEqual(aNewData, bNewData)) {
return false;
}
break;
}
if (aIdx === b.length) {
// we didn't find `aElt`'s systemId in b
return null;
}
}
// If we're here, then we've found all `a`'s systemId in `b` and they match
return true;
}
return null; // We didn't find the firstAElt`s systemId in `b`.
}