recursiveHash method

int recursiveHash()

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;
}