recursiveHash method
Hash function that works correctly with nested lists and maps.
Implementation
int recursiveHash() {
int result = 0;
var toDo = <Value?>[];
var visited = <Value?>{};
toDo.add(this);
while (toDo.isNotEmpty) {
final item = toDo.removeLast();
visited.add(item);
if (item is ValList) {
result = _rotateBits(result) ^ item.values.length.hashCode;
for (int i = item.values.length - 1; i >= 0; i--) {
final child = item.values[i]!;
if (!(child is ValList || child is ValMap) ||
!visited.contains(child)) {
toDo.add(child);
}
}
} else if (item is ValMap) {
result = _rotateBits(result) ^ item.map.length.hashCode;
for (var kv in item.map.entries) {
if (!(kv.key is ValList || kv.key is ValMap) ||
!visited.contains(kv.key)) {
toDo.add(kv.key);
}
if (!(kv.value is ValList || kv.value is ValMap) ||
!visited.contains(kv.value)) {
toDo.add(kv.value);
}
}
} else {
// Anything else, we can safely use the standard hash method
result = _rotateBits(result) ^ (item == null ? 0 : item.hash());
}
}
return result;
}