UNPKG

rx-player

Version:
163 lines (154 loc) 4.92 kB
/** * 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`. }