import {Operator, Stream} from '../core'; const empty = {}; export class DropRepeatsOperator implements Operator { public type = 'dropRepeats'; public out: Stream = null; private v: T = empty; constructor(public fn: (x: T, y: T) => boolean, public ins: Stream) { } _start(out: Stream): void { this.out = out; this.ins._add(this); } _stop(): void { this.ins._remove(this); this.out = null; this.v = empty; } isEq(x: T, y: T) { return this.fn ? this.fn(x, y) : x === y; } _n(t: T) { const u = this.out; if (!u) return; const v = this.v; if (v === empty || !this.isEq(t, v)) { u._n(t); } this.v = t; } _e(err: any) { const u = this.out; if (!u) return; u._e(err); } _c() { const u = this.out; if (!u) return; u._c(); } } /** * Drops consecutive duplicate values in a stream. * * Marble diagram: * * ```text * --1--2--1--1--1--2--3--4--3--3| * dropRepeats * --1--2--1--------2--3--4--3---| * ``` * * Example: * * ```js * import dropRepeats from 'xstream/extra/dropRepeats' * * const stream = xs.of(1, 2, 1, 1, 1, 2, 3, 4, 3, 3) * .compose(dropRepeats()) * * stream.addListener({ * next: i => console.log(i), * error: err => console.error(err), * complete: () => console.log('completed') * }) * ``` * * ```text * > 1 * > 2 * > 1 * > 2 * > 3 * > 4 * > 3 * > completed * ``` * * Example with a custom isEqual function: * * ```js * import dropRepeats from 'xstream/extra/dropRepeats' * * const stream = xs.of('a', 'b', 'a', 'A', 'B', 'b') * .compose(dropRepeats((x, y) => x.toLowerCase() === y.toLowerCase())) * * stream.addListener({ * next: i => console.log(i), * error: err => console.error(err), * complete: () => console.log('completed') * }) * ``` * * ```text * > a * > b * > a * > B * > completed * ``` * * @param {Function} isEqual An optional function of type * `(x: T, y: T) => boolean` that takes an event from the input stream and * checks if it is equal to previous event, by returning a boolean. * @return {Stream} */ export default function dropRepeats(isEqual: (x: T, y: T) => boolean = null): (ins: Stream) => Stream { return function dropRepeatsOperator(ins: Stream): Stream { return new Stream(new DropRepeatsOperator(isEqual, ins)); }; }