mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-20 09:35:38 -05:00
204 lines
4.7 KiB
TypeScript
204 lines
4.7 KiB
TypeScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
export interface IteratorDefinedResult<T> {
|
|
readonly done: false;
|
|
readonly value: T;
|
|
}
|
|
export interface IteratorUndefinedResult {
|
|
readonly done: true;
|
|
readonly value: undefined;
|
|
}
|
|
export const FIN: IteratorUndefinedResult = { done: true, value: undefined };
|
|
export type IteratorResult<T> = IteratorDefinedResult<T> | IteratorUndefinedResult;
|
|
|
|
export interface Iterator<T> {
|
|
next(): IteratorResult<T>;
|
|
}
|
|
|
|
export module Iterator {
|
|
const _empty: Iterator<any> = {
|
|
next() {
|
|
return FIN;
|
|
}
|
|
};
|
|
|
|
export function empty<T>(): Iterator<T> {
|
|
return _empty;
|
|
}
|
|
|
|
export function fromArray<T>(array: T[], index = 0, length = array.length): Iterator<T> {
|
|
return {
|
|
next(): IteratorResult<T> {
|
|
if (index >= length) {
|
|
return FIN;
|
|
}
|
|
|
|
return { done: false, value: array[index++] };
|
|
}
|
|
};
|
|
}
|
|
|
|
export function from<T>(elements: Iterator<T> | T[] | undefined): Iterator<T> {
|
|
if (!elements) {
|
|
return Iterator.empty();
|
|
} else if (Array.isArray(elements)) {
|
|
return Iterator.fromArray(elements);
|
|
} else {
|
|
return elements;
|
|
}
|
|
}
|
|
|
|
export function map<T, R>(iterator: Iterator<T>, fn: (t: T) => R): Iterator<R> {
|
|
return {
|
|
next() {
|
|
const element = iterator.next();
|
|
if (element.done) {
|
|
return FIN;
|
|
} else {
|
|
return { done: false, value: fn(element.value) };
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
export function filter<T>(iterator: Iterator<T>, fn: (t: T) => boolean): Iterator<T> {
|
|
return {
|
|
next() {
|
|
while (true) {
|
|
const element = iterator.next();
|
|
if (element.done) {
|
|
return FIN;
|
|
}
|
|
if (fn(element.value)) {
|
|
return { done: false, value: element.value };
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
export function forEach<T>(iterator: Iterator<T>, fn: (t: T) => void): void {
|
|
for (let next = iterator.next(); !next.done; next = iterator.next()) {
|
|
fn(next.value);
|
|
}
|
|
}
|
|
|
|
export function collect<T>(iterator: Iterator<T>): T[] {
|
|
const result: T[] = [];
|
|
forEach(iterator, value => result.push(value));
|
|
return result;
|
|
}
|
|
}
|
|
|
|
export type ISequence<T> = Iterator<T> | T[];
|
|
|
|
export function getSequenceIterator<T>(arg: Iterator<T> | T[]): Iterator<T> {
|
|
if (Array.isArray(arg)) {
|
|
return Iterator.fromArray(arg);
|
|
} else {
|
|
return arg;
|
|
}
|
|
}
|
|
|
|
export interface INextIterator<T> {
|
|
next(): T | null;
|
|
}
|
|
|
|
export class ArrayIterator<T> implements INextIterator<T> {
|
|
|
|
private items: T[];
|
|
protected start: number;
|
|
protected end: number;
|
|
protected index: number;
|
|
|
|
constructor(items: T[], start: number = 0, end: number = items.length, index = start - 1) {
|
|
this.items = items;
|
|
this.start = start;
|
|
this.end = end;
|
|
this.index = index;
|
|
}
|
|
|
|
public first(): T | null {
|
|
this.index = this.start;
|
|
return this.current();
|
|
}
|
|
|
|
public next(): T | null {
|
|
this.index = Math.min(this.index + 1, this.end);
|
|
return this.current();
|
|
}
|
|
|
|
protected current(): T | null {
|
|
if (this.index === this.start - 1 || this.index === this.end) {
|
|
return null;
|
|
}
|
|
|
|
return this.items[this.index];
|
|
}
|
|
}
|
|
|
|
export class ArrayNavigator<T> extends ArrayIterator<T> implements INavigator<T> {
|
|
|
|
constructor(items: T[], start: number = 0, end: number = items.length, index = start - 1) {
|
|
super(items, start, end, index);
|
|
}
|
|
|
|
public current(): T | null {
|
|
return super.current();
|
|
}
|
|
|
|
public previous(): T | null {
|
|
this.index = Math.max(this.index - 1, this.start - 1);
|
|
return this.current();
|
|
}
|
|
|
|
public first(): T | null {
|
|
this.index = this.start;
|
|
return this.current();
|
|
}
|
|
|
|
public last(): T | null {
|
|
this.index = this.end - 1;
|
|
return this.current();
|
|
}
|
|
|
|
public parent(): T | null {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export class MappedIterator<T, R> implements INextIterator<R> {
|
|
|
|
constructor(protected iterator: INextIterator<T>, protected fn: (item: T | null) => R) {
|
|
// noop
|
|
}
|
|
|
|
next() { return this.fn(this.iterator.next()); }
|
|
}
|
|
|
|
export interface INavigator<T> extends INextIterator<T> {
|
|
current(): T | null;
|
|
previous(): T | null;
|
|
parent(): T | null;
|
|
first(): T | null;
|
|
last(): T | null;
|
|
next(): T | null;
|
|
}
|
|
|
|
export class MappedNavigator<T, R> extends MappedIterator<T, R> implements INavigator<R> {
|
|
|
|
constructor(protected navigator: INavigator<T>, fn: (item: T) => R) {
|
|
super(navigator, fn);
|
|
}
|
|
|
|
current() { return this.fn(this.navigator.current()); }
|
|
previous() { return this.fn(this.navigator.previous()); }
|
|
parent() { return this.fn(this.navigator.parent()); }
|
|
first() { return this.fn(this.navigator.first()); }
|
|
last() { return this.fn(this.navigator.last()); }
|
|
next() { return this.fn(this.navigator.next()); }
|
|
}
|