17e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# Protocol Buffers - Google's data interchange format
27e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# Copyright 2008 Google Inc.  All rights reserved.
37e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# http://code.google.com/p/protobuf/
47e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang#
57e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# Redistribution and use in source and binary forms, with or without
67e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# modification, are permitted provided that the following conditions are
77e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# met:
87e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang#
97e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang#     * Redistributions of source code must retain the above copyright
107e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# notice, this list of conditions and the following disclaimer.
117e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang#     * Redistributions in binary form must reproduce the above
127e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# copyright notice, this list of conditions and the following disclaimer
137e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# in the documentation and/or other materials provided with the
147e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# distribution.
157e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang#     * Neither the name of Google Inc. nor the names of its
167e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# contributors may be used to endorse or promote products derived from
177e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# this software without specific prior written permission.
187e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang#
197e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
207e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
217e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
227e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
237e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
247e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
257e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
267e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
277e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
287e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
297e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
307e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
317e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang"""Contains container classes to represent different protocol buffer types.
327e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
337e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing WangThis file defines container classes which represent categories of protocol
347e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangbuffer field types which need extra maintenance. Currently these categories
357e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangare:
367e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  - Repeated scalar fields - These are all repeated fields which aren't
377e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    composite (e.g. they are of simple types like int32, string, etc).
387e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  - Repeated composite fields - Repeated fields which are composite. This
397e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    includes groups and nested messages.
407e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang"""
417e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
427e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang__author__ = 'petar@google.com (Petar Petrov)'
437e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
447e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
457e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangclass BaseContainer(object):
467e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
477e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  """Base container class."""
487e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
497e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  # Minimizes memory usage and disallows assignment to other attributes.
507e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  __slots__ = ['_message_listener', '_values']
517e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
527e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def __init__(self, message_listener):
537e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """
547e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    Args:
557e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      message_listener: A MessageListener implementation.
567e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang        The RepeatedScalarFieldContainer will call this object's
577e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang        Modified() method when it is modified.
587e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """
597e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    self._message_listener = message_listener
607e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    self._values = []
617e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
627e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def __getitem__(self, key):
637e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """Retrieves item by the specified key."""
647e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    return self._values[key]
657e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
667e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def __len__(self):
677e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """Returns the number of elements in the container."""
687e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    return len(self._values)
697e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
707e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def __ne__(self, other):
717e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """Checks if another instance isn't equal to this one."""
727e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    # The concrete classes should define __eq__.
737e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    return not self == other
747e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
757e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def __hash__(self):
767e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    raise TypeError('unhashable object')
777e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
787e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def __repr__(self):
797e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    return repr(self._values)
807e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
817e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def sort(self, *args, **kwargs):
827e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    # Continue to support the old sort_function keyword argument.
837e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    # This is expected to be a rare occurrence, so use LBYL to avoid
847e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    # the overhead of actually catching KeyError.
857e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    if 'sort_function' in kwargs:
867e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      kwargs['cmp'] = kwargs.pop('sort_function')
877e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    self._values.sort(*args, **kwargs)
887e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
897e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
907e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangclass RepeatedScalarFieldContainer(BaseContainer):
917e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
927e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  """Simple, type-checked, list-like container for holding repeated scalars."""
937e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
947e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  # Disallows assignment to other attributes.
957e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  __slots__ = ['_type_checker']
967e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
977e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def __init__(self, message_listener, type_checker):
987e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """
997e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    Args:
1007e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      message_listener: A MessageListener implementation.
1017e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang        The RepeatedScalarFieldContainer will call this object's
1027e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang        Modified() method when it is modified.
1037e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      type_checker: A type_checkers.ValueChecker instance to run on elements
1047e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang        inserted into this container.
1057e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """
1067e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    super(RepeatedScalarFieldContainer, self).__init__(message_listener)
1077e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    self._type_checker = type_checker
1087e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1097e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def append(self, value):
1107e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """Appends an item to the list. Similar to list.append()."""
1117e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    self._type_checker.CheckValue(value)
1127e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    self._values.append(value)
1137e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    if not self._message_listener.dirty:
1147e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      self._message_listener.Modified()
1157e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1167e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def insert(self, key, value):
1177e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """Inserts the item at the specified position. Similar to list.insert()."""
1187e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    self._type_checker.CheckValue(value)
1197e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    self._values.insert(key, value)
1207e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    if not self._message_listener.dirty:
1217e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      self._message_listener.Modified()
1227e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1237e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def extend(self, elem_seq):
1247e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """Extends by appending the given sequence. Similar to list.extend()."""
1257e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    if not elem_seq:
1267e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      return
1277e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1287e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    new_values = []
1297e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    for elem in elem_seq:
1307e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      self._type_checker.CheckValue(elem)
1317e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      new_values.append(elem)
1327e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    self._values.extend(new_values)
1337e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    self._message_listener.Modified()
1347e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1357e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def MergeFrom(self, other):
1367e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """Appends the contents of another repeated field of the same type to this
1377e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    one. We do not check the types of the individual fields.
1387e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """
1397e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    self._values.extend(other._values)
1407e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    self._message_listener.Modified()
1417e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1427e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def remove(self, elem):
1437e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """Removes an item from the list. Similar to list.remove()."""
1447e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    self._values.remove(elem)
1457e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    self._message_listener.Modified()
1467e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1477e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def __setitem__(self, key, value):
1487e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """Sets the item on the specified position."""
1497e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    self._type_checker.CheckValue(value)
1507e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    self._values[key] = value
1517e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    self._message_listener.Modified()
1527e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1537e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def __getslice__(self, start, stop):
1547e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """Retrieves the subset of items from between the specified indices."""
1557e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    return self._values[start:stop]
1567e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1577e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def __setslice__(self, start, stop, values):
1587e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """Sets the subset of items from between the specified indices."""
1597e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    new_values = []
1607e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    for value in values:
1617e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      self._type_checker.CheckValue(value)
1627e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      new_values.append(value)
1637e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    self._values[start:stop] = new_values
1647e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    self._message_listener.Modified()
1657e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1667e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def __delitem__(self, key):
1677e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """Deletes the item at the specified position."""
1687e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    del self._values[key]
1697e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    self._message_listener.Modified()
1707e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1717e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def __delslice__(self, start, stop):
1727e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """Deletes the subset of items from between the specified indices."""
1737e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    del self._values[start:stop]
1747e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    self._message_listener.Modified()
1757e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1767e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def __eq__(self, other):
1777e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """Compares the current instance with another one."""
1787e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    if self is other:
1797e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      return True
1807e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    # Special case for the same type which should be common and fast.
1817e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    if isinstance(other, self.__class__):
1827e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      return other._values == self._values
1837e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    # We are presumably comparing against some other sequence type.
1847e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    return other == self._values
1857e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1867e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1877e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangclass RepeatedCompositeFieldContainer(BaseContainer):
1887e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1897e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  """Simple, list-like container for holding repeated composite fields."""
1907e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1917e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  # Disallows assignment to other attributes.
1927e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  __slots__ = ['_message_descriptor']
1937e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1947e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def __init__(self, message_listener, message_descriptor):
1957e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """
1967e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    Note that we pass in a descriptor instead of the generated directly,
1977e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    since at the time we construct a _RepeatedCompositeFieldContainer we
1987e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    haven't yet necessarily initialized the type that will be contained in the
1997e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    container.
2007e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
2017e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    Args:
2027e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      message_listener: A MessageListener implementation.
2037e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang        The RepeatedCompositeFieldContainer will call this object's
2047e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang        Modified() method when it is modified.
2057e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      message_descriptor: A Descriptor instance describing the protocol type
2067e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang        that should be present in this container.  We'll use the
2077e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang        _concrete_class field of this descriptor when the client calls add().
2087e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """
2097e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    super(RepeatedCompositeFieldContainer, self).__init__(message_listener)
2107e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    self._message_descriptor = message_descriptor
2117e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
2127e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def add(self, **kwargs):
2137e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """Adds a new element at the end of the list and returns it. Keyword
2147e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    arguments may be used to initialize the element.
2157e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """
2167e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    new_element = self._message_descriptor._concrete_class(**kwargs)
2177e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    new_element._SetListener(self._message_listener)
2187e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    self._values.append(new_element)
2197e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    if not self._message_listener.dirty:
2207e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      self._message_listener.Modified()
2217e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    return new_element
2227e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
2237e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def extend(self, elem_seq):
2247e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """Extends by appending the given sequence of elements of the same type
2257e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    as this one, copying each individual message.
2267e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """
2277e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    message_class = self._message_descriptor._concrete_class
2287e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    listener = self._message_listener
2297e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    values = self._values
2307e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    for message in elem_seq:
2317e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      new_element = message_class()
2327e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      new_element._SetListener(listener)
2337e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      new_element.MergeFrom(message)
2347e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      values.append(new_element)
2357e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    listener.Modified()
2367e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
2377e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def MergeFrom(self, other):
2387e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """Appends the contents of another repeated field of the same type to this
2397e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    one, copying each individual message.
2407e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """
2417e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    self.extend(other._values)
2427e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
2437e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def remove(self, elem):
2447e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """Removes an item from the list. Similar to list.remove()."""
2457e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    self._values.remove(elem)
2467e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    self._message_listener.Modified()
2477e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
2487e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def __getslice__(self, start, stop):
2497e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """Retrieves the subset of items from between the specified indices."""
2507e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    return self._values[start:stop]
2517e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
2527e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def __delitem__(self, key):
2537e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """Deletes the item at the specified position."""
2547e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    del self._values[key]
2557e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    self._message_listener.Modified()
2567e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
2577e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def __delslice__(self, start, stop):
2587e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """Deletes the subset of items from between the specified indices."""
2597e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    del self._values[start:stop]
2607e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    self._message_listener.Modified()
2617e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
2627e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def __eq__(self, other):
2637e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """Compares the current instance with another one."""
2647e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    if self is other:
2657e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      return True
2667e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    if not isinstance(other, self.__class__):
2677e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      raise TypeError('Can only compare repeated composite fields against '
2687e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang                      'other repeated composite fields.')
2697e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    return self._values == other._values
270