1# Copyright (C) 2020 Google LLC
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#      http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15r"""Utility class for handling protobuf message."""
16
17from __future__ import absolute_import
18from __future__ import division
19from __future__ import print_function
20from google.protobuf import descriptor
21from six.moves import xrange  # pylint:disable=redefined-builtin
22
23
24def NormalizeRepeatedFields(protobuf_message):
25  """Sorts all repeated fields and removes duplicates.
26
27  Modifies pb in place.
28
29  Args:
30    protobuf_message: The Message object to normalize.
31
32  Returns:
33    protobuf_message, modified in place.
34  """
35  for desc, values in protobuf_message.ListFields():
36    if desc.label is descriptor.FieldDescriptor.LABEL_REPEATED:
37      # Sort then de-dup
38      values.sort()
39      # De-dupe in place. Can't use set, etc. because messages aren't
40      # hashable.
41      for i in xrange(len(values) - 1, 0, -1):
42        if values[i] == values[i - 1]:
43          del values[i]
44
45  return protobuf_message
46
47
48def Proto2Equals(a, b):
49  """Tests if two proto2 objects are equal.
50
51  Recurses into nested messages. Uses list (not set) semantics for comparing
52  repeated fields, ie duplicates and order matter.
53
54  Returns:
55    boolean
56  """
57  return (a.SerializeToString(deterministic=True)
58          == b.SerializeToString(deterministic=True))
59