xref: /aosp_15_r20/external/protobuf/python/google/protobuf/internal/containers.py (revision 1b3f573f81763fcece89efc2b6a5209149e44ab8)
1*1b3f573fSAndroid Build Coastguard Worker# Protocol Buffers - Google's data interchange format
2*1b3f573fSAndroid Build Coastguard Worker# Copyright 2008 Google Inc.  All rights reserved.
3*1b3f573fSAndroid Build Coastguard Worker# https://developers.google.com/protocol-buffers/
4*1b3f573fSAndroid Build Coastguard Worker#
5*1b3f573fSAndroid Build Coastguard Worker# Redistribution and use in source and binary forms, with or without
6*1b3f573fSAndroid Build Coastguard Worker# modification, are permitted provided that the following conditions are
7*1b3f573fSAndroid Build Coastguard Worker# met:
8*1b3f573fSAndroid Build Coastguard Worker#
9*1b3f573fSAndroid Build Coastguard Worker#     * Redistributions of source code must retain the above copyright
10*1b3f573fSAndroid Build Coastguard Worker# notice, this list of conditions and the following disclaimer.
11*1b3f573fSAndroid Build Coastguard Worker#     * Redistributions in binary form must reproduce the above
12*1b3f573fSAndroid Build Coastguard Worker# copyright notice, this list of conditions and the following disclaimer
13*1b3f573fSAndroid Build Coastguard Worker# in the documentation and/or other materials provided with the
14*1b3f573fSAndroid Build Coastguard Worker# distribution.
15*1b3f573fSAndroid Build Coastguard Worker#     * Neither the name of Google Inc. nor the names of its
16*1b3f573fSAndroid Build Coastguard Worker# contributors may be used to endorse or promote products derived from
17*1b3f573fSAndroid Build Coastguard Worker# this software without specific prior written permission.
18*1b3f573fSAndroid Build Coastguard Worker#
19*1b3f573fSAndroid Build Coastguard Worker# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20*1b3f573fSAndroid Build Coastguard Worker# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21*1b3f573fSAndroid Build Coastguard Worker# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22*1b3f573fSAndroid Build Coastguard Worker# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23*1b3f573fSAndroid Build Coastguard Worker# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24*1b3f573fSAndroid Build Coastguard Worker# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25*1b3f573fSAndroid Build Coastguard Worker# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26*1b3f573fSAndroid Build Coastguard Worker# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27*1b3f573fSAndroid Build Coastguard Worker# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28*1b3f573fSAndroid Build Coastguard Worker# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29*1b3f573fSAndroid Build Coastguard Worker# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30*1b3f573fSAndroid Build Coastguard Worker
31*1b3f573fSAndroid Build Coastguard Worker"""Contains container classes to represent different protocol buffer types.
32*1b3f573fSAndroid Build Coastguard Worker
33*1b3f573fSAndroid Build Coastguard WorkerThis file defines container classes which represent categories of protocol
34*1b3f573fSAndroid Build Coastguard Workerbuffer field types which need extra maintenance. Currently these categories
35*1b3f573fSAndroid Build Coastguard Workerare:
36*1b3f573fSAndroid Build Coastguard Worker
37*1b3f573fSAndroid Build Coastguard Worker-   Repeated scalar fields - These are all repeated fields which aren't
38*1b3f573fSAndroid Build Coastguard Worker    composite (e.g. they are of simple types like int32, string, etc).
39*1b3f573fSAndroid Build Coastguard Worker-   Repeated composite fields - Repeated fields which are composite. This
40*1b3f573fSAndroid Build Coastguard Worker    includes groups and nested messages.
41*1b3f573fSAndroid Build Coastguard Worker"""
42*1b3f573fSAndroid Build Coastguard Worker
43*1b3f573fSAndroid Build Coastguard Workerimport collections.abc
44*1b3f573fSAndroid Build Coastguard Workerimport copy
45*1b3f573fSAndroid Build Coastguard Workerimport pickle
46*1b3f573fSAndroid Build Coastguard Workerfrom typing import (
47*1b3f573fSAndroid Build Coastguard Worker    Any,
48*1b3f573fSAndroid Build Coastguard Worker    Iterable,
49*1b3f573fSAndroid Build Coastguard Worker    Iterator,
50*1b3f573fSAndroid Build Coastguard Worker    List,
51*1b3f573fSAndroid Build Coastguard Worker    MutableMapping,
52*1b3f573fSAndroid Build Coastguard Worker    MutableSequence,
53*1b3f573fSAndroid Build Coastguard Worker    NoReturn,
54*1b3f573fSAndroid Build Coastguard Worker    Optional,
55*1b3f573fSAndroid Build Coastguard Worker    Sequence,
56*1b3f573fSAndroid Build Coastguard Worker    TypeVar,
57*1b3f573fSAndroid Build Coastguard Worker    Union,
58*1b3f573fSAndroid Build Coastguard Worker    overload,
59*1b3f573fSAndroid Build Coastguard Worker)
60*1b3f573fSAndroid Build Coastguard Worker
61*1b3f573fSAndroid Build Coastguard Worker
62*1b3f573fSAndroid Build Coastguard Worker_T = TypeVar('_T')
63*1b3f573fSAndroid Build Coastguard Worker_K = TypeVar('_K')
64*1b3f573fSAndroid Build Coastguard Worker_V = TypeVar('_V')
65*1b3f573fSAndroid Build Coastguard Worker
66*1b3f573fSAndroid Build Coastguard Worker
67*1b3f573fSAndroid Build Coastguard Workerclass BaseContainer(Sequence[_T]):
68*1b3f573fSAndroid Build Coastguard Worker  """Base container class."""
69*1b3f573fSAndroid Build Coastguard Worker
70*1b3f573fSAndroid Build Coastguard Worker  # Minimizes memory usage and disallows assignment to other attributes.
71*1b3f573fSAndroid Build Coastguard Worker  __slots__ = ['_message_listener', '_values']
72*1b3f573fSAndroid Build Coastguard Worker
73*1b3f573fSAndroid Build Coastguard Worker  def __init__(self, message_listener: Any) -> None:
74*1b3f573fSAndroid Build Coastguard Worker    """
75*1b3f573fSAndroid Build Coastguard Worker    Args:
76*1b3f573fSAndroid Build Coastguard Worker      message_listener: A MessageListener implementation.
77*1b3f573fSAndroid Build Coastguard Worker        The RepeatedScalarFieldContainer will call this object's
78*1b3f573fSAndroid Build Coastguard Worker        Modified() method when it is modified.
79*1b3f573fSAndroid Build Coastguard Worker    """
80*1b3f573fSAndroid Build Coastguard Worker    self._message_listener = message_listener
81*1b3f573fSAndroid Build Coastguard Worker    self._values = []
82*1b3f573fSAndroid Build Coastguard Worker
83*1b3f573fSAndroid Build Coastguard Worker  @overload
84*1b3f573fSAndroid Build Coastguard Worker  def __getitem__(self, key: int) -> _T:
85*1b3f573fSAndroid Build Coastguard Worker    ...
86*1b3f573fSAndroid Build Coastguard Worker
87*1b3f573fSAndroid Build Coastguard Worker  @overload
88*1b3f573fSAndroid Build Coastguard Worker  def __getitem__(self, key: slice) -> List[_T]:
89*1b3f573fSAndroid Build Coastguard Worker    ...
90*1b3f573fSAndroid Build Coastguard Worker
91*1b3f573fSAndroid Build Coastguard Worker  def __getitem__(self, key):
92*1b3f573fSAndroid Build Coastguard Worker    """Retrieves item by the specified key."""
93*1b3f573fSAndroid Build Coastguard Worker    return self._values[key]
94*1b3f573fSAndroid Build Coastguard Worker
95*1b3f573fSAndroid Build Coastguard Worker  def __len__(self) -> int:
96*1b3f573fSAndroid Build Coastguard Worker    """Returns the number of elements in the container."""
97*1b3f573fSAndroid Build Coastguard Worker    return len(self._values)
98*1b3f573fSAndroid Build Coastguard Worker
99*1b3f573fSAndroid Build Coastguard Worker  def __ne__(self, other: Any) -> bool:
100*1b3f573fSAndroid Build Coastguard Worker    """Checks if another instance isn't equal to this one."""
101*1b3f573fSAndroid Build Coastguard Worker    # The concrete classes should define __eq__.
102*1b3f573fSAndroid Build Coastguard Worker    return not self == other
103*1b3f573fSAndroid Build Coastguard Worker
104*1b3f573fSAndroid Build Coastguard Worker  __hash__ = None
105*1b3f573fSAndroid Build Coastguard Worker
106*1b3f573fSAndroid Build Coastguard Worker  def __repr__(self) -> str:
107*1b3f573fSAndroid Build Coastguard Worker    return repr(self._values)
108*1b3f573fSAndroid Build Coastguard Worker
109*1b3f573fSAndroid Build Coastguard Worker  def sort(self, *args, **kwargs) -> None:
110*1b3f573fSAndroid Build Coastguard Worker    # Continue to support the old sort_function keyword argument.
111*1b3f573fSAndroid Build Coastguard Worker    # This is expected to be a rare occurrence, so use LBYL to avoid
112*1b3f573fSAndroid Build Coastguard Worker    # the overhead of actually catching KeyError.
113*1b3f573fSAndroid Build Coastguard Worker    if 'sort_function' in kwargs:
114*1b3f573fSAndroid Build Coastguard Worker      kwargs['cmp'] = kwargs.pop('sort_function')
115*1b3f573fSAndroid Build Coastguard Worker    self._values.sort(*args, **kwargs)
116*1b3f573fSAndroid Build Coastguard Worker
117*1b3f573fSAndroid Build Coastguard Worker  def reverse(self) -> None:
118*1b3f573fSAndroid Build Coastguard Worker    self._values.reverse()
119*1b3f573fSAndroid Build Coastguard Worker
120*1b3f573fSAndroid Build Coastguard Worker
121*1b3f573fSAndroid Build Coastguard Worker# TODO(slebedev): Remove this. BaseContainer does *not* conform to
122*1b3f573fSAndroid Build Coastguard Worker# MutableSequence, only its subclasses do.
123*1b3f573fSAndroid Build Coastguard Workercollections.abc.MutableSequence.register(BaseContainer)
124*1b3f573fSAndroid Build Coastguard Worker
125*1b3f573fSAndroid Build Coastguard Worker
126*1b3f573fSAndroid Build Coastguard Workerclass RepeatedScalarFieldContainer(BaseContainer[_T], MutableSequence[_T]):
127*1b3f573fSAndroid Build Coastguard Worker  """Simple, type-checked, list-like container for holding repeated scalars."""
128*1b3f573fSAndroid Build Coastguard Worker
129*1b3f573fSAndroid Build Coastguard Worker  # Disallows assignment to other attributes.
130*1b3f573fSAndroid Build Coastguard Worker  __slots__ = ['_type_checker']
131*1b3f573fSAndroid Build Coastguard Worker
132*1b3f573fSAndroid Build Coastguard Worker  def __init__(
133*1b3f573fSAndroid Build Coastguard Worker      self,
134*1b3f573fSAndroid Build Coastguard Worker      message_listener: Any,
135*1b3f573fSAndroid Build Coastguard Worker      type_checker: Any,
136*1b3f573fSAndroid Build Coastguard Worker  ) -> None:
137*1b3f573fSAndroid Build Coastguard Worker    """Args:
138*1b3f573fSAndroid Build Coastguard Worker
139*1b3f573fSAndroid Build Coastguard Worker      message_listener: A MessageListener implementation. The
140*1b3f573fSAndroid Build Coastguard Worker      RepeatedScalarFieldContainer will call this object's Modified() method
141*1b3f573fSAndroid Build Coastguard Worker      when it is modified.
142*1b3f573fSAndroid Build Coastguard Worker      type_checker: A type_checkers.ValueChecker instance to run on elements
143*1b3f573fSAndroid Build Coastguard Worker      inserted into this container.
144*1b3f573fSAndroid Build Coastguard Worker    """
145*1b3f573fSAndroid Build Coastguard Worker    super().__init__(message_listener)
146*1b3f573fSAndroid Build Coastguard Worker    self._type_checker = type_checker
147*1b3f573fSAndroid Build Coastguard Worker
148*1b3f573fSAndroid Build Coastguard Worker  def append(self, value: _T) -> None:
149*1b3f573fSAndroid Build Coastguard Worker    """Appends an item to the list. Similar to list.append()."""
150*1b3f573fSAndroid Build Coastguard Worker    self._values.append(self._type_checker.CheckValue(value))
151*1b3f573fSAndroid Build Coastguard Worker    if not self._message_listener.dirty:
152*1b3f573fSAndroid Build Coastguard Worker      self._message_listener.Modified()
153*1b3f573fSAndroid Build Coastguard Worker
154*1b3f573fSAndroid Build Coastguard Worker  def insert(self, key: int, value: _T) -> None:
155*1b3f573fSAndroid Build Coastguard Worker    """Inserts the item at the specified position. Similar to list.insert()."""
156*1b3f573fSAndroid Build Coastguard Worker    self._values.insert(key, self._type_checker.CheckValue(value))
157*1b3f573fSAndroid Build Coastguard Worker    if not self._message_listener.dirty:
158*1b3f573fSAndroid Build Coastguard Worker      self._message_listener.Modified()
159*1b3f573fSAndroid Build Coastguard Worker
160*1b3f573fSAndroid Build Coastguard Worker  def extend(self, elem_seq: Iterable[_T]) -> None:
161*1b3f573fSAndroid Build Coastguard Worker    """Extends by appending the given iterable. Similar to list.extend()."""
162*1b3f573fSAndroid Build Coastguard Worker    if elem_seq is None:
163*1b3f573fSAndroid Build Coastguard Worker      return
164*1b3f573fSAndroid Build Coastguard Worker    try:
165*1b3f573fSAndroid Build Coastguard Worker      elem_seq_iter = iter(elem_seq)
166*1b3f573fSAndroid Build Coastguard Worker    except TypeError:
167*1b3f573fSAndroid Build Coastguard Worker      if not elem_seq:
168*1b3f573fSAndroid Build Coastguard Worker        # silently ignore falsy inputs :-/.
169*1b3f573fSAndroid Build Coastguard Worker        # TODO(ptucker): Deprecate this behavior. b/18413862
170*1b3f573fSAndroid Build Coastguard Worker        return
171*1b3f573fSAndroid Build Coastguard Worker      raise
172*1b3f573fSAndroid Build Coastguard Worker
173*1b3f573fSAndroid Build Coastguard Worker    new_values = [self._type_checker.CheckValue(elem) for elem in elem_seq_iter]
174*1b3f573fSAndroid Build Coastguard Worker    if new_values:
175*1b3f573fSAndroid Build Coastguard Worker      self._values.extend(new_values)
176*1b3f573fSAndroid Build Coastguard Worker    self._message_listener.Modified()
177*1b3f573fSAndroid Build Coastguard Worker
178*1b3f573fSAndroid Build Coastguard Worker  def MergeFrom(
179*1b3f573fSAndroid Build Coastguard Worker      self,
180*1b3f573fSAndroid Build Coastguard Worker      other: Union['RepeatedScalarFieldContainer[_T]', Iterable[_T]],
181*1b3f573fSAndroid Build Coastguard Worker  ) -> None:
182*1b3f573fSAndroid Build Coastguard Worker    """Appends the contents of another repeated field of the same type to this
183*1b3f573fSAndroid Build Coastguard Worker    one. We do not check the types of the individual fields.
184*1b3f573fSAndroid Build Coastguard Worker    """
185*1b3f573fSAndroid Build Coastguard Worker    self._values.extend(other)
186*1b3f573fSAndroid Build Coastguard Worker    self._message_listener.Modified()
187*1b3f573fSAndroid Build Coastguard Worker
188*1b3f573fSAndroid Build Coastguard Worker  def remove(self, elem: _T):
189*1b3f573fSAndroid Build Coastguard Worker    """Removes an item from the list. Similar to list.remove()."""
190*1b3f573fSAndroid Build Coastguard Worker    self._values.remove(elem)
191*1b3f573fSAndroid Build Coastguard Worker    self._message_listener.Modified()
192*1b3f573fSAndroid Build Coastguard Worker
193*1b3f573fSAndroid Build Coastguard Worker  def pop(self, key: Optional[int] = -1) -> _T:
194*1b3f573fSAndroid Build Coastguard Worker    """Removes and returns an item at a given index. Similar to list.pop()."""
195*1b3f573fSAndroid Build Coastguard Worker    value = self._values[key]
196*1b3f573fSAndroid Build Coastguard Worker    self.__delitem__(key)
197*1b3f573fSAndroid Build Coastguard Worker    return value
198*1b3f573fSAndroid Build Coastguard Worker
199*1b3f573fSAndroid Build Coastguard Worker  @overload
200*1b3f573fSAndroid Build Coastguard Worker  def __setitem__(self, key: int, value: _T) -> None:
201*1b3f573fSAndroid Build Coastguard Worker    ...
202*1b3f573fSAndroid Build Coastguard Worker
203*1b3f573fSAndroid Build Coastguard Worker  @overload
204*1b3f573fSAndroid Build Coastguard Worker  def __setitem__(self, key: slice, value: Iterable[_T]) -> None:
205*1b3f573fSAndroid Build Coastguard Worker    ...
206*1b3f573fSAndroid Build Coastguard Worker
207*1b3f573fSAndroid Build Coastguard Worker  def __setitem__(self, key, value) -> None:
208*1b3f573fSAndroid Build Coastguard Worker    """Sets the item on the specified position."""
209*1b3f573fSAndroid Build Coastguard Worker    if isinstance(key, slice):
210*1b3f573fSAndroid Build Coastguard Worker      if key.step is not None:
211*1b3f573fSAndroid Build Coastguard Worker        raise ValueError('Extended slices not supported')
212*1b3f573fSAndroid Build Coastguard Worker      self._values[key] = map(self._type_checker.CheckValue, value)
213*1b3f573fSAndroid Build Coastguard Worker      self._message_listener.Modified()
214*1b3f573fSAndroid Build Coastguard Worker    else:
215*1b3f573fSAndroid Build Coastguard Worker      self._values[key] = self._type_checker.CheckValue(value)
216*1b3f573fSAndroid Build Coastguard Worker      self._message_listener.Modified()
217*1b3f573fSAndroid Build Coastguard Worker
218*1b3f573fSAndroid Build Coastguard Worker  def __delitem__(self, key: Union[int, slice]) -> None:
219*1b3f573fSAndroid Build Coastguard Worker    """Deletes the item at the specified position."""
220*1b3f573fSAndroid Build Coastguard Worker    del self._values[key]
221*1b3f573fSAndroid Build Coastguard Worker    self._message_listener.Modified()
222*1b3f573fSAndroid Build Coastguard Worker
223*1b3f573fSAndroid Build Coastguard Worker  def __eq__(self, other: Any) -> bool:
224*1b3f573fSAndroid Build Coastguard Worker    """Compares the current instance with another one."""
225*1b3f573fSAndroid Build Coastguard Worker    if self is other:
226*1b3f573fSAndroid Build Coastguard Worker      return True
227*1b3f573fSAndroid Build Coastguard Worker    # Special case for the same type which should be common and fast.
228*1b3f573fSAndroid Build Coastguard Worker    if isinstance(other, self.__class__):
229*1b3f573fSAndroid Build Coastguard Worker      return other._values == self._values
230*1b3f573fSAndroid Build Coastguard Worker    # We are presumably comparing against some other sequence type.
231*1b3f573fSAndroid Build Coastguard Worker    return other == self._values
232*1b3f573fSAndroid Build Coastguard Worker
233*1b3f573fSAndroid Build Coastguard Worker  def __deepcopy__(
234*1b3f573fSAndroid Build Coastguard Worker      self,
235*1b3f573fSAndroid Build Coastguard Worker      unused_memo: Any = None,
236*1b3f573fSAndroid Build Coastguard Worker  ) -> 'RepeatedScalarFieldContainer[_T]':
237*1b3f573fSAndroid Build Coastguard Worker    clone = RepeatedScalarFieldContainer(
238*1b3f573fSAndroid Build Coastguard Worker        copy.deepcopy(self._message_listener), self._type_checker)
239*1b3f573fSAndroid Build Coastguard Worker    clone.MergeFrom(self)
240*1b3f573fSAndroid Build Coastguard Worker    return clone
241*1b3f573fSAndroid Build Coastguard Worker
242*1b3f573fSAndroid Build Coastguard Worker  def __reduce__(self, **kwargs) -> NoReturn:
243*1b3f573fSAndroid Build Coastguard Worker    raise pickle.PickleError(
244*1b3f573fSAndroid Build Coastguard Worker        "Can't pickle repeated scalar fields, convert to list first")
245*1b3f573fSAndroid Build Coastguard Worker
246*1b3f573fSAndroid Build Coastguard Worker
247*1b3f573fSAndroid Build Coastguard Worker# TODO(slebedev): Constrain T to be a subtype of Message.
248*1b3f573fSAndroid Build Coastguard Workerclass RepeatedCompositeFieldContainer(BaseContainer[_T], MutableSequence[_T]):
249*1b3f573fSAndroid Build Coastguard Worker  """Simple, list-like container for holding repeated composite fields."""
250*1b3f573fSAndroid Build Coastguard Worker
251*1b3f573fSAndroid Build Coastguard Worker  # Disallows assignment to other attributes.
252*1b3f573fSAndroid Build Coastguard Worker  __slots__ = ['_message_descriptor']
253*1b3f573fSAndroid Build Coastguard Worker
254*1b3f573fSAndroid Build Coastguard Worker  def __init__(self, message_listener: Any, message_descriptor: Any) -> None:
255*1b3f573fSAndroid Build Coastguard Worker    """
256*1b3f573fSAndroid Build Coastguard Worker    Note that we pass in a descriptor instead of the generated directly,
257*1b3f573fSAndroid Build Coastguard Worker    since at the time we construct a _RepeatedCompositeFieldContainer we
258*1b3f573fSAndroid Build Coastguard Worker    haven't yet necessarily initialized the type that will be contained in the
259*1b3f573fSAndroid Build Coastguard Worker    container.
260*1b3f573fSAndroid Build Coastguard Worker
261*1b3f573fSAndroid Build Coastguard Worker    Args:
262*1b3f573fSAndroid Build Coastguard Worker      message_listener: A MessageListener implementation.
263*1b3f573fSAndroid Build Coastguard Worker        The RepeatedCompositeFieldContainer will call this object's
264*1b3f573fSAndroid Build Coastguard Worker        Modified() method when it is modified.
265*1b3f573fSAndroid Build Coastguard Worker      message_descriptor: A Descriptor instance describing the protocol type
266*1b3f573fSAndroid Build Coastguard Worker        that should be present in this container.  We'll use the
267*1b3f573fSAndroid Build Coastguard Worker        _concrete_class field of this descriptor when the client calls add().
268*1b3f573fSAndroid Build Coastguard Worker    """
269*1b3f573fSAndroid Build Coastguard Worker    super().__init__(message_listener)
270*1b3f573fSAndroid Build Coastguard Worker    self._message_descriptor = message_descriptor
271*1b3f573fSAndroid Build Coastguard Worker
272*1b3f573fSAndroid Build Coastguard Worker  def add(self, **kwargs: Any) -> _T:
273*1b3f573fSAndroid Build Coastguard Worker    """Adds a new element at the end of the list and returns it. Keyword
274*1b3f573fSAndroid Build Coastguard Worker    arguments may be used to initialize the element.
275*1b3f573fSAndroid Build Coastguard Worker    """
276*1b3f573fSAndroid Build Coastguard Worker    new_element = self._message_descriptor._concrete_class(**kwargs)
277*1b3f573fSAndroid Build Coastguard Worker    new_element._SetListener(self._message_listener)
278*1b3f573fSAndroid Build Coastguard Worker    self._values.append(new_element)
279*1b3f573fSAndroid Build Coastguard Worker    if not self._message_listener.dirty:
280*1b3f573fSAndroid Build Coastguard Worker      self._message_listener.Modified()
281*1b3f573fSAndroid Build Coastguard Worker    return new_element
282*1b3f573fSAndroid Build Coastguard Worker
283*1b3f573fSAndroid Build Coastguard Worker  def append(self, value: _T) -> None:
284*1b3f573fSAndroid Build Coastguard Worker    """Appends one element by copying the message."""
285*1b3f573fSAndroid Build Coastguard Worker    new_element = self._message_descriptor._concrete_class()
286*1b3f573fSAndroid Build Coastguard Worker    new_element._SetListener(self._message_listener)
287*1b3f573fSAndroid Build Coastguard Worker    new_element.CopyFrom(value)
288*1b3f573fSAndroid Build Coastguard Worker    self._values.append(new_element)
289*1b3f573fSAndroid Build Coastguard Worker    if not self._message_listener.dirty:
290*1b3f573fSAndroid Build Coastguard Worker      self._message_listener.Modified()
291*1b3f573fSAndroid Build Coastguard Worker
292*1b3f573fSAndroid Build Coastguard Worker  def insert(self, key: int, value: _T) -> None:
293*1b3f573fSAndroid Build Coastguard Worker    """Inserts the item at the specified position by copying."""
294*1b3f573fSAndroid Build Coastguard Worker    new_element = self._message_descriptor._concrete_class()
295*1b3f573fSAndroid Build Coastguard Worker    new_element._SetListener(self._message_listener)
296*1b3f573fSAndroid Build Coastguard Worker    new_element.CopyFrom(value)
297*1b3f573fSAndroid Build Coastguard Worker    self._values.insert(key, new_element)
298*1b3f573fSAndroid Build Coastguard Worker    if not self._message_listener.dirty:
299*1b3f573fSAndroid Build Coastguard Worker      self._message_listener.Modified()
300*1b3f573fSAndroid Build Coastguard Worker
301*1b3f573fSAndroid Build Coastguard Worker  def extend(self, elem_seq: Iterable[_T]) -> None:
302*1b3f573fSAndroid Build Coastguard Worker    """Extends by appending the given sequence of elements of the same type
303*1b3f573fSAndroid Build Coastguard Worker
304*1b3f573fSAndroid Build Coastguard Worker    as this one, copying each individual message.
305*1b3f573fSAndroid Build Coastguard Worker    """
306*1b3f573fSAndroid Build Coastguard Worker    message_class = self._message_descriptor._concrete_class
307*1b3f573fSAndroid Build Coastguard Worker    listener = self._message_listener
308*1b3f573fSAndroid Build Coastguard Worker    values = self._values
309*1b3f573fSAndroid Build Coastguard Worker    for message in elem_seq:
310*1b3f573fSAndroid Build Coastguard Worker      new_element = message_class()
311*1b3f573fSAndroid Build Coastguard Worker      new_element._SetListener(listener)
312*1b3f573fSAndroid Build Coastguard Worker      new_element.MergeFrom(message)
313*1b3f573fSAndroid Build Coastguard Worker      values.append(new_element)
314*1b3f573fSAndroid Build Coastguard Worker    listener.Modified()
315*1b3f573fSAndroid Build Coastguard Worker
316*1b3f573fSAndroid Build Coastguard Worker  def MergeFrom(
317*1b3f573fSAndroid Build Coastguard Worker      self,
318*1b3f573fSAndroid Build Coastguard Worker      other: Union['RepeatedCompositeFieldContainer[_T]', Iterable[_T]],
319*1b3f573fSAndroid Build Coastguard Worker  ) -> None:
320*1b3f573fSAndroid Build Coastguard Worker    """Appends the contents of another repeated field of the same type to this
321*1b3f573fSAndroid Build Coastguard Worker    one, copying each individual message.
322*1b3f573fSAndroid Build Coastguard Worker    """
323*1b3f573fSAndroid Build Coastguard Worker    self.extend(other)
324*1b3f573fSAndroid Build Coastguard Worker
325*1b3f573fSAndroid Build Coastguard Worker  def remove(self, elem: _T) -> None:
326*1b3f573fSAndroid Build Coastguard Worker    """Removes an item from the list. Similar to list.remove()."""
327*1b3f573fSAndroid Build Coastguard Worker    self._values.remove(elem)
328*1b3f573fSAndroid Build Coastguard Worker    self._message_listener.Modified()
329*1b3f573fSAndroid Build Coastguard Worker
330*1b3f573fSAndroid Build Coastguard Worker  def pop(self, key: Optional[int] = -1) -> _T:
331*1b3f573fSAndroid Build Coastguard Worker    """Removes and returns an item at a given index. Similar to list.pop()."""
332*1b3f573fSAndroid Build Coastguard Worker    value = self._values[key]
333*1b3f573fSAndroid Build Coastguard Worker    self.__delitem__(key)
334*1b3f573fSAndroid Build Coastguard Worker    return value
335*1b3f573fSAndroid Build Coastguard Worker
336*1b3f573fSAndroid Build Coastguard Worker  @overload
337*1b3f573fSAndroid Build Coastguard Worker  def __setitem__(self, key: int, value: _T) -> None:
338*1b3f573fSAndroid Build Coastguard Worker    ...
339*1b3f573fSAndroid Build Coastguard Worker
340*1b3f573fSAndroid Build Coastguard Worker  @overload
341*1b3f573fSAndroid Build Coastguard Worker  def __setitem__(self, key: slice, value: Iterable[_T]) -> None:
342*1b3f573fSAndroid Build Coastguard Worker    ...
343*1b3f573fSAndroid Build Coastguard Worker
344*1b3f573fSAndroid Build Coastguard Worker  def __setitem__(self, key, value):
345*1b3f573fSAndroid Build Coastguard Worker    # This method is implemented to make RepeatedCompositeFieldContainer
346*1b3f573fSAndroid Build Coastguard Worker    # structurally compatible with typing.MutableSequence. It is
347*1b3f573fSAndroid Build Coastguard Worker    # otherwise unsupported and will always raise an error.
348*1b3f573fSAndroid Build Coastguard Worker    raise TypeError(
349*1b3f573fSAndroid Build Coastguard Worker        f'{self.__class__.__name__} object does not support item assignment')
350*1b3f573fSAndroid Build Coastguard Worker
351*1b3f573fSAndroid Build Coastguard Worker  def __delitem__(self, key: Union[int, slice]) -> None:
352*1b3f573fSAndroid Build Coastguard Worker    """Deletes the item at the specified position."""
353*1b3f573fSAndroid Build Coastguard Worker    del self._values[key]
354*1b3f573fSAndroid Build Coastguard Worker    self._message_listener.Modified()
355*1b3f573fSAndroid Build Coastguard Worker
356*1b3f573fSAndroid Build Coastguard Worker  def __eq__(self, other: Any) -> bool:
357*1b3f573fSAndroid Build Coastguard Worker    """Compares the current instance with another one."""
358*1b3f573fSAndroid Build Coastguard Worker    if self is other:
359*1b3f573fSAndroid Build Coastguard Worker      return True
360*1b3f573fSAndroid Build Coastguard Worker    if not isinstance(other, self.__class__):
361*1b3f573fSAndroid Build Coastguard Worker      raise TypeError('Can only compare repeated composite fields against '
362*1b3f573fSAndroid Build Coastguard Worker                      'other repeated composite fields.')
363*1b3f573fSAndroid Build Coastguard Worker    return self._values == other._values
364*1b3f573fSAndroid Build Coastguard Worker
365*1b3f573fSAndroid Build Coastguard Worker
366*1b3f573fSAndroid Build Coastguard Workerclass ScalarMap(MutableMapping[_K, _V]):
367*1b3f573fSAndroid Build Coastguard Worker  """Simple, type-checked, dict-like container for holding repeated scalars."""
368*1b3f573fSAndroid Build Coastguard Worker
369*1b3f573fSAndroid Build Coastguard Worker  # Disallows assignment to other attributes.
370*1b3f573fSAndroid Build Coastguard Worker  __slots__ = ['_key_checker', '_value_checker', '_values', '_message_listener',
371*1b3f573fSAndroid Build Coastguard Worker               '_entry_descriptor']
372*1b3f573fSAndroid Build Coastguard Worker
373*1b3f573fSAndroid Build Coastguard Worker  def __init__(
374*1b3f573fSAndroid Build Coastguard Worker      self,
375*1b3f573fSAndroid Build Coastguard Worker      message_listener: Any,
376*1b3f573fSAndroid Build Coastguard Worker      key_checker: Any,
377*1b3f573fSAndroid Build Coastguard Worker      value_checker: Any,
378*1b3f573fSAndroid Build Coastguard Worker      entry_descriptor: Any,
379*1b3f573fSAndroid Build Coastguard Worker  ) -> None:
380*1b3f573fSAndroid Build Coastguard Worker    """
381*1b3f573fSAndroid Build Coastguard Worker    Args:
382*1b3f573fSAndroid Build Coastguard Worker      message_listener: A MessageListener implementation.
383*1b3f573fSAndroid Build Coastguard Worker        The ScalarMap will call this object's Modified() method when it
384*1b3f573fSAndroid Build Coastguard Worker        is modified.
385*1b3f573fSAndroid Build Coastguard Worker      key_checker: A type_checkers.ValueChecker instance to run on keys
386*1b3f573fSAndroid Build Coastguard Worker        inserted into this container.
387*1b3f573fSAndroid Build Coastguard Worker      value_checker: A type_checkers.ValueChecker instance to run on values
388*1b3f573fSAndroid Build Coastguard Worker        inserted into this container.
389*1b3f573fSAndroid Build Coastguard Worker      entry_descriptor: The MessageDescriptor of a map entry: key and value.
390*1b3f573fSAndroid Build Coastguard Worker    """
391*1b3f573fSAndroid Build Coastguard Worker    self._message_listener = message_listener
392*1b3f573fSAndroid Build Coastguard Worker    self._key_checker = key_checker
393*1b3f573fSAndroid Build Coastguard Worker    self._value_checker = value_checker
394*1b3f573fSAndroid Build Coastguard Worker    self._entry_descriptor = entry_descriptor
395*1b3f573fSAndroid Build Coastguard Worker    self._values = {}
396*1b3f573fSAndroid Build Coastguard Worker
397*1b3f573fSAndroid Build Coastguard Worker  def __getitem__(self, key: _K) -> _V:
398*1b3f573fSAndroid Build Coastguard Worker    try:
399*1b3f573fSAndroid Build Coastguard Worker      return self._values[key]
400*1b3f573fSAndroid Build Coastguard Worker    except KeyError:
401*1b3f573fSAndroid Build Coastguard Worker      key = self._key_checker.CheckValue(key)
402*1b3f573fSAndroid Build Coastguard Worker      val = self._value_checker.DefaultValue()
403*1b3f573fSAndroid Build Coastguard Worker      self._values[key] = val
404*1b3f573fSAndroid Build Coastguard Worker      return val
405*1b3f573fSAndroid Build Coastguard Worker
406*1b3f573fSAndroid Build Coastguard Worker  def __contains__(self, item: _K) -> bool:
407*1b3f573fSAndroid Build Coastguard Worker    # We check the key's type to match the strong-typing flavor of the API.
408*1b3f573fSAndroid Build Coastguard Worker    # Also this makes it easier to match the behavior of the C++ implementation.
409*1b3f573fSAndroid Build Coastguard Worker    self._key_checker.CheckValue(item)
410*1b3f573fSAndroid Build Coastguard Worker    return item in self._values
411*1b3f573fSAndroid Build Coastguard Worker
412*1b3f573fSAndroid Build Coastguard Worker  @overload
413*1b3f573fSAndroid Build Coastguard Worker  def get(self, key: _K) -> Optional[_V]:
414*1b3f573fSAndroid Build Coastguard Worker    ...
415*1b3f573fSAndroid Build Coastguard Worker
416*1b3f573fSAndroid Build Coastguard Worker  @overload
417*1b3f573fSAndroid Build Coastguard Worker  def get(self, key: _K, default: _T) -> Union[_V, _T]:
418*1b3f573fSAndroid Build Coastguard Worker    ...
419*1b3f573fSAndroid Build Coastguard Worker
420*1b3f573fSAndroid Build Coastguard Worker  # We need to override this explicitly, because our defaultdict-like behavior
421*1b3f573fSAndroid Build Coastguard Worker  # will make the default implementation (from our base class) always insert
422*1b3f573fSAndroid Build Coastguard Worker  # the key.
423*1b3f573fSAndroid Build Coastguard Worker  def get(self, key, default=None):
424*1b3f573fSAndroid Build Coastguard Worker    if key in self:
425*1b3f573fSAndroid Build Coastguard Worker      return self[key]
426*1b3f573fSAndroid Build Coastguard Worker    else:
427*1b3f573fSAndroid Build Coastguard Worker      return default
428*1b3f573fSAndroid Build Coastguard Worker
429*1b3f573fSAndroid Build Coastguard Worker  def __setitem__(self, key: _K, value: _V) -> _T:
430*1b3f573fSAndroid Build Coastguard Worker    checked_key = self._key_checker.CheckValue(key)
431*1b3f573fSAndroid Build Coastguard Worker    checked_value = self._value_checker.CheckValue(value)
432*1b3f573fSAndroid Build Coastguard Worker    self._values[checked_key] = checked_value
433*1b3f573fSAndroid Build Coastguard Worker    self._message_listener.Modified()
434*1b3f573fSAndroid Build Coastguard Worker
435*1b3f573fSAndroid Build Coastguard Worker  def __delitem__(self, key: _K) -> None:
436*1b3f573fSAndroid Build Coastguard Worker    del self._values[key]
437*1b3f573fSAndroid Build Coastguard Worker    self._message_listener.Modified()
438*1b3f573fSAndroid Build Coastguard Worker
439*1b3f573fSAndroid Build Coastguard Worker  def __len__(self) -> int:
440*1b3f573fSAndroid Build Coastguard Worker    return len(self._values)
441*1b3f573fSAndroid Build Coastguard Worker
442*1b3f573fSAndroid Build Coastguard Worker  def __iter__(self) -> Iterator[_K]:
443*1b3f573fSAndroid Build Coastguard Worker    return iter(self._values)
444*1b3f573fSAndroid Build Coastguard Worker
445*1b3f573fSAndroid Build Coastguard Worker  def __repr__(self) -> str:
446*1b3f573fSAndroid Build Coastguard Worker    return repr(self._values)
447*1b3f573fSAndroid Build Coastguard Worker
448*1b3f573fSAndroid Build Coastguard Worker  def MergeFrom(self, other: 'ScalarMap[_K, _V]') -> None:
449*1b3f573fSAndroid Build Coastguard Worker    self._values.update(other._values)
450*1b3f573fSAndroid Build Coastguard Worker    self._message_listener.Modified()
451*1b3f573fSAndroid Build Coastguard Worker
452*1b3f573fSAndroid Build Coastguard Worker  def InvalidateIterators(self) -> None:
453*1b3f573fSAndroid Build Coastguard Worker    # It appears that the only way to reliably invalidate iterators to
454*1b3f573fSAndroid Build Coastguard Worker    # self._values is to ensure that its size changes.
455*1b3f573fSAndroid Build Coastguard Worker    original = self._values
456*1b3f573fSAndroid Build Coastguard Worker    self._values = original.copy()
457*1b3f573fSAndroid Build Coastguard Worker    original[None] = None
458*1b3f573fSAndroid Build Coastguard Worker
459*1b3f573fSAndroid Build Coastguard Worker  # This is defined in the abstract base, but we can do it much more cheaply.
460*1b3f573fSAndroid Build Coastguard Worker  def clear(self) -> None:
461*1b3f573fSAndroid Build Coastguard Worker    self._values.clear()
462*1b3f573fSAndroid Build Coastguard Worker    self._message_listener.Modified()
463*1b3f573fSAndroid Build Coastguard Worker
464*1b3f573fSAndroid Build Coastguard Worker  def GetEntryClass(self) -> Any:
465*1b3f573fSAndroid Build Coastguard Worker    return self._entry_descriptor._concrete_class
466*1b3f573fSAndroid Build Coastguard Worker
467*1b3f573fSAndroid Build Coastguard Worker
468*1b3f573fSAndroid Build Coastguard Workerclass MessageMap(MutableMapping[_K, _V]):
469*1b3f573fSAndroid Build Coastguard Worker  """Simple, type-checked, dict-like container for with submessage values."""
470*1b3f573fSAndroid Build Coastguard Worker
471*1b3f573fSAndroid Build Coastguard Worker  # Disallows assignment to other attributes.
472*1b3f573fSAndroid Build Coastguard Worker  __slots__ = ['_key_checker', '_values', '_message_listener',
473*1b3f573fSAndroid Build Coastguard Worker               '_message_descriptor', '_entry_descriptor']
474*1b3f573fSAndroid Build Coastguard Worker
475*1b3f573fSAndroid Build Coastguard Worker  def __init__(
476*1b3f573fSAndroid Build Coastguard Worker      self,
477*1b3f573fSAndroid Build Coastguard Worker      message_listener: Any,
478*1b3f573fSAndroid Build Coastguard Worker      message_descriptor: Any,
479*1b3f573fSAndroid Build Coastguard Worker      key_checker: Any,
480*1b3f573fSAndroid Build Coastguard Worker      entry_descriptor: Any,
481*1b3f573fSAndroid Build Coastguard Worker  ) -> None:
482*1b3f573fSAndroid Build Coastguard Worker    """
483*1b3f573fSAndroid Build Coastguard Worker    Args:
484*1b3f573fSAndroid Build Coastguard Worker      message_listener: A MessageListener implementation.
485*1b3f573fSAndroid Build Coastguard Worker        The ScalarMap will call this object's Modified() method when it
486*1b3f573fSAndroid Build Coastguard Worker        is modified.
487*1b3f573fSAndroid Build Coastguard Worker      key_checker: A type_checkers.ValueChecker instance to run on keys
488*1b3f573fSAndroid Build Coastguard Worker        inserted into this container.
489*1b3f573fSAndroid Build Coastguard Worker      value_checker: A type_checkers.ValueChecker instance to run on values
490*1b3f573fSAndroid Build Coastguard Worker        inserted into this container.
491*1b3f573fSAndroid Build Coastguard Worker      entry_descriptor: The MessageDescriptor of a map entry: key and value.
492*1b3f573fSAndroid Build Coastguard Worker    """
493*1b3f573fSAndroid Build Coastguard Worker    self._message_listener = message_listener
494*1b3f573fSAndroid Build Coastguard Worker    self._message_descriptor = message_descriptor
495*1b3f573fSAndroid Build Coastguard Worker    self._key_checker = key_checker
496*1b3f573fSAndroid Build Coastguard Worker    self._entry_descriptor = entry_descriptor
497*1b3f573fSAndroid Build Coastguard Worker    self._values = {}
498*1b3f573fSAndroid Build Coastguard Worker
499*1b3f573fSAndroid Build Coastguard Worker  def __getitem__(self, key: _K) -> _V:
500*1b3f573fSAndroid Build Coastguard Worker    key = self._key_checker.CheckValue(key)
501*1b3f573fSAndroid Build Coastguard Worker    try:
502*1b3f573fSAndroid Build Coastguard Worker      return self._values[key]
503*1b3f573fSAndroid Build Coastguard Worker    except KeyError:
504*1b3f573fSAndroid Build Coastguard Worker      new_element = self._message_descriptor._concrete_class()
505*1b3f573fSAndroid Build Coastguard Worker      new_element._SetListener(self._message_listener)
506*1b3f573fSAndroid Build Coastguard Worker      self._values[key] = new_element
507*1b3f573fSAndroid Build Coastguard Worker      self._message_listener.Modified()
508*1b3f573fSAndroid Build Coastguard Worker      return new_element
509*1b3f573fSAndroid Build Coastguard Worker
510*1b3f573fSAndroid Build Coastguard Worker  def get_or_create(self, key: _K) -> _V:
511*1b3f573fSAndroid Build Coastguard Worker    """get_or_create() is an alias for getitem (ie. map[key]).
512*1b3f573fSAndroid Build Coastguard Worker
513*1b3f573fSAndroid Build Coastguard Worker    Args:
514*1b3f573fSAndroid Build Coastguard Worker      key: The key to get or create in the map.
515*1b3f573fSAndroid Build Coastguard Worker
516*1b3f573fSAndroid Build Coastguard Worker    This is useful in cases where you want to be explicit that the call is
517*1b3f573fSAndroid Build Coastguard Worker    mutating the map.  This can avoid lint errors for statements like this
518*1b3f573fSAndroid Build Coastguard Worker    that otherwise would appear to be pointless statements:
519*1b3f573fSAndroid Build Coastguard Worker
520*1b3f573fSAndroid Build Coastguard Worker      msg.my_map[key]
521*1b3f573fSAndroid Build Coastguard Worker    """
522*1b3f573fSAndroid Build Coastguard Worker    return self[key]
523*1b3f573fSAndroid Build Coastguard Worker
524*1b3f573fSAndroid Build Coastguard Worker  @overload
525*1b3f573fSAndroid Build Coastguard Worker  def get(self, key: _K) -> Optional[_V]:
526*1b3f573fSAndroid Build Coastguard Worker    ...
527*1b3f573fSAndroid Build Coastguard Worker
528*1b3f573fSAndroid Build Coastguard Worker  @overload
529*1b3f573fSAndroid Build Coastguard Worker  def get(self, key: _K, default: _T) -> Union[_V, _T]:
530*1b3f573fSAndroid Build Coastguard Worker    ...
531*1b3f573fSAndroid Build Coastguard Worker
532*1b3f573fSAndroid Build Coastguard Worker  # We need to override this explicitly, because our defaultdict-like behavior
533*1b3f573fSAndroid Build Coastguard Worker  # will make the default implementation (from our base class) always insert
534*1b3f573fSAndroid Build Coastguard Worker  # the key.
535*1b3f573fSAndroid Build Coastguard Worker  def get(self, key, default=None):
536*1b3f573fSAndroid Build Coastguard Worker    if key in self:
537*1b3f573fSAndroid Build Coastguard Worker      return self[key]
538*1b3f573fSAndroid Build Coastguard Worker    else:
539*1b3f573fSAndroid Build Coastguard Worker      return default
540*1b3f573fSAndroid Build Coastguard Worker
541*1b3f573fSAndroid Build Coastguard Worker  def __contains__(self, item: _K) -> bool:
542*1b3f573fSAndroid Build Coastguard Worker    item = self._key_checker.CheckValue(item)
543*1b3f573fSAndroid Build Coastguard Worker    return item in self._values
544*1b3f573fSAndroid Build Coastguard Worker
545*1b3f573fSAndroid Build Coastguard Worker  def __setitem__(self, key: _K, value: _V) -> NoReturn:
546*1b3f573fSAndroid Build Coastguard Worker    raise ValueError('May not set values directly, call my_map[key].foo = 5')
547*1b3f573fSAndroid Build Coastguard Worker
548*1b3f573fSAndroid Build Coastguard Worker  def __delitem__(self, key: _K) -> None:
549*1b3f573fSAndroid Build Coastguard Worker    key = self._key_checker.CheckValue(key)
550*1b3f573fSAndroid Build Coastguard Worker    del self._values[key]
551*1b3f573fSAndroid Build Coastguard Worker    self._message_listener.Modified()
552*1b3f573fSAndroid Build Coastguard Worker
553*1b3f573fSAndroid Build Coastguard Worker  def __len__(self) -> int:
554*1b3f573fSAndroid Build Coastguard Worker    return len(self._values)
555*1b3f573fSAndroid Build Coastguard Worker
556*1b3f573fSAndroid Build Coastguard Worker  def __iter__(self) -> Iterator[_K]:
557*1b3f573fSAndroid Build Coastguard Worker    return iter(self._values)
558*1b3f573fSAndroid Build Coastguard Worker
559*1b3f573fSAndroid Build Coastguard Worker  def __repr__(self) -> str:
560*1b3f573fSAndroid Build Coastguard Worker    return repr(self._values)
561*1b3f573fSAndroid Build Coastguard Worker
562*1b3f573fSAndroid Build Coastguard Worker  def MergeFrom(self, other: 'MessageMap[_K, _V]') -> None:
563*1b3f573fSAndroid Build Coastguard Worker    # pylint: disable=protected-access
564*1b3f573fSAndroid Build Coastguard Worker    for key in other._values:
565*1b3f573fSAndroid Build Coastguard Worker      # According to documentation: "When parsing from the wire or when merging,
566*1b3f573fSAndroid Build Coastguard Worker      # if there are duplicate map keys the last key seen is used".
567*1b3f573fSAndroid Build Coastguard Worker      if key in self:
568*1b3f573fSAndroid Build Coastguard Worker        del self[key]
569*1b3f573fSAndroid Build Coastguard Worker      self[key].CopyFrom(other[key])
570*1b3f573fSAndroid Build Coastguard Worker    # self._message_listener.Modified() not required here, because
571*1b3f573fSAndroid Build Coastguard Worker    # mutations to submessages already propagate.
572*1b3f573fSAndroid Build Coastguard Worker
573*1b3f573fSAndroid Build Coastguard Worker  def InvalidateIterators(self) -> None:
574*1b3f573fSAndroid Build Coastguard Worker    # It appears that the only way to reliably invalidate iterators to
575*1b3f573fSAndroid Build Coastguard Worker    # self._values is to ensure that its size changes.
576*1b3f573fSAndroid Build Coastguard Worker    original = self._values
577*1b3f573fSAndroid Build Coastguard Worker    self._values = original.copy()
578*1b3f573fSAndroid Build Coastguard Worker    original[None] = None
579*1b3f573fSAndroid Build Coastguard Worker
580*1b3f573fSAndroid Build Coastguard Worker  # This is defined in the abstract base, but we can do it much more cheaply.
581*1b3f573fSAndroid Build Coastguard Worker  def clear(self) -> None:
582*1b3f573fSAndroid Build Coastguard Worker    self._values.clear()
583*1b3f573fSAndroid Build Coastguard Worker    self._message_listener.Modified()
584*1b3f573fSAndroid Build Coastguard Worker
585*1b3f573fSAndroid Build Coastguard Worker  def GetEntryClass(self) -> Any:
586*1b3f573fSAndroid Build Coastguard Worker    return self._entry_descriptor._concrete_class
587*1b3f573fSAndroid Build Coastguard Worker
588*1b3f573fSAndroid Build Coastguard Worker
589*1b3f573fSAndroid Build Coastguard Workerclass _UnknownField:
590*1b3f573fSAndroid Build Coastguard Worker  """A parsed unknown field."""
591*1b3f573fSAndroid Build Coastguard Worker
592*1b3f573fSAndroid Build Coastguard Worker  # Disallows assignment to other attributes.
593*1b3f573fSAndroid Build Coastguard Worker  __slots__ = ['_field_number', '_wire_type', '_data']
594*1b3f573fSAndroid Build Coastguard Worker
595*1b3f573fSAndroid Build Coastguard Worker  def __init__(self, field_number, wire_type, data):
596*1b3f573fSAndroid Build Coastguard Worker    self._field_number = field_number
597*1b3f573fSAndroid Build Coastguard Worker    self._wire_type = wire_type
598*1b3f573fSAndroid Build Coastguard Worker    self._data = data
599*1b3f573fSAndroid Build Coastguard Worker    return
600*1b3f573fSAndroid Build Coastguard Worker
601*1b3f573fSAndroid Build Coastguard Worker  def __lt__(self, other):
602*1b3f573fSAndroid Build Coastguard Worker    # pylint: disable=protected-access
603*1b3f573fSAndroid Build Coastguard Worker    return self._field_number < other._field_number
604*1b3f573fSAndroid Build Coastguard Worker
605*1b3f573fSAndroid Build Coastguard Worker  def __eq__(self, other):
606*1b3f573fSAndroid Build Coastguard Worker    if self is other:
607*1b3f573fSAndroid Build Coastguard Worker      return True
608*1b3f573fSAndroid Build Coastguard Worker    # pylint: disable=protected-access
609*1b3f573fSAndroid Build Coastguard Worker    return (self._field_number == other._field_number and
610*1b3f573fSAndroid Build Coastguard Worker            self._wire_type == other._wire_type and
611*1b3f573fSAndroid Build Coastguard Worker            self._data == other._data)
612*1b3f573fSAndroid Build Coastguard Worker
613*1b3f573fSAndroid Build Coastguard Worker
614*1b3f573fSAndroid Build Coastguard Workerclass UnknownFieldRef:  # pylint: disable=missing-class-docstring
615*1b3f573fSAndroid Build Coastguard Worker
616*1b3f573fSAndroid Build Coastguard Worker  def __init__(self, parent, index):
617*1b3f573fSAndroid Build Coastguard Worker    self._parent = parent
618*1b3f573fSAndroid Build Coastguard Worker    self._index = index
619*1b3f573fSAndroid Build Coastguard Worker
620*1b3f573fSAndroid Build Coastguard Worker  def _check_valid(self):
621*1b3f573fSAndroid Build Coastguard Worker    if not self._parent:
622*1b3f573fSAndroid Build Coastguard Worker      raise ValueError('UnknownField does not exist. '
623*1b3f573fSAndroid Build Coastguard Worker                       'The parent message might be cleared.')
624*1b3f573fSAndroid Build Coastguard Worker    if self._index >= len(self._parent):
625*1b3f573fSAndroid Build Coastguard Worker      raise ValueError('UnknownField does not exist. '
626*1b3f573fSAndroid Build Coastguard Worker                       'The parent message might be cleared.')
627*1b3f573fSAndroid Build Coastguard Worker
628*1b3f573fSAndroid Build Coastguard Worker  @property
629*1b3f573fSAndroid Build Coastguard Worker  def field_number(self):
630*1b3f573fSAndroid Build Coastguard Worker    self._check_valid()
631*1b3f573fSAndroid Build Coastguard Worker    # pylint: disable=protected-access
632*1b3f573fSAndroid Build Coastguard Worker    return self._parent._internal_get(self._index)._field_number
633*1b3f573fSAndroid Build Coastguard Worker
634*1b3f573fSAndroid Build Coastguard Worker  @property
635*1b3f573fSAndroid Build Coastguard Worker  def wire_type(self):
636*1b3f573fSAndroid Build Coastguard Worker    self._check_valid()
637*1b3f573fSAndroid Build Coastguard Worker    # pylint: disable=protected-access
638*1b3f573fSAndroid Build Coastguard Worker    return self._parent._internal_get(self._index)._wire_type
639*1b3f573fSAndroid Build Coastguard Worker
640*1b3f573fSAndroid Build Coastguard Worker  @property
641*1b3f573fSAndroid Build Coastguard Worker  def data(self):
642*1b3f573fSAndroid Build Coastguard Worker    self._check_valid()
643*1b3f573fSAndroid Build Coastguard Worker    # pylint: disable=protected-access
644*1b3f573fSAndroid Build Coastguard Worker    return self._parent._internal_get(self._index)._data
645*1b3f573fSAndroid Build Coastguard Worker
646*1b3f573fSAndroid Build Coastguard Worker
647*1b3f573fSAndroid Build Coastguard Workerclass UnknownFieldSet:
648*1b3f573fSAndroid Build Coastguard Worker  """UnknownField container"""
649*1b3f573fSAndroid Build Coastguard Worker
650*1b3f573fSAndroid Build Coastguard Worker  # Disallows assignment to other attributes.
651*1b3f573fSAndroid Build Coastguard Worker  __slots__ = ['_values']
652*1b3f573fSAndroid Build Coastguard Worker
653*1b3f573fSAndroid Build Coastguard Worker  def __init__(self):
654*1b3f573fSAndroid Build Coastguard Worker    self._values = []
655*1b3f573fSAndroid Build Coastguard Worker
656*1b3f573fSAndroid Build Coastguard Worker  def __getitem__(self, index):
657*1b3f573fSAndroid Build Coastguard Worker    if self._values is None:
658*1b3f573fSAndroid Build Coastguard Worker      raise ValueError('UnknownFields does not exist. '
659*1b3f573fSAndroid Build Coastguard Worker                       'The parent message might be cleared.')
660*1b3f573fSAndroid Build Coastguard Worker    size = len(self._values)
661*1b3f573fSAndroid Build Coastguard Worker    if index < 0:
662*1b3f573fSAndroid Build Coastguard Worker      index += size
663*1b3f573fSAndroid Build Coastguard Worker    if index < 0 or index >= size:
664*1b3f573fSAndroid Build Coastguard Worker      raise IndexError('index %d out of range'.index)
665*1b3f573fSAndroid Build Coastguard Worker
666*1b3f573fSAndroid Build Coastguard Worker    return UnknownFieldRef(self, index)
667*1b3f573fSAndroid Build Coastguard Worker
668*1b3f573fSAndroid Build Coastguard Worker  def _internal_get(self, index):
669*1b3f573fSAndroid Build Coastguard Worker    return self._values[index]
670*1b3f573fSAndroid Build Coastguard Worker
671*1b3f573fSAndroid Build Coastguard Worker  def __len__(self):
672*1b3f573fSAndroid Build Coastguard Worker    if self._values is None:
673*1b3f573fSAndroid Build Coastguard Worker      raise ValueError('UnknownFields does not exist. '
674*1b3f573fSAndroid Build Coastguard Worker                       'The parent message might be cleared.')
675*1b3f573fSAndroid Build Coastguard Worker    return len(self._values)
676*1b3f573fSAndroid Build Coastguard Worker
677*1b3f573fSAndroid Build Coastguard Worker  def _add(self, field_number, wire_type, data):
678*1b3f573fSAndroid Build Coastguard Worker    unknown_field = _UnknownField(field_number, wire_type, data)
679*1b3f573fSAndroid Build Coastguard Worker    self._values.append(unknown_field)
680*1b3f573fSAndroid Build Coastguard Worker    return unknown_field
681*1b3f573fSAndroid Build Coastguard Worker
682*1b3f573fSAndroid Build Coastguard Worker  def __iter__(self):
683*1b3f573fSAndroid Build Coastguard Worker    for i in range(len(self)):
684*1b3f573fSAndroid Build Coastguard Worker      yield UnknownFieldRef(self, i)
685*1b3f573fSAndroid Build Coastguard Worker
686*1b3f573fSAndroid Build Coastguard Worker  def _extend(self, other):
687*1b3f573fSAndroid Build Coastguard Worker    if other is None:
688*1b3f573fSAndroid Build Coastguard Worker      return
689*1b3f573fSAndroid Build Coastguard Worker    # pylint: disable=protected-access
690*1b3f573fSAndroid Build Coastguard Worker    self._values.extend(other._values)
691*1b3f573fSAndroid Build Coastguard Worker
692*1b3f573fSAndroid Build Coastguard Worker  def __eq__(self, other):
693*1b3f573fSAndroid Build Coastguard Worker    if self is other:
694*1b3f573fSAndroid Build Coastguard Worker      return True
695*1b3f573fSAndroid Build Coastguard Worker    # Sort unknown fields because their order shouldn't
696*1b3f573fSAndroid Build Coastguard Worker    # affect equality test.
697*1b3f573fSAndroid Build Coastguard Worker    values = list(self._values)
698*1b3f573fSAndroid Build Coastguard Worker    if other is None:
699*1b3f573fSAndroid Build Coastguard Worker      return not values
700*1b3f573fSAndroid Build Coastguard Worker    values.sort()
701*1b3f573fSAndroid Build Coastguard Worker    # pylint: disable=protected-access
702*1b3f573fSAndroid Build Coastguard Worker    other_values = sorted(other._values)
703*1b3f573fSAndroid Build Coastguard Worker    return values == other_values
704*1b3f573fSAndroid Build Coastguard Worker
705*1b3f573fSAndroid Build Coastguard Worker  def _clear(self):
706*1b3f573fSAndroid Build Coastguard Worker    for value in self._values:
707*1b3f573fSAndroid Build Coastguard Worker      # pylint: disable=protected-access
708*1b3f573fSAndroid Build Coastguard Worker      if isinstance(value._data, UnknownFieldSet):
709*1b3f573fSAndroid Build Coastguard Worker        value._data._clear()  # pylint: disable=protected-access
710*1b3f573fSAndroid Build Coastguard Worker    self._values = None
711