Deserializes `nested_proto`.

  Args:
    nested_proto: An instance of `module_pb2.NestedData`.
    process_leafs: A function to be applied to the leaf values of the nested
      structure.

  Returns:
    An instance of `string`, `tuple`, `dict` or `namedtuple`.

  Raises:
    base_errors.ModuleInfoError: If the probobuf is of the wrong type or
      if some of its fields are missing.

def _nested_from_proto(nested_proto, process_leafs):
  """Deserializes `nested_proto`.

  Args:
    nested_proto: An instance of `module_pb2.NestedData`.
    process_leafs: A function to be applied to the leaf values of the nested
      structure.

  Returns:
    An instance of `string`, `tuple`, `dict` or `namedtuple`.

  Raises:
    base_errors.ModuleInfoError: If the probobuf is of the wrong type or
      if some of its fields are missing.
  """
  if not isinstance(nested_proto, module_pb2.NestedData):
    raise base_errors.ModuleInfoError("Expected module_pb2.NestedData.")

  if nested_proto.HasField("value"):
    value = nested_proto.value
    if not value:
      value = _UnserializableObject()
    else:
      value = process_leafs(value)
    return value
  elif nested_proto.HasField("list"):
    return [_nested_from_proto(child, process_leafs)
            for child in nested_proto.list.list]
  elif nested_proto.HasField("tuple"):
    return tuple(_nested_from_proto(child, process_leafs)
                 for child in nested_proto.tuple.list)
  elif nested_proto.HasField("dict"):
    return {name: _nested_from_proto(child, process_leafs)
            for name, child in six.iteritems(nested_proto.dict.map)}
  elif nested_proto.HasField("named_tuple"):
    tmp_dict = {name: _nested_from_proto(child, process_leafs)
                for name, child in six.iteritems(nested_proto.named_tuple.map)}
    # Note that this needs to be a named tuple to work with existing usage.
    NamedTuple = collections.namedtuple(  # pylint: disable=invalid-name
        nested_proto.named_tuple.name, tmp_dict.keys())
    return NamedTuple(**tmp_dict)
  elif nested_proto.HasField("special_type"):
    if nested_proto.special_type.name not in _TO_PROTO_SPECIAL_TYPES:
      return _UnserializableObject()
    type_info = _TO_PROTO_SPECIAL_TYPES[nested_proto.special_type.name]
    return type_info.from_proto(nested_proto.special_type.object, process_leafs)
  else:
    raise base_errors.ModuleInfoError(
        "Cannot deserialize a `ModuleInfo` protobuf with no fields.")