113 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
			
		
		
	
	
			113 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
| /*
 | |
| Copyright 2016 OpenMarket Ltd
 | |
| 
 | |
| 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.
 | |
| */
 | |
| 
 | |
| /**
 | |
|  * For two objects of the form { key: [val1, val2, val3] }, work out the added/removed
 | |
|  * values. Entirely new keys will result in the entire value array being added.
 | |
|  * @param {Object} before
 | |
|  * @param {Object} after
 | |
|  * @return {Object[]} An array of objects with the form:
 | |
|  * { key: $KEY, val: $VALUE, place: "add|del" }
 | |
|  */
 | |
| module.exports.getKeyValueArrayDiffs = function(before, after) {
 | |
|     const results = [];
 | |
|     const delta = {};
 | |
|     Object.keys(before).forEach(function(beforeKey) {
 | |
|         delta[beforeKey] = delta[beforeKey] || 0; // init to 0 initially
 | |
|         delta[beforeKey]--; // keys present in the past have -ve values
 | |
|     });
 | |
|     Object.keys(after).forEach(function(afterKey) {
 | |
|         delta[afterKey] = delta[afterKey] || 0; // init to 0 initially
 | |
|         delta[afterKey]++; // keys present in the future have +ve values
 | |
|     });
 | |
| 
 | |
|     Object.keys(delta).forEach(function(muxedKey) {
 | |
|         switch (delta[muxedKey]) {
 | |
|             case 1: // A new key in after
 | |
|                 after[muxedKey].forEach(function(afterVal) {
 | |
|                     results.push({ place: "add", key: muxedKey, val: afterVal });
 | |
|                 });
 | |
|                 break;
 | |
|             case -1: // A before key was removed
 | |
|                 before[muxedKey].forEach(function(beforeVal) {
 | |
|                     results.push({ place: "del", key: muxedKey, val: beforeVal });
 | |
|                 });
 | |
|                 break;
 | |
|             case 0: {// A mix of added/removed keys
 | |
|                 // compare old & new vals
 | |
|                 const itemDelta = {};
 | |
|                 before[muxedKey].forEach(function(beforeVal) {
 | |
|                     itemDelta[beforeVal] = itemDelta[beforeVal] || 0;
 | |
|                     itemDelta[beforeVal]--;
 | |
|                 });
 | |
|                 after[muxedKey].forEach(function(afterVal) {
 | |
|                     itemDelta[afterVal] = itemDelta[afterVal] || 0;
 | |
|                     itemDelta[afterVal]++;
 | |
|                 });
 | |
| 
 | |
|                 Object.keys(itemDelta).forEach(function(item) {
 | |
|                     if (itemDelta[item] === 1) {
 | |
|                         results.push({ place: "add", key: muxedKey, val: item });
 | |
|                     } else if (itemDelta[item] === -1) {
 | |
|                         results.push({ place: "del", key: muxedKey, val: item });
 | |
|                     } else {
 | |
|                         // itemDelta of 0 means it was unchanged between before/after
 | |
|                     }
 | |
|                 });
 | |
|                 break;
 | |
|             }
 | |
|             default:
 | |
|                 console.error("Calculated key delta of " + delta[muxedKey] + " - this should never happen!");
 | |
|                 break;
 | |
|         }
 | |
|     });
 | |
| 
 | |
|     return results;
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Shallow-compare two objects for equality: each key and value must be identical
 | |
|  * @param {Object} objA First object to compare against the second
 | |
|  * @param {Object} objB Second object to compare against the first
 | |
|  * @return {boolean} whether the two objects have same key=values
 | |
|  */
 | |
| module.exports.shallowEqual = function(objA, objB) {
 | |
|     if (objA === objB) {
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     if (typeof objA !== 'object' || objA === null ||
 | |
|           typeof objB !== 'object' || objB === null) {
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     const keysA = Object.keys(objA);
 | |
|     const keysB = Object.keys(objB);
 | |
| 
 | |
|     if (keysA.length !== keysB.length) {
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     for (let i = 0; i < keysA.length; i++) {
 | |
|         const key = keysA[i];
 | |
|         if (!objB.hasOwnProperty(key) || objA[key] !== objB[key]) {
 | |
|             return false;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return true;
 | |
| };
 |