100 lines
2.5 KiB
TypeScript
100 lines
2.5 KiB
TypeScript
|
import * as v6 from './constants';
|
||
|
import { sprintf } from 'sprintf-js';
|
||
|
|
||
|
export function groupPossibilities(possibilities: string[]): string {
|
||
|
return sprintf('(%s)', possibilities.join('|'));
|
||
|
}
|
||
|
|
||
|
export function padGroup(group: string): string {
|
||
|
if (group.length < 4) {
|
||
|
return sprintf('0{0,%d}%s', 4 - group.length, group);
|
||
|
}
|
||
|
|
||
|
return group;
|
||
|
}
|
||
|
|
||
|
export const ADDRESS_BOUNDARY = '[^A-Fa-f0-9:]';
|
||
|
|
||
|
export function simpleRegularExpression(groups: string[]) {
|
||
|
const zeroIndexes: number[] = [];
|
||
|
|
||
|
groups.forEach((group, i) => {
|
||
|
const groupInteger = parseInt(group, 16);
|
||
|
|
||
|
if (groupInteger === 0) {
|
||
|
zeroIndexes.push(i);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
// You can technically elide a single 0, this creates the regular expressions
|
||
|
// to match that eventuality
|
||
|
const possibilities = zeroIndexes.map((zeroIndex) =>
|
||
|
groups
|
||
|
.map((group, i) => {
|
||
|
if (i === zeroIndex) {
|
||
|
const elision = i === 0 || i === v6.GROUPS - 1 ? ':' : '';
|
||
|
|
||
|
return groupPossibilities([padGroup(group), elision]);
|
||
|
}
|
||
|
|
||
|
return padGroup(group);
|
||
|
})
|
||
|
.join(':')
|
||
|
);
|
||
|
|
||
|
// The simplest case
|
||
|
possibilities.push(groups.map(padGroup).join(':'));
|
||
|
|
||
|
return groupPossibilities(possibilities);
|
||
|
}
|
||
|
|
||
|
export function possibleElisions(
|
||
|
elidedGroups: number,
|
||
|
moreLeft?: boolean,
|
||
|
moreRight?: boolean
|
||
|
): string {
|
||
|
const left = moreLeft ? '' : ':';
|
||
|
const right = moreRight ? '' : ':';
|
||
|
|
||
|
const possibilities = [];
|
||
|
|
||
|
// 1. elision of everything (::)
|
||
|
if (!moreLeft && !moreRight) {
|
||
|
possibilities.push('::');
|
||
|
}
|
||
|
|
||
|
// 2. complete elision of the middle
|
||
|
if (moreLeft && moreRight) {
|
||
|
possibilities.push('');
|
||
|
}
|
||
|
|
||
|
if ((moreRight && !moreLeft) || (!moreRight && moreLeft)) {
|
||
|
// 3. complete elision of one side
|
||
|
possibilities.push(':');
|
||
|
}
|
||
|
|
||
|
// 4. elision from the left side
|
||
|
possibilities.push(sprintf('%s(:0{1,4}){1,%d}', left, elidedGroups - 1));
|
||
|
|
||
|
// 5. elision from the right side
|
||
|
possibilities.push(sprintf('(0{1,4}:){1,%d}%s', elidedGroups - 1, right));
|
||
|
|
||
|
// 6. no elision
|
||
|
possibilities.push(sprintf('(0{1,4}:){%d}0{1,4}', elidedGroups - 1));
|
||
|
|
||
|
// 7. elision (including sloppy elision) from the middle
|
||
|
for (let groups = 1; groups < elidedGroups - 1; groups++) {
|
||
|
for (let position = 1; position < elidedGroups - groups; position++) {
|
||
|
possibilities.push(
|
||
|
sprintf(
|
||
|
'(0{1,4}:){%d}:(0{1,4}:){%d}0{1,4}',
|
||
|
position,
|
||
|
elidedGroups - position - groups - 1
|
||
|
)
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return groupPossibilities(possibilities);
|
||
|
}
|