function extractSegmentRange()

in packages/core/micro/src/permutation/index.ts [79:151]


function extractSegmentRange(segment: PermutationSegment, start: number, length: number) {
    switch (segment.kind) {
        case PermutationKind.Empty:
            return emptyPair;

        case PermutationKind.Direct:
            return {
                retained: segment,
                removed: { kind: PermutationKind.Direct, content: segment.content.splice(start, length) },
            };

        case PermutationKind.RunLength:
            const content = segment.content;
            const size = content.length;

            let startIndex = 0;
            let startPos = start;
            while (startIndex < size) {
                const len = content[startIndex];
                if (startPos < len) {
                    break;
                }
                startPos -= len;
                startIndex += 2;
            }

            let endIndex = 0;
            let endPos = start + length;
            while (endIndex < size) {
                const len = content[endIndex];
                if (endPos < len) {
                    break;
                }
                endPos -= len;
                endIndex += 2;
            }

            if (startIndex === endIndex) {
                const len = content[startIndex];
                const base = content[startIndex + 1];
                const result = {
                    retained: segment,
                    removed: { kind: PermutationKind.RunLength, content: [len, base + startPos] }
                };
                if (startPos === 0) {
                    content[startIndex] = len - endPos;
                    content[startIndex + 1] = base + endPos;
                    return result;
                }
                if (endPos > 0) {
                    content.splice(startIndex, 2, startPos, base, len - endPos, base + endPos);
                } else {
                    content[startIndex] = startPos;
                }
                return result
            }

            const wholeStartIndex = startPos === 0 ? startIndex : startIndex + 2;
            const toRemove = endIndex - wholeStartIndex;
            endIndex -= toRemove;
            const removed: number[] = toRemove > 0 ? content.splice(wholeStartIndex, toRemove) : [];
            if (startPos > 0) {
                removed.unshift(content[startIndex] - startPos, content[startIndex + 1] + startPos);
                content[startIndex] = startPos;
            }
            if (endPos > 0) {
                removed[removed.length] = endPos;
                removed[removed.length] = content[endIndex + 1] - endPos;
                content[endIndex] -= endPos;
            }
            return { retained: segment, removed: { kind: PermutationKind.RunLength, content: removed } };
    }
}