docs: private static Url parseUrl(final String spec) {
  		final Url url = new Url();
  		int startIndex = 0;
  		int endIndex = spec.length();
  
  		// Section 2.4.1: Parsing the Fragment Identifier
  		//
  		// If the parse string contains a crosshatch "#" character, then the
  		// substring after the first (left-most) crosshatch "#" and up to the
  		// end of the parse string is the <fragment> identifier. If the
  		// crosshatch is the last character, or no crosshatch is present, then
  		// the fragment identifier is empty. The matched substring, including
  		// the crosshatch character, is removed from the parse string before
  		// continuing.
  		//
  		// Note that the fragment identifier is not considered part of the URL.
  		// However, since it is often attached to the URL, parsers must be able
  		// to recognize and set aside fragment identifiers as part of the
  		// process.
  		final int crosshatchIndex = indexOf(spec, '#', startIndex, endIndex);
  
  		if (crosshatchIndex >= 0) {
  			url.fragment_ = spec.substring(crosshatchIndex + 1, endIndex);
  			endIndex = crosshatchIndex;
  		}
  		// Section 2.4.2: Parsing the Scheme
  		//
  		// If the parse string contains a colon ":" after the first character
  		// and before any characters not allowed as part of a scheme name (i.e.,
  		// any not an alphanumeric, plus "+", period ".", or hyphen "-"), the
  		// <scheme> of the URL is the substring of characters up to but not
  		// including the first colon. These characters and the colon are then
  		// removed from the parse string before continuing.
  		final int colonIndex = indexOf(spec, ':', startIndex, endIndex);
  
  		if (colonIndex > 0) {
  			final String scheme = spec.substring(startIndex, colonIndex);
  			if (isValidScheme(scheme)) {
  				url.scheme_ = scheme;
  				startIndex = colonIndex + 1;
  			}
  		}
  
  		// Section 2.4.3: Parsing the Network Location/Login
  		//
  		// If the parse string begins with a double-slash "//", then the
  		// substring of characters after the double-slash and up to, but not
  		// including, the next slash "/" character is the network location/login
  		// (<net_loc>) of the URL. If no trailing slash "/" is present, the
  		// entire remaining parse string is assigned to <net_loc>. The double-
  		// slash and <net_loc> are removed from the parse string before
  		// continuing.
  		//
  		// Note: We also accept a question mark "?" or a semicolon ";" character as
  		// delimiters for the network location/login (<net_loc>) of the URL.
  		final int locationStartIndex;
  		int locationEndIndex;
  
  		if (spec.startsWith("//", startIndex)) {
  			locationStartIndex = startIndex + 2;
  			locationEndIndex = indexOf(spec, '/', locationStartIndex, endIndex);
  			if (locationEndIndex >= 0) {
  				startIndex = locationEndIndex;
  			}
  		} else {
  			locationStartIndex = -1;
  			locationEndIndex = -1;
  		}
  		// Section 2.4.4: Parsing the Query Information
  		//
  		// If the parse string contains a question mark "?" character, then the
  		// substring after the first (left-most) question mark "?" and up to the
  		// end of the parse string is the <query> information. If the question
  		// mark is the last character, or no question mark is present, then the
  		// query information is empty. The matched substring, including the
  		// question mark character, is removed from the parse string before
  		// continuing.
  		final int questionMarkIndex = indexOf(spec, '?', startIndex, endIndex);
  
  		if (questionMarkIndex >= 0) {
  			if ((locationStartIndex >= 0) && (locationEndIndex < 0)) {
  				// The substring of characters after the double-slash and up to, but not
  				// including, the question mark "?" character is the network location/login
  				// (<net_loc>) of the URL.
  				locationEndIndex = questionMarkIndex;
  				startIndex = questionMarkIndex;
  			}
  			url.query_ = spec.substring(questionMarkIndex + 1, endIndex);
  			endIndex = questionMarkIndex;
  		}
  		// Section 2.4.5: Parsing the Parameters
  		//
  		// If the parse string contains a semicolon ";" character, then the
  		// substring after the first (left-most) semicolon ";" and up to the end
  		// of the parse string is the parameters (<params>). If the semicolon
  		// is the last character, or no semicolon is present, then <params> is
  		// empty. The matched substring, including the semicolon character, is
  		// removed from the parse string before continuing.
  		final int semicolonIndex = indexOf(spec, ';', startIndex, endIndex);
  
  		if (semicolonIndex >= 0) {
  			if ((locationStartIndex >= 0) && (locationEndIndex < 0)) {
  				// The substring of characters after the double-slash and up to, but not
  				// including, the semicolon ";" character is the network location/login
  				// (<net_loc>) of the URL.
  				locationEndIndex = semicolonIndex;
  				startIndex = semicolonIndex;
  			}
  			url.parameters_ = spec.substring(semicolonIndex + 1, endIndex);
  			endIndex = semicolonIndex;
  		}
  
  		// Section 2.4.6: Parsing the Path
  		//
  		// After the above steps, all that is left of the parse string is the URL <path> and the
  		// slash "/" that may precede it. Even though the initial slash is not part of the URL path,
  		// the parser must remember whether or not it was present so that later processes can
  		// differentiate between relative and absolute paths. Often this is done by simply storing
  		// the preceding slash along with the path.
  		if ((locationStartIndex >= 0) && (locationEndIndex < 0)) {
  			// The entire remaining parse string is assigned to the network location/login
  			// (<net_loc>) of the URL.
  			locationEndIndex = endIndex;
  		} else if (startIndex < endIndex) {
  			url.path_ = spec.substring(startIndex, endIndex);
  		}
  		// Set the network location/login (<net_loc>) of the URL.
  		if ((locationStartIndex >= 0) && (locationEndIndex >= 0)) {
  			url.location_ = spec.substring(locationStartIndex, locationEndIndex);
  		}
  
  		return url;
  	}