// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

part of protobuf;

// TODO(antonm): reconsider later if PbList should take care of equality.
bool _deepEquals(lhs, rhs) {
  // Some GeneratedMessages implement Map, so test this first.
  if (lhs is GeneratedMessage) return lhs == rhs;
  if (rhs is GeneratedMessage) return false;
  if ((lhs is List) && (rhs is List)) return _areListsEqual(lhs, rhs);
  if ((lhs is Map) && (rhs is Map)) return _areMapsEqual(lhs, rhs);
  if ((lhs is ByteData) && (rhs is ByteData)) {
    return _areByteDataEqual(lhs, rhs);
  }
  return lhs == rhs;
}

bool _areListsEqual(List lhs, List rhs) {
  if (lhs.length != rhs.length) return false;
  for (var i = 0; i < lhs.length; i++) {
    if (!_deepEquals(lhs[i], rhs[i])) return false;
  }
  return true;
}

bool _areMapsEqual(Map lhs, Map rhs) {
  if (lhs.length != rhs.length) return false;
  return lhs.keys.every((key) => _deepEquals(lhs[key], rhs[key]));
}

bool _areByteDataEqual(ByteData lhs, ByteData rhs) {
  Uint8List asBytes(d) =>
      Uint8List.view(d.buffer, d.offsetInBytes, d.lengthInBytes);
  return _areListsEqual(asBytes(lhs), asBytes(rhs));
}

@Deprecated('This function was not intended to be public. '
    'It will be removed from the public api in next major version. ')
List<T> sorted<T>(Iterable<T> list) => List.from(list)..sort();

List<T> _sorted<T>(Iterable<T> list) => List.from(list)..sort();

class _HashUtils {
// Jenkins hash functions copied from https://github.com/google/quiver-dart/blob/master/lib/src/core/hash.dart.

  static int _combine(int hash, int value) {
    hash = 0x1fffffff & (hash + value);
    hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
    return hash ^ (hash >> 6);
  }

  static int _finish(int hash) {
    hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
    hash = hash ^ (hash >> 11);
    return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
  }

  /// Generates a hash code for multiple [objects].
  static int _hashObjects(Iterable objects) =>
      _finish(objects.fold(0, (h, i) => _combine(h, i.hashCode)));

  /// Generates a hash code for two objects.
  static int _hash2(a, b) =>
      _finish(_combine(_combine(0, a.hashCode), b.hashCode));
}
