| # Copyright (C) 2020 Google LLC |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| r"""Utility class for handling protobuf message.""" |
| |
| from __future__ import absolute_import |
| from __future__ import division |
| from __future__ import print_function |
| from google.protobuf import descriptor |
| from six.moves import xrange # pylint:disable=redefined-builtin |
| |
| |
| def NormalizeRepeatedFields(protobuf_message): |
| """Sorts all repeated fields and removes duplicates. |
| |
| Modifies pb in place. |
| |
| Args: |
| protobuf_message: The Message object to normalize. |
| |
| Returns: |
| protobuf_message, modified in place. |
| """ |
| for desc, values in protobuf_message.ListFields(): |
| if desc.label is descriptor.FieldDescriptor.LABEL_REPEATED: |
| # Sort then de-dup |
| values.sort() |
| # De-dupe in place. Can't use set, etc. because messages aren't |
| # hashable. |
| for i in xrange(len(values) - 1, 0, -1): |
| if values[i] == values[i - 1]: |
| del values[i] |
| |
| return protobuf_message |
| |
| |
| def Proto2Equals(a, b): |
| """Tests if two proto2 objects are equal. |
| |
| Recurses into nested messages. Uses list (not set) semantics for comparing |
| repeated fields, ie duplicates and order matter. |
| |
| Returns: |
| boolean |
| """ |
| return (a.SerializeToString(deterministic=True) |
| == b.SerializeToString(deterministic=True)) |