code: private static String percentDecode(String encoded)
      {
          Preconditions.checkArgument(ascii().matchesAllOf(encoded), "string must be ASCII");
  
          ByteArrayOutputStream out = new ByteArrayOutputStream(encoded.length());
          for (int i = 0; i < encoded.length(); i++) {
              char c = encoded.charAt(i);
  
              if (c == '%') {
                  Preconditions.checkArgument(i + 2 < encoded.length(), "percent encoded value is truncated");
  
                  int high = Character.digit(encoded.charAt(i + 1), 16);
                  int low = Character.digit(encoded.charAt(i + 2), 16);
  
                  Preconditions.checkArgument(high != -1 && low != -1, "percent encoded value is not a valid hex string: ", encoded.substring(i, i + 2));
  
                  int value = (high << 4) | (low);
                  out.write(value);
                  i += 2;
              }
              else {
                  out.write((int) c);
              }
          }
  
          try {
              return UTF_8.newDecoder()
                      .onMalformedInput(CodingErrorAction.REPORT)
                      .decode(ByteBuffer.wrap(out.toByteArray()))
                      .toString();
          }
          catch (CharacterCodingException e) {
              throw new IllegalArgumentException("input does not represent a proper UTF8-encoded string");
          }
      }
docs: input must be an ASCII string representing a percent-encoded UTF-8 byte sequence