docs: def decipher_response(status_code: int, headers: Mapping[str, str],
                        body: bytes) -> Tuple[Any, Optional[RateLimit], Optional[str]]:
      """Decipher an HTTP response for a GitHub API request.
  
      The mapping providing the headers is expected to support lowercase keys.
  
      The parameters of this function correspond to the three main parts
      of an HTTP response: the status code, headers, and body. Assuming
      no errors which lead to an exception being raised, a 3-item tuple
      is returned. The first item is the decoded body (typically a JSON
      object, but possibly None or a string depending on the content
      type of the body). The second item is an instance of RateLimit
      based on what the response specified.
  
      The last item of the tuple is the URL where to request the next
      part of results. If there are no more results then None is
      returned. Do be aware that the URL can be a URI template and so
      may need to be expanded.
  
      If the status code is anything other than 200, 201, or 204, then
      an HTTPException is raised.
      """
      data = _decode_body(headers.get("content-type"), body)
      if status_code in {200, 201, 204}:
          return data, RateLimit.from_http(headers), _next_link(headers.get("link"))
      else:
          try:
              message = data["message"]
          except (TypeError, KeyError):
              message = None
          exc_type: Type[HTTPException]
          if status_code >= 500:
              exc_type = GitHubBroken
          elif status_code >= 400:
              exc_type = BadRequest
              if status_code == 403:
                  rate_limit = RateLimit.from_http(headers)
                  if rate_limit and not rate_limit.remaining:
                      raise RateLimitExceeded(rate_limit, message)
              elif status_code == 422:
                  errors = data.get("errors", None)
                  if errors:
                      fields = ", ".join(repr(e["field"]) for e in errors)
                      message = f"{message} for {fields}"
                  else:
                      message = data["message"]
                  raise InvalidField(errors, message)
          elif status_code >= 300:
              exc_type = RedirectionException
          else:
              exc_type = HTTPException
          status_code_enum = http.HTTPStatus(status_code)
          args: Union[Tuple[http.HTTPStatus, str], Tuple[http.HTTPStatus]]
          if message:
              args = status_code_enum, message
          else:
              args = status_code_enum,
          raise exc_type(*args)