<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 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)