"The URI class. See [RFC 3986][rfc3986] for specifications. [rfc3986]: http://tools.ietf.org/html/rfc3986" by("Stéphane Épardaud") shared class Uri(scheme = null, authority = defaultAuthority, path = defaultPath, query = defaultQuery, fragment = null) { "The optional URI scheme: `http`, `https`, `mailto`…" shared String? scheme; "The optional Authority part (contains user, password, host and port)" shared Authority authority; "The optional Path part" shared Path path; "The optional query part" shared Query query; "The optional fragment (hash) part" shared String? fragment; "Returns true if this is a relative URI" shared Boolean relative { return !scheme exists; } "Returns the path as an externalisable (percent-encoded) string representation. Can be an empty string." shared String pathPart { return path.string; } "Returns the query as an externalisable (percent-encoded) string representation. Can be null." shared String? queryPart { return query.specified then query.string; } String toRepresentation(Boolean human) { StringBuilder b = StringBuilder(); if(exists scheme) { b.append(scheme); b.append(":"); } if(authority.specified) { b.append("//"); b.append(authority.toRepresentation(human)); } b.append(path.toRepresentation(human)); if(query.specified) { b.append("?"); b.append(query.toRepresentation(human)); } if(exists fragment) { b.append("#"); b.append(human then fragment else percentEncoder.encodeFragment(fragment)); } return b.string; } "Returns an externalisable (percent-encoded) representation of this URI." shared actual String string { return toRepresentation(false); } "Returns a human (not parseable) representation of this URI." shared String humanRepresentation { return toRepresentation(true); } "Create a new [[Uri]] based on this [[Uri]], replacing the `scheme` with the given value" shared Uri withScheme(String? scheme) => Uri(scheme, authority, path, query, fragment); "Create a new [[Uri]] based on this [[Uri]], replacing the `authority` with the given value" shared Uri withAuthority(Authority authority) => Uri(scheme, authority, path, query, fragment); Path makePathAbsoluteIfRequired(Authority authority, Path path){ if(!path.absolute && authority.specified){ return Path(true, *path.segments); }else{ return path; } } "Create a new [[Uri]] based on this [[Uri]], replacing the `path` with the given value" shared Uri withPath(Path path){ return Uri(scheme, authority, makePathAbsoluteIfRequired(authority, path), query, fragment); } "Create a new [[Uri]] based on this [[Uri]], replacing the `query` with the given value" shared Uri withQuery(Query query) => Uri(scheme, authority, path, query, fragment); "Create a new [[Uri]] based on this [[Uri]], replacing the `fragment` with the given value" shared Uri withFragment(String? fragment) => Uri(scheme, authority, path, query, fragment); "Create a new [[Uri]] based on this [[Uri]], replacing the specified values" shared Uri with(String? scheme = this.scheme, Authority authority = this.authority, Path path = this.path, Query query = this.query, String? fragment = this.fragment) => Uri(scheme, authority, makePathAbsoluteIfRequired(authority, path), query, fragment); "Returns true if the given object is the same as this object" shared actual Boolean equals(Object that) { if(is Uri that) { if(this === that) { return true; } return eq(scheme, that.scheme) && authority == that.authority && path == that.path && query == that.query && eq(fragment, that.fragment); } return false; } shared actual Integer hash { variable value hash = 1; hash = 31*hash + (scheme?.hash else 0); hash = 31*hash + authority.hash; hash = 31*hash + path.hash; hash = 31*hash + query.hash; hash = 31*hash + (fragment?.hash else 0); return hash; } }