UNPKG

matrix-react-sdk

Version:
214 lines (199 loc) 19.1 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.LruCache = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _logger = require("matrix-js-sdk/src/logger"); /* Copyright 2024 New Vector Ltd. Copyright 2023 The Matrix.org Foundation C.I.C. SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ /** * Least Recently Used cache. * Can be initialised with a capacity and drops the least recently used items. * This cache should be error robust: Cache miss on error. * * Implemented via a key lookup map and a double linked list: * head tail * a next → b next → c → next null * null ← prev a ← prev b ← prev c * * @template K - Type of the key used to look up the values inside the cache * @template V - Type of the values inside the cache */ class LruCache { /** * @param capacity - Cache capcity. * @throws {Error} - Raises an error if the cache capacity is less than 1. */ constructor(capacity) { /** Head of the list. */ (0, _defineProperty2.default)(this, "head", null); /** Tail of the list */ (0, _defineProperty2.default)(this, "tail", null); /** Key lookup map */ (0, _defineProperty2.default)(this, "map", void 0); this.capacity = capacity; if (this.capacity < 1) { throw new Error("Cache capacity must be at least 1"); } this.map = new Map(); } /** * Whether the cache contains an item under this key. * Marks the item as most recently used. * * @param key - Key of the item * @returns true: item in cache, else false */ has(key) { try { return this.getItem(key) !== undefined; } catch (e) { // Should not happen but makes it more robust to the unknown. this.onError(e); return false; } } /** * Returns an item from the cache. * Marks the item as most recently used. * * @param key - Key of the item * @returns The value if found, else undefined */ get(key) { try { return this.getItem(key)?.value; } catch (e) { // Should not happen but makes it more robust to the unknown. this.onError(e); return undefined; } } /** * Adds an item to the cache. * A newly added item will be the set as the most recently used. * * @param key - Key of the item * @param value - Item value */ set(key, value) { try { this.safeSet(key, value); } catch (e) { // Should not happen but makes it more robust to the unknown. this.onError(e); } } /** * Deletes an item from the cache. * * @param key - Key of the item to be removed */ delete(key) { const item = this.map.get(key); // Unknown item. if (!item) return; try { this.removeItemFromList(item); this.map.delete(key); } catch (e) { // Should not happen but makes it more robust to the unknown. this.onError(e); } } /** * Clears the cache. */ clear() { this.map = new Map(); this.head = null; this.tail = null; } /** * Returns an iterator over the cached values. */ *values() { for (const item of this.map.values()) { yield item.value; } } safeSet(key, value) { const item = this.getItem(key); if (item) { // The item is already stored under this key. Update the value. item.value = value; return; } const newItem = { key, value, next: null, prev: null }; if (this.head) { // Put item in front of the list. this.head.prev = newItem; newItem.next = this.head; } this.setHeadTail(newItem); // Store item in lookup map. this.map.set(key, newItem); if (this.tail && this.map.size > this.capacity) { // Map size exceeded cache capcity. Drop tail item. this.delete(this.tail.key); } } onError(e) { _logger.logger.warn("LruCache error", e); this.clear(); } getItem(key) { const item = this.map.get(key); // Not in cache. if (!item) return undefined; // Item is already at the head of the list. // No update required. if (item === this.head) return item; this.removeItemFromList(item); // Put item to the front. if (this.head) { this.head.prev = item; } item.prev = null; item.next = this.head; this.setHeadTail(item); return item; } setHeadTail(item) { if (item.prev === null) { // Item has no previous item → head this.head = item; } if (item.next === null) { // Item has no next item → tail this.tail = item; } } removeItemFromList(item) { if (item === this.head) { this.head = item.next; } if (item === this.tail) { this.tail = item.prev; } if (item.prev) { item.prev.next = item.next; } if (item.next) { item.next.prev = item.prev; } } } exports.LruCache = LruCache; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbG9nZ2VyIiwicmVxdWlyZSIsIkxydUNhY2hlIiwiY29uc3RydWN0b3IiLCJjYXBhY2l0eSIsIl9kZWZpbmVQcm9wZXJ0eTIiLCJkZWZhdWx0IiwiRXJyb3IiLCJtYXAiLCJNYXAiLCJoYXMiLCJrZXkiLCJnZXRJdGVtIiwidW5kZWZpbmVkIiwiZSIsIm9uRXJyb3IiLCJnZXQiLCJ2YWx1ZSIsInNldCIsInNhZmVTZXQiLCJkZWxldGUiLCJpdGVtIiwicmVtb3ZlSXRlbUZyb21MaXN0IiwiY2xlYXIiLCJoZWFkIiwidGFpbCIsInZhbHVlcyIsIm5ld0l0ZW0iLCJuZXh0IiwicHJldiIsInNldEhlYWRUYWlsIiwic2l6ZSIsImxvZ2dlciIsIndhcm4iLCJleHBvcnRzIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL0xydUNhY2hlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qXG5Db3B5cmlnaHQgMjAyNCBOZXcgVmVjdG9yIEx0ZC5cbkNvcHlyaWdodCAyMDIzIFRoZSBNYXRyaXgub3JnIEZvdW5kYXRpb24gQy5JLkMuXG5cblNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBR1BMLTMuMC1vbmx5IE9SIEdQTC0zLjAtb25seVxuUGxlYXNlIHNlZSBMSUNFTlNFIGZpbGVzIGluIHRoZSByZXBvc2l0b3J5IHJvb3QgZm9yIGZ1bGwgZGV0YWlscy5cbiovXG5cbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy9sb2dnZXJcIjtcblxuaW50ZXJmYWNlIENhY2hlSXRlbTxLLCBWPiB7XG4gICAga2V5OiBLO1xuICAgIHZhbHVlOiBWO1xuICAgIC8qKiBOZXh0IGl0ZW0gaW4gdGhlIGxpc3QgKi9cbiAgICBuZXh0OiBDYWNoZUl0ZW08SywgVj4gfCBudWxsO1xuICAgIC8qKiBQcmV2aW91cyBpdGVtIGluIHRoZSBsaXN0ICovXG4gICAgcHJldjogQ2FjaGVJdGVtPEssIFY+IHwgbnVsbDtcbn1cblxuLyoqXG4gKiBMZWFzdCBSZWNlbnRseSBVc2VkIGNhY2hlLlxuICogQ2FuIGJlIGluaXRpYWxpc2VkIHdpdGggYSBjYXBhY2l0eSBhbmQgZHJvcHMgdGhlIGxlYXN0IHJlY2VudGx5IHVzZWQgaXRlbXMuXG4gKiBUaGlzIGNhY2hlIHNob3VsZCBiZSBlcnJvciByb2J1c3Q6IENhY2hlIG1pc3Mgb24gZXJyb3IuXG4gKlxuICogSW1wbGVtZW50ZWQgdmlhIGEga2V5IGxvb2t1cCBtYXAgYW5kIGEgZG91YmxlIGxpbmtlZCBsaXN0OlxuICogICAgICAgICAgICAgaGVhZCAgICAgICAgICAgICAgdGFpbFxuICogICAgICAgICAgICAgIGEgbmV4dCDihpIgYiBuZXh0IOKGkiBjIOKGkiBuZXh0IG51bGxcbiAqICBudWxsIOKGkCBwcmV2IGEg4oaQIHByZXYgYiDihpAgcHJldiBjXG4gKlxuICogQHRlbXBsYXRlIEsgLSBUeXBlIG9mIHRoZSBrZXkgdXNlZCB0byBsb29rIHVwIHRoZSB2YWx1ZXMgaW5zaWRlIHRoZSBjYWNoZVxuICogQHRlbXBsYXRlIFYgLSBUeXBlIG9mIHRoZSB2YWx1ZXMgaW5zaWRlIHRoZSBjYWNoZVxuICovXG5leHBvcnQgY2xhc3MgTHJ1Q2FjaGU8SywgVj4ge1xuICAgIC8qKiBIZWFkIG9mIHRoZSBsaXN0LiAqL1xuICAgIHByaXZhdGUgaGVhZDogQ2FjaGVJdGVtPEssIFY+IHwgbnVsbCA9IG51bGw7XG4gICAgLyoqIFRhaWwgb2YgdGhlIGxpc3QgKi9cbiAgICBwcml2YXRlIHRhaWw6IENhY2hlSXRlbTxLLCBWPiB8IG51bGwgPSBudWxsO1xuICAgIC8qKiBLZXkgbG9va3VwIG1hcCAqL1xuICAgIHByaXZhdGUgbWFwOiBNYXA8SywgQ2FjaGVJdGVtPEssIFY+PjtcblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBjYXBhY2l0eSAtIENhY2hlIGNhcGNpdHkuXG4gICAgICogQHRocm93cyB7RXJyb3J9IC0gUmFpc2VzIGFuIGVycm9yIGlmIHRoZSBjYWNoZSBjYXBhY2l0eSBpcyBsZXNzIHRoYW4gMS5cbiAgICAgKi9cbiAgICBwdWJsaWMgY29uc3RydWN0b3IocHJpdmF0ZSBjYXBhY2l0eTogbnVtYmVyKSB7XG4gICAgICAgIGlmICh0aGlzLmNhcGFjaXR5IDwgMSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2FjaGUgY2FwYWNpdHkgbXVzdCBiZSBhdCBsZWFzdCAxXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5tYXAgPSBuZXcgTWFwKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgY2FjaGUgY29udGFpbnMgYW4gaXRlbSB1bmRlciB0aGlzIGtleS5cbiAgICAgKiBNYXJrcyB0aGUgaXRlbSBhcyBtb3N0IHJlY2VudGx5IHVzZWQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ga2V5IC0gS2V5IG9mIHRoZSBpdGVtXG4gICAgICogQHJldHVybnMgdHJ1ZTogaXRlbSBpbiBjYWNoZSwgZWxzZSBmYWxzZVxuICAgICAqL1xuICAgIHB1YmxpYyBoYXMoa2V5OiBLKTogYm9vbGVhbiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5nZXRJdGVtKGtleSkgIT09IHVuZGVmaW5lZDtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgLy8gU2hvdWxkIG5vdCBoYXBwZW4gYnV0IG1ha2VzIGl0IG1vcmUgcm9idXN0IHRvIHRoZSB1bmtub3duLlxuICAgICAgICAgICAgdGhpcy5vbkVycm9yKGUpO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhbiBpdGVtIGZyb20gdGhlIGNhY2hlLlxuICAgICAqIE1hcmtzIHRoZSBpdGVtIGFzIG1vc3QgcmVjZW50bHkgdXNlZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBrZXkgLSBLZXkgb2YgdGhlIGl0ZW1cbiAgICAgKiBAcmV0dXJucyBUaGUgdmFsdWUgaWYgZm91bmQsIGVsc2UgdW5kZWZpbmVkXG4gICAgICovXG4gICAgcHVibGljIGdldChrZXk6IEspOiBWIHwgdW5kZWZpbmVkIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmdldEl0ZW0oa2V5KT8udmFsdWU7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIC8vIFNob3VsZCBub3QgaGFwcGVuIGJ1dCBtYWtlcyBpdCBtb3JlIHJvYnVzdCB0byB0aGUgdW5rbm93bi5cbiAgICAgICAgICAgIHRoaXMub25FcnJvcihlKTtcbiAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGFuIGl0ZW0gdG8gdGhlIGNhY2hlLlxuICAgICAqIEEgbmV3bHkgYWRkZWQgaXRlbSB3aWxsIGJlIHRoZSBzZXQgYXMgdGhlIG1vc3QgcmVjZW50bHkgdXNlZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBrZXkgLSBLZXkgb2YgdGhlIGl0ZW1cbiAgICAgKiBAcGFyYW0gdmFsdWUgLSBJdGVtIHZhbHVlXG4gICAgICovXG4gICAgcHVibGljIHNldChrZXk6IEssIHZhbHVlOiBWKTogdm9pZCB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICB0aGlzLnNhZmVTZXQoa2V5LCB2YWx1ZSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIC8vIFNob3VsZCBub3QgaGFwcGVuIGJ1dCBtYWtlcyBpdCBtb3JlIHJvYnVzdCB0byB0aGUgdW5rbm93bi5cbiAgICAgICAgICAgIHRoaXMub25FcnJvcihlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERlbGV0ZXMgYW4gaXRlbSBmcm9tIHRoZSBjYWNoZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBrZXkgLSBLZXkgb2YgdGhlIGl0ZW0gdG8gYmUgcmVtb3ZlZFxuICAgICAqL1xuICAgIHB1YmxpYyBkZWxldGUoa2V5OiBLKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGl0ZW0gPSB0aGlzLm1hcC5nZXQoa2V5KTtcblxuICAgICAgICAvLyBVbmtub3duIGl0ZW0uXG4gICAgICAgIGlmICghaXRlbSkgcmV0dXJuO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICB0aGlzLnJlbW92ZUl0ZW1Gcm9tTGlzdChpdGVtKTtcbiAgICAgICAgICAgIHRoaXMubWFwLmRlbGV0ZShrZXkpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAvLyBTaG91bGQgbm90IGhhcHBlbiBidXQgbWFrZXMgaXQgbW9yZSByb2J1c3QgdG8gdGhlIHVua25vd24uXG4gICAgICAgICAgICB0aGlzLm9uRXJyb3IoZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDbGVhcnMgdGhlIGNhY2hlLlxuICAgICAqL1xuICAgIHB1YmxpYyBjbGVhcigpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5tYXAgPSBuZXcgTWFwKCk7XG4gICAgICAgIHRoaXMuaGVhZCA9IG51bGw7XG4gICAgICAgIHRoaXMudGFpbCA9IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhbiBpdGVyYXRvciBvdmVyIHRoZSBjYWNoZWQgdmFsdWVzLlxuICAgICAqL1xuICAgIHB1YmxpYyAqdmFsdWVzKCk6IEl0ZXJhYmxlSXRlcmF0b3I8Vj4ge1xuICAgICAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgdGhpcy5tYXAudmFsdWVzKCkpIHtcbiAgICAgICAgICAgIHlpZWxkIGl0ZW0udmFsdWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHNhZmVTZXQoa2V5OiBLLCB2YWx1ZTogVik6IHZvaWQge1xuICAgICAgICBjb25zdCBpdGVtID0gdGhpcy5nZXRJdGVtKGtleSk7XG5cbiAgICAgICAgaWYgKGl0ZW0pIHtcbiAgICAgICAgICAgIC8vIFRoZSBpdGVtIGlzIGFscmVhZHkgc3RvcmVkIHVuZGVyIHRoaXMga2V5LiBVcGRhdGUgdGhlIHZhbHVlLlxuICAgICAgICAgICAgaXRlbS52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgbmV3SXRlbTogQ2FjaGVJdGVtPEssIFY+ID0ge1xuICAgICAgICAgICAga2V5LFxuICAgICAgICAgICAgdmFsdWUsXG4gICAgICAgICAgICBuZXh0OiBudWxsLFxuICAgICAgICAgICAgcHJldjogbnVsbCxcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAodGhpcy5oZWFkKSB7XG4gICAgICAgICAgICAvLyBQdXQgaXRlbSBpbiBmcm9udCBvZiB0aGUgbGlzdC5cbiAgICAgICAgICAgIHRoaXMuaGVhZC5wcmV2ID0gbmV3SXRlbTtcbiAgICAgICAgICAgIG5ld0l0ZW0ubmV4dCA9IHRoaXMuaGVhZDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc2V0SGVhZFRhaWwobmV3SXRlbSk7XG5cbiAgICAgICAgLy8gU3RvcmUgaXRlbSBpbiBsb29rdXAgbWFwLlxuICAgICAgICB0aGlzLm1hcC5zZXQoa2V5LCBuZXdJdGVtKTtcblxuICAgICAgICBpZiAodGhpcy50YWlsICYmIHRoaXMubWFwLnNpemUgPiB0aGlzLmNhcGFjaXR5KSB7XG4gICAgICAgICAgICAvLyBNYXAgc2l6ZSBleGNlZWRlZCBjYWNoZSBjYXBjaXR5LiBEcm9wIHRhaWwgaXRlbS5cbiAgICAgICAgICAgIHRoaXMuZGVsZXRlKHRoaXMudGFpbC5rZXkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvbkVycm9yKGU6IHVua25vd24pOiB2b2lkIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oXCJMcnVDYWNoZSBlcnJvclwiLCBlKTtcbiAgICAgICAgdGhpcy5jbGVhcigpO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0SXRlbShrZXk6IEspOiBDYWNoZUl0ZW08SywgVj4gfCB1bmRlZmluZWQge1xuICAgICAgICBjb25zdCBpdGVtID0gdGhpcy5tYXAuZ2V0KGtleSk7XG5cbiAgICAgICAgLy8gTm90IGluIGNhY2hlLlxuICAgICAgICBpZiAoIWl0ZW0pIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICAgICAgLy8gSXRlbSBpcyBhbHJlYWR5IGF0IHRoZSBoZWFkIG9mIHRoZSBsaXN0LlxuICAgICAgICAvLyBObyB1cGRhdGUgcmVxdWlyZWQuXG4gICAgICAgIGlmIChpdGVtID09PSB0aGlzLmhlYWQpIHJldHVybiBpdGVtO1xuXG4gICAgICAgIHRoaXMucmVtb3ZlSXRlbUZyb21MaXN0KGl0ZW0pO1xuXG4gICAgICAgIC8vIFB1dCBpdGVtIHRvIHRoZSBmcm9udC5cblxuICAgICAgICBpZiAodGhpcy5oZWFkKSB7XG4gICAgICAgICAgICB0aGlzLmhlYWQucHJldiA9IGl0ZW07XG4gICAgICAgIH1cblxuICAgICAgICBpdGVtLnByZXYgPSBudWxsO1xuICAgICAgICBpdGVtLm5leHQgPSB0aGlzLmhlYWQ7XG5cbiAgICAgICAgdGhpcy5zZXRIZWFkVGFpbChpdGVtKTtcblxuICAgICAgICByZXR1cm4gaXRlbTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHNldEhlYWRUYWlsKGl0ZW06IENhY2hlSXRlbTxLLCBWPik6IHZvaWQge1xuICAgICAgICBpZiAoaXRlbS5wcmV2ID09PSBudWxsKSB7XG4gICAgICAgICAgICAvLyBJdGVtIGhhcyBubyBwcmV2aW91cyBpdGVtIOKGkiBoZWFkXG4gICAgICAgICAgICB0aGlzLmhlYWQgPSBpdGVtO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGl0ZW0ubmV4dCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgLy8gSXRlbSBoYXMgbm8gbmV4dCBpdGVtIOKGkiB0YWlsXG4gICAgICAgICAgICB0aGlzLnRhaWwgPSBpdGVtO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSByZW1vdmVJdGVtRnJvbUxpc3QoaXRlbTogQ2FjaGVJdGVtPEssIFY+KTogdm9pZCB7XG4gICAgICAgIGlmIChpdGVtID09PSB0aGlzLmhlYWQpIHtcbiAgICAgICAgICAgIHRoaXMuaGVhZCA9IGl0ZW0ubmV4dDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpdGVtID09PSB0aGlzLnRhaWwpIHtcbiAgICAgICAgICAgIHRoaXMudGFpbCA9IGl0ZW0ucHJldjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpdGVtLnByZXYpIHtcbiAgICAgICAgICAgIGl0ZW0ucHJldi5uZXh0ID0gaXRlbS5uZXh0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGl0ZW0ubmV4dCkge1xuICAgICAgICAgICAgaXRlbS5uZXh0LnByZXYgPSBpdGVtLnByZXY7XG4gICAgICAgIH1cbiAgICB9XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBUUEsSUFBQUEsT0FBQSxHQUFBQyxPQUFBO0FBUkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBYUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDTyxNQUFNQyxRQUFRLENBQU87RUFReEI7QUFDSjtBQUNBO0FBQ0E7RUFDV0MsV0FBV0EsQ0FBU0MsUUFBZ0IsRUFBRTtJQVg3QztJQUFBLElBQUFDLGdCQUFBLENBQUFDLE9BQUEsZ0JBQ3VDLElBQUk7SUFDM0M7SUFBQSxJQUFBRCxnQkFBQSxDQUFBQyxPQUFBLGdCQUN1QyxJQUFJO0lBQzNDO0lBQUEsSUFBQUQsZ0JBQUEsQ0FBQUMsT0FBQTtJQUFBLEtBTzJCRixRQUFnQixHQUFoQkEsUUFBZ0I7SUFDdkMsSUFBSSxJQUFJLENBQUNBLFFBQVEsR0FBRyxDQUFDLEVBQUU7TUFDbkIsTUFBTSxJQUFJRyxLQUFLLENBQUMsbUNBQW1DLENBQUM7SUFDeEQ7SUFFQSxJQUFJLENBQUNDLEdBQUcsR0FBRyxJQUFJQyxHQUFHLENBQUMsQ0FBQztFQUN4Qjs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtFQUNXQyxHQUFHQSxDQUFDQyxHQUFNLEVBQVc7SUFDeEIsSUFBSTtNQUNBLE9BQU8sSUFB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