Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d6de952
commit caa2d62
Showing
3 changed files
with
208 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
'use strict'; | ||
/*! (c) Andrea Giammarchi - ISC */ | ||
|
||
const {crawl} = require('./index.js'); | ||
|
||
const LIST = '[]'; | ||
|
||
const {iterator} = Symbol; | ||
|
||
// copy objects/arrays and transform iterables in arrays | ||
const copy = input => { | ||
if (typeof input === 'object' && input) { | ||
if (iterator in input) { | ||
const values = []; | ||
for (const value of input) | ||
values.push(copy(value)); | ||
input = values; | ||
} | ||
else { | ||
const output = {}; | ||
for (const key in input) | ||
output[key] = copy(input[key]); | ||
input = output; | ||
} | ||
} | ||
return input; | ||
}; | ||
|
||
/** | ||
* @typedef {[array[], object]} PackedResult an array with values as first entry, | ||
* and the optimized object as second one. | ||
*/ | ||
|
||
/** | ||
* Given one or more target paths, returns a specialized object that can be | ||
* unpacked later on, through the indexed values grouped as unique IDs. | ||
* Please note: this method **mutates** the entry `object`. | ||
* @param {string[]} targets paths to transform as indexed values. | ||
* @param {Array|Object} object a JSON serializable object. | ||
* @returns {PackedResult} | ||
*/ | ||
const packDirect = (targets, object) => { | ||
const _ = new Map; | ||
const callback = ({id, hint}, target) => { | ||
if (!_.has(id)) | ||
_.set(id, new Map); | ||
const map = _.get(id); | ||
const result = []; | ||
const all = hint === LIST; | ||
for (const values of all ? target : [target]) { | ||
const indexes = []; | ||
for (const value of values) { | ||
if (!map.has(value)) | ||
map.set(value, map.size); | ||
indexes.push(map.get(value)); | ||
} | ||
result.push([indexes, id]); | ||
} | ||
return all ? result : result.shift(); | ||
}; | ||
crawl(targets, callback, object); | ||
return [[..._.values()].map(_ => [..._.keys()]), object]; | ||
}; | ||
exports.packDirect = packDirect; | ||
|
||
/** | ||
* Given one or more target paths, returns a specialized object that can be | ||
* unpacked later on, through the indexed values grouped as unique IDs. | ||
* @param {string[]} targets paths to transform as indexed values. | ||
* @param {Array|Object} object a JSON serializable object. | ||
* @returns {PackedResult} | ||
*/ | ||
const packCopy = (targets, object) => packDirect(targets, copy(object)); | ||
exports.packCopy = packCopy; | ||
|
||
/** | ||
* Given the same `targets` used to pack an object, returns the original object with | ||
* indexed values revived as original values. | ||
* Please note: this method **mutates** the passed `object` within the `$` field. | ||
* @param {string[]} targets paths to reach and revive indexes as values. | ||
* @param {PackedResult} array | ||
* @returns {Array|Object} | ||
*/ | ||
const unpackDirect = (targets, [_, $]) => { | ||
const callback = ({hint}, target) => { | ||
const result = []; | ||
const all = hint === LIST; | ||
for (const [indexes, index] of all ? target : [target]) | ||
result.push(indexes.map(_[index].get, _[index])); | ||
return all ? result : result.shift(); | ||
}; | ||
_ = _.map(indexes => indexes.reduce((map, v, i) => map.set(i, v), new Map)); | ||
crawl(targets, callback, $); | ||
return $; | ||
}; | ||
exports.unpackDirect = unpackDirect; | ||
|
||
/** | ||
* Given the same `targets` used to pack an object, returns a copy of the original object | ||
* with indexed values revived as original values. | ||
* @param {string[]} targets paths to reach and revive indexes as values. | ||
* @param {PackedResult} array | ||
* @returns {Array|Object} | ||
*/ | ||
const unpackCopy = (targets, [_, $]) => unpackDirect(targets, [_, copy($)]); | ||
exports.unpackCopy = unpackCopy; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
/*! (c) Andrea Giammarchi - ISC */ | ||
|
||
import {crawl} from './index.js'; | ||
|
||
const LIST = '[]'; | ||
|
||
const {iterator} = Symbol; | ||
|
||
// copy objects/arrays and transform iterables in arrays | ||
const copy = input => { | ||
if (typeof input === 'object' && input) { | ||
if (iterator in input) { | ||
const values = []; | ||
for (const value of input) | ||
values.push(copy(value)); | ||
input = values; | ||
} | ||
else { | ||
const output = {}; | ||
for (const key in input) | ||
output[key] = copy(input[key]); | ||
input = output; | ||
} | ||
} | ||
return input; | ||
}; | ||
|
||
/** | ||
* @typedef {[array[], object]} PackedResult an array with values as first entry, | ||
* and the optimized object as second one. | ||
*/ | ||
|
||
/** | ||
* Given one or more target paths, returns a specialized object that can be | ||
* unpacked later on, through the indexed values grouped as unique IDs. | ||
* Please note: this method **mutates** the entry `object`. | ||
* @param {string[]} targets paths to transform as indexed values. | ||
* @param {Array|Object} object a JSON serializable object. | ||
* @returns {PackedResult} | ||
*/ | ||
export const packDirect = (targets, object) => { | ||
const _ = new Map; | ||
const callback = ({id, hint}, target) => { | ||
if (!_.has(id)) | ||
_.set(id, new Map); | ||
const map = _.get(id); | ||
const result = []; | ||
const all = hint === LIST; | ||
for (const values of all ? target : [target]) { | ||
const indexes = []; | ||
for (const value of values) { | ||
if (!map.has(value)) | ||
map.set(value, map.size); | ||
indexes.push(map.get(value)); | ||
} | ||
result.push([indexes, id]); | ||
} | ||
return all ? result : result.shift(); | ||
}; | ||
crawl(targets, callback, object); | ||
return [[..._.values()].map(_ => [..._.keys()]), object]; | ||
}; | ||
|
||
/** | ||
* Given one or more target paths, returns a specialized object that can be | ||
* unpacked later on, through the indexed values grouped as unique IDs. | ||
* @param {string[]} targets paths to transform as indexed values. | ||
* @param {Array|Object} object a JSON serializable object. | ||
* @returns {PackedResult} | ||
*/ | ||
export const packCopy = (targets, object) => packDirect(targets, copy(object)); | ||
|
||
/** | ||
* Given the same `targets` used to pack an object, returns the original object with | ||
* indexed values revived as original values. | ||
* Please note: this method **mutates** the passed `object` within the `$` field. | ||
* @param {string[]} targets paths to reach and revive indexes as values. | ||
* @param {PackedResult} array | ||
* @returns {Array|Object} | ||
*/ | ||
export const unpackDirect = (targets, [_, $]) => { | ||
const callback = ({hint}, target) => { | ||
const result = []; | ||
const all = hint === LIST; | ||
for (const [indexes, index] of all ? target : [target]) | ||
result.push(indexes.map(_[index].get, _[index])); | ||
return all ? result : result.shift(); | ||
}; | ||
_ = _.map(indexes => indexes.reduce((map, v, i) => map.set(i, v), new Map)); | ||
crawl(targets, callback, $); | ||
return $; | ||
}; | ||
|
||
/** | ||
* Given the same `targets` used to pack an object, returns a copy of the original object | ||
* with indexed values revived as original values. | ||
* @param {string[]} targets paths to reach and revive indexes as values. | ||
* @param {PackedResult} array | ||
* @returns {Array|Object} | ||
*/ | ||
export const unpackCopy = (targets, [_, $]) => unpackDirect(targets, [_, copy($)]); |