Skip to content

Instantly share code, notes, and snippets.

@Geokureli
Last active July 7, 2023 15:53
Show Gist options
  • Save Geokureli/ca54e1b0afc3a69d645eefb58fe57a90 to your computer and use it in GitHub Desktop.
Save Geokureli/ca54e1b0afc3a69d645eefb58fe57a90 to your computer and use it in GitHub Desktop.
typedef JsonMapRaw<T> =
{
var keys:Array<String>;
var values:Array<T>;
}
/**
* A list of keys and values, used to serialize maps, usually for JSON or external saving.
* Note: Not meant to replace maps in any way, only meant for converting to and from json.
*/
abstract JsonMap<T>(JsonMapRaw<T>) from JsonMapRaw<T>
{
public function new (?keys:Array<String>, ?values:Array<T>)
{
if (keys == null)
keys = [];
if (values == null)
values = [];
this = { keys:keys, values:values };
}
@:arrayAccess
public function set(key:String, value:T):T
{
var index = this.keys.indexOf(key);
if (index == -1)
index = this.keys.push(key) - 1;
return this.values[index] = value;
}
/**
* Retrieves the value with the specified key. If no key exists, `null` is returned.
*/
@:arrayAccess
public function get(key:String):Null<T>
{
final index = this.keys.indexOf(key);
return index == -1 ? null : this.values[index];
}
/**
* Retrieves the value with the specified key without checking if the key exists.
*/
public function getUnsafe(key:String):T
{
return this.values[this.keys.indexOf(key)];
}
/**
* Simply adds the key and value, does NOT check that the key is new.
* @param key
* @param value
*/
public function addUnsafe(key:String, value:T)
{
this.keys.push(key);
this.values.push(value);
}
public function exists(key:String):Bool
{
return this.keys.contains(key);
}
public function iterator()
{
return this.values.iterator();
}
public function keys()
{
return this.keys.iterator();
}
public function keyValueIterator():KeyValueIterator<String, T>
{
return new JsonMapKeyValueIterator(this);
// JsonMapKeyValueIterator<JsonMap.T> should be KeyValueIterator<String, JsonMap.T>
}
public function toString()
{
var result = "";
var first = true;
for (key=>value in keyValueIterator())
{
if (!first)
result += ', ';
first = false;
result += '"$key" => $value';
}
}
public function toMap(?map:Map<String, T>)
{
if (map == null)
map = [];
for (key=>value in keyValueIterator())
map.set(key, value);
return map;
}
static public function fromMap<T>(map:Map<String, T>)
{
final result = new JsonMap<T>();
for (key=>value in map)
result.addUnsafe(key, value);
return result;
}
}
class JsonMapKeyValueIterator<T>
{
final map:JsonMapRaw<T>;
var index:Int;
inline public function new(map:JsonMap<T>)
{
this.map = cast map;
this.index = 0;
}
inline public function hasNext()
{
return map.keys.length > index;
}
inline public function next()
{
final i = index++;
return { key:map.keys[i], value:map.values[i] };
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment