private function scanCodepoint(): string
    {
        $buffer = &$this->buffer;
        $offset = &$this->offset;

        $codepoint = $buffer[$offset++];
        $ord = \ord($codepoint);

        if (!($ord >> 7)) {
            return $codepoint;
        }

        if (!(($ord >> 5) ^ 0b110)) {
            $expect = 1;
        } elseif (!(($ord >> 4) ^ 0b1110)) {
            $expect = 2;
        } elseif (!(($ord >> 3) ^ 0b11110)) {
            $expect = 3;
        } else {
            $expect = 0; // This'll throw in just a moment.
        }

        $continuationBytes = "";
        do {
            $temp = \substr($buffer, $offset, $expect);
            $deltaLength = \strlen($temp);
            $expect -= $deltaLength;
            $continuationBytes .= $temp;
        } while ($expect > 0 && $this->refillBuffer());

        $offset += $deltaLength;

        for (
            $i = 0, $continuationBytesLength = \strlen($continuationBytes);
            $i < $continuationBytesLength;
            $i++
        ) {
            $byte = $continuationBytes[$i];

            if ((\ord($byte) >> 6) ^ 0b10) {
                break;
            }

            $codepoint .= $byte;
        }

        $chr = \IntlChar::chr($codepoint);

        if ($chr === null) {
            throw new ParseException($this->getIllFormedUtf8ExceptionMessage($codepoint));
        }

        return $chr;
    }