123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- 'use strict';
- const Ref = require('./ref');
- const internals = {};
- internals.extendedCheckForValue = function (value, insensitive) {
- const valueType = typeof value;
- if (valueType === 'object') {
- if (value instanceof Date) {
- return (item) => {
- return item instanceof Date && value.getTime() === item.getTime();
- };
- }
- if (Buffer.isBuffer(value)) {
- return (item) => {
- return Buffer.isBuffer(item) && value.length === item.length && value.toString('binary') === item.toString('binary');
- };
- }
- }
- else if (insensitive && valueType === 'string') {
- const lowercaseValue = value.toLowerCase();
- return (item) => {
- return typeof item === 'string' && lowercaseValue === item.toLowerCase();
- };
- }
- return null;
- };
- module.exports = class InternalSet {
- constructor(from) {
- this._set = new Set(from);
- this._hasRef = false;
- }
- add(value, refs) {
- const isRef = Ref.isRef(value);
- if (!isRef && this.has(value, null, null, false)) {
- return this;
- }
- if (refs !== undefined) { // If it's a merge, we don't have any refs
- Ref.push(refs, value);
- }
- this._set.add(value);
- this._hasRef |= isRef;
- return this;
- }
- merge(add, remove) {
- for (const item of add._set) {
- this.add(item);
- }
- for (const item of remove._set) {
- this.remove(item);
- }
- return this;
- }
- remove(value) {
- this._set.delete(value);
- return this;
- }
- has(value, state, options, insensitive) {
- return !!this.get(value, state, options, insensitive);
- }
- get(value, state, options, insensitive) {
- if (!this._set.size) {
- return false;
- }
- const hasValue = this._set.has(value);
- if (hasValue) {
- return { value };
- }
- const extendedCheck = internals.extendedCheckForValue(value, insensitive);
- if (!extendedCheck) {
- if (state && this._hasRef) {
- for (let item of this._set) {
- if (Ref.isRef(item)) {
- item = [].concat(item(state.reference || state.parent, options));
- const found = item.indexOf(value);
- if (found >= 0) {
- return { value: item[found] };
- }
- }
- }
- }
- return false;
- }
- return this._has(value, state, options, extendedCheck);
- }
- _has(value, state, options, check) {
- const checkRef = !!(state && this._hasRef);
- const isReallyEqual = function (item) {
- if (value === item) {
- return true;
- }
- return check(item);
- };
- for (let item of this._set) {
- if (checkRef && Ref.isRef(item)) { // Only resolve references if there is a state, otherwise it's a merge
- item = item(state.reference || state.parent, options);
- if (Array.isArray(item)) {
- const found = item.findIndex(isReallyEqual);
- if (found >= 0) {
- return {
- value: item[found]
- };
- }
- continue;
- }
- }
- if (isReallyEqual(item)) {
- return {
- value: item
- };
- }
- }
- return false;
- }
- values(options) {
- if (options && options.stripUndefined) {
- const values = [];
- for (const item of this._set) {
- if (item !== undefined) {
- values.push(item);
- }
- }
- return values;
- }
- return Array.from(this._set);
- }
- slice() {
- const set = new InternalSet(this._set);
- set._hasRef = this._hasRef;
- return set;
- }
- concat(source) {
- const set = new InternalSet([...this._set, ...source._set]);
- set._hasRef = !!(this._hasRef | source._hasRef);
- return set;
- }
- };
|