git » sdk » omemo » tree

[omemo] / snikket / Map.js.hx

package snikket;

import haxe.Constraints.IMap;
import js.lib.HaxeIterator;
import js.lib.Map as NativeMap;
using Lambda;

// Use ES6 maps instead of Haxe maps
@:forward
abstract Map<K,V>(NativeMap<K,V>) {
	public inline function set(k:K, v:V):Void {
		this.set(k, v);
	}

	public inline function get(k:K):Null<V> {
		return this.get(k);
	}

	public inline function exists(k:K):Bool {
		return this.has(k);
	}

	public inline function remove(k:K):Bool {
		return this.delete(k);
	}

	public inline function keys():Iterator<K> {
		return new HaxeIterator(this.keys());
	}

	public inline function iterator():Iterator<V> {
		return new HaxeIterator(this.values());
	}

	public inline function keyValueIterator():KeyValueIterator<K, V> {
		return new HaxeKVIterator(this.entries());
	}

	// This shouldn't be needed but complier wants it...
	public inline function flatMap<B>(f:(item:V)->Iterable<B>): Array<B> {
		return { iterator: () -> this.iterator() }.flatMap(f);
	}

	@:arrayAccess @:noCompletion public inline function arrayRead(k:K) {
		return this.get(k);
	}

	@:arrayAccess @:noCompletion public inline function arrayWrite(k:K, v:V):V {
		this.set(k, v);
		return v;
	}

	@:from static function fromMap<K,V>(map:haxe.ds.Map<K,V>):Map<K, V> {
		final result = new NativeMap();
		for (k => v in map) {
			result.set(k, v);
		}
		return cast result;
	}

	@:from static inline function fromArray<K,V>(iterable:Iterable<js.lib.KeyValue<K,V>>):Map<K, V> {
		return cast new NativeMap(iterable);
	}
}

class HaxeKVIterator<K,V> {
	final jsIterator: js.lib.Iterator<js.lib.KeyValue<K,V>>;
	var lastStep: js.lib.Iterator.IteratorStep<js.lib.KeyValue<K,V>>;

	public inline function new(jsIterator: js.lib.Iterator<js.lib.KeyValue<K,V>>) {
		this.jsIterator = jsIterator;
		lastStep = jsIterator.next();
	}

	public inline function hasNext(): Bool {
		return !lastStep.done;
	}

	public inline function next(): { key: K, value: V } {
		var v = lastStep.value;
		lastStep = jsIterator.next();
		return { key: v.key, value: v.value };
	}
}