code: def _walk_fields(proto: message.Message, fields: FieldTypes):
      """Yields fields in a proto.
  
      Args:
        proto: Parent proto of any message type.
        fields: List of string/int/map key fields, e.g. ["nodes", "attr", "value"]
          can represent `proto.nodes.attr["value"]`.
  
      Yields:
        Tuple of (
          Field in the proto or `None` if none are found,
          Field descriptor,
          Key into this map field (or None),
          Index into this repeated field (or None))
      """
      if not isinstance(fields, list):
          fields = [fields]
  
      field_proto = proto
      parent_desc = proto.DESCRIPTOR
      i = 0
      while i < len(fields):
          field = fields[i]
          field_desc = None
          map_key = None
          index = None
  
          if parent_desc is None:
              raise ValueError(
                  f"Unable to find fields: {fields} in proto of type {type(proto)}."
              )
  
          if isinstance(field, int):
              try:
                  field_desc = parent_desc.fields_by_number[field]
              except KeyError:
                  raise KeyError(  # pylint:disable=raise-missing-from
                      f"Unable to find field number {field} in {parent_desc.full_name}. "
                      f"Valid field numbers: {parent_desc.fields_by_number.keys()}"
                  )
          elif isinstance(field, str):
              try:
                  field_desc = parent_desc.fields_by_name[field]
              except KeyError:
                  raise KeyError(  # pylint:disable=raise-missing-from
                      f"Unable to find field '{field}' in {parent_desc.full_name}. "
                      f"Valid field names: {parent_desc.fields_by_name.keys()}"
                  )
          else:  # bool (only expected as map key)
              raise TypeError("Unexpected bool found in field list.")
  
          i += 1
          parent_desc = field_desc.message_type
          if field_proto is not None:
              field_proto = getattr(field_proto, field_desc.name)
  
          # Handle special fields types (map key and list index).
          if _is_map(parent_desc) and i < len(fields):
              # Next field is the map key.
              map_key = fields[i]
  
              try:
                  field_proto = (
                      field_proto[map_key]
                      if field_proto is not None
                      else None
                  )
              except KeyError:
                  field_proto = None
              i += 1
  
              if i < len(fields):
                  # The next field must be from the Value Message.
                  value_desc = parent_desc.fields_by_name["value"]
                  assert value_desc.message_type is not None
                  parent_desc = value_desc.message_type
  
          elif is_repeated(field_desc) and i < len(fields):
              # The next field is the index within the list.
              index = fields[i]
              try:
                  field_proto = (
                      field_proto[index]
                      if field_proto is not None
                      else None
                  )
              except IndexError:
                  field_proto = None
              i += 1
  
          yield field_proto, field_desc, map_key, index
  
file_path: tensorflow/tensorflow/tools/proto_splitter/util.py
imports: from collections.abc import Sequence
  from typing import Any, Optional, Union
  from google.protobuf import descriptor
  from google.protobuf import message
  from tensorflow.tools.proto_splitter import chunk_pb2
label_desc: Use image node_id 4 for calling a global function with example usage: _walk_fields(proto, fields) without return types