Pull request 734: + client: 1778 Add ip sort function, write unit tests

Close 

Squashed commit of the following:

commit ba63e147311799b17deaa97d7a12c2e0ec44a2ed
Merge: 143ba427 705a9d90
Author: ArtemBaskal <a.baskal@adguard.com>
Date:   Thu Aug 13 12:00:10 2020 +0300

    Merge branch 'master' into feature/1778

commit 143ba42707da3d7eece9f3e137a8b245f7f7888f
Merge: 483d2ff9 97df1989
Author: ArtemBaskal <a.baskal@adguard.com>
Date:   Thu Aug 13 11:16:46 2020 +0300

    Merge branch 'master' into feature/1778

commit 483d2ff9fa3de706d94a647701f1d26a3bcbb217
Author: ArtemBaskal <a.baskal@adguard.com>
Date:   Wed Aug 12 13:34:21 2020 +0300

    Always put ipv4 before ipv6 in sort, add invalid input unit tests

commit 26eb41b313785fe7ffaf98a7573cc5eef0dca14f
Author: ArtemBaskal <a.baskal@adguard.com>
Date:   Wed Aug 12 11:27:46 2020 +0300

    Rewrite tests: replace ipv4-mapped adresses

commit 4ecf287fd46945effe9ff11cfc9ae49217b9c796
Author: ArtemBaskal <a.baskal@adguard.com>
Date:   Tue Aug 11 19:05:15 2020 +0300

    Minor fix

commit 3e5e2a6bb1f2f166619da54e5ade0904fe22a20d
Author: ArtemBaskal <a.baskal@adguard.com>
Date:   Tue Aug 11 19:01:26 2020 +0300

    + client: 1778 Add ip sort function, write unit tests
This commit is contained in:
Artem Baskal 2020-08-13 12:16:52 +03:00
parent 705a9d909d
commit 2f8e34e73b
6 changed files with 427 additions and 4 deletions
client/src/helpers

View file

@ -681,3 +681,68 @@ export const processContent = (content) => (Array.isArray(content)
export const getObjectKeysSorted = (object, sortKey) => Object.entries(object)
.sort(([, { [sortKey]: order1 }], [, { [sortKey]: order2 }]) => order1 - order2)
.map(([key]) => key);
/**
* @param ip
* @returns {[IPv4|IPv6, 33|129]}
*/
const getParsedIpWithPrefixLength = (ip) => {
const MAX_PREFIX_LENGTH_V4 = 32;
const MAX_PREFIX_LENGTH_V6 = 128;
const parsedIp = ipaddr.parse(ip);
const prefixLength = parsedIp.kind() === 'ipv4' ? MAX_PREFIX_LENGTH_V4 : MAX_PREFIX_LENGTH_V6;
// Increment prefix length to always put IP after CIDR, e.g. 127.0.0.1/32, 127.0.0.1
return [parsedIp, prefixLength + 1];
};
/**
* Helper function for IP and CIDR comparison (supports both v4 and v6)
* @param item - ip or cidr
* @returns {number[]}
*/
const getAddressesComparisonBytes = (item) => {
// Sort ipv4 before ipv6
const IP_V4_COMPARISON_CODE = 0;
const IP_V6_COMPARISON_CODE = 1;
const [parsedIp, cidr] = ipaddr.isValid(item)
? getParsedIpWithPrefixLength(item)
: ipaddr.parseCIDR(item);
const [normalizedBytes, ipVersionComparisonCode] = parsedIp.kind() === 'ipv4'
? [parsedIp.toIPv4MappedAddress().parts, IP_V4_COMPARISON_CODE]
: [parsedIp.parts, IP_V6_COMPARISON_CODE];
return [ipVersionComparisonCode, ...normalizedBytes, cidr];
};
/**
* Compare function for IP and CIDR sort in ascending order (supports both v4 and v6)
* @param a
* @param b
* @returns {number} -1 | 0 | 1
*/
export const sortIp = (a, b) => {
try {
const comparisonBytesA = getAddressesComparisonBytes(a);
const comparisonBytesB = getAddressesComparisonBytes(b);
for (let i = 0; i < comparisonBytesA.length; i += 1) {
const byteA = comparisonBytesA[i];
const byteB = comparisonBytesB[i];
if (byteA === byteB) {
// eslint-disable-next-line no-continue
continue;
}
return byteA > byteB ? 1 : -1;
}
return 0;
} catch (e) {
console.error(e);
return 0;
}
};