#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.
#

"""Collection of useful coders.

Only those coders listed in __all__ are part of the public API of this module.

## On usage of `pickle`, `dill` and `pickler` in Beam

In Beam, we generally we use `pickle` for pipeline elements and `dill` for
more complex types, like user functions.

`pickler` is Beam's own wrapping of dill + compression + error handling.
It serves also as an API to mask the actual encoding layer (so we can
change it from `dill` if necessary).

We created `_MemoizingPickleCoder` to improve performance when serializing
complex user types for the execution of SDF. Specifically to address
BEAM-12781, where many identical `BoundedSource` instances are being
encoded.

"""
# pytype: skip-file

import base64
import decimal
import pickle
from functools import lru_cache
from typing import TYPE_CHECKING
from typing import Any
from typing import Callable
from typing import Dict
from typing import Iterable
from typing import List
from typing import Optional
from typing import Sequence
from typing import Tuple
from typing import Type
from typing import TypeVar
from typing import overload

import google.protobuf.wrappers_pb2
import proto
from google.protobuf import message

from apache_beam.coders import coder_impl
from apache_beam.coders.avro_record import AvroRecord
from apache_beam.internal import cloudpickle_pickler
from apache_beam.portability import common_urns
from apache_beam.portability import python_urns
from apache_beam.portability.api import beam_runner_api_pb2
from apache_beam.typehints import typehints
from apache_beam.utils import proto_utils
from apache_beam.utils import windowed_value

if TYPE_CHECKING:
  from apache_beam.coders.typecoders import CoderRegistry
  from apache_beam.runners.pipeline_context import PipelineContext

# pylint: disable=wrong-import-order, wrong-import-position, ungrouped-imports
try:
  from .stream import get_varint_size
except ImportError:
  from .slow_stream import get_varint_size
# pylint: enable=wrong-import-order, wrong-import-position, ungrouped-imports

# pylint: disable=wrong-import-order, wrong-import-position
# Avoid dependencies on the full SDK.
try:
  # Import dill from the pickler module to make sure our monkey-patching of dill
  # occurs.
  from apache_beam.internal.dill_pickler import dill
except ImportError:
  dill = None

__all__ = [
    'Coder',
    'AvroGenericCoder',
    'BooleanCoder',
    'BytesCoder',
    'CloudpickleCoder',
    'DillCoder',
    'FastPrimitivesCoder',
    'FloatCoder',
    'IterableCoder',
    'ListCoder',
    'MapCoder',
    'NullableCoder',
    'PickleCoder',
    'ProtoCoder',
    'ProtoPlusCoder',
    'ShardedKeyCoder',
    'SinglePrecisionFloatCoder',
    'SingletonCoder',
    'StrUtf8Coder',
    'TimestampCoder',
    'TupleCoder',
    'TupleSequenceCoder',
    'VarIntCoder',
    'WindowedValueCoder',
    'ParamWindowedValueCoder',
    'BigIntegerCoder',
    'DecimalCoder',
    'PaneInfoCoder'
]

T = TypeVar('T')
CoderT = TypeVar('CoderT', bound='Coder')
ProtoCoderT = TypeVar('ProtoCoderT', bound='ProtoCoder')
ConstructorFn = Callable[[Optional[Any], List['Coder'], 'PipelineContext'], Any]


def serialize_coder(coder):
  from apache_beam.internal import pickler
  return b'%s$%s' % (
      coder.__class__.__name__.encode('utf-8'),
      pickler.dumps(coder, use_zlib=True))


def deserialize_coder(serialized):
  from apache_beam.internal import pickler
  return pickler.loads(serialized.split(b'$', 1)[1], use_zlib=True)


# pylint: enable=wrong-import-order, wrong-import-position


class Coder(object):
  """Base class for coders."""
  def encode(self, value):
    # type: (Any) -> bytes

    """Encodes the given object into a byte string."""
    raise NotImplementedError('Encode not implemented: %s.' % self)

  def decode(self, encoded):
    """Decodes the given byte string into the corresponding object."""
    raise NotImplementedError('Decode not implemented: %s.' % self)

  def encode_nested(self, value):
    """Uses the underlying implementation to encode in nested format."""
    return self.get_impl().encode_nested(value)

  def decode_nested(self, encoded):
    """Uses the underlying implementation to decode in nested format."""
    return self.get_impl().decode_nested(encoded)

  def is_deterministic(self):
    # type: () -> bool

    """Whether this coder is guaranteed to encode values deterministically.

    A deterministic coder is required for key coders in GroupByKey operations
    to produce consistent results.

    For example, note that the default coder, the PickleCoder, is not
    deterministic: the ordering of picked entries in maps may vary across
    executions since there is no defined order, and such a coder is not in
    general suitable for usage as a key coder in GroupByKey operations, since
    each instance of the same key may be encoded differently.

    Returns:
      Whether coder is deterministic.
    """
    return False

  def as_deterministic_coder(self, step_label, error_message=None):
    """Returns a deterministic version of self, if possible.

    Otherwise raises a value error.
    """
    if self.is_deterministic():
      return self
    else:
      raise ValueError(
          error_message or
          "%s cannot be made deterministic for '%s'." % (self, step_label))

  def estimate_size(self, value):
    """Estimates the encoded size of the given value, in bytes.

    Dataflow estimates the encoded size of a PCollection processed in a pipeline
    step by using the estimated size of a random sample of elements in that
    PCollection.

    The default implementation encodes the given value and returns its byte
    size.  If a coder can provide a fast estimate of the encoded size of a value
    (e.g., if the encoding has a fixed size), it can provide its estimate here
    to improve performance.

    Arguments:
      value: the value whose encoded size is to be estimated.

    Returns:
      The estimated encoded size of the given value.
    """
    return len(self.encode(value))

  # ===========================================================================
  # Methods below are internal SDK details that don't need to be modified for
  # user-defined coders.
  # ===========================================================================

  def _create_impl(self):
    # type: () -> coder_impl.CoderImpl

    """Creates a CoderImpl to do the actual encoding and decoding.
    """
    return coder_impl.CallbackCoderImpl(
        self.encode, self.decode, self.estimate_size)

  def get_impl(self):
    """For internal use only; no backwards-compatibility guarantees.

    Returns the CoderImpl backing this Coder.
    """
    if not hasattr(self, '_impl'):
      self._impl = self._create_impl()
      assert isinstance(self._impl, coder_impl.CoderImpl)
    return self._impl

  def __getstate__(self):
    return self._dict_without_impl()

  def _dict_without_impl(self):
    if hasattr(self, '_impl'):
      d = dict(self.__dict__)
      del d['_impl']
      return d
    return self.__dict__

  def to_type_hint(self):
    # TODO: After https://github.com/apache/beam/issues/18490 we should be
    # able to infer the type hint rather than require every subclass define
    # it
    raise NotImplementedError

  @classmethod
  def from_type_hint(cls, unused_typehint, unused_registry):
    # type: (Type[CoderT], Any, CoderRegistry) -> CoderT
    # If not overridden, just construct the coder without arguments.
    return cls()

  def is_kv_coder(self):
    # type: () -> bool
    return False

  def key_coder(self):
    # type: () -> Coder
    if self.is_kv_coder():
      raise NotImplementedError('key_coder: %s' % self)
    else:
      raise ValueError('Not a KV coder: %s.' % self)

  def value_coder(self):
    # type: () -> Coder
    if self.is_kv_coder():
      raise NotImplementedError('value_coder: %s' % self)
    else:
      raise ValueError('Not a KV coder: %s.' % self)

  def _get_component_coders(self):
    # type: () -> Sequence[Coder]

    """For internal use only; no backwards-compatibility guarantees.

    Returns the internal component coders of this coder."""
    # This is an internal detail of the Coder API and does not need to be
    # refined in user-defined Coders.
    return []

  def __repr__(self):
    return self.__class__.__name__

  # pylint: disable=protected-access
  def __eq__(self, other):
    return (
        self.__class__ == other.__class__ and
        self._dict_without_impl() == other._dict_without_impl())

  # pylint: enable=protected-access

  def __hash__(self):
    return hash(type(self))

  _known_urns = {}  # type: Dict[str, Tuple[type, ConstructorFn]]

  @classmethod
  @overload
  def register_urn(
      cls,
      urn,  # type: str
      parameter_type,  # type: Optional[Type[T]]
  ):
    # type: (...) -> Callable[[Callable[[T, List[Coder], PipelineContext], Any]], Callable[[T, List[Coder], PipelineContext], Any]]
    pass

  @classmethod
  @overload
  def register_urn(
      cls,
      urn,  # type: str
      parameter_type,  # type: Optional[Type[T]]
      fn  # type: Callable[[T, List[Coder], PipelineContext], Any]
  ):
    # type: (...) -> None
    pass

  @classmethod
  def register_urn(cls, urn, parameter_type, fn=None):
    """Registers a urn with a constructor.

    For example, if 'beam:fn:foo' had parameter type FooPayload, one could
    write `RunnerApiFn.register_urn('bean:fn:foo', FooPayload, foo_from_proto)`
    where foo_from_proto took as arguments a FooPayload and a PipelineContext.
    This function can also be used as a decorator rather than passing the
    callable in as the final parameter.

    A corresponding to_runner_api_parameter method would be expected that
    returns the tuple ('beam:fn:foo', FooPayload)
    """
    def register(fn):
      cls._known_urns[urn] = parameter_type, fn
      return fn

    if fn:
      # Used as a statement.
      register(fn)
    else:
      # Used as a decorator.
      return register

  def to_runner_api(self, context):
    # type: (PipelineContext) -> beam_runner_api_pb2.Coder
    urn, typed_param, components = self.to_runner_api_parameter(context)
    return beam_runner_api_pb2.Coder(
        spec=beam_runner_api_pb2.FunctionSpec(
            urn=urn,
            payload=typed_param if isinstance(typed_param, (bytes, type(None)))
            else typed_param.SerializeToString()),
        component_coder_ids=[context.coders.get_id(c) for c in components])

  @classmethod
  def from_runner_api(cls, coder_proto, context):
    # type: (Type[CoderT], beam_runner_api_pb2.Coder, PipelineContext) -> CoderT

    """Converts from an FunctionSpec to a Fn object.

    Prefer registering a urn with its parameter type and constructor.
    """
    parameter_type, constructor = cls._known_urns[coder_proto.spec.urn]
    return constructor(
        proto_utils.parse_Bytes(coder_proto.spec.payload, parameter_type),
        [context.coders.get_by_id(c) for c in coder_proto.component_coder_ids],
        context)

  def to_runner_api_parameter(self, context):
    # type: (Optional[PipelineContext]) -> Tuple[str, Any, Sequence[Coder]]
    return (
        python_urns.PICKLED_CODER,
        google.protobuf.wrappers_pb2.BytesValue(value=serialize_coder(self)),
        ())

  @staticmethod
  def register_structured_urn(urn, cls):
    # type: (str, Type[Coder]) -> None

    """Register a coder that's completely defined by its urn and its
    component(s), if any, which are passed to construct the instance.
    """
    setattr(
        cls,
        'to_runner_api_parameter', lambda self, unused_context:
        (urn, None, self._get_component_coders()))

    # pylint: disable=unused-variable
    @Coder.register_urn(urn, None)
    def from_runner_api_parameter(unused_payload, components, unused_context):
      if components:
        return cls(*components)
      else:
        return cls()

  def version_tag(self) -> str:
    """For internal use. Appends a version tag to the coder key in the pipeline
    proto. Some runners (e.g. DataflowRunner) use coder key/id to verify if a
    pipeline is update compatible. If the implementation of a coder changed
    in an update incompatible way a version tag can be added to fail
    compatibility checks.
    """
    return ""


@Coder.register_urn(
    python_urns.PICKLED_CODER, google.protobuf.wrappers_pb2.BytesValue)
def _pickle_from_runner_api_parameter(payload, components, context):
  return deserialize_coder(payload.value)


class StrUtf8Coder(Coder):
  """A coder used for reading and writing strings as UTF-8."""
  def encode(self, value):
    return value.encode('utf-8')

  def decode(self, value):
    return value.decode('utf-8')

  def is_deterministic(self):
    # type: () -> bool
    return True

  def to_type_hint(self):
    return str


Coder.register_structured_urn(common_urns.coders.STRING_UTF8.urn, StrUtf8Coder)


class ToBytesCoder(Coder):
  """A default string coder used if no sink coder is specified."""
  def encode(self, value):
    return value if isinstance(value, bytes) else str(value).encode('utf-8')

  def decode(self, _):
    raise NotImplementedError('ToBytesCoder cannot be used for decoding.')

  def is_deterministic(self):
    # type: () -> bool
    return True


# alias to the old class name for a courtesy to users who reference it
ToStringCoder = ToBytesCoder


class FastCoder(Coder):
  """Coder subclass used when a (faster) CoderImpl is supplied directly.

  The Coder class defines _create_impl in terms of encode() and decode();
  this class inverts that by defining encode() and decode() in terms of
  _create_impl().
  """
  def encode(self, value):
    """Encodes the given object into a byte string."""
    return self.get_impl().encode(value)

  def decode(self, encoded):
    """Decodes the given byte string into the corresponding object."""
    return self.get_impl().decode(encoded)

  def estimate_size(self, value):
    return self.get_impl().estimate_size(value)

  def _create_impl(self):
    raise NotImplementedError


class BytesCoder(FastCoder):
  """Byte string coder."""
  def _create_impl(self):
    return coder_impl.BytesCoderImpl()

  def is_deterministic(self):
    # type: () -> bool
    return True

  def to_type_hint(self):
    return bytes

  def __eq__(self, other):
    return type(self) == type(other)

  def __hash__(self):
    return hash(type(self))


Coder.register_structured_urn(common_urns.coders.BYTES.urn, BytesCoder)


class BooleanCoder(FastCoder):
  def _create_impl(self):
    return coder_impl.BooleanCoderImpl()

  def is_deterministic(self):
    # type: () -> bool
    return True

  def to_type_hint(self):
    return bool

  def __eq__(self, other):
    return type(self) == type(other)

  def __hash__(self):
    return hash(type(self))


Coder.register_structured_urn(common_urns.coders.BOOL.urn, BooleanCoder)


class MapCoder(FastCoder):
  def __init__(self, key_coder, value_coder):
    # type: (Coder, Coder) -> None
    self._key_coder = key_coder
    self._value_coder = value_coder

  def _create_impl(self):
    return coder_impl.MapCoderImpl(
        self._key_coder.get_impl(), self._value_coder.get_impl())

  @classmethod
  def from_type_hint(cls, typehint, registry):
    # type: (typehints.DictConstraint, CoderRegistry) -> MapCoder
    return cls(
        registry.get_coder(typehint.key_type),
        registry.get_coder(typehint.value_type))

  def to_type_hint(self):
    return typehints.Dict[self._key_coder.to_type_hint(),
                          self._value_coder.to_type_hint()]

  def is_deterministic(self):
    # type: () -> bool
    # Map ordering is non-deterministic
    return False

  def as_deterministic_coder(self, step_label, error_message=None):
    return DeterministicMapCoder(
        self._key_coder.as_deterministic_coder(step_label, error_message),
        self._value_coder.as_deterministic_coder(step_label, error_message))

  def __eq__(self, other):
    return (
        type(self) == type(other) and self._key_coder == other._key_coder and
        self._value_coder == other._value_coder)

  def __hash__(self):
    return hash(type(self)) + hash(self._key_coder) + hash(self._value_coder)

  def __repr__(self):
    return 'MapCoder[%s, %s]' % (self._key_coder, self._value_coder)


# This is a separate class from MapCoder as the former is a standard coder with
# no way to carry the is_deterministic bit.
class DeterministicMapCoder(FastCoder):
  def __init__(self, key_coder, value_coder):
    # type: (Coder, Coder) -> None
    assert key_coder.is_deterministic()
    assert value_coder.is_deterministic()
    self._key_coder = key_coder
    self._value_coder = value_coder

  def _create_impl(self):
    return coder_impl.MapCoderImpl(
        self._key_coder.get_impl(), self._value_coder.get_impl(), True)

  def is_deterministic(self):
    return True

  def __eq__(self, other):
    return (
        type(self) == type(other) and self._key_coder == other._key_coder and
        self._value_coder == other._value_coder)

  def __hash__(self):
    return hash(type(self)) + hash(self._key_coder) + hash(self._value_coder)

  def __repr__(self):
    return 'DeterministicMapCoder[%s, %s]' % (
        self._key_coder, self._value_coder)


class NullableCoder(FastCoder):
  def __init__(self, value_coder):
    # type: (Coder) -> None
    self._value_coder = value_coder

  def _create_impl(self):
    return coder_impl.NullableCoderImpl(self._value_coder.get_impl())

  def to_type_hint(self):
    return typehints.Optional[self._value_coder.to_type_hint()]

  def _get_component_coders(self):
    # type: () -> List[Coder]
    return [self._value_coder]

  @classmethod
  def from_type_hint(cls, typehint, registry):
    if typehints.is_nullable(typehint):
      return cls(
          registry.get_coder(
              typehints.get_concrete_type_from_nullable(typehint)))
    else:
      raise TypeError(
          'Typehint is not of nullable type, '
          'and cannot be converted to a NullableCoder',
          typehint)

  def is_deterministic(self):
    # type: () -> bool
    return self._value_coder.is_deterministic()

  def as_deterministic_coder(self, step_label, error_message=None):
    if self.is_deterministic():
      return self
    else:
      deterministic_value_coder = self._value_coder.as_deterministic_coder(
          step_label, error_message)
      return NullableCoder(deterministic_value_coder)

  def __eq__(self, other):
    return (
        type(self) == type(other) and self._value_coder == other._value_coder)

  def __hash__(self):
    return hash(type(self)) + hash(self._value_coder)

  def __repr__(self):
    return 'NullableCoder[%s]' % self._value_coder


Coder.register_structured_urn(common_urns.coders.NULLABLE.urn, NullableCoder)


class VarIntCoder(FastCoder):
  """Variable-length integer coder  matches Java SDK's VarLongCoder."""
  def _create_impl(self):
    return coder_impl.VarIntCoderImpl()

  def is_deterministic(self):
    # type: () -> bool
    return True

  def to_type_hint(self):
    return int

  def __eq__(self, other):
    return type(self) == type(other)

  def __hash__(self):
    return hash(type(self))


Coder.register_structured_urn(common_urns.coders.VARINT.urn, VarIntCoder)


class VarInt32Coder(FastCoder):
  """Variable-length integer coder matches Java SDK's VarIntCoder."""
  def _create_impl(self):
    return coder_impl.VarInt32CoderImpl()

  def is_deterministic(self):
    # type: () -> bool
    return True

  def to_type_hint(self):
    return int

  def __eq__(self, other):
    return type(self) == type(other)

  def __hash__(self):
    return hash(type(self))


class BigEndianShortCoder(FastCoder):
  """A coder used for big-endian int16 values."""
  def _create_impl(self):
    return coder_impl.BigEndianShortCoderImpl()

  def is_deterministic(self):
    # type: () -> bool
    return True

  def to_type_hint(self):
    return int

  def __eq__(self, other):
    return type(self) == type(other)

  def __hash__(self):
    return hash(type(self))


class SinglePrecisionFloatCoder(FastCoder):
  """A coder used for single-precision floating-point values."""
  def _create_impl(self):
    return coder_impl.SinglePrecisionFloatCoderImpl()

  def is_deterministic(self):
    # type: () -> bool
    return True

  def to_type_hint(self):
    return float

  def __eq__(self, other):
    return type(self) == type(other)

  def __hash__(self):
    return hash(type(self))


class FloatCoder(FastCoder):
  """A coder used for **double-precision** floating-point values.

  Note that the name "FloatCoder" is in reference to Python's ``float`` built-in
  which is generally implemented using C doubles. See
  :class:`SinglePrecisionFloatCoder` for a single-precision version of this
  coder.
  """
  def _create_impl(self):
    return coder_impl.FloatCoderImpl()

  def is_deterministic(self):
    # type: () -> bool
    return True

  def to_type_hint(self):
    return float

  def __eq__(self, other):
    return type(self) == type(other)

  def __hash__(self):
    return hash(type(self))


Coder.register_structured_urn(common_urns.coders.DOUBLE.urn, FloatCoder)


class TimestampCoder(FastCoder):
  """A coder used for timeutil.Timestamp values."""
  def _create_impl(self):
    return coder_impl.TimestampCoderImpl()

  def is_deterministic(self):
    # type: () -> bool
    return True

  def __eq__(self, other):
    return type(self) == type(other)

  def __hash__(self):
    return hash(type(self))


class _TimerCoder(FastCoder):
  """A coder used for timer values.

  For internal use."""
  def __init__(self, key_coder, window_coder):
    # type: (Coder, Coder) -> None
    self._key_coder = key_coder
    self._window_coder = window_coder

  def _get_component_coders(self):
    # type: () -> List[Coder]
    return [self._key_coder, self._window_coder]

  def _create_impl(self):
    return coder_impl.TimerCoderImpl(
        self._key_coder.get_impl(), self._window_coder.get_impl())

  def is_deterministic(self):
    # type: () -> bool
    return (
        self._key_coder.is_deterministic() and
        self._window_coder.is_deterministic())

  def __eq__(self, other):
    return (
        type(self) == type(other) and self._key_coder == other._key_coder and
        self._window_coder == other._window_coder)

  def __hash__(self):
    return hash(type(self)) + hash(self._key_coder) + hash(self._window_coder)


Coder.register_structured_urn(common_urns.coders.TIMER.urn, _TimerCoder)


class SingletonCoder(FastCoder):
  """A coder that always encodes exactly one value."""
  def __init__(self, value):
    self._value = value

  def _create_impl(self):
    return coder_impl.SingletonCoderImpl(self._value)

  def is_deterministic(self):
    # type: () -> bool
    return True

  def __eq__(self, other):
    return type(self) == type(other) and self._value == other._value

  def __hash__(self):
    return hash(self._value)


def maybe_dill_dumps(o):
  """Pickle using cPickle or the Dill pickler as a fallback."""
  # We need to use the dill pickler for objects of certain custom classes,
  # including, for example, ones that contain lambdas.
  try:
    return pickle.dumps(o, pickle.HIGHEST_PROTOCOL)
  except Exception:  # pylint: disable=broad-except
    return dill.dumps(o)


def maybe_dill_loads(o):
  """Unpickle using cPickle or the Dill pickler as a fallback."""
  try:
    return pickle.loads(o)
  except Exception:  # pylint: disable=broad-except
    return dill.loads(o)


class _PickleCoderBase(FastCoder):
  """Base class for pickling coders."""
  def is_deterministic(self):
    # type: () -> bool
    # Note that the default coder, the PickleCoder, is not deterministic (for
    # example, the ordering of picked entries in maps may vary across
    # executions), and so is not in general suitable for usage as a key coder in
    # GroupByKey operations.
    return False

  # We allow .key_coder() and .value_coder() to be called on PickleCoder since
  # we can't always infer the return values of lambdas in ParDo operations, the
  # result of which may be used in a GroupBykey.
  def is_kv_coder(self):
    # type: () -> bool
    return True

  def key_coder(self):
    return self

  def value_coder(self):
    return self

  def __eq__(self, other):
    return type(self) == type(other)

  def __hash__(self):
    return hash(type(self))


class _MemoizingPickleCoder(_PickleCoderBase):
  """Coder using Python's pickle functionality with memoization."""
  def __init__(self, cache_size=16):
    super().__init__()
    self.cache_size = cache_size

  def _create_impl(self):
    from apache_beam.internal import pickler
    dumps = pickler.dumps

    mdumps = lru_cache(maxsize=self.cache_size, typed=True)(dumps)

    def _nonhashable_dumps(x):
      try:
        return mdumps(x)
      except TypeError:
        return dumps(x)

    return coder_impl.CallbackCoderImpl(_nonhashable_dumps, pickler.loads)

  def as_deterministic_coder(self, step_label, error_message=None):
    return FastPrimitivesCoder(self, requires_deterministic=step_label)

  def to_type_hint(self):
    return Any


class PickleCoder(_PickleCoderBase):
  """Coder using Python's pickle functionality."""
  def _create_impl(self):
    dumps = pickle.dumps
    protocol = pickle.HIGHEST_PROTOCOL
    return coder_impl.CallbackCoderImpl(
        lambda x: dumps(x, protocol), pickle.loads)

  def as_deterministic_coder(self, step_label, error_message=None):
    return FastPrimitivesCoder(self, requires_deterministic=step_label)

  def to_type_hint(self):
    return Any


class DillCoder(_PickleCoderBase):
  """Coder using dill's pickle functionality."""
  def __init__(self):
    if not dill:
      raise RuntimeError(
          "This pipeline contains a DillCoder which requires "
          "the dill package. Install the dill package with the dill extra "
          "e.g. apache-beam[dill]")

  def _create_impl(self):
    return coder_impl.CallbackCoderImpl(maybe_dill_dumps, maybe_dill_loads)


class CloudpickleCoder(_PickleCoderBase):
  """Coder using Apache Beam's vendored Cloudpickle pickler."""
  def _create_impl(self):
    return coder_impl.CallbackCoderImpl(
        cloudpickle_pickler.dumps, cloudpickle_pickler.loads)


class DeterministicFastPrimitivesCoderV2(FastCoder):
  """Throws runtime errors when encoding non-deterministic values."""
  def __init__(self, coder, step_label):
    self._underlying_coder = coder
    self._step_label = step_label
    self._use_relative_filepaths = True
    self._version_tag = "v2_69"

    # Versions prior to 2.69.0 did not use relative filepaths.
    from apache_beam.options.pipeline_options_context import get_pipeline_options
    opts = get_pipeline_options()
    if opts and opts.is_compat_version_prior_to("2.69.0"):
      self._version_tag = ""
      self._use_relative_filepaths = False

  def _create_impl(self):
    return coder_impl.FastPrimitivesCoderImpl(
        self._underlying_coder.get_impl(),
        requires_deterministic_step_label=self._step_label,
        force_use_dill=False,
        use_relative_filepaths=self._use_relative_filepaths)

  def is_deterministic(self):
    # type: () -> bool
    return True

  def is_kv_coder(self):
    # type: () -> bool
    return True

  def key_coder(self):
    return self

  def value_coder(self):
    return self

  def to_type_hint(self):
    return Any

  def to_runner_api_parameter(self, context):
    # type: (Optional[PipelineContext]) -> Tuple[str, Any, Sequence[Coder]]
    return (
        python_urns.PICKLED_CODER,
        google.protobuf.wrappers_pb2.BytesValue(value=serialize_coder(self)),
        ())

  def version_tag(self):
    return self._version_tag


class DeterministicFastPrimitivesCoder(FastCoder):
  """Throws runtime errors when encoding non-deterministic values."""
  def __init__(self, coder, step_label):
    self._underlying_coder = coder
    self._step_label = step_label

  def _create_impl(self):
    return coder_impl.FastPrimitivesCoderImpl(
        self._underlying_coder.get_impl(),
        requires_deterministic_step_label=self._step_label,
        force_use_dill=True)

  def is_deterministic(self):
    # type: () -> bool
    return True

  def is_kv_coder(self):
    # type: () -> bool
    return True

  def key_coder(self):
    return self

  def value_coder(self):
    return self

  def to_type_hint(self):
    return Any


def _should_force_use_dill():
  from apache_beam.options.pipeline_options_context import get_pipeline_options

  opts = get_pipeline_options()
  if opts is None or not opts.is_compat_version_prior_to("2.68.0"):
    return False

  try:
    import dill
    assert dill.__version__ == "0.3.1.1"
  except Exception as e:
    raise RuntimeError("This pipeline runs with the pipeline option " \
    "--update_compatibility_version=2.67.0 or earlier. When running with " \
    "this option on SDKs 2.68.0 or later, you must ensure dill==0.3.1.1 " \
    f"is installed. Error {e}")
  return True


def _update_compatible_deterministic_fast_primitives_coder(coder, step_label):
  """ Returns the update compatible version of DeterministicFastPrimitivesCoder
   The differences are in how "special types" e.g. NamedTuples, Dataclasses are
   deterministically encoded.

   - In SDK version <= 2.67.0 dill is used to encode "special types"
   - In SDK version 2.68.0 cloudpickle is used to encode "special types" with
   absolute filepaths in code objects and dynamic functions.
   - In SDK version 2.69.0 cloudpickle is used to encode "special types" with
   relative filepaths in code objects and dynamic functions.
  """
  if _should_force_use_dill():
    return DeterministicFastPrimitivesCoder(coder, step_label)
  return DeterministicFastPrimitivesCoderV2(coder, step_label)


class FastPrimitivesCoder(FastCoder):
  """Encodes simple primitives (e.g. str, int) efficiently.

  For unknown types, falls back to another coder (e.g. PickleCoder).
  """
  def __init__(self, fallback_coder=PickleCoder()):
    # type: (Coder) -> None
    self._fallback_coder = fallback_coder

  def _create_impl(self):
    return coder_impl.FastPrimitivesCoderImpl(self._fallback_coder.get_impl())

  def is_deterministic(self):
    # type: () -> bool
    return self._fallback_coder.is_deterministic()

  def as_deterministic_coder(self, step_label, error_message=None):
    if self.is_deterministic():
      return self
    else:
      return _update_compatible_deterministic_fast_primitives_coder(
          self, step_label)

  def to_type_hint(self):
    return Any

  # We allow .key_coder() and .value_coder() to be called on FastPrimitivesCoder
  # since we can't always infer the return values of lambdas in ParDo
  # operations, the result of which may be used in a GroupBykey.
  def is_kv_coder(self):
    # type: () -> bool
    return True

  def key_coder(self):
    return self

  def value_coder(self):
    return self

  def __eq__(self, other):
    return type(self) == type(other)

  def __hash__(self):
    return hash(type(self))


class FakeDeterministicFastPrimitivesCoder(FastPrimitivesCoder):
  """A FastPrimitivesCoder that claims to be deterministic.

  This can be registered as a fallback coder to go back to the behavior before
  deterministic encoding was enforced (BEAM-11719).
  """
  def is_deterministic(self):
    return True


class Base64PickleCoder(Coder):
  """Coder of objects by Python pickle, then base64 encoding."""

  # TODO(robertwb): Do base64 encoding where it's needed (e.g. in json) rather
  # than via a special Coder.

  def encode(self, value):
    return base64.b64encode(pickle.dumps(value, pickle.HIGHEST_PROTOCOL))

  def decode(self, encoded):
    return pickle.loads(base64.b64decode(encoded))

  def is_deterministic(self):
    # type: () -> bool
    # Note that the Base64PickleCoder is not deterministic.  See the
    # corresponding comments for PickleCoder above.
    return False

  # We allow .key_coder() and .value_coder() to be called on Base64PickleCoder
  # since we can't always infer the return values of lambdas in ParDo
  # operations, the result of which may be used in a GroupBykey.
  #
  # TODO(ccy): this is currently only used for KV values from Create transforms.
  # Investigate a way to unify this with PickleCoder.
  def is_kv_coder(self):
    # type: () -> bool
    return True

  def key_coder(self):
    return self

  def value_coder(self):
    return self


class ProtoCoder(FastCoder):
  """A Coder for Google Protocol Buffers.

  It supports both Protocol Buffers syntax versions 2 and 3. However,
  the runtime version of the python protobuf library must exactly match the
  version of the protoc compiler what was used to generate the protobuf
  messages.

  ProtoCoder is registered in the global CoderRegistry as the default coder for
  any protobuf Message object.

  """
  def __init__(self, proto_message_type):
    # type: (Type[google.protobuf.message.Message]) -> None
    self.proto_message_type = proto_message_type

  def _create_impl(self):
    return coder_impl.ProtoCoderImpl(self.proto_message_type)

  def is_deterministic(self):
    # type: () -> bool
    # TODO(vikasrk): A proto message can be deterministic if it does not contain
    # a Map.
    return False

  def as_deterministic_coder(self, step_label, error_message=None):
    return DeterministicProtoCoder(self.proto_message_type)

  def __eq__(self, other):
    return (
        type(self) == type(other) and
        self.proto_message_type == other.proto_message_type)

  def __hash__(self):
    return hash(self.proto_message_type)

  @classmethod
  def from_type_hint(cls, typehint, unused_registry):
    # The typehint must be a strict subclass of google.protobuf.message.Message.
    # ProtoCoder cannot work with message.Message itself, as deserialization of
    # a serialized proto requires knowledge of the desired concrete proto
    # subclass which is not stored in the encoded bytes themselves. If this
    # occurs, an error is raised and the system defaults to other fallback
    # coders.
    if (issubclass(typehint, proto_utils.message_types) and
        typehint != message.Message):
      return cls(typehint)
    else:
      raise ValueError((
          'Expected a strict subclass of google.protobuf.message.Message'
          ', but got a %s' % typehint))

  def to_type_hint(self):
    return self.proto_message_type


class DeterministicProtoCoder(ProtoCoder):
  """A deterministic Coder for Google Protocol Buffers.

  It supports both Protocol Buffers syntax versions 2 and 3. However,
  the runtime version of the python protobuf library must exactly match the
  version of the protoc compiler what was used to generate the protobuf
  messages.
  """
  def _create_impl(self):
    return coder_impl.DeterministicProtoCoderImpl(self.proto_message_type)

  def is_deterministic(self):
    # type: () -> bool
    return True

  def as_deterministic_coder(self, step_label, error_message=None):
    return self


class ProtoPlusCoder(FastCoder):
  """A Coder for Google Protocol Buffers wrapped using the proto-plus library.

  ProtoPlusCoder is registered in the global CoderRegistry as the default coder
  for any proto.Message object.
  """
  def __init__(self, proto_plus_message_type):
    # type: (Type[proto.Message]) -> None
    self.proto_plus_message_type = proto_plus_message_type

  def _create_impl(self):
    return coder_impl.ProtoPlusCoderImpl(self.proto_plus_message_type)

  def is_deterministic(self):
    return True

  def __eq__(self, other):
    return (
        type(self) == type(other) and
        self.proto_plus_message_type == other.proto_plus_message_type)

  def __hash__(self):
    return hash(self.proto_plus_message_type)

  @classmethod
  def from_type_hint(cls, typehint, unused_registry):
    if issubclass(typehint, proto.Message):
      return cls(typehint)
    else:
      raise ValueError(
          'Expected a subclass of proto.Message, but got a %s' % typehint)

  def to_type_hint(self):
    return self.proto_plus_message_type


AVRO_GENERIC_CODER_URN = "beam:coder:avro:generic:v1"


class AvroGenericCoder(FastCoder):
  """A coder used for AvroRecord values."""
  def __init__(self, schema):
    self.schema = schema

  def _create_impl(self):
    return coder_impl.AvroCoderImpl(self.schema)

  def is_deterministic(self):
    # TODO(https://github.com/apache/beam/issues/19628): need to confirm if
    # it's deterministic
    return False

  def __eq__(self, other):
    return type(self) == type(other) and self.schema == other.schema

  def __hash__(self):
    return hash(self.schema)

  def to_type_hint(self):
    return AvroRecord

  def to_runner_api_parameter(self, context):
    return AVRO_GENERIC_CODER_URN, self.schema.encode('utf-8'), ()

  @staticmethod
  @Coder.register_urn(AVRO_GENERIC_CODER_URN, bytes)
  def from_runner_api_parameter(payload, unused_components, unused_context):
    return AvroGenericCoder(payload.decode('utf-8'))


class TupleCoder(FastCoder):
  """Coder of tuple objects."""
  def __init__(self, components):
    # type: (Iterable[Coder]) -> None
    self._coders = tuple(components)

  def _create_impl(self):
    return coder_impl.TupleCoderImpl([c.get_impl() for c in self._coders])

  def is_deterministic(self):
    # type: () -> bool
    return all(c.is_deterministic() for c in self._coders)

  def as_deterministic_coder(self, step_label, error_message=None):
    if self.is_deterministic():
      return self
    else:
      return TupleCoder([
          c.as_deterministic_coder(step_label, error_message)
          for c in self._coders
      ])

  def to_type_hint(self):
    return typehints.Tuple[tuple(c.to_type_hint() for c in self._coders)]

  @classmethod
  def from_type_hint(cls, typehint, registry):
    # type: (typehints.TupleConstraint, CoderRegistry) -> TupleCoder
    return cls([registry.get_coder(t) for t in typehint.tuple_types])

  def _get_component_coders(self):
    # type: () -> Tuple[Coder, ...]
    return self.coders()

  def coders(self):
    # type: () -> Tuple[Coder, ...]
    return self._coders

  def is_kv_coder(self):
    # type: () -> bool
    return len(self._coders) == 2

  def key_coder(self):
    # type: () -> Coder
    if len(self._coders) != 2:
      raise ValueError('TupleCoder does not have exactly 2 components.')
    return self._coders[0]

  def value_coder(self):
    # type: () -> Coder
    if len(self._coders) != 2:
      raise ValueError('TupleCoder does not have exactly 2 components.')
    return self._coders[1]

  def __repr__(self):
    return 'TupleCoder[%s]' % ', '.join(str(c) for c in self._coders)

  def __eq__(self, other):
    return type(self) == type(other) and self._coders == other.coders()

  def __hash__(self):
    return hash(self._coders)

  def to_runner_api_parameter(self, context):
    if self.is_kv_coder():
      return common_urns.coders.KV.urn, None, self.coders()
    else:
      return python_urns.TUPLE_CODER, None, self.coders()

  @staticmethod
  @Coder.register_urn(common_urns.coders.KV.urn, None)
  @Coder.register_urn(python_urns.TUPLE_CODER, None)
  def from_runner_api_parameter(unused_payload, components, unused_context):
    return TupleCoder(components)


class TupleSequenceCoder(FastCoder):
  """Coder of homogeneous tuple objects."""
  def __init__(self, elem_coder):
    # type: (Coder) -> None
    self._elem_coder = elem_coder

  def value_coder(self):
    return self._elem_coder

  def _create_impl(self):
    return coder_impl.TupleSequenceCoderImpl(self._elem_coder.get_impl())

  def is_deterministic(self):
    # type: () -> bool
    return self._elem_coder.is_deterministic()

  def as_deterministic_coder(self, step_label, error_message=None):
    if self.is_deterministic():
      return self
    else:
      return TupleSequenceCoder(
          self._elem_coder.as_deterministic_coder(step_label, error_message))

  @classmethod
  def from_type_hint(cls, typehint, registry):
    # type: (Any, CoderRegistry) -> TupleSequenceCoder
    return cls(registry.get_coder(typehint.inner_type))

  def _get_component_coders(self):
    # type: () -> Tuple[Coder, ...]
    return (self._elem_coder, )

  def __repr__(self):
    return 'TupleSequenceCoder[%r]' % self._elem_coder

  def __eq__(self, other):
    return (
        type(self) == type(other) and self._elem_coder == other.value_coder())

  def __hash__(self):
    return hash((type(self), self._elem_coder))


class ListLikeCoder(FastCoder):
  """Coder of iterables of homogeneous objects."""
  def __init__(self, elem_coder):
    # type: (Coder) -> None
    self._elem_coder = elem_coder

  def _create_impl(self):
    return coder_impl.IterableCoderImpl(self._elem_coder.get_impl())

  def is_deterministic(self):
    # type: () -> bool
    return self._elem_coder.is_deterministic()

  def as_deterministic_coder(self, step_label, error_message=None):
    if self.is_deterministic():
      return self
    else:
      return type(self)(
          self._elem_coder.as_deterministic_coder(step_label, error_message))

  def value_coder(self):
    return self._elem_coder

  @classmethod
  def from_type_hint(cls, typehint, registry):
    # type: (Any, CoderRegistry) -> ListLikeCoder
    return cls(registry.get_coder(typehint.inner_type))

  def _get_component_coders(self):
    # type: () -> Tuple[Coder, ...]
    return (self._elem_coder, )

  def __repr__(self):
    return '%s[%r]' % (self.__class__.__name__, self._elem_coder)

  def __eq__(self, other):
    return (
        type(self) == type(other) and self._elem_coder == other.value_coder())

  def __hash__(self):
    return hash((type(self), self._elem_coder))


class IterableCoder(ListLikeCoder):
  """Coder of iterables of homogeneous objects."""
  def to_type_hint(self):
    return typehints.Iterable[self._elem_coder.to_type_hint()]


Coder.register_structured_urn(common_urns.coders.ITERABLE.urn, IterableCoder)


class ListCoder(ListLikeCoder):
  """Coder of Python lists."""
  def to_type_hint(self):
    return typehints.List[self._elem_coder.to_type_hint()]

  def _create_impl(self):
    return coder_impl.ListCoderImpl(self._elem_coder.get_impl())


class GlobalWindowCoder(SingletonCoder):
  """Coder for global windows."""
  def __init__(self):
    from apache_beam.transforms import window
    super().__init__(window.GlobalWindow())


Coder.register_structured_urn(
    common_urns.coders.GLOBAL_WINDOW.urn, GlobalWindowCoder)


class IntervalWindowCoder(FastCoder):
  """Coder for an window defined by a start timestamp and a duration."""
  def _create_impl(self):
    return coder_impl.IntervalWindowCoderImpl()

  def is_deterministic(self):
    # type: () -> bool
    return True

  def __eq__(self, other):
    return type(self) == type(other)

  def __hash__(self):
    return hash(type(self))


Coder.register_structured_urn(
    common_urns.coders.INTERVAL_WINDOW.urn, IntervalWindowCoder)


class _OrderedUnionCoder(FastCoder):
  def __init__(
      self, *coder_types: Tuple[type, Coder], fallback_coder: Optional[Coder]):
    self._coder_types = coder_types
    self._fallback_coder = fallback_coder

  def _create_impl(self):
    return coder_impl._OrderedUnionCoderImpl(
        [(t, c.get_impl()) for t, c in self._coder_types],
        fallback_coder_impl=self._fallback_coder.get_impl()
        if self._fallback_coder else None)

  def is_deterministic(self) -> bool:
    return (
        all(c.is_deterministic() for _, c in self._coder_types) and (
            self._fallback_coder is None or
            self._fallback_coder.is_deterministic()))

  def to_type_hint(self):
    return Any

  def __eq__(self, other):
    return (
        type(self) == type(other) and
        self._coder_types == other._coder_types and
        self._fallback_coder == other._fallback_coder)

  def __hash__(self):
    return hash((type(self), tuple(self._coder_types), self._fallback_coder))


class WindowedValueCoder(FastCoder):
  """Coder for windowed values."""
  def __init__(self, wrapped_value_coder, window_coder=None):
    # type: (Coder, Optional[Coder]) -> None
    if not window_coder:
      # Avoid circular imports.
      from apache_beam.transforms import window
      window_coder = _OrderedUnionCoder(
          (window.GlobalWindow, GlobalWindowCoder()),
          (window.IntervalWindow, IntervalWindowCoder()),
          fallback_coder=PickleCoder())
    self.wrapped_value_coder = wrapped_value_coder
    self.timestamp_coder = TimestampCoder()
    self.window_coder = window_coder

  def _create_impl(self):
    return coder_impl.WindowedValueCoderImpl(
        self.wrapped_value_coder.get_impl(),
        self.timestamp_coder.get_impl(),
        self.window_coder.get_impl())

  def is_deterministic(self):
    # type: () -> bool
    return all(
        c.is_deterministic() for c in
        [self.wrapped_value_coder, self.timestamp_coder, self.window_coder])

  def _get_component_coders(self):
    # type: () -> List[Coder]
    return [self.wrapped_value_coder, self.window_coder]

  def is_kv_coder(self):
    # type: () -> bool
    return self.wrapped_value_coder.is_kv_coder()

  def key_coder(self):
    # type: () -> Coder
    return self.wrapped_value_coder.key_coder()

  def value_coder(self):
    # type: () -> Coder
    return self.wrapped_value_coder.value_coder()

  def __repr__(self):
    return (
        f'WindowedValueCoder[window_coder={self.window_coder}, '
        f'wrapped_value_coder={self.wrapped_value_coder}]')

  def __eq__(self, other):
    return (
        type(self) == type(other) and
        self.wrapped_value_coder == other.wrapped_value_coder and
        self.timestamp_coder == other.timestamp_coder and
        self.window_coder == other.window_coder)

  def __hash__(self):
    return hash(
        (self.wrapped_value_coder, self.timestamp_coder, self.window_coder))

  @classmethod
  def from_type_hint(cls, typehint, registry):
    # type: (Any, CoderRegistry) -> WindowedValueCoder
    # Ideally this'd take two parameters so that one could hint at
    # the window type as well instead of falling back to the
    # pickle coders.
    return cls(registry.get_coder(typehint.inner_type))

  def to_type_hint(self):
    return typehints.WindowedValue[self.wrapped_value_coder.to_type_hint()]


Coder.register_structured_urn(
    common_urns.coders.WINDOWED_VALUE.urn, WindowedValueCoder)


class ParamWindowedValueCoder(WindowedValueCoder):
  """A coder used for parameterized windowed values."""
  def __init__(self, payload, components):
    super().__init__(components[0], components[1])
    self.payload = payload

  def _create_impl(self):
    return coder_impl.ParamWindowedValueCoderImpl(
        self.wrapped_value_coder.get_impl(),
        self.window_coder.get_impl(),
        self.payload)

  def is_deterministic(self):
    # type: () -> bool
    return self.wrapped_value_coder.is_deterministic()

  def __repr__(self):
    return 'ParamWindowedValueCoder[%s]' % self.wrapped_value_coder

  def __eq__(self, other):
    return (
        type(self) == type(other) and
        self.wrapped_value_coder == other.wrapped_value_coder and
        self.window_coder == other.window_coder and
        self.payload == other.payload)

  def __hash__(self):
    return hash((self.wrapped_value_coder, self.window_coder, self.payload))

  @staticmethod
  @Coder.register_urn(common_urns.coders.PARAM_WINDOWED_VALUE.urn, bytes)
  def from_runner_api_parameter(payload, components, unused_context):
    return ParamWindowedValueCoder(payload, components)

  def to_runner_api_parameter(self, context):
    return (
        common_urns.coders.PARAM_WINDOWED_VALUE.urn,
        self.payload, (self.wrapped_value_coder, self.window_coder))


class LengthPrefixCoder(FastCoder):
  """For internal use only; no backwards-compatibility guarantees.

  Coder which prefixes the length of the encoded object in the stream."""
  def __init__(self, value_coder):
    # type: (Coder) -> None
    self._value_coder = value_coder

  def _create_impl(self):
    return coder_impl.LengthPrefixCoderImpl(self._value_coder.get_impl())

  def is_deterministic(self):
    # type: () -> bool
    return self._value_coder.is_deterministic()

  def estimate_size(self, value):
    value_size = self._value_coder.estimate_size(value)
    return get_varint_size(value_size) + value_size

  def value_coder(self):
    return self._value_coder

  def _get_component_coders(self):
    # type: () -> Tuple[Coder, ...]
    return (self._value_coder, )

  def __repr__(self):
    return 'LengthPrefixCoder[%r]' % self._value_coder

  def __eq__(self, other):
    return (
        type(self) == type(other) and self._value_coder == other._value_coder)

  def __hash__(self):
    return hash((type(self), self._value_coder))

  def to_type_hint(length_prefix_coder):
    return length_prefix_coder.value_coder().to_type_hint()


Coder.register_structured_urn(
    common_urns.coders.LENGTH_PREFIX.urn, LengthPrefixCoder)


class StateBackedIterableCoder(FastCoder):
  DEFAULT_WRITE_THRESHOLD = 1

  def __init__(
      self,
      element_coder,  # type: Coder
      read_state=None,  # type: Optional[coder_impl.IterableStateReader]
      write_state=None,  # type: Optional[coder_impl.IterableStateWriter]
      write_state_threshold=DEFAULT_WRITE_THRESHOLD):
    self._element_coder = element_coder
    self._read_state = read_state
    self._write_state = write_state
    self._write_state_threshold = write_state_threshold

  def _create_impl(self):
    return coder_impl.IterableCoderImpl(
        self._element_coder.get_impl(),
        self._read_state,
        self._write_state,
        self._write_state_threshold)

  def is_deterministic(self):
    # type: () -> bool
    return False

  def _get_component_coders(self):
    # type: () -> Tuple[Coder, ...]
    return (self._element_coder, )

  def __repr__(self):
    return 'StateBackedIterableCoder[%r]' % self._element_coder

  def __eq__(self, other):
    return (
        type(self) == type(other) and
        self._element_coder == other._element_coder and
        self._write_state_threshold == other._write_state_threshold)

  def __hash__(self):
    return hash((type(self), self._element_coder, self._write_state_threshold))

  def to_runner_api_parameter(self, context):
    # type: (Optional[PipelineContext]) -> Tuple[str, Any, Sequence[Coder]]
    return (
        common_urns.coders.STATE_BACKED_ITERABLE.urn,
        str(self._write_state_threshold).encode('ascii'),
        self._get_component_coders())

  @staticmethod
  @Coder.register_urn(common_urns.coders.STATE_BACKED_ITERABLE.urn, bytes)
  def from_runner_api_parameter(payload, components, context):
    return StateBackedIterableCoder(
        components[0],
        read_state=context.iterable_state_read,
        write_state=context.iterable_state_write,
        write_state_threshold=int(payload)
        if payload else StateBackedIterableCoder.DEFAULT_WRITE_THRESHOLD)


class ShardedKeyCoder(FastCoder):
  """A coder for sharded key."""
  def __init__(self, key_coder):
    # type: (Coder) -> None
    self._key_coder = key_coder

  def _get_component_coders(self):
    # type: () -> List[Coder]
    return [self._key_coder]

  def _create_impl(self):
    return coder_impl.ShardedKeyCoderImpl(self._key_coder.get_impl())

  def is_deterministic(self):
    # type: () -> bool
    return self._key_coder.is_deterministic()

  def to_type_hint(self):
    from apache_beam.typehints import sharded_key_type
    return sharded_key_type.ShardedKeyTypeConstraint(
        self._key_coder.to_type_hint())

  @classmethod
  def from_type_hint(cls, typehint, registry):
    from apache_beam.typehints import sharded_key_type
    if isinstance(typehint, sharded_key_type.ShardedKeyTypeConstraint):
      return cls(registry.get_coder(typehint.key_type))
    else:
      raise ValueError((
          'Expected an instance of ShardedKeyTypeConstraint'
          ', but got a %s' % typehint))

  def __eq__(self, other):
    return type(self) == type(other) and self._key_coder == other._key_coder

  def __hash__(self):
    return hash(type(self)) + hash(self._key_coder)

  def __repr__(self):
    return 'ShardedKeyCoder[%s]' % self._key_coder


Coder.register_structured_urn(
    common_urns.coders.SHARDED_KEY.urn, ShardedKeyCoder)


class TimestampPrefixingWindowCoder(FastCoder):
  """For internal use only; no backwards-compatibility guarantees.

  Coder which prefixes the max timestamp of arbitrary window to its encoded
  form."""
  def __init__(self, window_coder: Coder) -> None:
    self._window_coder = window_coder

  def _create_impl(self):
    return coder_impl.TimestampPrefixingWindowCoderImpl(
        self._window_coder.get_impl())

  def to_type_hint(self):
    return self._window_coder.to_type_hint()

  def _get_component_coders(self) -> List[Coder]:
    return [self._window_coder]

  def is_deterministic(self) -> bool:
    return self._window_coder.is_deterministic()

  def __repr__(self):
    return 'TimestampPrefixingWindowCoder[%r]' % self._window_coder

  def __eq__(self, other):
    return (
        type(self) == type(other) and self._window_coder == other._window_coder)

  def __hash__(self):
    return hash((type(self), self._window_coder))


Coder.register_structured_urn(
    common_urns.coders.CUSTOM_WINDOW.urn, TimestampPrefixingWindowCoder)


class TimestampPrefixingOpaqueWindowCoder(FastCoder):
  """For internal use only; no backwards-compatibility guarantees.

  Coder which decodes windows as bytes."""
  def __init__(self) -> None:
    pass

  def _create_impl(self):
    return coder_impl.TimestampPrefixingOpaqueWindowCoderImpl()

  def is_deterministic(self) -> bool:
    return True

  def __repr__(self):
    return 'TimestampPrefixingOpaqueWindowCoder'

  def __eq__(self, other):
    return type(self) == type(other)

  def __hash__(self):
    return hash((type(self)))


Coder.register_structured_urn(
    python_urns.TIMESTAMP_PREFIXED_OPAQUE_WINDOW_CODER,
    TimestampPrefixingOpaqueWindowCoder)


class BigIntegerCoder(FastCoder):
  def _create_impl(self):
    return coder_impl.BigIntegerCoderImpl()

  def is_deterministic(self):
    # type: () -> bool
    return True

  def to_type_hint(self):
    return int

  def __eq__(self, other):
    return type(self) == type(other)

  def __hash__(self):
    return hash(type(self))


class PaneInfoCoder(FastCoder):
  def _create_impl(self):
    return coder_impl.PaneInfoCoderImpl()

  def is_deterministic(self):
    # type: () -> bool
    return True

  def to_type_hint(self):
    return windowed_value.PaneInfo

  def __eq__(self, other):
    return type(self) == type(other)

  def __hash__(self):
    return hash(type(self))


class DecimalCoder(FastCoder):
  def _create_impl(self):
    return coder_impl.DecimalCoderImpl()

  def is_deterministic(self):
    # type: () -> bool
    return True

  def to_type_hint(self):
    return decimal.Decimal

  def __eq__(self, other):
    return type(self) == type(other)

  def __hash__(self):
    return hash(type(self))
