//  [java]
    private static Bytes decodePercentsAndEncodeToUtf8(String value, int start, int end, boolean isPath) {
        final int length = end - start;
        if (length == 0) {
            return isPath ? ROOT_PATH : EMPTY_QUERY;
        }

        final Bytes buf = new Bytes(Math.max(length * 3 / 2, 4));
        boolean wasSlash = false;
        for (final CodePointIterator i = new CodePointIterator(value, start, end);
             i.hasNextCodePoint();/* noop */) {
            final int pos = i.position();
            final int cp = i.nextCodePoint();

            if (cp == '%') {
                final int hexEnd = pos + 3;
                if (hexEnd > end) {
                    // '%' or '%x' (must be followed by two hexadigits)
                    return null;
                }

                final int digit1 = decodeHexNibble(value.charAt(pos + 1));
                final int digit2 = decodeHexNibble(value.charAt(pos + 2));
                if (digit1 < 0 || digit2 < 0) {
                    // The first or second digit is not hexadecimal.
                    return null;
                }

                final int decoded = (digit1 << 4) | digit2;
                if (isPath) {
                    if (decoded == '/') {
                        // Do not decode '%2F' and '%2f' in the path to '/' for compatibility with
                        // other implementations in the ecosystem, e.g. HTTP/JSON to gRPC transcoding.
                        // https://github.com/googleapis/googleapis/blob/02710fa0ea5312d79d7fb986c9c9823fb41049a9/google/api/http.proto#L257-L258
                        buf.ensure(1);
                        buf.addEncoded((byte) '/');
                        wasSlash = false;
                    } else {
                        if (appendOneByte(buf, decoded, wasSlash, isPath)) {
                            wasSlash = false;
                        } else {
                            return null;
                        }
                    }
                } else {
                    // If query:
                    if (RESERVED_CHARS.get(decoded)) {
                        buf.ensure(1);
                        buf.addEncoded((byte) decoded);
                        wasSlash = false;
                    } else if (appendOneByte(buf, decoded, wasSlash, isPath)) {
                        wasSlash = decoded == '/';
                    } else {
                        return null;
                    }
                }

                i.position(hexEnd);
                continue;
            }

            if (cp == '+' && !isPath) {
                buf.ensure(1);
                buf.addEncoded((byte) ' ');
                wasSlash = false;
                continue;
            }

            if (cp <= 0x7F) {
                if (!appendOneByte(buf, cp, wasSlash, isPath)) {
                    return null;
                }
                wasSlash = cp == '/';
                continue;
            }

            if (cp <= 0x7ff) {
                buf.ensure(2);
                buf.addEncoded((byte) ((cp >>> 6) | 0b110_00000));
                buf.addEncoded((byte) (cp & 0b111111 | 0b10_000000));
            } else if (cp <= 0xffff) {
                buf.ensure(3);
                buf.addEncoded((byte) ((cp >>> 12) | 0b1110_0000));
                buf.addEncoded((byte) (((cp >>> 6) & 0b111111) | 0b10_000000));
                buf.addEncoded((byte) ((cp & 0b111111) | 0b10_000000));
            } else if (cp <= 0x1fffff) {
                buf.ensure(4);
                buf.addEncoded((byte) ((cp >>> 18) | 0b11110_000));
                buf.addEncoded((byte) (((cp >>> 12) & 0b111111) | 0b10_000000));
                buf.addEncoded((byte) (((cp >>> 6) & 0b111111) | 0b10_000000));
                buf.addEncoded((byte) ((cp & 0b111111) | 0b10_000000));
            } else if (cp <= 0x3ffffff) {
                // A valid unicode character will never reach here, but for completeness.
                // http://unicode.org/mail-arch/unicode-ml/Archives-Old/UML018/0330.html
                buf.ensure(5);
                buf.addEncoded((byte) ((cp >>> 24) | 0b111110_00));
                buf.addEncoded((byte) (((cp >>> 18) & 0b111111) | 0b10_000000));
                buf.addEncoded((byte) (((cp >>> 12) & 0b111111) | 0b10_000000));
                buf.addEncoded((byte) (((cp >>> 6) & 0b111111) | 0b10_000000));
                buf.addEncoded((byte) ((cp & 0b111111) | 0b10_000000));
            } else {
                // A valid unicode character will never reach here, but for completeness.
                // http://unicode.org/mail-arch/unicode-ml/Archives-Old/UML018/0330.html
                buf.ensure(6);
                buf.addEncoded((byte) ((cp >>> 30) | 0b1111110_0));
                buf.addEncoded((byte) (((cp >>> 24) & 0b111111) | 0b10_000000));
                buf.addEncoded((byte) (((cp >>> 18) & 0b111111) | 0b10_000000));
                buf.addEncoded((byte) (((cp >>> 12) & 0b111111) | 0b10_000000));
                buf.addEncoded((byte) (((cp >>> 6) & 0b111111) | 0b10_000000));
                buf.addEncoded((byte) ((cp & 0b111111) | 0b10_000000));
            }

            wasSlash = false;
        }

        return buf;
    }