Converts a Firestore protobuf ``Value`` to a native Python value.

    Args:
        value (google.cloud.firestore_v1beta1.types.Value): A
            Firestore protobuf to be decoded / parsed / converted.
        client (~.firestore_v1beta1.client.Client): A client that has
            a document factory.

    Returns:
        Union[NoneType, bool, int, float, datetime.datetime, \
            str, bytes, dict, ~google.cloud.Firestore.GeoPoint]: A native
        Python value converted from the ``value``.

    Raises:
        NotImplementedError: If the ``value_type`` is ``reference_value``.
        ValueError: If the ``value_type`` is unknown.

def decode_value(value, client):
    """Converts a Firestore protobuf ``Value`` to a native Python value.

    Args:
        value (google.cloud.firestore_v1beta1.types.Value): A
            Firestore protobuf to be decoded / parsed / converted.
        client (~.firestore_v1beta1.client.Client): A client that has
            a document factory.

    Returns:
        Union[NoneType, bool, int, float, datetime.datetime, \
            str, bytes, dict, ~google.cloud.Firestore.GeoPoint]: A native
        Python value converted from the ``value``.

    Raises:
        NotImplementedError: If the ``value_type`` is ``reference_value``.
        ValueError: If the ``value_type`` is unknown.
    """
    value_type = value.WhichOneof("value_type")

    if value_type == "null_value":
        return None
    elif value_type == "boolean_value":
        return value.boolean_value
    elif value_type == "integer_value":
        return value.integer_value
    elif value_type == "double_value":
        return value.double_value
    elif value_type == "timestamp_value":
        return DatetimeWithNanoseconds.from_timestamp_pb(value.timestamp_value)
    elif value_type == "string_value":
        return value.string_value
    elif value_type == "bytes_value":
        return value.bytes_value
    elif value_type == "reference_value":
        return reference_value_to_document(value.reference_value, client)
    elif value_type == "geo_point_value":
        return GeoPoint(value.geo_point_value.latitude, value.geo_point_value.longitude)
    elif value_type == "array_value":
        return [decode_value(element, client) for element in value.array_value.values]
    elif value_type == "map_value":
        return decode_dict(value.map_value.fields, client)
    else:
        raise ValueError("Unknown ``value_type``", value_type)