@rimbu/bimap
Version:
A bidirectional immutable Map of keys and values for TypeScript
110 lines (91 loc) • 2.95 kB
text/typescript
import {
BiMapBuilder,
BiMapEmpty,
BiMapNonEmptyImpl,
} from '@rimbu/bimap/custom';
import type { BiMap } from '@rimbu/bimap';
import type { RMap } from '@rimbu/collection-types/map';
import type { ArrayNonEmpty } from '@rimbu/common';
import { Reducer, type StreamSource } from '@rimbu/stream';
import { isEmptyStreamSourceInstance } from '@rimbu/stream/custom';
export class BiMapContext<UK, UV, Tp extends BiMap.Types = BiMap.Types>
implements BiMap.Context<UK, UV>
{
constructor(
readonly keyValueContext: RMap.Context<UK>,
readonly valueKeyContext: RMap.Context<UV>
) {}
get typeTag(): 'BiMap' {
return 'BiMap';
}
get _types(): Tp {
return undefined as any;
}
readonly _empty: BiMap<any, any> = Object.freeze(
new BiMapEmpty<any, any>(this)
);
readonly empty = <K extends UK, V extends UV>(): BiMap<K, V> => {
return this._empty;
};
readonly of: any = <K, V>(
...entries: ArrayNonEmpty<readonly [K, V]>
): [K, V] extends [UK, UV] ? BiMap.NonEmpty<K, V> : never => {
return this.from(entries);
};
readonly from = <K, V>(
...sources: ArrayNonEmpty<StreamSource<readonly [K, V]>>
): [K, V] extends [UK, UV] ? BiMap<K, V> | any : never => {
if (sources.length === 1) {
const source = sources[0];
if (source instanceof BiMapNonEmptyImpl && source.context === this)
return source as any;
}
let builder: BiMap.Builder<K, V> = this.builder() as any;
let i = -1;
const length = sources.length;
while (++i < length) {
const source = sources[i];
if (isEmptyStreamSourceInstance(source)) continue;
if (
builder.isEmpty &&
source instanceof BiMapNonEmptyImpl &&
source.context === this
) {
if (i === length - 1) return source as any;
builder = source.toBuilder();
continue;
}
builder.addEntries(source);
}
return builder.build() as any;
};
readonly builder = <K extends UK, V extends UV>(): BiMap.Builder<K, V> => {
return new BiMapBuilder(this as unknown as BiMapContext<K, V>);
};
readonly reducer = <K extends UK, V extends UV>(
source?: StreamSource<readonly [K, V]>
): Reducer<readonly [K, V], BiMap<K, V>> => {
return Reducer.create(
() =>
undefined === source
? this.builder<K, V>()
: (this.from(source) as BiMap<K, V>).toBuilder(),
(builder, entry) => {
builder.addEntry(entry);
return builder;
},
(builder) => builder.build()
);
};
createNonEmptyImpl<K extends UK, V extends UV>(
keyValueMap: RMap.NonEmpty<K, V>,
valueKeyMap: RMap.NonEmpty<V, K>
): BiMapNonEmptyImpl<K, V> {
return new BiMapNonEmptyImpl(this as any, keyValueMap, valueKeyMap);
}
createBuilder<K extends UK, V extends UV>(
source?: BiMapNonEmptyImpl<K, V>
): BiMapBuilder<K, V> {
return new BiMapBuilder(this as any, source);
}
}